diff --git a/.ci/beats-tester-bc.groovy b/.ci/beats-tester-bc.groovy index d7fb36f15bd..d026fa77a15 100644 --- a/.ci/beats-tester-bc.groovy +++ b/.ci/beats-tester-bc.groovy @@ -7,7 +7,7 @@ pipeline { environment { BASE_DIR = 'src/github.com/elastic/beats' PIPELINE_LOG_LEVEL = "INFO" - BEATS_TESTER_JOB = 'Beats/beats-tester-mbp/master' + BEATS_TESTER_JOB = 'Beats/beats-tester-mbp/main' BASE_URL = "https://staging.elastic.co/${params.version}/downloads" APM_BASE_URL = "${env.BASE_URL}/apm-server" BEATS_BASE_URL = "${env.BASE_URL}/beats" diff --git a/.ci/beats-tester.groovy b/.ci/beats-tester.groovy index 8d96fb1efea..ef0b8382826 100644 --- a/.ci/beats-tester.groovy +++ b/.ci/beats-tester.groovy @@ -7,7 +7,7 @@ pipeline { environment { BASE_DIR = 'src/github.com/elastic/beats' PIPELINE_LOG_LEVEL = "INFO" - BEATS_TESTER_JOB = 'Beats/beats-tester-mbp/master' + BEATS_TESTER_JOB = 'Beats/beats-tester-mbp/main' } options { timeout(time: 1, unit: 'HOURS') diff --git a/.ci/jobs/apm-beats-update.yml b/.ci/jobs/apm-beats-update.yml index 678a9fbcd67..a1fe03b0df2 100644 --- a/.ci/jobs/apm-beats-update.yml +++ b/.ci/jobs/apm-beats-update.yml @@ -18,7 +18,7 @@ discover-pr-forks-trust: 'permission' discover-pr-origin: 'merge-current' discover-tags: true - head-filter-regex: '(master|7\.[x789]|7\.1\d|8\.\d+|PR-.*|v\d+\.\d+\.\d+)' + head-filter-regex: '(master|7\.1[6789]|8\.\d+|PR-.*|v\d+\.\d+\.\d+)' disable-pr-notifications: true notification-context: 'apm-beats-update' repo: 'beats' @@ -36,10 +36,7 @@ name: 'master' case-sensitive: true - regex-name: - regex: '7\.[x789]' - case-sensitive: true - - regex-name: - regex: '7\.1\d' + regex: '7\.1[6789]' case-sensitive: true - regex-name: regex: '8\.\d+' diff --git a/.ci/jobs/beats-release-changelog.yml b/.ci/jobs/beats-release-changelog.yml index 1cbd94c7168..6a331022e8f 100644 --- a/.ci/jobs/beats-release-changelog.yml +++ b/.ci/jobs/beats-release-changelog.yml @@ -17,4 +17,4 @@ credentials-id: f6c7695a-671e-4f4f-a331-acdce44ff9ba reference-repo: /var/lib/jenkins/.git-references/ingest-dev.git branches: - - master + - main diff --git a/.ci/jobs/beats-release-minor-major.yml b/.ci/jobs/beats-release-minor-major.yml index 91c7d105fb8..04a2e07046d 100644 --- a/.ci/jobs/beats-release-minor-major.yml +++ b/.ci/jobs/beats-release-minor-major.yml @@ -17,4 +17,4 @@ credentials-id: f6c7695a-671e-4f4f-a331-acdce44ff9ba reference-repo: /var/lib/jenkins/.git-references/ingest-dev.git branches: - - master + - main diff --git a/.ci/jobs/beats-release-patch.yml b/.ci/jobs/beats-release-patch.yml index 4d205f79647..80c401e6c20 100644 --- a/.ci/jobs/beats-release-patch.yml +++ b/.ci/jobs/beats-release-patch.yml @@ -17,4 +17,4 @@ credentials-id: f6c7695a-671e-4f4f-a331-acdce44ff9ba reference-repo: /var/lib/jenkins/.git-references/ingest-dev.git branches: - - master + - main diff --git a/.ci/jobs/beats-tester.yml b/.ci/jobs/beats-tester.yml index 14cc1007c56..dc268c0eefa 100644 --- a/.ci/jobs/beats-tester.yml +++ b/.ci/jobs/beats-tester.yml @@ -14,7 +14,7 @@ discover-pr-forks-trust: 'permission' discover-pr-origin: 'merge-current' discover-tags: true - head-filter-regex: '(master|7\.([x9]|1\d+)|8\.\d+|PR-.*|v\d+\.\d+\.\d+)' + head-filter-regex: '(master|7\.1[6789]|8\.\d+|PR-.*|v\d+\.\d+\.\d+)' disable-pr-notifications: true notification-context: 'beats-tester' repo: 'beats' @@ -32,7 +32,7 @@ name: 'master' case-sensitive: true - regex-name: - regex: '7\.([x9]|1\d+)' + regex: '7\.1[6789]' case-sensitive: true - regex-name: regex: '8\.\d+' diff --git a/.ci/jobs/beats.yml b/.ci/jobs/beats.yml index e9a26c87a0d..638051d8a2e 100644 --- a/.ci/jobs/beats.yml +++ b/.ci/jobs/beats.yml @@ -17,7 +17,7 @@ discover-pr-forks-strategy: 'merge-current' discover-pr-forks-trust: 'permission' discover-pr-origin: 'merge-current' - head-filter-regex: '(master|6\.[89]|7\.16|8\.\d+|PR-.*|v\d+\.\d+\.\d+)' + head-filter-regex: '(master|6\.[89]|7\.1[6789]|8\.\d+|PR-.*|v\d+\.\d+\.\d+)' discover-tags: true notification-context: "beats-ci" repo: 'beats' @@ -39,10 +39,7 @@ regex: '6\.[89]' case-sensitive: true - regex-name: - regex: '7\.[x789]' - case-sensitive: true - - regex-name: - regex: '7\.1\d' + regex: '7\.1[6789]' case-sensitive: true - regex-name: regex: '8\.\d+' diff --git a/.ci/jobs/packaging.yml b/.ci/jobs/packaging.yml index baa3ce45035..97f9462d8f6 100644 --- a/.ci/jobs/packaging.yml +++ b/.ci/jobs/packaging.yml @@ -14,7 +14,7 @@ discover-pr-forks-trust: 'permission' discover-pr-origin: 'merge-current' discover-tags: true - head-filter-regex: '(master|7\.[x789]|7\.1\d|8\.\d+|PR-.*|v\d+\.\d+\.\d+)' + head-filter-regex: '(master|7\.1[6789]|8\.\d+|PR-.*|v\d+\.\d+\.\d+)' disable-pr-notifications: true notification-context: 'beats-packaging' repo: 'beats' @@ -32,10 +32,7 @@ name: 'master' case-sensitive: true - regex-name: - regex: '7\.[x789]' - case-sensitive: true - - regex-name: - regex: '7\.1\d' + regex: '7\.1[6789]' case-sensitive: true - regex-name: regex: '8\.\d+' diff --git a/.ci/packaging.groovy b/.ci/packaging.groovy index 7c4ce7b5e8f..7be1628e138 100644 --- a/.ci/packaging.groovy +++ b/.ci/packaging.groovy @@ -101,7 +101,6 @@ pipeline { 'auditbeat', 'filebeat', 'heartbeat', - 'journalbeat', 'metricbeat', 'packetbeat', 'winlogbeat', @@ -111,7 +110,6 @@ pipeline { 'x-pack/filebeat', 'x-pack/functionbeat', 'x-pack/heartbeat', - // 'x-pack/journalbeat', 'x-pack/metricbeat', 'x-pack/osquerybeat', 'x-pack/packetbeat', @@ -199,7 +197,6 @@ pipeline { 'auditbeat', 'filebeat', 'heartbeat', - 'journalbeat', 'metricbeat', 'packetbeat', 'x-pack/auditbeat', @@ -277,8 +274,6 @@ def pushCIDockerImages(Map args = [:]) { tagAndPush(beatName: 'filebeat', arch: arch) } else if (env?.BEATS_FOLDER?.endsWith('heartbeat')) { tagAndPush(beatName: 'heartbeat', arch: arch) - } else if ("${env.BEATS_FOLDER}" == "journalbeat"){ - tagAndPush(beatName: 'journalbeat', arch: arch) } else if (env?.BEATS_FOLDER?.endsWith('metricbeat')) { tagAndPush(beatName: 'metricbeat', arch: arch) } else if (env?.BEATS_FOLDER?.endsWith('osquerybeat')) { diff --git a/.ci/packer_cache.sh b/.ci/packer_cache.sh index 1627343c612..9b444376924 100755 --- a/.ci/packer_cache.sh +++ b/.ci/packer_cache.sh @@ -21,7 +21,7 @@ function dockerPullCommonImages() { docker.elastic.co/observability-ci/database-enterprise:12.2.0.1 docker.elastic.co/beats-dev/fpm:1.11.0 golang:1.14.12-stretch - centos:7 + ubuntu:20.04 " for image in ${DOCKER_IMAGES} ; do (retry 2 docker pull ${image}) || echo "Error pulling ${image} Docker image. Continuing." diff --git a/.ci/schedule-daily.groovy b/.ci/schedule-daily.groovy index adad76cbd76..a326d9759cf 100644 --- a/.ci/schedule-daily.groovy +++ b/.ci/schedule-daily.groovy @@ -20,9 +20,7 @@ pipeline { stages { stage('Nighly beats builds') { steps { - runBuild(quietPeriod: 0, job: 'Beats/beats/master') - runBuild(quietPeriod: 2000, job: 'Beats/beats/7.16') - runBuild(quietPeriod: 4000, job: 'Beats/beats/7.15') + runBuilds(quietPeriodFactor: 2000, branches: ['master', '8.', '7.', '7.']) } } } @@ -33,7 +31,37 @@ pipeline { } } -def runBuild(Map args = [:]) { - def jobName = args.job - build(quietPeriod: args.quietPeriod, job: jobName, parameters: [booleanParam(name: 'macosTest', value: true)], wait: false, propagate: false) +def runBuilds(Map args = [:]) { + def branches = [] + // Expand macros and filter duplicated matches. + args.branches.each { branch -> + def branchName = getBranchName(branch) + if (!branches.contains(branchName)) { + branches << branchName + } + } + + def quietPeriod = 0 + branches.each { branch -> + build(quietPeriod: quietPeriod, job: "Beats/beats/${branch}", parameters: [booleanParam(name: 'macosTest', value: true)], wait: false, propagate: false) + // Increate the quiet period for the next iteration + quietPeriod += args.quietPeriodFactor + } +} + +def getBranchName(branch) { + // special macro to look for the latest minor version + if (branch.contains('8.')) { + return bumpUtils.getMajorMinor(bumpUtils.getCurrentMinorReleaseFor8()) + } + if (branch.contains('8.')) { + return bumpUtils.getMajorMinor(bumpUtils.getNextMinorReleaseFor8()) + } + if (branch.contains('7.')) { + return bumpUtils.getMajorMinor(bumpUtils.getCurrentMinorReleaseFor7()) + } + if (branch.contains('7.')) { + return bumpUtils.getMajorMinor(bumpUtils.getNextMinorReleaseFor7()) + } + return branch } diff --git a/.ci/schedule-weekly.groovy b/.ci/schedule-weekly.groovy index 74293ab7b9f..a42ae7934fd 100644 --- a/.ci/schedule-weekly.groovy +++ b/.ci/schedule-weekly.groovy @@ -20,9 +20,7 @@ pipeline { stages { stage('Weekly beats builds') { steps { - runBuild(quietPeriod: 0, job: 'Beats/beats/master') - runBuild(quietPeriod: 1000, job: 'Beats/beats/7.16') - runBuild(quietPeriod: 2000, job: 'Beats/beats/7.15') + runBuilds(quietPeriodFactor: 1000, branches: ['master', '8.', '7.', '7.']) } } } @@ -33,7 +31,37 @@ pipeline { } } -def runBuild(Map args = [:]) { - def jobName = args.job - build(quietPeriod: args.quietPeriod, job: jobName, parameters: [booleanParam(name: 'awsCloudTests', value: true)], wait: false, propagate: false) +def runBuilds(Map args = [:]) { + def branches = [] + // Expand macros and filter duplicated matches. + args.branches.each { branch -> + def branchName = getBranchName(branch) + if (!branches.contains(branchName)) { + branches << branchName + } + } + + def quietPeriod = 0 + branches.each { branch -> + build(quietPeriod: quietPeriod, job: "Beats/beats/${branch}", parameters: [booleanParam(name: 'awsCloudTests', value: true)], wait: false, propagate: false) + // Increate the quiet period for the next iteration + quietPeriod += args.quietPeriodFactor + } +} + +def getBranchName(branch) { + // special macro to look for the latest minor version + if (branch.contains('8.')) { + return bumpUtils.getMajorMinor(bumpUtils.getCurrentMinorReleaseFor8()) + } + if (branch.contains('8.')) { + return bumpUtils.getMajorMinor(bumpUtils.getNextMinorReleaseFor8()) + } + if (branch.contains('7.')) { + return bumpUtils.getMajorMinor(bumpUtils.getCurrentMinorReleaseFor7()) + } + if (branch.contains('7.')) { + return bumpUtils.getMajorMinor(bumpUtils.getNextMinorReleaseFor7()) + } + return branch } diff --git a/.ci/scripts/kind-setup.sh b/.ci/scripts/kind-setup.sh index d2c9eeeb771..fa4f66dd6e6 100755 --- a/.ci/scripts/kind-setup.sh +++ b/.ci/scripts/kind-setup.sh @@ -1,23 +1,5 @@ #!/usr/bin/env bash set -exuo pipefail -kind create cluster --image kindest/node:${K8S_VERSION} --config - <=1" actions: - merge: + queue: method: squash - strict: false + name: default - name: delete upstream branch after merging changes on testing/environments/snapshot* or it's closed conditions: - or: @@ -87,9 +106,9 @@ pull_request_rules: - head~=^add-backport-next.* - "#approved-reviews-by>=1" actions: - merge: + queue: method: squash - strict: false + name: default - name: delete upstream branch with changes on ^.mergify.yml that has been merged or closed conditions: - or: @@ -101,6 +120,18 @@ pull_request_rules: - files~=^\.mergify\.yml$ actions: delete_head_branch: + - name: notify the backport has not been merged yet + conditions: + - -merged + - -closed + - author=mergify[bot] + - "#check-success>0" + - schedule=Mon-Mon 06:00-10:00[Europe/Paris] + - "#assignee>=1" + actions: + comment: + message: | + This pull request has not been merged yet. Could you please review and merge it @{{ assignee | join(', @') }}? 🙏 - name: notify the backport policy conditions: - -label~=^backport @@ -167,6 +198,19 @@ pull_request_rules: labels: - "backport" title: "[{{ destination_branch }}](backport #{{ number }}) {{ title }}" + - name: backport patches to 7.17 branch + conditions: + - merged + - label=backport-v7.17.0 + actions: + backport: + assignees: + - "{{ author }}" + branches: + - "7.17" + labels: + - "backport" + title: "[{{ destination_branch }}](backport #{{ number }}) {{ title }}" - name: backport patches to 8.0 branch conditions: - merged diff --git a/CHANGELOG-developer.next.asciidoc b/CHANGELOG-developer.next.asciidoc index 485f4d4152f..dcb2a5665f4 100644 --- a/CHANGELOG-developer.next.asciidoc +++ b/CHANGELOG-developer.next.asciidoc @@ -58,6 +58,7 @@ The list below covers the major changes between 7.0.0-rc2 and master only. - Removed the `common.Float` type. {issue}28279[28279] {pull}28280[28280] {pull}28376[28376] - Removed Beat generators. {pull}28816[28816] - libbeat.logp package forces ECS compliant logs. Logs are JSON formatted. Options to enable ECS/JSON have been removed. {issue}15544[15544] {pull}28573[28573] +- Removed deprecated disk spool from Beats. Use disk queue instead. {pull}28869[28869] ==== Bugfixes @@ -67,6 +68,7 @@ The list below covers the major changes between 7.0.0-rc2 and master only. - Remove `event.dataset` (ECS) annotion from `libbeat.logp`. {issue}27404[27404] - Errors should be thrown as errors. Metricsets inside Metricbeat will now throw errors as the `error` log level. {pull}27804[27804] - Avoid panicking in `add_fields` processor when input event.Fields is a nil map. {pull}28219[28219] +- Drop event batch when get HTTP status 413 from Elasticsearch to avoid infinite loop {issue}14350[14350] {pull}29368[29368] ==== Added diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc index 8f0348c51b1..c61cdbccb99 100644 --- a/CHANGELOG.asciidoc +++ b/CHANGELOG.asciidoc @@ -3,6 +3,11 @@ :issue: https://github.com/elastic/beats/issues/ :pull: https://github.com/elastic/beats/pull/ +[[release-notes-8.0.0-rc1]] +=== Beats version 8.0.0-rc1 + +Changes will be described in a later RC / GA. + [[release-notes-8.0.0-beta1]] === Beats version 8.0.0-beta1 @@ -17,6 +22,218 @@ Changes will be described in a later alpha / beta. === Beats version 8.0.0-alpha1 Changes will be described in a later alpha / beta. +[[release-notes-7.16.3]] +=== Beats version 7.16.3 +https://github.com/elastic/beats/compare/v7.16.2...v7.16.3[View commits] + +==== Bugfixes + +*Affecting all Beats* + +- Fields of type `match_only_text` (i.e. `message`) and `wildcard` were missing from the template's `default_field` list. {issue}29633[29633] {pull}29634[29634] + +[[release-notes-7.16.2]] +=== Beats version 7.16.2 +https://github.com/elastic/beats/compare/v7.16.1...v7.16.2[View commits] + +==== Bugfixes + +*Filebeat* + +- Resolve issue with @timestamp for `defender_atp`. {pull}28272[28272] +- Fix handling of escaped newlines in the `decode_cef` processor. {issue}16995[16995] {pull}29268[29268] + +==== Added + +*Filebeat* + +- Update Cisco module to enable TCP input. {issue}26118[26118] {issue}28821[28821] {pull}26159[26159] + +*Winlogbeat* + +- Add configuration option for registry file flush timeout {issue}29001[29001] {pull}29053[29053] + +[[release-notes-7.16.1]] +=== Beats version 7.16.1 +https://github.com/elastic/beats/compare/v7.16.0...v7.16.1[View commits] + +==== Bugfixes + +*Affecting all Beats* + +- Overwrite index name in index template correctly. {issue}28571[28571] {pull}29299[29299] + +==== Added + +*Filebeat* + +- Add elapsed time information to `aws-s3` input errors and log messages. {pull}29328[29328] + +[[release-notes-7.16.0]] +=== Beats version 7.16.0 +https://github.com/elastic/beats/compare/v7.15.2...v7.16.0[View commits] + +==== Breaking changes + +*Affecting all Beats* + +- Load index templates v2 (composable index templates) by default when talking to ES 7.16 or ES 8.x. Please note that you cannot load templates into Elasticsearch 7.8 or older with this default. To load templates to these ES version, set `setup.template.type` back to `legacy`. {pull}28538[28538] +- Previously, RE2 and thus Golang had a bug where `(|a)*` matched more characters than `(|a)+`. To stay consistent with PCRE, the bug was fixed. Configurations that rely on the old, buggy behaviour has to be adjusted. See more about Golang bug: https://github.com/golang/go/issues/46123 {pull}27543[27543] +- Remove Journalbeat. Use `journald` input of Filebeat instead. {pull}29131[29131] + +*Heartbeat* + +- Change behavior in case of duplicate monitor IDs in configs to be last monitor wins. {pull}29041[29041] + +*Metricbeat* + +- Align fields to Beats naming conventions in GCP module. {issue}27231[27231] {pull}27974[27974] + +*Functionbeat* + +- Support for Google Cloud Functions have been removed, as it has been in Beta for a long time and been broken for a few releases. Please use other tools provided by Elastic to fetch data from GCP (e.g. Filebeat). + +==== Bugfixes + +*Affecting all Beats* + +- Fix discovery of Nomad allocations with multiple events during startup. {pull}28700[28700] +- Fix the wrong beat name on monitoring and state endpoint {issue}27755[27755] +- Skip configuration checks in autodiscover for configurations that are already running {pull}29048[29048] +- Fix `decode_json_processor` to always respect `add_error_key` {pull}29107[29107] +- Fix `add_labels` flattening of array values. {pull}29211[29211] +- Skip `add_kubernetes_metadata` processor when Kubernetes metadata are already present {pull}27689[27689] + +*Auditbeat* + +- Fix handling of root and relative paths {issue}24430[24430] {pull}28354[28354] +- Fix handling of long file names on Windows. {issue}25334[25334] {pull}28517[28517] +- System/socket dataset: Fix uninstallation of return kprobes. {issue}28608[28608] {pull}28609[28609] +- Fix auditbeat tracing struct decoding. {pull}28580[28580] + +*Filebeat* + +- Update indentation for azure filebeat configuration. {pull}26604[26604] +- Tolerate faults when Windows Event Log session is interrupted {issue}27947[27947] {pull}28191[28191] +- Add support for username in Cisco ASA security negotiation logs {pull}26975[26975] +- Relax time parsing and capture group and session type in Cisco ASA module {issue}24710[24710] {pull}28325[28325] +- Correctly track bytes read when max_bytes is exceeded. {issue}28317[28317] {pull}28352[28352] +- Fix parsing of apache log levels including numbers. {pull}28717[28717] +- Upgrade `azure-eventhub` SDK reference, contains potential checkpoint fixes. {pull}28919[28919] +- Revert usageDetails api version to 2019-01-01. {pull}28995[28995] +- Fix in `aws-s3` input regarding provider discovery through endpoint {pull}28963[28963] +- Fix `threatintel.misp` filters configuration. {issue}27970[27970] +- Fix opening files on Windows in filestream so open files can be deleted. {issue}29113[29113] {pull}29180[29180] + +*Heartbeat* + +- Fix broken seccomp filtering and improve security via `setcap` and `setuid` when running as root on linux in containers. {pull}27878[27878] +- Log browser `zip_url` download failures as `warn` instead of as `info`. {pull}28440[28440] +- Properly locate base stream in fleet configs. {pull}28455[28455] +- Stop logging params values. {pull}28774[28774] +- Remove accidentally included `cups` library in Docker images. {pull}28853[pull] +- Fix broken monitors with newer versions of image relying on `dup3`. {pull}28938[pull + +*Metricbeat* + +- `beat` module respects `basepath` config option. {pull}28162[28162] +- Fix list_docker.go {pull}28374[28374] +- Fix RDS metadata in Cloudwatch metricset. {pull}29106[29106] +- Errors should be thrown as errors. Metricsets inside metricbeat will now throw errors as the `error` log level. {pull}27804[27804] + +*Winlogbeat* + +- Tolerate faults when Windows Event Log session is interrupted {issue}27947[27947] {pull}28191[28191] +- Add ECS 1.9 new users fields {pull}26509[26509] +- Don't split hyphenated tokens {pull}28483[28483] +- Correctly handle AccessMask if it is an integer or list of masks. {pull}29016[29016] + +==== Added + +*Affecting all Beats* + +- Allow non-padded base64 data to be decoded by `decode_base64_field` {pull}27311[27311], {issue}27021[27021] +- The Kafka support library Sarama has been updated to 1.29.1. {pull}27717[27717] +- Kafka is now supported up to version 2.8.0. {pull}27720[27720] +- Add Huawei Cloud provider to add_cloud_metadata. {pull}27607[27607] +- Add default seccomp policy for linux arm64. {pull}27955[27955] +- Add cluster level add_kubernetes_metadata support for centralized enrichment {pull}24621[24621] +- Update cloud.google.com/go library. {pull}28229[28229] +- Add additional metadata to the root HTTP endpoint. {pull}28265[28265] +- Upgrade k8s.io/client-go library. {pull}28228[28228] +- Update ECS to 1.12.0. {pull}27770[27770] +- Fields mapped as `match_only_text` will automatically fallback to a `text` mapping when using Elasticsearch versions that do not support `match_only_text`. {pull}27770[27770] +- Do not load ML jobs to Elasticsearch 8.x from new Beats 7.x releases. {pull}27771[27771] +- Update kubernetes scheduler and controllermanager endpoints in elastic-agent-standalone-kubernetes.yaml with secure ports {pull}28675[28675] +- Add default seccomp policy for Linux arm64. {pull}27955[27955] +- Add `http.pprof.enabled` option to libbeat to allow http/pprof endpoints on the socket that libbeat creates for metrics. {issue}21965[21965] +- Enable IMDSv2 support for `add_cloud_metadata` processor on AWS. {issue}22101[22101] {pull}28285[28285] + +*Filebeat* + +- Add `timezone` config option to the `decode_cef` processor. {issue}27232[27232] {pull}27727[27727] +- Add `timezone` config option to the `syslog` input. {pull}27727[27727] +- Added support for parsing syslog dates containing a leading 0 (e.g. `Sep 01`) rather than a space. {pull}27775[27775] +- Add base64 Encode functionality to `httpjson` input. {pull}27681[27681] +- Add `join` and `sprintf` functions to `httpjson` input. {pull}27735[27735] +- Improve memory usage of line reader of `log` and `filestream` input. {pull}27782[27782] +- Add `ignore_empty_value` flag to `httpjson` `split` processor. {pull}27880[27880] +- Add support for passing a prefix on S3 bucket list mode for AWS-S3 input {pull}28252[28252] {issue}27965[27965] +- Update Cisco ASA/FTD ingest pipeline grok/dissect patterns for multiple message IDs. {issue}26869[26869] {pull}26879[26879] +- Add write access to `url.value` from `request.transforms` in `httpjson` input. {pull}27937[27937] +- Add Base64 encoded HMAC and UUID template functions to `httpjson` input {pull}27873[27873] +- Release checkpoint module as GA. {pull}27814[27814] +- Make aws-cloudwatch input GA. {pull}28161[28161] +- Move processing to ingest node for AWS vpcflow fileset. {pull}28168[28168] +- Release zoom module as GA. {pull}28106[28106] +- Add support for secondary object attribute handling in ThreatIntel MISP module {pull}28124[28124] +- Azure signinlogs - Add support for ManagedIdentitySignInLogs, NonInteractiveUserSignInLogs, and ServicePrincipalSignInLogs. {issue}23653[23653] +- Add `base64Decode` and `base64DecodeNoPad` functions to `httpsjon` templates. {pull}28385[28385] +- Add 'early_limit' config option for Rate-Limiting `httpjson`. Default rate-limiting for Okta will start when remaining is `1`. {pull}28513[28513] +- Add latency config option for `aws-cloudwatch` input. {pull}28509[28509] +- Added proxy support to `threatintel/malwarebazaar`. {pull}28533[28533] +- Sophos UTM: Support logs containing hostname in Syslog header. {pull}28638[28638] +- Moving Oracle Filebeat module to GA. {pull}28754[28754] +- Add support in `aws-s3` input for S3 notification from SNS to SQS. {pull}28800[28800] +- Add support in `aws-s3` input for custom script parsing of S3 notifications. {pull}28946[28946] +- Improve error handling in `aws-s3` input for malformed S3 notifications. {issue}28828[28828] {pull}28946[28946] +- `filestream` and `log` inputs accept null (`\u0000`) as line terminator. {pull}28998[28998] + +*Heartbeat* + +- Support JSON expressions / validation of JSON arrays. {pull}28073[28073] +- Experimental `run once` mode. {pull}25972[25972] +- Add `keyword` multi-field mapping for `synthetics.step.name`. {pull}28452[28452] + +*Metricbeat* + +- Enable `journald` input type in Filebeat. {issue}7955[7955] {pull}27351[27351] +- Added a new beta `enterprisesearch` module for Elastic Enterprise Search {pull}27549[27549] +- Register additional name for `storage` metricset in the azure module. {pull}28447[28447] +- Update reference to gosigar pacakge for filesystem windows fix. {pull}28909[28909] +- Override `Host()` on statsd MetricSet {pull}29103[29103] +- Add Linux pressure metricset {pull}27355[27355] +- Add User-Agent header to HTTP requests. {issue}18160[18160] {pull}27509[27509] + +*Functionbeat* + +- Add support for AWS Kinesis record deaggregation {pull}28241[28241] + +*Winlogbeat* + +- Add support for event language selection from config file {pull}19818[19818] + +==== Deprecated + +*Affecting all Beats* + +- Deprecate `setup.template.type`. In the future Beats will load data streams instead of regular indices. + +*Filebeat* + +- Deprecate `log` input in favour of `filestream` input. {pull}28623[28623] + + [[release-notes-7.15.2]] === Beats version 7.15.2 https://github.com/elastic/beats/compare/v7.15.1...v7.15.2[View commits] diff --git a/CHANGELOG.next.asciidoc b/CHANGELOG.next.asciidoc index dcd03b0ee70..a2a9ba049eb 100644 --- a/CHANGELOG.next.asciidoc +++ b/CHANGELOG.next.asciidoc @@ -10,71 +10,46 @@ https://github.com/elastic/beats/compare/v7.0.0-alpha2...master[Check the HEAD d *Affecting all Beats* -- Remove the non-ECS `agent.hostname` field. Use the `agent.name` or `agent.id` fields for an identifier. {issue}16377[16377] {pull}18328[18328] -- Make error message about locked data path actionable. {pull}18667[18667] - Remove the deprecated `xpack.monitoring.*` settings. Going forward only `monitoring.*` settings may be used. {issue}9424[9424] {pull}18608[18608] -- Skip add_kubernetes_metadata processor when kubernetes metadata are already present {pull}27689[27689] - Remove deprecated/undocumented IncludeCreatorMetadata setting from kubernetes metadata config options {pull}28006[28006] - Remove deprecated fields from kubernetes module {pull}28046[28046] - Remove deprecated config option aws_partition. {pull}28120[28120] - Improve stats API {pull}27963[27963] -- Enable IMDSv2 support for `add_cloud_metadata` processor on AWS. {issue}22101[22101] {pull}28285[28285] -- Update kubernetes.namespace from keyword to group field and add name, labels, annotations, uuid as its fields {pull}27917[27917] - Libbeat: logp package forces ECS compliant logs. Logs are JSON formatted. Options to enable ECS/JSON have been removed. {issue}15544[15544] {pull}28573[28573] -- Previously, RE2 and thus Golang had a bug where `(|a)*` matched more characters than `(|a)+`. To stay consistent with PCRE, the bug was fixed. Configurations that rely on the old, buggy behaviour has to be adjusted. See more about Golang bug: https://github.com/golang/go/issues/46123 {pull}27543[27543] - Update docker client. {pull}28716[28716] - Remove `auto` from the available options of `setup.ilm.enabled` and set the default value to `true`. {pull}28671[28671] - add_process_metadata processor: Replace usage of deprecated `process.ppid` field with `process.parent.pid`. {pull}28620[28620] - add_docker_metadata processor: Replace usage of deprecated `process.ppid` field with `process.parent.pid`. {pull}28620[28620] +- Use data streams instead of indices for storing events from Beats. {pull}28450[28450] +- Remove option `setup.template.type` and always load composable template with data streams. {pull}28450[28450] +- Remove several ILM options (`rollover_alias` and `pattern`) as data streams does not require index aliases. {pull}28450[28450] - Index template's default_fields setting is only populated with ECS fields. {pull}28596[28596] {issue}28215[28215] +- Remove deprecated `--template` and `--ilm-policy` flags. Use `--index-management` instead. {pull}28870[28870] +- Remove options `logging.files.suffix` and default to datetime endings. {pull}28927[28927] +- Remove Journalbeat. Use `journald` input of Filebeat instead. {pull}29131[29131] +- `include_matches` option of `journald` input no longer accepts a list of string. {pull}29294[29294] +- Add job.name in pods controlled by Jobs {pull}28954[28954] +- Change Docker base image from CentOS 7 to Ubuntu 20.04 {pull}29681[29681] *Auditbeat* - File integrity dataset (macOS): Replace unnecessary `file.origin.raw` (type keyword) with `file.origin.text` (type `text`). {issue}12423[12423] {pull}15630[15630] - Change event.kind=error to event.kind=event to comply with ECS. {issue}18870[18870] {pull}20685[20685] -- File integrity dataset: Remove non-ECS `hash.*` fields. Hashes are under `file.hash.*`. {issue}19039[19039] {pull}28378[28378] -- Auditd dataset: Removes the authentication_success and authentication_failure event.type values for user logins. {issue}19039[19039] {pull}28378[28378] -- Fix handling of long file names on Windows. {issue}25334[25334] {pull}28517[28517] -- System/socket dataset: Fix uninstallation of return kprobes. {issue}28608[28608] {pull}28609[28609] -- Replace usage of deprecated `process.ppid` field with `process.parent.pid`. {pull}28620[28620] -- Fix auditbeat tracing struct decoding. {pull}28580[28580] *Filebeat* - Fix parsing of Elasticsearch node name by `elasticsearch/slowlog` fileset. {pull}14547[14547] -- With the default configuration the following modules will no longer send the `host` field that contains information about the host on which Filebeat is running. You can revert this change by configuring tags for the module and omitting `forwarded` from the list. {issue}13920[13920] -- Preserve case of http.request.method. ECS prior to 1.6 specified normalizing to lowercase, which lost information. Affects filesets: apache/access, elasticsearch/audit, iis/access, iis/error, nginx/access, nginx/ingress_controller, aws/elb, suricata/eve, zeek/http. {issue}18154[18154] {pull}18359[18359] - With the default configuration the cloud modules (aws, azure, googlecloud, o365, okta) - With the default configuration the cef and panw modules will no longer send the `host` -- Preserve case of http.request.method. ECS prior to 1.6 specified normalizing to lowercase, which lost information. Affects filesets: apache/access, elasticsearch/audit, iis/access, iis/error, nginx/access, nginx/ingress_controller, aws/elb, suricata/eve, zeek/http. {issue}18154[18154] {pull}18359[18359] - Add `while_pattern` type to multiline reader. {pull}19662[19662] -- Add support for GMT timezone offsets in `decode_cef`. {pull}20993[20993] -- Fix parsing of Elasticsearch node name by `elasticsearch/slowlog` fileset. {pull}14547[14547] -- Removes old module aliases for `googlecloud` (moved to gcp) and `apache2` (moved to apache). {pull}27919[27919] -- Removes old module name aliases (gsuite) and removing old cyberark module in favor of the new cyberarkpas{pull}27915[27915] -- Only filesets that are explicitly configured will be enabled. {issue}17256[17256] {pull}27526[27526] -- All filesets are disabled in the default configuration. {issue}17256[17256] {pull}27762[27762] -- Remove deprecated fields in Kafka module. {pull}27938[27938] -- Remove deprecated fields in coredns module. {pull}28196[28196] -- Remove old `httpjson` config implementation. {pull}28054[28054] -- Added dataset `threatq` to the `threatintel` module to ingest indicators from ThreatQ {issue}27423[27423] -- Fail to start Filebat if none between `queue_url`, `bucket_arn` or `non_aws_bucket_name` is set for a configured aws-s3 input {issue}13911[13911] {pull}28666[28666] -- All modules: Replace usages of deprecated ECS fields `process.ppid` and `log.original` with `process.parent.pid` and `event.original`. {pull}28620[28620] -- Replace usages of `host.user.*` fields with `user.*` in `cisco`, `microsoft` and `oracle` modules. {pull}28620[28620] -- Remove `docker` input. Please use `filestream` input with `container` parser or `container` input. {pull}28817[28817] +- auditd dataset: Use process.args to store program arguments instead of auditd.log.aNNN fields. {pull}29601[29601] *Heartbeat* - -*Journalbeat* - -- Rename field `journald.process.capabilites` to `journald.process.capabilities` to fix spelling. {pull}28065[28065] -- Rename field `log.syslog.facility.name` to `log.syslog.facility.code` because the value is numeric rather than the facility name. {pull}28065[28065] +- Only add monitor.status to browser events when summary. {pull}29460[29460] +- Also add summary to journeys for which the synthetics runner crashes. {pull}29606[29606] *Metricbeat* -- Add Linux pressure metricset {pull}27355[27355] -- Add User-Agent header to HTTP requests. {issue}18160[18160] {pull}27509[27509] -- Errors should be thrown as errors. Metricsets inside Metricbeat will now throw errors as the `error` log level. {pull}27804[27804] - Remove deprecated fields in Docker module. {issue}11835[11835] {pull}27933[27933] - Remove deprecated fields in Kafka module. {pull}27938[27938] - Remove deprecated config option default_region from aws module. {pull}28120[28120] @@ -83,8 +58,8 @@ https://github.com/elastic/beats/compare/v7.0.0-alpha2...master[Check the HEAD d - Remove linux-only metrics from diskio, memory {pull}28292[28292] - Remove deprecated config option perfmon.counters from windows/perfmon metricset. {pull}28282[28282] - Remove deprecated fields in Redis module. {issue}11835[11835] {pull}28246[28246] -- Align fields to Beats naming conventions in GCP module. {issue}27231[27231] {pull}27974[27974] - system/process metricset: Replace usage of deprecated `process.ppid` field with `process.parent.pid`. {pull}28620[28620] +- Remove overriding of index pattern on the Kubernetes overview dashboard. {pull}29676[29676] *Packetbeat* @@ -92,6 +67,7 @@ https://github.com/elastic/beats/compare/v7.0.0-alpha2...master[Check the HEAD d - `event.category` no longer contains the value `network_traffic` because this is not a valid ECS event category value. {pull}20556[20556] - Remove deprecated TLS fields in favor of tls.server.x509 and tls.client.x509 ECS fields. {pull}28487[28487] - HTTP: The field `http.request.method` will maintain its original case. {pull}28620[28620] +- Unify gopacket dependencies. {pull}29167[29167] *Winlogbeat* @@ -100,145 +76,56 @@ https://github.com/elastic/beats/compare/v7.0.0-alpha2...master[Check the HEAD d - Improve ECS field mappings in Sysmon module. Hashes are now also populated to the corresponding `process.hash`, `process.pe.imphash`, `file.hash`, or `file.pe.imphash`. {issue}18364[18364] - Improve ECS field mappings in Sysmon module. `file.name`, `file.directory`, and `file.extension` are now populated. {issue}18364[18364] - Improve ECS field mappings in Sysmon module. `rule.name` is populated for all events when present. {issue}18364[18364] -- Fix unprefixed fields in `fields.yml` for Powershell module {issue}18984[18984] - Remove top level `hash` property from sysmon events {pull}20653[20653] +- Move module processing from local Javascript processor to ingest node {issue}29184[29184] {pull}29435[29435] *Functionbeat* -- Support for Google Cloud Functions have been removed, as it has been in Beta for a long time and been broken for a few releases. Please use other tools provided by Elastic to fetch data from GCP (e.g. Filebeat). ==== Bugfixes *Affecting all Beats* -- Fix a race condition with the Kafka pipeline client, it is possible that `Close()` get called before `Connect()` . {issue}11945[11945] -- Allow users to configure only `cluster_uuid` setting under `monitoring` namespace. {pull}14338[14338] -- Update replicaset group to apps/v1 {pull}15854[15802] -- Fix missing output in dockerlogbeat {pull}15719[15719] -- Fix issue where TLS settings would be ignored when a forward proxy was in use. {pull}15516[15516] -- Update replicaset group to apps/v1 {pull}15854[15802] -- Add `ssl.ca_sha256` option to the supported TLS option, this allow to check that a specific certificate is used as part of the verified chain. {issue}15717[15717] -- Improve some logging messages for add_kubernetes_metadata processor {pull}16866{16866} -- Do not rotate log files on startup when interval is configured and rotateonstartup is disabled. {pull}17613[17613] -- Fix `setup.dashboards.index` setting not working. {pull}17749[17749] -- Fix Elasticsearch license endpoint URL referenced in error message. {issue}17880[17880] {pull}18030[18030] -- Change `decode_json_fields` processor, to merge parsed json objects with existing objects in the event instead of fully replacing them. {pull}17958[17958] -- Gives monitoring reporter hosts, if configured, total precedence over corresponding output hosts. {issue}17937[17937] {pull}17991[17991] -- Change `decode_json_fields` processor, to merge parsed json objects with existing objects in the event instead of fully replacing them. {pull}17958[17958] -- [Autodiscover] Check if runner is already running before starting again. {pull}18564[18564] -- Fix an issue where error messages are not accurate in mapstriface. {issue}18662[18662] {pull}18663[18663] -- Fix regression in `add_kubernetes_metadata`, so configured `indexers` and `matchers` are used if defaults are not disabled. {issue}18481[18481] {pull}18818[18818] -- Fix the `translate_sid` processor's handling of unconfigured target fields. {issue}18990[18990] {pull}18991[18991] -- Fixed a service restart failure under Windows. {issue}18914[18914] {pull}18916[18916] -- Fix terminating pod autodiscover issue. {pull}20084[20084] -- Fix seccomp policy for calls to `chmod` and `chown`. {pull}20054[20054] -- Output errors when Kibana index pattern setup fails. {pull}20121[20121] -- Fix issue in autodiscover that kept inputs stopped after config updates. {pull}20305[20305] -- Add service resource in k8s cluster role. {pull}20546[20546] -- Periodic metrics in logs will now report `libbeat.output.events.active` and `beat.memstats.rss` -- Allows disable pod events enrichment with deployment name {pull}28521[28521] -- Fix `fingerprint` processor to give it access to the `@timestamp` field. {issue}28683[28683] -- Fix the wrong beat name on monitoring and state endpoint {issue}27755[27755] *Auditbeat* - system/package: Fix parsing of Installed-Size field of DEB packages. {issue}16661[16661] {pull}17188[17188] - system module: Fix panic during initialisation when /proc/stat can't be read. {pull}17569[17569] - system/package: Fix an error that can occur while trying to persist package metadata. {issue}18536[18536] {pull}18887[18887] -- Fix handling of root and relative paths {issue}24430[24430] {pull}28354[28354] +- system/socket: Fix bugs leading to wrong process being attributed to flows. {pull}29166[29166] {issue}17165[17165] +- system/socket: Fix process name and arg truncation for long names, paths and args lists. {issue}24667[24667] {pull}29410[29410] +- system/socket: Fix startup errors on newer 5.x kernels due to missing _do_fork function. {issue}29607[29607] {pull}29744[29744] +- libbeat/processors/add_process_metadata: Fix memory leak in process cache. {issue}24890[24890] {pull}29717[29717] *Filebeat* -- cisco/asa fileset: Fix parsing of 302021 message code. {pull}14519[14519] -- Fix filebeat azure dashboards, event category should be `Alert`. {pull}14668[14668] -- Fix s3 input with cloudtrail fileset reading json file. {issue}16374[16374] {pull}16441[16441] -- Add queue_url definition in manifest file for aws module. {pull}16640[16640] -- Add queue_url definition in manifest file for aws module. {pull}16640{16640} -- Fix `elasticsearch.gc` fileset to not collect _all_ logs when Elasticsearch is running in Docker. {issue}13164[13164] {issue}16583[16583] {pull}17164[17164] -- Fixed a mapping exception when ingesting CEF logs that used the spriv or dpriv extensions. {issue}17216[17216] {pull}17220[17220] -- Remove migrationVersion map 7.7.0 reference from Kibana dashboard file to fix backward compatibility issues. {pull}17425[17425] -- Fix issue 17734 to retry on rate-limit error in the Filebeat httpjson input. {issue}17734[17734] {pull}17735[17735] -- Fixed `cloudfoundry.access` to have the correct `cloudfoundry.app.id` contents. {pull}17847[17847] -- Fixing `ingress_controller.` fields to be of type keyword instead of text. {issue}17834[17834] -- Fixed typo in log message. {pull}17897[17897] -- Fix `o365` module ignoring `var.api` settings. {pull}18948[18948] -- Fix `netflow` module to support 7 bytepad for IPFIX template. {issue}18098[18098] -- Update container name for the azure filesets. {pull}19899[19899] -- Fix `o365` module ignoring `var.api` settings. {pull}18948[18948] -- Fix S3 input to trim delimiter /n from each log line. {pull}19972[19972] -- Fix s3 input parsing json file without expand_event_list_from_field. {issue}19902[19902] {pull}19962[19962] {pull}20370[20370] -- Fix millisecond timestamp normalization issues in CrowdStrike module {issue}20035[20035], {pull}20138[20138] -- Fix support for message code 106100 in Cisco ASA and FTD. {issue}19350[19350] {pull}20245[20245] -- Fix `fortinet` setting `event.timezone` to the system one when no `tz` field present {pull}20273[20273] -- Fix `okta` geoip lookup in pipeline for `destination.ip` {pull}20454[20454] -- Fix mapping exception in the `googlecloud/audit` dataset pipeline. {issue}18465[18465] {pull}20465[20465] -- Fix `cisco` asa and ftd parsing of messages 106102 and 106103. {pull}20469[20469] -- Update indentation for azure filebeat configuration. {pull}26604[26604] -- Add support for passing a prefix on S3 bucket list mode for AWS-S3 input {pull}28252[28252] {issue}27965[27965] -- Resolve issue with @timestamp for defender_atp. {pull}28272[28272] -- Tolerate faults when Windows Event Log session is interrupted {issue}27947[27947] {pull}28191[28191] -- Add support for username in cisco asa security negotiation logs {pull}26975[26975] -- Relax time parsing and capture group and session type in Cisco ASA module {issue}24710[24710] {pull}28325[28325] -- Correctly track bytes read when max_bytes is exceeded. {issue}28317[28317] {pull}28352[28352] -- Upgrade azure-eventhub sdk reference, contains potential checkpoint fixes. {pull}28919[28919] -- Revert usageDetails api version to 2019-01-01. {pull}28995[28995] -- Fix in `aws-s3` input regarding provider discovery through endpoint {pull}28963[28963] +- aws-s3: Stop trying to increase SQS message visibility after ReceiptHandleIsInvalid errors. {pull}29480[29480] +- Fix handling of IPv6 addresses in netflow flow events. {issue}19210[19210] {pull}29383[29383] +- Fix `sophos` KV splitting and syslog header handling {issue}24237[24237] {pull}29331[29331] +- Undo deletion of endpoint config from cloudtrail fileset in {pull}29415[29415]. {pull}29450[29450] +- ibmmq: Fixed `@timestamp` not being populated with correct values. {pull}29773[29773] *Heartbeat* -- Fix broken seccomp filtering and improve security via `setcap` and `setuid` when running as root on linux in containers. {pull}27878[27878] -- Log browser `zip_url` download failures as `warn` instead of as `info`. {pull}28440[28440] -- Properly locate base stream in fleet configs. {pull}28455[28455] -- Stop logging params values. {pull}28774[28774] -- Remove accidentally included cups library in docker images. {pull}28853[pull] -- Fix broken monitors with newer versions of image relying on dup3. {pull}28938[pull] - -*Journalbeat* - +- Fix race condition in http monitors using `mode:all` that can cause crashes. {pull}29697[pull] *Metricbeat* -- Fix checking tagsFilter using length in cloudwatch metricset. {pull}14525[14525] -- Log bulk failures from bulk API requests to monitoring cluster. {issue}14303[14303] {pull}14356[14356] -- Fix skipping protocol scheme by light modules. {pull}16205[pull] -- Revert changes in `docker` module: add size flag to docker.container. {pull}16600[16600] -- Fix detection and logging of some error cases with light modules. {pull}14706[14706] -- Fix imports after PR was merged before rebase. {pull}16756[16756] -- Reduce memory usage in `elasticsearch/index` metricset. {issue}16503[16503] {pull}16538[16538] -- Fix issue in Jolokia module when mbean contains multiple quoted properties. {issue}17375[17375] {pull}17374[17374] -- Fix issue in Jolokia module when mbean contains multiple quoted properties. {issue}17375[17375] {pull}17374[17374] -- Fix azure storage dashboards. {pull}17590[17590] -- Metricbeat no longer needs to be started strictly after Logstash for `logstash-xpack` module to report correct data. {issue}17261[17261] {pull}17497[17497] -- Fix pubsub metricset to collect all GA stage metrics from gcp stackdriver. {issue}17154[17154] {pull}17600[17600] -- Add privileged option so as mb to access data dir in Openshift. {pull}17606[17606] -- Fix "ID" event generator of Google Cloud module {issue}17160[17160] {pull}17608[17608] -- Add privileged option for Auditbeat in Openshift {pull}17637[17637] -- Fix storage metricset to allow config without region/zone. {issue}17623[17623] {pull}17624[17624] -- Fix overflow on Prometheus rates when new buckets are added on the go. {pull}17753[17753] -- Remove specific win32 api errors from events in perfmon. {issue}18292[18292] {pull}18361[18361] -- Fix application_pool metricset after pdh changes. {pull}18477[18477] -- Fix panic on `metricbeat test modules` when modules are configured in `metricbeat.modules`. {issue}18789[18789] {pull}18797[18797] -- Fix getting gcp compute instance metadata with partial zone/region in config. {pull}18757[18757] -- Add missing network.sent_packets_count metric into compute metricset in googlecloud module. {pull}18802[18802] -- Fix compute and pubsub dashboard for googlecloud module. {issue}18962[18962] {pull}18980[18980] -- Fix crash on vsphere module when Host information is not available. {issue}18996[18996] {pull}19078[19078] -- Modify doc for app_insights metricset to contain example of config. {pull}20185[20185] -- Add required option for `metrics` in app_insights. {pull}20406[20406] -- Groups same timestamp metric values to one event in the app_insights metricset. {pull}20403[20403] -- `beat` module respects `basepath` config option. {pull}28162[28162] -- Fix list_docker.go {pull}28374[28374] - Use xpack.enabled on SM modules to write into .monitoring indices when using Metricbeat standalone {pull}28365[28365] - Fix in rename processor to ingest metrics for `write.iops` to proper field instead of `write_iops` in rds metricset. {pull}28960[28960] +- Enhance filter check in kubernetes event metricset. {pull}29470[29470] +- Fix gcp metrics metricset apply aligner to all metric_types {pull}29514[29513] +- Extract correct index property in kibana.stats metricset {pull}29622[29622] +- Fixed bug with `elasticsearch/cluster_stats` metricset not recording license expiration date correctly. {pull}29711[29711] *Packetbeat* +- Prevent incorrect use of AMQP protocol parsing from causing silent failure. {pull}29017[29017] +- Fix error handling in MongoDB protocol parsing. {pull}29017[29017] *Winlogbeat* -- Add source.ip validation for event ID 4778 in the Security module. {issue}19627[19627] -- Tolerate faults when Windows Event Log session is interrupted {issue}27947[27947] {pull}28191[28191] -- Add ECS 1.9 new users fields {pull}26509[26509] -- Don't split hyphenated tokens {pull}28483[28483] +- Add provider names to Security pipeline conditional check in routing pipeline. {issue}27288[27288] {pull}29781[29781] *Functionbeat* @@ -250,128 +137,53 @@ https://github.com/elastic/beats/compare/v7.0.0-alpha2...master[Check the HEAD d *Affecting all Beats* -- Decouple Debug logging from fail_on_error logic for rename, copy, truncate processors {pull}12451[12451] -- Fingerprint processor adds a new xxhash hashing algorithm {pull}15418[15418] -- Update RPM packages contained in Beat Docker images. {issue}17035[17035] -- Update documentation for system.process.memory fields to include clarification on Windows os's. {pull}17268[17268] -- When using the `decode_json_fields` processor, decoded fields are now deep-merged into existing event. {pull}17958[17958] -- Update documentation for system.process.memory fields to include clarification on Windows os's. {pull}17268[17268] -- Add keystore support for autodiscover static configurations. {pull]16306[16306] -- When using the `decode_json_fields` processor, decoded fields are now deep-merged into existing event. {pull}17958[17958] -- Add keystore support for autodiscover static configurations. {pull]16306[16306] -- Add TLS support to Kerberos authentication in Elasticsearch. {pull}18607[18607] - Add config option `rotate_on_startup` to file output {issue}19150[19150] {pull}19347[19347] -- Set index.max_docvalue_fields_search in index template to increase value to 200 fields. {issue}20215[20215] -- Allow non-padded base64 data to be decoded by decode_base64_field {pull}27311[27311], {issue}27021[27021] -- The Kafka support library Sarama has been updated to 1.29.1. {pull}27717[27717] -- Kafka is now supported up to version 2.8.0. {pull}27720[27720] -- Add Huawei Cloud provider to add_cloud_metadata. {pull}27607[27607] -- Add default seccomp policy for linux arm64. {pull}27955[27955] -- Add cluster level add_kubernetes_metadata support for centralized enrichment {pull}24621[24621] -- Update ECS to 1.12.0. {pull}27770[27770] -- Fields mapped as `match_only_text` will automatically fallback to a `text` mapping when using Elasticsearch versions that do not support `match_only_text`. {pull}27770[27770] -- Update cloud.google.com/go library. {pull}28229[28229] -- Add additional metadata to the root HTTP endpoint. {pull}28265[28265] -- Upgrade k8s.io/client-go library. {pull}28228[28228] -- Upgrade prometheus library. {pull}28716[28716] - Name all k8s workqueue. {pull}28085[28085] -- Update kubernetes scheduler and controllermanager endpoints in elastic-agent-standalone-kubernetes.yaml with secure ports {pull}28675[28675] -- Add options to configure k8s client qps/burst. {pull}28151[28151] - Update to ECS 8.0 fields. {pull}28620[28620] -- Add http.pprof.enabled option to libbeat to allow http/pprof endpoints on the socket that libbeat creates for metrics. {issue}21965[21965] - Support custom analyzers in fields.yml. {issue}28540[28540] {pull}28926[28926] +- Discover changes in Kubernetes nodes metadata as soon as they happen. {pull}23139[23139] +- Support self signed certificates on outputs {pull}29229[29229] +- Update k8s library {pull}29394[29394] +- Add FIPS configuration option for all AWS API calls. {pull}28899[28899] +- Add `default_region` config to AWS common module. {pull}29415[29415] +- Add support for latest k8s versions v1.23 and v1.22 {pull}29575[29575] *Auditbeat* -- Reference kubernetes manifests include configuration for auditd and enrichment with kubernetes metadata. {pull}17431[17431] *Filebeat* -- `container` and `docker` inputs now support reading of labels and env vars written by docker JSON file logging driver. {issue}8358[8358] -- Add `index` option to all inputs to directly set a per-input index value. {pull}14010[14010] -- move create-[module,fileset,fields] to mage and enable in x-pack/filebeat {pull}15836[15836] -- Work on e2e ACK's for the azure-eventhub input {issue}15671[15671] {pull}16215[16215] -- Add a TLS test and more debug output to httpjson input {pull}16315[16315] -- Add an SSL config example in config.yml for filebeat MISP module. {pull}16320[16320] -- Update filebeat httpjson input to support pagination via Header and Okta module. {pull}16354[16354] -- Add a TLS test and more debug output to httpjson input {pull}16315[16315] -- Add an SSL config example in config.yml for filebeat MISP module. {pull}16320[16320] -- Added documentation for running Filebeat in Cloud Foundry. {pull}17275[17275] -- Release Google Cloud module as GA. {pull}17511[17511] -- Improve ECS categorization field mappings for nats module. {issue}16173[16173] {pull}17550[17550] -- Enhance `elasticsearch/slowlog` fileset to handle ECS-compatible logs emitted by Elasticsearch. {issue}17715[17715] {pull}17729[17729] -- Added documentation for running Filebeat in Cloud Foundry. {pull}17275[17275] -- Release Google Cloud module as GA. {pull}17511[17511] -- Update filebeat httpjson input to support pagination via Header and Okta module. {pull}16354[16354] -- Change the `json.*` input settings implementation to merge parsed json objects with existing objects in the event instead of fully replacing them. {pull}17958[17958] -- Add support for array parsing in azure-eventhub input. {pull}18585[18585] -- Add support for array parsing in azure-eventhub input. {pull}18585[18585] -- Improved performance of PANW sample dashboards. {issue}19031[19031] {pull}19032[19032] -- Add event.ingested for CrowdStrike module {pull}20138[20138] -- Add support for additional fields and FirewallMatchEvent type events in CrowdStrike module {pull}20138[20138] -- Add `timezone` config option to the `decode_cef` processor. {issue}27232[27232] {pull}27727[27727] -- Add `timezone` config option to the `syslog` input. {pull}27727[27727] -- Added support for parsing syslog dates containing a leading 0 (e.g. `Sep 01`) rather than a space. {pull}27775[27775] -- Add base64 Encode functionality to httpjson input. {pull}27681[27681] -- Add `join` and `sprintf` functions to `httpjson` input. {pull}27735[27735] -- Improve memory usage of line reader of `log` and `filestream` input. {pull}27782[27782] -- Add `ignore_empty_value` flag to `httpjson` `split` processor. {pull}27880[27880] -- Update Cisco ASA/FTD ingest pipeline grok/dissect patterns for multiple message IDs. {issue}26869[26869] {pull}26879[26879] -- Add write access to `url.value` from `request.transforms` in `httpjson` input. {pull}27937[27937] -- Add Base64 encoded HMAC and UUID template functions to `httpjson` input {pull}27873[27873] -- Release checkpoint module as GA. {pull}27814[27814] -- Make aws-cloudwatch input GA. {pull}28161[28161] -- Move processing to ingest node for AWS vpcflow fileset. {pull}28168[28168] -- Release zoom module as GA. {pull}28106[28106] -- Add support for secondary object attribute handling in ThreatIntel MISP module {pull}28124[28124] -- Azure signinlogs - Add support for ManagedIdentitySignInLogs, NonInteractiveUserSignInLogs, and ServicePrincipalSignInLogs. {issue}23653[23653] -- Add `base64Decode` and `base64DecodeNoPad` functions to `httpsjon` templates. {pull}28385[28385] -- Add 'early_limit' config option for Rate-Limiting `httpjson`. Default rate-limiting for Okta will start when remaining is `1`. {pull}28513[28513] -- Add latency config option for aws-cloudwatch input. {pull}28509[28509] -- Added proxy support to threatintel/malwarebazaar. {pull}28533[28533] - Add `text/csv` decoder to `httpjson` input {pull}28564[28564] - Update `aws-s3` input to connect to non AWS S3 buckets {issue}28222[28222] {pull}28234[28234] -- Sophos UTM: Support logs containing hostname in syslog header. {pull}28638[28638] -- Moving Oracle Filebeat module to GA. {pull}28754[28754] - Add support for '/var/log/pods/' path for add_kubernetes_metadata processor with `resource_type: pod`. {pull}28868[28868] - Add documentation for add_kubernetes_metadata processors `log_path` matcher. {pull}28868[28868] -- Add support in aws-s3 input for s3 notification from SNS to SQS. {pull}28800[28800] +- Add support for parsers on journald input {pull}29070[29070] +- Add support in httpjson input for oAuth2ProviderDefault of password grant_type. {pull}29087[29087] +- Add support for filtering in journald input with `unit`, `kernel`, `identifiers` and `include_matches`. {pull}29294[29294] +- Add new `userAgent` and `beatInfo` template functions for httpjson input {pull}29528[29528] *Heartbeat* -- Support JSON expressions / validation of JSON arrays. {pull}28073[28073] -- Experimental 'run once' mode. {pull}25972[25972] -- Add `keyword` multi-field mapping for `synthetics.step.name`. {pull}28452[28452] - -*Journalbeat* *Metricbeat* -- Move the windows pdh implementation from perfmon to a shared location in order for future modules/metricsets to make use of. {pull}15503[15503] -- Add database_account azure metricset. {issue}15758[15758] -- Add database_account azure metricset. {issue}15758[15758] -- Release Zookeeper/connection module as GA. {issue}14281[14281] {pull}17043[17043] -- Add dashboard for pubsub metricset in googlecloud module. {pull}17161[17161] -- Added documentation for running Metricbeat in Cloud Foundry. {pull}17275[17275] -- Added documentation for running Metricbeat in Cloud Foundry. {pull}17275[17275] -- Remove required for region/zone and make stackdriver a metricset in googlecloud. {issue}16785[16785] {pull}18398[18398] -- Add memory metrics into compute googlecloud. {pull}18802[18802] -- Enable `journald` input type in Filebeat. {issue}7955[7955] {pull}27351[27351] -- Added a new beta `enterprisesearch` module for Elastic Enterprise Search {pull}27549[27549] - Preliminary AIX support {pull}27954[27954] -- Register additional name for `storage` metricset in the azure module. {pull}28447[28447] -- Update reference to gosigar pacakge for filesystem windows fix. {pull}28909[28909] +- Add option to skip older k8s events {pull}29396[29396] +- Add `add_resource_metadata` configuration to Kubernetes module. {pull}29133[29133] +- Add `container.id` and `container.runtime` ECS fields in container metricset. {pull}29560[29560] +- Add `memory.workingset.limit.pct` field in Kubernetes container/pod metricset. {pull}29547[29547] +- Add k8s metadata in state_cronjob metricset. {pull}29572[29572] +- Add `elasticsearch.cluster.id` field to Beat and Kibana modules. {pull}29577[29577] +- Add `elasticsearch.cluster.id` field to Logstash module. {pull}29625[29625] *Packetbeat* *Functionbeat* -- Add support for AWS Kinesis record deaggregation {pull}28241[28241] *Winlogbeat* -- Add more DNS error codes to the Sysmon module. {issue}15685[15685] -- Add support for event language selection from config file {pull}19818[19818] +- Add support for custom XML queries {issue}1054[1054] {pull}29330[29330] *Elastic Log Driver* @@ -384,12 +196,9 @@ https://github.com/elastic/beats/compare/v7.0.0-alpha2...master[Check the HEAD d *Filebeat* -- Deprecate `log` input in favour of `filestream` input. {pull}28623[28623] *Heartbeat* -*Journalbeat* - *Metricbeat* @@ -402,3 +211,9 @@ https://github.com/elastic/beats/compare/v7.0.0-alpha2...master[Check the HEAD d ==== Known Issue *Journalbeat* + + + + + + diff --git a/Jenkinsfile b/Jenkinsfile index 35ae38cb840..0f8fbcf2596 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -291,13 +291,13 @@ def generateStages(Map args = [:]) { def cloud(Map args = [:]) { withGithubNotify(context: args.context) { withNode(labels: args.label, forceWorkspace: true){ - startCloudTestEnv(name: args.directory, dirs: args.dirs) + startCloudTestEnv(name: args.directory, dirs: args.dirs, withAWS: args.withAWS) } - withCloudTestEnv() { + withCloudTestEnv(args) { try { target(context: args.context, command: args.command, directory: args.directory, label: args.label, withModule: args.withModule, isMage: true, id: args.id) } finally { - terraformCleanup(name: args.directory, dir: args.directory) + terraformCleanup(name: args.directory, dir: args.directory, withAWS: args.withAWS) } } } @@ -431,8 +431,6 @@ def pushCIDockerImages(Map args = [:]) { tagAndPush(beatName: 'filebeat', arch: arch) } else if (beatsFolder.endsWith('heartbeat')) { tagAndPush(beatName: 'heartbeat', arch: arch) - } else if ("${beatsFolder}" == "journalbeat"){ - tagAndPush(beatName: 'journalbeat', arch: arch) } else if (beatsFolder.endsWith('metricbeat')) { tagAndPush(beatName: 'metricbeat', arch: arch) } else if ("${beatsFolder}" == "packetbeat"){ @@ -556,7 +554,7 @@ def e2e_with_entrypoint(Map args = [:]) { def dockerLogFile = "docker_logs_${entrypoint}.log" dir("${env.WORKSPACE}/src/github.com/elastic/e2e-testing") { // TBC with the target branch if running on a PR basis. - git(branch: 'master', credentialsId: '2a9602aa-ab9f-4e52-baf3-b71ca88469c7-UserAndToken', url: 'https://github.com/elastic/e2e-testing.git') + git(branch: 'main', credentialsId: '2a9602aa-ab9f-4e52-baf3-b71ca88469c7-UserAndToken', url: 'https://github.com/elastic/e2e-testing.git') if(isDockerInstalled()) { dockerLogin(secret: "${DOCKER_ELASTIC_SECRET}", registry: "${DOCKER_REGISTRY}") } @@ -636,7 +634,7 @@ def withBeatsEnv(Map args = [:], Closure body) { if(isUnix()) { gox_flags = (isArm() && is64arm()) ? '-arch arm' : '-arch amd64' - path = "${env.WORKSPACE}/bin:${env.PATH}" + path = "${env.WORKSPACE}/bin:${env.PATH}:/usr/local/bin" magefile = "${WORKSPACE}/.magefile" pythonEnv = "${WORKSPACE}/python-env" testResults = '**/build/TEST*.xml' @@ -704,6 +702,7 @@ def withBeatsEnv(Map args = [:], Closure body) { error("Error '${err.toString()}'") } finally { if (archive) { + archiveArtifacts(allowEmptyArchive: true, artifacts: "${directory}/build/system-tests/docker-logs/TEST-docker-compose-*.log") archiveTestOutput(directory: directory, testResults: testResults, artifacts: artifacts, id: args.id, upload: upload) } tearDown() @@ -868,14 +867,15 @@ def tarAndUploadArtifacts(Map args = [:]) { * This method executes a closure with credentials for cloud test * environments. */ -def withCloudTestEnv(Closure body) { +def withCloudTestEnv(Map args = [:], Closure body) { def maskedVars = [] def testTags = "${env.TEST_TAGS}" // Allow AWS credentials when the build was configured to do so with: // - the cloudtests build parameters // - the aws github label - if (params.allCloudTests || params.awsCloudTests || matchesPrLabel(label: 'aws')) { + // - forced with the cloud argument aws github label + if (params.allCloudTests || params.awsCloudTests || matchesPrLabel(label: 'aws') || args.get('withAWS', false)) { testTags = "${testTags},aws" def aws = getVaultSecret(secret: "${AWS_ACCOUNT_SECRET}").data if (!aws.containsKey('access_key')) { @@ -889,6 +889,7 @@ def withCloudTestEnv(Closure body) { [var: "AWS_ACCESS_KEY_ID", password: aws.access_key], [var: "AWS_SECRET_ACCESS_KEY", password: aws.secret_key], ]) + log(level: 'INFO', text: 'withCloudTestEnv: it has been configured to run in AWS.') } withEnv([ @@ -914,7 +915,7 @@ def startCloudTestEnv(Map args = [:]) { String name = normalise(args.name) def dirs = args.get('dirs',[]) stage("${name}-prepare-cloud-env"){ - withCloudTestEnv() { + withCloudTestEnv(args) { withBeatsEnv(archive: false, withModule: false) { try { dirs?.each { folder -> @@ -957,7 +958,7 @@ def terraformCleanup(Map args = [:]) { String name = normalise(args.name) String directory = args.dir stage("${name}-tear-down-cloud-env"){ - withCloudTestEnv() { + withCloudTestEnv(args) { withBeatsEnv(archive: false, withModule: false) { unstash("terraform-${name}") retryWithSleep(retries: 2, seconds: 5, backoff: true) { @@ -1082,6 +1083,7 @@ class RunCommand extends co.elastic.beats.BeatsFunction { public run(Map args = [:]){ steps.stageStatusCache(args){ def withModule = args.content.get('withModule', false) + def withAWS = args.content.get('withAWS', false) // // What's the retry policy for fighting the flakiness: // 1) Lint/Packaging/Cloud/k8sTest stages don't retry, since their failures are normally legitim @@ -1140,7 +1142,7 @@ class RunCommand extends co.elastic.beats.BeatsFunction { steps.k8sTest(context: args.context, versions: args.content.k8sTest.split(','), label: args.label, id: args.id) } if(args?.content?.containsKey('cloud')) { - steps.cloud(context: args.context, command: args.content.cloud, directory: args.project, label: args.label, withModule: withModule, dirs: args.content.dirs, id: args.id) + steps.cloud(context: args.context, command: args.content.cloud, directory: args.project, label: args.label, withModule: withModule, dirs: args.content.dirs, id: args.id, withAWS: withAWS) } } } diff --git a/Makefile b/Makefile index 1975bac3165..9139d4ad34e 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ BUILD_DIR=$(CURDIR)/build COVERAGE_DIR=$(BUILD_DIR)/coverage -BEATS?=auditbeat filebeat heartbeat journalbeat metricbeat packetbeat winlogbeat x-pack/functionbeat x-pack/elastic-agent x-pack/osquerybeat +BEATS?=auditbeat filebeat heartbeat metricbeat packetbeat winlogbeat x-pack/functionbeat x-pack/elastic-agent x-pack/osquerybeat PROJECTS=libbeat $(BEATS) PROJECTS_ENV=libbeat filebeat metricbeat PYTHON_ENV?=$(BUILD_DIR)/python-env @@ -128,8 +128,9 @@ check-no-changes: ## check-python : Python Linting. .PHONY: check-python check-python: python-env - @$(FIND) -name *.py -name *.py -not -path "*/build/*" -exec $(PYTHON_ENV)/bin/autopep8 -d --max-line-length 120 {} \; | (! grep . -q) || (echo "Code differs from autopep8's style" && false) - @$(FIND) -name *.py -not -path "*/build/*" | xargs $(PYTHON_ENV)/bin/pylint --py3k -E || (echo "Code is not compatible with Python 3" && false) + @. $(PYTHON_ENV)/bin/activate; \ + $(FIND) -name *.py -name *.py -not -path "*/build/*" -exec $(PYTHON_ENV)/bin/autopep8 -d --max-line-length 120 {} \; | (! grep . -q) || (echo "Code differs from autopep8's style" && false); \ + $(FIND) -name *.py -not -path "*/build/*" | xargs $(PYTHON_ENV)/bin/pylint --py3k -E || (echo "Code is not compatible with Python 3" && false) ## check-headers : Check the license headers. .PHONY: check-headers @@ -183,10 +184,11 @@ notice: ## python-env : Sets up the virtual python environment. .PHONY: python-env python-env: - @test -d $(PYTHON_ENV) || ${PYTHON_EXE} -m venv $(VENV_PARAMS) $(PYTHON_ENV) - @$(PYTHON_ENV)/bin/pip install -q --upgrade pip autopep8==1.5.4 pylint==2.4.4 + @test -f $(PYTHON_ENV)/bin/activate || ${PYTHON_EXE} -m venv $(VENV_PARAMS) $(PYTHON_ENV) + @. $(PYTHON_ENV)/bin/activate; \ + ${PYTHON_EXE} -m pip install -q --upgrade pip autopep8==1.5.4 pylint==2.4.4; \ + find $(PYTHON_ENV) -type d -name dist-packages -exec sh -c "echo dist-packages > {}.pth" ';' @# Work around pip bug. See: https://github.com/pypa/pip/issues/4464 - @find $(PYTHON_ENV) -type d -name dist-packages -exec sh -c "echo dist-packages > {}.pth" ';' ## test-apm : Tests if apm works with the current code .PHONY: test-apm diff --git a/NOTICE.txt b/NOTICE.txt index d5599add95e..7853a149231 100644 --- a/NOTICE.txt +++ b/NOTICE.txt @@ -1,5 +1,5 @@ Elastic Beats -Copyright 2014-2021 Elasticsearch BV +Copyright 2014-2022 Elasticsearch BV This product includes software developed by The Apache Software Foundation (http://www.apache.org/). @@ -10,12 +10,12 @@ Third party libraries used by the Elastic Beats project: -------------------------------------------------------------------------------- -Dependency : cloud.google.com/go -Version: v0.83.0 +Dependency : cloud.google.com/go/bigquery +Version: v1.8.0 Licence type (autodetected): Apache-2.0 -------------------------------------------------------------------------------- -Contents of probable licence file $GOMODCACHE/cloud.google.com/go@v0.83.0/LICENSE: +Contents of probable licence file $GOMODCACHE/cloud.google.com/go/bigquery@v1.8.0/LICENSE: Apache License @@ -222,12 +222,12 @@ Contents of probable licence file $GOMODCACHE/cloud.google.com/go@v0.83.0/LICENS -------------------------------------------------------------------------------- -Dependency : cloud.google.com/go/bigquery -Version: v1.8.0 +Dependency : cloud.google.com/go/monitoring +Version: v1.1.0 Licence type (autodetected): Apache-2.0 -------------------------------------------------------------------------------- -Contents of probable licence file $GOMODCACHE/cloud.google.com/go/bigquery@v1.8.0/LICENSE: +Contents of probable licence file $GOMODCACHE/cloud.google.com/go/monitoring@v1.1.0/LICENSE: Apache License @@ -435,11 +435,11 @@ Contents of probable licence file $GOMODCACHE/cloud.google.com/go/bigquery@v1.8. -------------------------------------------------------------------------------- Dependency : cloud.google.com/go/pubsub -Version: v1.3.1 +Version: v1.17.1 Licence type (autodetected): Apache-2.0 -------------------------------------------------------------------------------- -Contents of probable licence file $GOMODCACHE/cloud.google.com/go/pubsub@v1.3.1/LICENSE: +Contents of probable licence file $GOMODCACHE/cloud.google.com/go/pubsub@v1.17.1/LICENSE: Apache License @@ -7641,217 +7641,6 @@ Contents of probable licence file $GOMODCACHE/github.com/elastic/go-sysinfo@v1.7 limitations under the License. --------------------------------------------------------------------------------- -Dependency : github.com/elastic/go-txfile -Version: v0.0.8 -Licence type (autodetected): Apache-2.0 --------------------------------------------------------------------------------- - -Contents of probable licence file $GOMODCACHE/github.com/elastic/go-txfile@v0.0.8/LICENSE: - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - 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. - - -------------------------------------------------------------------------------- Dependency : github.com/elastic/go-ucfg Version: v0.8.3 @@ -10357,12 +10146,12 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- -Dependency : github.com/adriansr/gopacket -Version: v1.1.18-0.20200327165309-dd62abfa8a41 +Dependency : github.com/elastic/gopacket +Version: v1.1.20-0.20211202005954-d412fca7f83a Licence type (autodetected): BSD-3-Clause -------------------------------------------------------------------------------- -Contents of probable licence file $GOMODCACHE/github.com/adriansr/gopacket@v1.1.18-0.20200327165309-dd62abfa8a41/LICENSE: +Contents of probable licence file $GOMODCACHE/github.com/elastic/gopacket@v1.1.20-0.20211202005954-d412fca7f83a/LICENSE: Copyright (c) 2012 Google, Inc. All rights reserved. Copyright (c) 2009-2011 Andreas Krennmair. All rights reserved. @@ -10645,11 +10434,11 @@ Contents of probable licence file $GOMODCACHE/github.com/gorhill/cronexpr@v0.0.0 -------------------------------------------------------------------------------- Dependency : github.com/gorilla/mux -Version: v1.7.3 +Version: v1.8.0 Licence type (autodetected): BSD-3-Clause -------------------------------------------------------------------------------- -Contents of probable licence file $GOMODCACHE/github.com/gorilla/mux@v1.7.3/LICENSE: +Contents of probable licence file $GOMODCACHE/github.com/gorilla/mux@v1.8.0/LICENSE: Copyright (c) 2012-2018 The Gorilla Authors. All rights reserved. @@ -15052,44 +14841,6 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. --------------------------------------------------------------------------------- -Dependency : github.com/tsg/gopacket -Version: v0.0.0-20200626092518-2ab8e397a786 -Licence type (autodetected): BSD-3-Clause --------------------------------------------------------------------------------- - -Contents of probable licence file $GOMODCACHE/github.com/tsg/gopacket@v0.0.0-20200626092518-2ab8e397a786/LICENSE: - -Copyright (c) 2012 Google, Inc. All rights reserved. -Copyright (c) 2009-2011 Andreas Krennmair. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Andreas Krennmair, Google, nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - -------------------------------------------------------------------------------- Dependency : github.com/ugorji/go/codec Version: v1.1.8 @@ -16905,11 +16656,11 @@ THE SOFTWARE. -------------------------------------------------------------------------------- Dependency : golang.org/x/crypto -Version: v0.0.0-20210616213533-5ff15b29337e +Version: v0.0.0-20210817164053-32db794688a5 Licence type (autodetected): BSD-3-Clause -------------------------------------------------------------------------------- -Contents of probable licence file $GOMODCACHE/golang.org/x/crypto@v0.0.0-20210616213533-5ff15b29337e/LICENSE: +Contents of probable licence file $GOMODCACHE/golang.org/x/crypto@v0.0.0-20210817164053-32db794688a5/LICENSE: Copyright (c) 2009 The Go Authors. All rights reserved. @@ -17016,11 +16767,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- Dependency : golang.org/x/oauth2 -Version: v0.0.0-20210514164344-f6687ab2804c +Version: v0.0.0-20211005180243-6b3c2da341f1 Licence type (autodetected): BSD-3-Clause -------------------------------------------------------------------------------- -Contents of probable licence file $GOMODCACHE/golang.org/x/oauth2@v0.0.0-20210514164344-f6687ab2804c/LICENSE: +Contents of probable licence file $GOMODCACHE/golang.org/x/oauth2@v0.0.0-20211005180243-6b3c2da341f1/LICENSE: Copyright (c) 2009 The Go Authors. All rights reserved. @@ -17164,11 +16915,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- Dependency : golang.org/x/time -Version: v0.0.0-20210611083556-38a9dc6acbc6 +Version: v0.0.0-20210723032227-1f47c861a9ac Licence type (autodetected): BSD-3-Clause -------------------------------------------------------------------------------- -Contents of probable licence file $GOMODCACHE/golang.org/x/time@v0.0.0-20210611083556-38a9dc6acbc6/LICENSE: +Contents of probable licence file $GOMODCACHE/golang.org/x/time@v0.0.0-20210723032227-1f47c861a9ac/LICENSE: Copyright (c) 2009 The Go Authors. All rights reserved. @@ -17238,11 +16989,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- Dependency : google.golang.org/api -Version: v0.48.0 +Version: v0.58.0 Licence type (autodetected): BSD-3-Clause -------------------------------------------------------------------------------- -Contents of probable licence file $GOMODCACHE/google.golang.org/api@v0.48.0/LICENSE: +Contents of probable licence file $GOMODCACHE/google.golang.org/api@v0.58.0/LICENSE: Copyright (c) 2011 Google Inc. All rights reserved. @@ -18534,11 +18285,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- Dependency : k8s.io/api -Version: v0.21.1 +Version: v0.23.0 Licence type (autodetected): Apache-2.0 -------------------------------------------------------------------------------- -Contents of probable licence file $GOMODCACHE/k8s.io/api@v0.21.1/LICENSE: +Contents of probable licence file $GOMODCACHE/k8s.io/api@v0.23.0/LICENSE: Apache License @@ -18746,11 +18497,11 @@ Contents of probable licence file $GOMODCACHE/k8s.io/api@v0.21.1/LICENSE: -------------------------------------------------------------------------------- Dependency : k8s.io/apimachinery -Version: v0.21.1 +Version: v0.23.0 Licence type (autodetected): Apache-2.0 -------------------------------------------------------------------------------- -Contents of probable licence file $GOMODCACHE/k8s.io/apimachinery@v0.21.1/LICENSE: +Contents of probable licence file $GOMODCACHE/k8s.io/apimachinery@v0.23.0/LICENSE: Apache License @@ -18958,11 +18709,11 @@ Contents of probable licence file $GOMODCACHE/k8s.io/apimachinery@v0.21.1/LICENS -------------------------------------------------------------------------------- Dependency : k8s.io/client-go -Version: v0.21.1 +Version: v0.23.0 Licence type (autodetected): Apache-2.0 -------------------------------------------------------------------------------- -Contents of probable licence file $GOMODCACHE/k8s.io/client-go@v0.21.1/LICENSE: +Contents of probable licence file $GOMODCACHE/k8s.io/client-go@v0.23.0/LICENSE: Apache License @@ -19581,12 +19332,12 @@ Indirect dependencies -------------------------------------------------------------------------------- -Dependency : cloud.google.com/go/storage -Version: v1.10.0 +Dependency : cloud.google.com/go +Version: v0.97.0 Licence type (autodetected): Apache-2.0 -------------------------------------------------------------------------------- -Contents of probable licence file $GOMODCACHE/cloud.google.com/go/storage@v1.10.0/LICENSE: +Contents of probable licence file $GOMODCACHE/cloud.google.com/go@v0.97.0/LICENSE: Apache License @@ -19793,12 +19544,13 @@ Contents of probable licence file $GOMODCACHE/cloud.google.com/go/storage@v1.10. -------------------------------------------------------------------------------- -Dependency : code.cloudfoundry.org/go-diodes -Version: v0.0.0-20190809170250-f77fb823c7ee +Dependency : cloud.google.com/go/kms +Version: v1.0.0 Licence type (autodetected): Apache-2.0 -------------------------------------------------------------------------------- -Contents of probable licence file $GOMODCACHE/code.cloudfoundry.org/go-diodes@v0.0.0-20190809170250-f77fb823c7ee/LICENSE: +Contents of probable licence file $GOMODCACHE/cloud.google.com/go/kms@v1.0.0/LICENSE: + Apache License Version 2.0, January 2004 @@ -20002,13 +19754,14 @@ Contents of probable licence file $GOMODCACHE/code.cloudfoundry.org/go-diodes@v0 See the License for the specific language governing permissions and limitations under the License. + -------------------------------------------------------------------------------- -Dependency : code.cloudfoundry.org/gofileutils -Version: v0.0.0-20170111115228-4d0c80011a0f +Dependency : cloud.google.com/go/storage +Version: v1.10.0 Licence type (autodetected): Apache-2.0 -------------------------------------------------------------------------------- -Contents of probable licence file $GOMODCACHE/code.cloudfoundry.org/gofileutils@v0.0.0-20170111115228-4d0c80011a0f/LICENSE: +Contents of probable licence file $GOMODCACHE/cloud.google.com/go/storage@v1.10.0/LICENSE: Apache License @@ -20215,171 +19968,222 @@ Contents of probable licence file $GOMODCACHE/code.cloudfoundry.org/gofileutils@ -------------------------------------------------------------------------------- -Dependency : code.cloudfoundry.org/rfc5424 -Version: v0.0.0-20180905210152-236a6d29298a -Licence type (autodetected): BSD-2-Clause +Dependency : code.cloudfoundry.org/go-diodes +Version: v0.0.0-20190809170250-f77fb823c7ee +Licence type (autodetected): Apache-2.0 -------------------------------------------------------------------------------- -Contents of probable licence file $GOMODCACHE/code.cloudfoundry.org/rfc5424@v0.0.0-20180905210152-236a6d29298a/LICENSE: - -BSD 2-Clause License +Contents of probable licence file $GOMODCACHE/code.cloudfoundry.org/go-diodes@v0.0.0-20190809170250-f77fb823c7ee/LICENSE: -Copyright (c) 2016, Ross Kinder -All rights reserved. + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION -* Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. + 1. Definitions. -* Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. --------------------------------------------------------------------------------- -Dependency : github.com/Azure/azure-amqp-common-go/v3 -Version: v3.2.1 -Licence type (autodetected): MIT --------------------------------------------------------------------------------- + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. -Contents of probable licence file $GOMODCACHE/github.com/!azure/azure-amqp-common-go/v3@v3.2.1/LICENSE: + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. - MIT License + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. - Copyright (c) Microsoft Corporation. All rights reserved. + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. --------------------------------------------------------------------------------- -Dependency : github.com/Azure/azure-pipeline-go -Version: v0.2.1 -Licence type (autodetected): MIT --------------------------------------------------------------------------------- + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. -Contents of probable licence file $GOMODCACHE/github.com/!azure/azure-pipeline-go@v0.2.1/LICENSE: + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: - MIT License + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and - Copyright (c) Microsoft Corporation. All rights reserved. + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. --------------------------------------------------------------------------------- -Dependency : github.com/Azure/go-amqp -Version: v0.16.0 -Licence type (autodetected): MIT --------------------------------------------------------------------------------- + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. -Contents of probable licence file $GOMODCACHE/github.com/!azure/go-amqp@v0.16.0/LICENSE: + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. - MIT License - - Copyright (C) 2017 Kale Blankenship - Portions Copyright (C) Microsoft Corporation - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. --------------------------------------------------------------------------------- -Dependency : github.com/Azure/go-ansiterm -Version: v0.0.0-20170929234023-d6e3b3328b78 -Licence type (autodetected): MIT --------------------------------------------------------------------------------- + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. -Contents of probable licence file $GOMODCACHE/github.com/!azure/go-ansiterm@v0.0.0-20170929234023-d6e3b3328b78/LICENSE: + END OF TERMS AND CONDITIONS -The MIT License (MIT) + APPENDIX: How to apply the Apache License to your work. -Copyright (c) 2015 Microsoft Corporation + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: + Copyright [yyyy] [name of copyright owner] -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. + 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 -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. + 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. -------------------------------------------------------------------------------- -Dependency : github.com/Azure/go-autorest -Version: v14.2.0+incompatible +Dependency : code.cloudfoundry.org/gofileutils +Version: v0.0.0-20170111115228-4d0c80011a0f Licence type (autodetected): Apache-2.0 -------------------------------------------------------------------------------- -Contents of probable licence file $GOMODCACHE/github.com/!azure/go-autorest@v14.2.0+incompatible/LICENSE: +Contents of probable licence file $GOMODCACHE/code.cloudfoundry.org/gofileutils@v0.0.0-20170111115228-4d0c80011a0f/LICENSE: Apache License @@ -20559,7 +20363,18 @@ Contents of probable licence file $GOMODCACHE/github.com/!azure/go-autorest@v14. END OF TERMS AND CONDITIONS - Copyright 2015 Microsoft Corporation + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -20575,213 +20390,171 @@ Contents of probable licence file $GOMODCACHE/github.com/!azure/go-autorest@v14. -------------------------------------------------------------------------------- -Dependency : github.com/Azure/go-autorest/autorest/azure/cli -Version: v0.3.1 -Licence type (autodetected): Apache-2.0 +Dependency : code.cloudfoundry.org/rfc5424 +Version: v0.0.0-20180905210152-236a6d29298a +Licence type (autodetected): BSD-2-Clause -------------------------------------------------------------------------------- -Contents of probable licence file $GOMODCACHE/github.com/!azure/go-autorest/autorest/azure/cli@v0.3.1/LICENSE: +Contents of probable licence file $GOMODCACHE/code.cloudfoundry.org/rfc5424@v0.0.0-20180905210152-236a6d29298a/LICENSE: +BSD 2-Clause License - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ +Copyright (c) 2016, Ross Kinder +All rights reserved. - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: - 1. Definitions. +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. +-------------------------------------------------------------------------------- +Dependency : github.com/Azure/azure-amqp-common-go/v3 +Version: v3.2.1 +Licence type (autodetected): MIT +-------------------------------------------------------------------------------- - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. +Contents of probable licence file $GOMODCACHE/github.com/!azure/azure-amqp-common-go/v3@v3.2.1/LICENSE: - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. + MIT License - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). + Copyright (c) Microsoft Corporation. All rights reserved. - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. +-------------------------------------------------------------------------------- +Dependency : github.com/Azure/azure-pipeline-go +Version: v0.2.1 +Licence type (autodetected): MIT +-------------------------------------------------------------------------------- - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: +Contents of probable licence file $GOMODCACHE/github.com/!azure/azure-pipeline-go@v0.2.1/LICENSE: - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and + MIT License - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and + Copyright (c) Microsoft Corporation. All rights reserved. - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. +-------------------------------------------------------------------------------- +Dependency : github.com/Azure/go-amqp +Version: v0.16.0 +Licence type (autodetected): MIT +-------------------------------------------------------------------------------- - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. +Contents of probable licence file $GOMODCACHE/github.com/!azure/go-amqp@v0.16.0/LICENSE: - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. + MIT License + + Copyright (C) 2017 Kale Blankenship + Portions Copyright (C) Microsoft Corporation + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. +-------------------------------------------------------------------------------- +Dependency : github.com/Azure/go-ansiterm +Version: v0.0.0-20170929234023-d6e3b3328b78 +Licence type (autodetected): MIT +-------------------------------------------------------------------------------- - END OF TERMS AND CONDITIONS +Contents of probable licence file $GOMODCACHE/github.com/!azure/go-ansiterm@v0.0.0-20170929234023-d6e3b3328b78/LICENSE: - Copyright 2015 Microsoft Corporation +The MIT License (MIT) - 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 +Copyright (c) 2015 Microsoft Corporation - http://www.apache.org/licenses/LICENSE-2.0 +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: - 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. +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. -------------------------------------------------------------------------------- -Dependency : github.com/Azure/go-autorest/autorest/mocks -Version: v0.4.1 +Dependency : github.com/Azure/go-autorest +Version: v14.2.0+incompatible Licence type (autodetected): Apache-2.0 -------------------------------------------------------------------------------- -Contents of probable licence file $GOMODCACHE/github.com/!azure/go-autorest/autorest/mocks@v0.4.1/LICENSE: +Contents of probable licence file $GOMODCACHE/github.com/!azure/go-autorest@v14.2.0+incompatible/LICENSE: Apache License @@ -20977,12 +20750,12 @@ Contents of probable licence file $GOMODCACHE/github.com/!azure/go-autorest/auto -------------------------------------------------------------------------------- -Dependency : github.com/Azure/go-autorest/autorest/to -Version: v0.4.0 +Dependency : github.com/Azure/go-autorest/autorest/azure/cli +Version: v0.3.1 Licence type (autodetected): Apache-2.0 -------------------------------------------------------------------------------- -Contents of probable licence file $GOMODCACHE/github.com/!azure/go-autorest/autorest/to@v0.4.0/LICENSE: +Contents of probable licence file $GOMODCACHE/github.com/!azure/go-autorest/autorest/azure/cli@v0.3.1/LICENSE: Apache License @@ -21178,12 +20951,12 @@ Contents of probable licence file $GOMODCACHE/github.com/!azure/go-autorest/auto -------------------------------------------------------------------------------- -Dependency : github.com/Azure/go-autorest/autorest/validation -Version: v0.3.1 +Dependency : github.com/Azure/go-autorest/autorest/mocks +Version: v0.4.1 Licence type (autodetected): Apache-2.0 -------------------------------------------------------------------------------- -Contents of probable licence file $GOMODCACHE/github.com/!azure/go-autorest/autorest/validation@v0.3.1/LICENSE: +Contents of probable licence file $GOMODCACHE/github.com/!azure/go-autorest/autorest/mocks@v0.4.1/LICENSE: Apache License @@ -21379,12 +21152,12 @@ Contents of probable licence file $GOMODCACHE/github.com/!azure/go-autorest/auto -------------------------------------------------------------------------------- -Dependency : github.com/Azure/go-autorest/logger -Version: v0.2.1 +Dependency : github.com/Azure/go-autorest/autorest/to +Version: v0.4.0 Licence type (autodetected): Apache-2.0 -------------------------------------------------------------------------------- -Contents of probable licence file $GOMODCACHE/github.com/!azure/go-autorest/logger@v0.2.1/LICENSE: +Contents of probable licence file $GOMODCACHE/github.com/!azure/go-autorest/autorest/to@v0.4.0/LICENSE: Apache License @@ -21580,12 +21353,12 @@ Contents of probable licence file $GOMODCACHE/github.com/!azure/go-autorest/logg -------------------------------------------------------------------------------- -Dependency : github.com/Azure/go-autorest/tracing -Version: v0.6.0 +Dependency : github.com/Azure/go-autorest/autorest/validation +Version: v0.3.1 Licence type (autodetected): Apache-2.0 -------------------------------------------------------------------------------- -Contents of probable licence file $GOMODCACHE/github.com/!azure/go-autorest/tracing@v0.6.0/LICENSE: +Contents of probable licence file $GOMODCACHE/github.com/!azure/go-autorest/autorest/validation@v0.3.1/LICENSE: Apache License @@ -21781,43 +21554,214 @@ Contents of probable licence file $GOMODCACHE/github.com/!azure/go-autorest/trac -------------------------------------------------------------------------------- -Dependency : github.com/BurntSushi/toml -Version: v0.3.1 -Licence type (autodetected): MIT +Dependency : github.com/Azure/go-autorest/logger +Version: v0.2.1 +Licence type (autodetected): Apache-2.0 -------------------------------------------------------------------------------- -Contents of probable licence file $GOMODCACHE/github.com/!burnt!sushi/toml@v0.3.1/COPYING: +Contents of probable licence file $GOMODCACHE/github.com/!azure/go-autorest/logger@v0.2.1/LICENSE: -The MIT License (MIT) -Copyright (c) 2013 TOML authors + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. + 1. Definitions. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + Copyright 2015 Microsoft Corporation + + 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. -------------------------------------------------------------------------------- -Dependency : github.com/OneOfOne/xxhash -Version: v1.2.2 +Dependency : github.com/Azure/go-autorest/tracing +Version: v0.6.0 Licence type (autodetected): Apache-2.0 -------------------------------------------------------------------------------- -Contents of probable licence file $GOMODCACHE/github.com/!one!of!one/xxhash@v1.2.2/LICENSE: +Contents of probable licence file $GOMODCACHE/github.com/!azure/go-autorest/tracing@v0.6.0/LICENSE: + Apache License Version 2.0, January 2004 @@ -21996,29 +21940,32 @@ Contents of probable licence file $GOMODCACHE/github.com/!one!of!one/xxhash@v1.2 END OF TERMS AND CONDITIONS - APPENDIX: How to apply the Apache License to your work. + Copyright 2015 Microsoft Corporation - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "{}" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. + 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. -------------------------------------------------------------------------------- -Dependency : github.com/Shopify/toxiproxy -Version: v2.1.4+incompatible +Dependency : github.com/BurntSushi/toml +Version: v0.3.1 Licence type (autodetected): MIT -------------------------------------------------------------------------------- -Contents of probable licence file $GOMODCACHE/github.com/!shopify/toxiproxy@v2.1.4+incompatible/LICENSE: +Contents of probable licence file $GOMODCACHE/github.com/!burnt!sushi/toml@v0.3.1/COPYING: The MIT License (MIT) -Copyright (c) 2014 Shopify +Copyright (c) 2013 TOML authors Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -22027,58 +21974,286 @@ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - - - --------------------------------------------------------------------------------- -Dependency : github.com/akavel/rsrc -Version: v0.8.0 -Licence type (autodetected): MIT --------------------------------------------------------------------------------- - -Contents of probable licence file $GOMODCACHE/github.com/akavel/rsrc@v0.8.0/LICENSE.txt: - -The MIT License (MIT) - -Copyright (c) 2013-2017 The rsrc Authors. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. -------------------------------------------------------------------------------- -Dependency : github.com/apache/thrift -Version: v0.13.1-0.20200603211036-eac4d0c79a5f +Dependency : github.com/OneOfOne/xxhash +Version: v1.2.2 Licence type (autodetected): Apache-2.0 -------------------------------------------------------------------------------- -Contents of probable licence file $GOMODCACHE/github.com/apache/thrift@v0.13.1-0.20200603211036-eac4d0c79a5f/LICENSE: - +Contents of probable licence file $GOMODCACHE/github.com/!one!of!one/xxhash@v1.2.2/LICENSE: + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + +-------------------------------------------------------------------------------- +Dependency : github.com/Shopify/toxiproxy +Version: v2.1.4+incompatible +Licence type (autodetected): MIT +-------------------------------------------------------------------------------- + +Contents of probable licence file $GOMODCACHE/github.com/!shopify/toxiproxy@v2.1.4+incompatible/LICENSE: + +The MIT License (MIT) + +Copyright (c) 2014 Shopify + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + + +-------------------------------------------------------------------------------- +Dependency : github.com/akavel/rsrc +Version: v0.8.0 +Licence type (autodetected): MIT +-------------------------------------------------------------------------------- + +Contents of probable licence file $GOMODCACHE/github.com/akavel/rsrc@v0.8.0/LICENSE.txt: + +The MIT License (MIT) + +Copyright (c) 2013-2017 The rsrc Authors. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + + +-------------------------------------------------------------------------------- +Dependency : github.com/apache/thrift +Version: v0.13.1-0.20200603211036-eac4d0c79a5f +Licence type (autodetected): Apache-2.0 +-------------------------------------------------------------------------------- + +Contents of probable licence file $GOMODCACHE/github.com/apache/thrift@v0.13.1-0.20200603211036-eac4d0c79a5f/LICENSE: + Apache License Version 2.0, January 2004 @@ -24124,11 +24299,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- Dependency : github.com/evanphx/json-patch -Version: v4.9.0+incompatible +Version: v4.12.0+incompatible Licence type (autodetected): BSD-3-Clause -------------------------------------------------------------------------------- -Contents of probable licence file $GOMODCACHE/github.com/evanphx/json-patch@v4.9.0+incompatible/LICENSE: +Contents of probable licence file $GOMODCACHE/github.com/evanphx/json-patch@v4.12.0+incompatible/LICENSE: Copyright (c) 2014, Evan Phoenix All rights reserved. @@ -24502,11 +24677,11 @@ SOFTWARE. -------------------------------------------------------------------------------- Dependency : github.com/go-logr/logr -Version: v0.4.0 +Version: v1.2.0 Licence type (autodetected): Apache-2.0 -------------------------------------------------------------------------------- -Contents of probable licence file $GOMODCACHE/github.com/go-logr/logr@v0.4.0/LICENSE: +Contents of probable licence file $GOMODCACHE/github.com/go-logr/logr@v1.2.0/LICENSE: Apache License Version 2.0, January 2004 @@ -26567,11 +26742,11 @@ Contents of probable licence file $GOMODCACHE/github.com/google/shlex@v0.0.0-201 -------------------------------------------------------------------------------- Dependency : github.com/googleapis/gax-go/v2 -Version: v2.0.5 +Version: v2.1.1 Licence type (autodetected): BSD-3-Clause -------------------------------------------------------------------------------- -Contents of probable licence file $GOMODCACHE/github.com/googleapis/gax-go/v2@v2.0.5/LICENSE: +Contents of probable licence file $GOMODCACHE/github.com/googleapis/gax-go/v2@v2.1.1/LICENSE: Copyright 2016, Google Inc. All rights reserved. @@ -26604,11 +26779,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- Dependency : github.com/googleapis/gnostic -Version: v0.4.1 +Version: v0.5.5 Licence type (autodetected): Apache-2.0 -------------------------------------------------------------------------------- -Contents of probable licence file $GOMODCACHE/github.com/googleapis/gnostic@v0.4.1/LICENSE: +Contents of probable licence file $GOMODCACHE/github.com/googleapis/gnostic@v0.5.5/LICENSE: Apache License @@ -30275,11 +30450,11 @@ SOFTWARE. -------------------------------------------------------------------------------- Dependency : github.com/json-iterator/go -Version: v1.1.11 +Version: v1.1.12 Licence type (autodetected): MIT -------------------------------------------------------------------------------- -Contents of probable licence file $GOMODCACHE/github.com/json-iterator/go@v1.1.11/LICENSE: +Contents of probable licence file $GOMODCACHE/github.com/json-iterator/go@v1.1.12/LICENSE: MIT License @@ -30304,36 +30479,6 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------------------------------- -Dependency : github.com/jstemmer/go-junit-report -Version: v0.9.1 -Licence type (autodetected): MIT --------------------------------------------------------------------------------- - -Contents of probable licence file $GOMODCACHE/github.com/jstemmer/go-junit-report@v0.9.1/LICENSE: - -Copyright (c) 2012 Joel Stemmer - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - -------------------------------------------------------------------------------- Dependency : github.com/jtolds/gls Version: v4.20.0+incompatible @@ -31891,11 +32036,11 @@ Contents of probable licence file $GOMODCACHE/github.com/modern-go/concurrent@v0 -------------------------------------------------------------------------------- Dependency : github.com/modern-go/reflect2 -Version: v1.0.1 +Version: v1.0.2 Licence type (autodetected): Apache-2.0 -------------------------------------------------------------------------------- -Contents of probable licence file $GOMODCACHE/github.com/modern-go/reflect2@v1.0.1/LICENSE: +Contents of probable licence file $GOMODCACHE/github.com/modern-go/reflect2@v1.0.2/LICENSE: Apache License Version 2.0, January 2004 @@ -32164,11 +32309,11 @@ SOFTWARE. -------------------------------------------------------------------------------- Dependency : github.com/onsi/ginkgo -Version: v1.12.1 +Version: v1.14.0 Licence type (autodetected): MIT -------------------------------------------------------------------------------- -Contents of probable licence file $GOMODCACHE/github.com/onsi/ginkgo@v1.12.1/LICENSE: +Contents of probable licence file $GOMODCACHE/github.com/onsi/ginkgo@v1.14.0/LICENSE: Copyright (c) 2013-2014 Onsi Fakhouri @@ -33855,12 +34000,262 @@ Contents of probable licence file $GOMODCACHE/github.com/urso/diag@v0.0.0-202002 -------------------------------------------------------------------------------- -Dependency : github.com/urso/go-bin -Version: v0.0.0-20180220135811-781c575c9f0e +Dependency : github.com/xdg/stringprep +Version: v1.0.3 +Licence type (autodetected): Apache-2.0 +-------------------------------------------------------------------------------- + +Contents of probable licence file $GOMODCACHE/github.com/xdg/stringprep@v1.0.3/LICENSE: + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + +-------------------------------------------------------------------------------- +Dependency : github.com/yuin/gopher-lua +Version: v0.0.0-20170403160031-b402f3114ec7 +Licence type (autodetected): MIT +-------------------------------------------------------------------------------- + +Contents of probable licence file $GOMODCACHE/github.com/yuin/gopher-lua@v0.0.0-20170403160031-b402f3114ec7/LICENSE: + +The MIT License (MIT) + +Copyright (c) 2015 Yusuke Inuzuka + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +-------------------------------------------------------------------------------- +Dependency : go.elastic.co/fastjson +Version: v1.1.0 +Licence type (autodetected): MIT +-------------------------------------------------------------------------------- + +Contents of probable licence file $GOMODCACHE/go.elastic.co/fastjson@v1.1.0/LICENSE: + +Copyright 2018 Elasticsearch BV + +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. + +--- + +Copyright (c) 2016 Mail.Ru Group + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + +-------------------------------------------------------------------------------- +Dependency : go.opencensus.io +Version: v0.23.0 Licence type (autodetected): Apache-2.0 -------------------------------------------------------------------------------- -Contents of probable licence file $GOMODCACHE/github.com/urso/go-bin@v0.0.0-20180220135811-781c575c9f0e/LICENSE: +Contents of probable licence file $GOMODCACHE/go.opencensus.io@v0.23.0/LICENSE: + Apache License Version 2.0, January 2004 @@ -34064,14 +34459,185 @@ Contents of probable licence file $GOMODCACHE/github.com/urso/go-bin@v0.0.0-2018 See the License for the specific language governing permissions and limitations under the License. +-------------------------------------------------------------------------------- +Dependency : go.uber.org/goleak +Version: v1.1.10 +Licence type (autodetected): MIT +-------------------------------------------------------------------------------- + +Contents of probable licence file $GOMODCACHE/go.uber.org/goleak@v1.1.10/LICENSE: + +The MIT License (MIT) + +Copyright (c) 2018 Uber Technologies, Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + -------------------------------------------------------------------------------- -Dependency : github.com/urso/magetools -Version: v0.0.0-20200125210132-c2e338f92f3a +Dependency : go.uber.org/tools +Version: v0.0.0-20190618225709-2cfd321de3ee +Licence type (autodetected): MIT +-------------------------------------------------------------------------------- + +Contents of probable licence file $GOMODCACHE/go.uber.org/tools@v0.0.0-20190618225709-2cfd321de3ee/LICENSE: + +Copyright (c) 2017 Uber Technologies, Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + + +-------------------------------------------------------------------------------- +Dependency : golang.org/x/mod +Version: v0.5.1 +Licence type (autodetected): BSD-3-Clause +-------------------------------------------------------------------------------- + +Contents of probable licence file $GOMODCACHE/golang.org/x/mod@v0.5.1/LICENSE: + +Copyright (c) 2009 The Go Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +-------------------------------------------------------------------------------- +Dependency : golang.org/x/term +Version: v0.0.0-20210615171337-6886f2dfbf5b +Licence type (autodetected): BSD-3-Clause +-------------------------------------------------------------------------------- + +Contents of probable licence file $GOMODCACHE/golang.org/x/term@v0.0.0-20210615171337-6886f2dfbf5b/LICENSE: + +Copyright (c) 2009 The Go Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +-------------------------------------------------------------------------------- +Dependency : golang.org/x/xerrors +Version: v0.0.0-20200804184101-5ec99f83aff1 +Licence type (autodetected): BSD-3-Clause +-------------------------------------------------------------------------------- + +Contents of probable licence file $GOMODCACHE/golang.org/x/xerrors@v0.0.0-20200804184101-5ec99f83aff1/LICENSE: + +Copyright (c) 2019 The Go Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +-------------------------------------------------------------------------------- +Dependency : google.golang.org/appengine +Version: v1.6.7 Licence type (autodetected): Apache-2.0 -------------------------------------------------------------------------------- -Contents of probable licence file $GOMODCACHE/github.com/urso/magetools@v0.0.0-20200125210132-c2e338f92f3a/LICENSE: +Contents of probable licence file $GOMODCACHE/google.golang.org/appengine@v1.6.7/LICENSE: + Apache License Version 2.0, January 2004 @@ -34277,12 +34843,47 @@ Contents of probable licence file $GOMODCACHE/github.com/urso/magetools@v0.0.0-2 -------------------------------------------------------------------------------- -Dependency : github.com/urso/qcgen -Version: v0.0.0-20180131103024-0b059e7db4f4 +Dependency : gopkg.in/check.v1 +Version: v1.0.0-20201130134442-10cb98267c6c +Licence type (autodetected): BSD-2-Clause +-------------------------------------------------------------------------------- + +Contents of probable licence file $GOMODCACHE/gopkg.in/check.v1@v1.0.0-20201130134442-10cb98267c6c/LICENSE: + +Gocheck - A rich testing framework for Go + +Copyright (c) 2010-2013 Gustavo Niemeyer + +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +-------------------------------------------------------------------------------- +Dependency : gopkg.in/jcmturner/aescts.v1 +Version: v1.0.1 Licence type (autodetected): Apache-2.0 -------------------------------------------------------------------------------- -Contents of probable licence file $GOMODCACHE/github.com/urso/qcgen@v0.0.0-20180131103024-0b059e7db4f4/LICENSE: +Contents of probable licence file $GOMODCACHE/gopkg.in/jcmturner/aescts.v1@v1.0.1/LICENSE: Apache License Version 2.0, January 2004 @@ -34464,7 +35065,7 @@ Contents of probable licence file $GOMODCACHE/github.com/urso/qcgen@v0.0.0-20180 APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" + boilerplate notice, with the fields enclosed by brackets "{}" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a @@ -34472,7 +35073,7 @@ Contents of probable licence file $GOMODCACHE/github.com/urso/qcgen@v0.0.0-20180 same "printed page" as the copyright notice for easier identification within third-party archives. - Copyright [yyyy] [name of copyright owner] + Copyright {yyyy} {name of copyright owner} Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -34488,13 +35089,12 @@ Contents of probable licence file $GOMODCACHE/github.com/urso/qcgen@v0.0.0-20180 -------------------------------------------------------------------------------- -Dependency : github.com/xdg/stringprep -Version: v1.0.3 +Dependency : gopkg.in/jcmturner/dnsutils.v1 +Version: v1.0.1 Licence type (autodetected): Apache-2.0 -------------------------------------------------------------------------------- -Contents of probable licence file $GOMODCACHE/github.com/xdg/stringprep@v1.0.3/LICENSE: - +Contents of probable licence file $GOMODCACHE/gopkg.in/jcmturner/dnsutils.v1@v1.0.1/LICENSE: Apache License Version 2.0, January 2004 @@ -34671,1129 +35271,41 @@ Contents of probable licence file $GOMODCACHE/github.com/xdg/stringprep@v1.0.3/L incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. + END OF TERMS AND CONDITIONS --------------------------------------------------------------------------------- -Dependency : github.com/yuin/gopher-lua -Version: v0.0.0-20170403160031-b402f3114ec7 -Licence type (autodetected): MIT --------------------------------------------------------------------------------- - -Contents of probable licence file $GOMODCACHE/github.com/yuin/gopher-lua@v0.0.0-20170403160031-b402f3114ec7/LICENSE: - -The MIT License (MIT) - -Copyright (c) 2015 Yusuke Inuzuka - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - - --------------------------------------------------------------------------------- -Dependency : go.elastic.co/fastjson -Version: v1.1.0 -Licence type (autodetected): MIT --------------------------------------------------------------------------------- - -Contents of probable licence file $GOMODCACHE/go.elastic.co/fastjson@v1.1.0/LICENSE: - -Copyright 2018 Elasticsearch BV - -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. + APPENDIX: How to apply the Apache License to your work. ---- + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. -Copyright (c) 2016 Mail.Ru Group + Copyright [yyyy] [name of copyright owner] -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + 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 -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + http://www.apache.org/licenses/LICENSE-2.0 -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + 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. -------------------------------------------------------------------------------- -Dependency : go.opencensus.io -Version: v0.23.0 +Dependency : gopkg.in/jcmturner/goidentity.v3 +Version: v3.0.0 Licence type (autodetected): Apache-2.0 -------------------------------------------------------------------------------- -Contents of probable licence file $GOMODCACHE/go.opencensus.io@v0.23.0/LICENSE: - - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - 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. - --------------------------------------------------------------------------------- -Dependency : go.uber.org/goleak -Version: v1.1.10 -Licence type (autodetected): MIT --------------------------------------------------------------------------------- - -Contents of probable licence file $GOMODCACHE/go.uber.org/goleak@v1.1.10/LICENSE: - -The MIT License (MIT) - -Copyright (c) 2018 Uber Technologies, Inc. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - - --------------------------------------------------------------------------------- -Dependency : go.uber.org/tools -Version: v0.0.0-20190618225709-2cfd321de3ee -Licence type (autodetected): MIT --------------------------------------------------------------------------------- - -Contents of probable licence file $GOMODCACHE/go.uber.org/tools@v0.0.0-20190618225709-2cfd321de3ee/LICENSE: - -Copyright (c) 2017 Uber Technologies, Inc. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - - --------------------------------------------------------------------------------- -Dependency : golang.org/x/mod -Version: v0.5.1 -Licence type (autodetected): BSD-3-Clause --------------------------------------------------------------------------------- - -Contents of probable licence file $GOMODCACHE/golang.org/x/mod@v0.5.1/LICENSE: - -Copyright (c) 2009 The Go Authors. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google Inc. nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - --------------------------------------------------------------------------------- -Dependency : golang.org/x/term -Version: v0.0.0-20210220032956-6a3ed077a48d -Licence type (autodetected): BSD-3-Clause --------------------------------------------------------------------------------- - -Contents of probable licence file $GOMODCACHE/golang.org/x/term@v0.0.0-20210220032956-6a3ed077a48d/LICENSE: - -Copyright (c) 2009 The Go Authors. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google Inc. nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - --------------------------------------------------------------------------------- -Dependency : golang.org/x/xerrors -Version: v0.0.0-20200804184101-5ec99f83aff1 -Licence type (autodetected): BSD-3-Clause --------------------------------------------------------------------------------- - -Contents of probable licence file $GOMODCACHE/golang.org/x/xerrors@v0.0.0-20200804184101-5ec99f83aff1/LICENSE: - -Copyright (c) 2019 The Go Authors. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google Inc. nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - --------------------------------------------------------------------------------- -Dependency : google.golang.org/appengine -Version: v1.6.7 -Licence type (autodetected): Apache-2.0 --------------------------------------------------------------------------------- - -Contents of probable licence file $GOMODCACHE/google.golang.org/appengine@v1.6.7/LICENSE: - - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - 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. - - --------------------------------------------------------------------------------- -Dependency : gopkg.in/check.v1 -Version: v1.0.0-20201130134442-10cb98267c6c -Licence type (autodetected): BSD-2-Clause --------------------------------------------------------------------------------- - -Contents of probable licence file $GOMODCACHE/gopkg.in/check.v1@v1.0.0-20201130134442-10cb98267c6c/LICENSE: - -Gocheck - A rich testing framework for Go - -Copyright (c) 2010-2013 Gustavo Niemeyer - -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -1. Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. -2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - --------------------------------------------------------------------------------- -Dependency : gopkg.in/jcmturner/aescts.v1 -Version: v1.0.1 -Licence type (autodetected): Apache-2.0 --------------------------------------------------------------------------------- - -Contents of probable licence file $GOMODCACHE/gopkg.in/jcmturner/aescts.v1@v1.0.1/LICENSE: - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "{}" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright {yyyy} {name of copyright owner} - - 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. - - --------------------------------------------------------------------------------- -Dependency : gopkg.in/jcmturner/dnsutils.v1 -Version: v1.0.1 -Licence type (autodetected): Apache-2.0 --------------------------------------------------------------------------------- - -Contents of probable licence file $GOMODCACHE/gopkg.in/jcmturner/dnsutils.v1@v1.0.1/LICENSE: - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - 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. - - --------------------------------------------------------------------------------- -Dependency : gopkg.in/jcmturner/goidentity.v3 -Version: v3.0.0 -Licence type (autodetected): Apache-2.0 --------------------------------------------------------------------------------- - -Contents of probable licence file $GOMODCACHE/gopkg.in/jcmturner/goidentity.v3@v3.0.0/LICENSE: +Contents of probable licence file $GOMODCACHE/gopkg.in/jcmturner/goidentity.v3@v3.0.0/LICENSE: Apache License Version 2.0, January 2004 @@ -36564,11 +36076,11 @@ third-party archives. -------------------------------------------------------------------------------- Dependency : k8s.io/klog/v2 -Version: v2.9.0 +Version: v2.30.0 Licence type (autodetected): Apache-2.0 -------------------------------------------------------------------------------- -Contents of probable licence file $GOMODCACHE/k8s.io/klog/v2@v2.9.0/LICENSE: +Contents of probable licence file $GOMODCACHE/k8s.io/klog/v2@v2.30.0/LICENSE: Apache License Version 2.0, January 2004 @@ -36765,11 +36277,11 @@ third-party archives. -------------------------------------------------------------------------------- Dependency : k8s.io/kube-openapi -Version: v0.0.0-20210305001622-591a79e4bda7 +Version: v0.0.0-20211115234752-e816edb12b65 Licence type (autodetected): Apache-2.0 -------------------------------------------------------------------------------- -Contents of probable licence file $GOMODCACHE/k8s.io/kube-openapi@v0.0.0-20210305001622-591a79e4bda7/LICENSE: +Contents of probable licence file $GOMODCACHE/k8s.io/kube-openapi@v0.0.0-20211115234752-e816edb12b65/LICENSE: Apache License @@ -36977,11 +36489,11 @@ Contents of probable licence file $GOMODCACHE/k8s.io/kube-openapi@v0.0.0-2021030 -------------------------------------------------------------------------------- Dependency : k8s.io/utils -Version: v0.0.0-20201110183641-67b214c5f920 +Version: v0.0.0-20210930125809-cb0fa318a74b Licence type (autodetected): Apache-2.0 -------------------------------------------------------------------------------- -Contents of probable licence file $GOMODCACHE/k8s.io/utils@v0.0.0-20201110183641-67b214c5f920/LICENSE: +Contents of probable licence file $GOMODCACHE/k8s.io/utils@v0.0.0-20210930125809-cb0fa318a74b/LICENSE: Apache License @@ -37593,13 +37105,261 @@ library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. +-------------------------------------------------------------------------------- +Dependency : sigs.k8s.io/json +Version: v0.0.0-20211020170558-c049b76a60c6 +Licence type (autodetected): Apache-2.0 +-------------------------------------------------------------------------------- + +Contents of probable licence file $GOMODCACHE/sigs.k8s.io/json@v0.0.0-20211020170558-c049b76a60c6/LICENSE: + +Files other than internal/golang/* licensed under: + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + 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. + + +------------------ + +internal/golang/* files licensed under: + + +Copyright (c) 2009 The Go Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + -------------------------------------------------------------------------------- Dependency : sigs.k8s.io/structured-merge-diff/v4 -Version: v4.1.0 +Version: v4.1.2 Licence type (autodetected): Apache-2.0 -------------------------------------------------------------------------------- -Contents of probable licence file $GOMODCACHE/sigs.k8s.io/structured-merge-diff/v4@v4.1.0/LICENSE: +Contents of probable licence file $GOMODCACHE/sigs.k8s.io/structured-merge-diff/v4@v4.1.2/LICENSE: Apache License Version 2.0, January 2004 diff --git a/README.md b/README.md index 32d411d74ac..6707fced374 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,6 @@ Beat | Description [Filebeat](https://github.com/elastic/beats/tree/master/filebeat) | Tails and ships log files [Functionbeat](https://github.com/elastic/beats/tree/master/x-pack/functionbeat) | Read and ships events from serverless infrastructure. [Heartbeat](https://github.com/elastic/beats/tree/master/heartbeat) | Ping remote services for availability -[Journalbeat](https://github.com/elastic/beats/tree/master/journalbeat) | Read and ships event from Journald. [Metricbeat](https://github.com/elastic/beats/tree/master/metricbeat) | Fetches sets of metrics from the operating system and services [Packetbeat](https://github.com/elastic/beats/tree/master/packetbeat) | Monitors the network and applications by sniffing packets [Winlogbeat](https://github.com/elastic/beats/tree/master/winlogbeat) | Fetches and ships Windows Event logs @@ -45,7 +44,6 @@ on the [elastic.co site](https://www.elastic.co/guide/): * [Filebeat](https://www.elastic.co/guide/en/beats/filebeat/current/index.html) * [Functionbeat](https://www.elastic.co/guide/en/beats/functionbeat/current/index.html) * [Heartbeat](https://www.elastic.co/guide/en/beats/heartbeat/current/index.html) -* [Journalbeat](https://www.elastic.co/guide/en/beats/journalbeat/current/index.html) * [Metricbeat](https://www.elastic.co/guide/en/beats/metricbeat/current/index.html) * [Packetbeat](https://www.elastic.co/guide/en/beats/packetbeat/current/index.html) * [Winlogbeat](https://www.elastic.co/guide/en/beats/winlogbeat/current/index.html) diff --git a/auditbeat/Dockerfile b/auditbeat/Dockerfile index ceccec4026d..08cff3f06a7 100644 --- a/auditbeat/Dockerfile +++ b/auditbeat/Dockerfile @@ -1,8 +1,8 @@ -FROM golang:1.17.2 +FROM golang:1.17.5 RUN \ apt-get update \ - && apt-get install -y --no-install-recommends \ + && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \ python3 \ python3-pip \ python3-venv \ diff --git a/auditbeat/Jenkinsfile.yml b/auditbeat/Jenkinsfile.yml index ec64b4fc3d7..7b17f617776 100644 --- a/auditbeat/Jenkinsfile.yml +++ b/auditbeat/Jenkinsfile.yml @@ -44,7 +44,7 @@ stages: macos: mage: "mage build unitTest" platforms: ## override default label in this specific stage. - - "macosx&&x86_64" + - "orka && darwin && poc" when: ## Override the top-level when. comments: - "/test auditbeat for macos" diff --git a/auditbeat/auditbeat.reference.yml b/auditbeat/auditbeat.reference.yml index 3d1435314b4..27be08dd194 100644 --- a/auditbeat/auditbeat.reference.yml +++ b/auditbeat/auditbeat.reference.yml @@ -197,66 +197,6 @@ auditbeat.modules: # length of its retry interval each time, up to this maximum. #max_retry_interval: 30s - # The spool queue will store events in a local spool file, before - # forwarding the events to the outputs. - # Note: the spool queue is deprecated and will be removed in the future. - # Use the disk queue instead. - # - # The spool file is a circular buffer, which blocks once the file/buffer is full. - # Events are put into a write buffer and flushed once the write buffer - # is full or the flush_timeout is triggered. - # Once ACKed by the output, events are removed immediately from the queue, - # making space for new events to be persisted. - #spool: - # The file namespace configures the file path and the file creation settings. - # Once the file exists, the `size`, `page_size` and `prealloc` settings - # will have no more effect. - #file: - # Location of spool file. The default value is ${path.data}/spool.dat. - #path: "${path.data}/spool.dat" - - # Configure file permissions if file is created. The default value is 0600. - #permissions: 0600 - - # File size hint. The spool blocks, once this limit is reached. The default value is 100 MiB. - #size: 100MiB - - # The files page size. A file is split into multiple pages of the same size. The default value is 4KiB. - #page_size: 4KiB - - # If prealloc is set, the required space for the file is reserved using - # truncate. The default value is true. - #prealloc: true - - # Spool writer settings - # Events are serialized into a write buffer. The write buffer is flushed if: - # - The buffer limit has been reached. - # - The configured limit of buffered events is reached. - # - The flush timeout is triggered. - #write: - # Sets the write buffer size. - #buffer_size: 1MiB - - # Maximum duration after which events are flushed if the write buffer - # is not full yet. The default value is 1s. - #flush.timeout: 1s - - # Number of maximum buffered events. The write buffer is flushed once the - # limit is reached. - #flush.events: 16384 - - # Configure the on-disk event encoding. The encoding can be changed - # between restarts. - # Valid encodings are: json, ubjson, and cbor. - #codec: cbor - #read: - # Reader flush timeout, waiting for more events to become available, so - # to fill a complete batch as required by the outputs. - # If flush_timeout is 0, all available events are forwarded to the - # outputs immediately. - # The default value is 0s. - #flush.timeout: 0s - # Sets the maximum number of CPUs that can be executing simultaneously. The # default is the number of logical CPUs available in the system. #max_procs: @@ -573,6 +513,13 @@ output.elasticsearch: # The pin is a base64 encoded string of the SHA-256 fingerprint. #ssl.ca_sha256: "" + # A root CA HEX encoded fingerprint. During the SSL handshake if the + # fingerprint matches the root CA certificate, it will be added to + # the provided list of root CAs (`certificate_authorities`), if the + # list is empty or not defined, the matching certificate will be the + # only one in the list. Then the normal SSL validation happens. + #ssl.ca_trusted_fingerprint: "" + # Enable Kerberos support. Kerberos is automatically enabled if any Kerberos setting is set. #kerberos.enabled: true @@ -705,6 +652,13 @@ output.elasticsearch: # The pin is a base64 encoded string of the SHA-256 fingerprint. #ssl.ca_sha256: "" + # A root CA HEX encoded fingerprint. During the SSL handshake if the + # fingerprint matches the root CA certificate, it will be added to + # the provided list of root CAs (`certificate_authorities`), if the + # list is empty or not defined, the matching certificate will be the + # only one in the list. Then the normal SSL validation happens. + #ssl.ca_trusted_fingerprint: "" + # The number of times to retry publishing an event after a publishing failure. # After the specified number of retries, the events are typically dropped. # Some Beats, such as Filebeat and Winlogbeat, ignore the max_retries setting @@ -906,6 +860,13 @@ output.elasticsearch: # The pin is a base64 encoded string of the SHA-256 fingerprint. #ssl.ca_sha256: "" + # A root CA HEX encoded fingerprint. During the SSL handshake if the + # fingerprint matches the root CA certificate, it will be added to + # the provided list of root CAs (`certificate_authorities`), if the + # list is empty or not defined, the matching certificate will be the + # only one in the list. Then the normal SSL validation happens. + #ssl.ca_trusted_fingerprint: "" + # Enable Kerberos support. Kerberos is automatically enabled if any Kerberos setting is set. #kerberos.enabled: true @@ -1070,6 +1031,13 @@ output.elasticsearch: # The pin is a base64 encoded string of the SHA-256 fingerprint. #ssl.ca_sha256: "" + # A root CA HEX encoded fingerprint. During the SSL handshake if the + # fingerprint matches the root CA certificate, it will be added to + # the provided list of root CAs (`certificate_authorities`), if the + # list is empty or not defined, the matching certificate will be the + # only one in the list. Then the normal SSL validation happens. + #ssl.ca_trusted_fingerprint: "" + # -------------------------------- File Output --------------------------------- #output.file: @@ -1089,7 +1057,7 @@ output.elasticsearch: #path: "/tmp/auditbeat" # Name of the generated files. The default is `auditbeat` and it generates - # files: `auditbeat`, `auditbeat.1`, `auditbeat.2`, etc. + # files: `auditbeat-{datetime}.ndjson`, `auditbeat-{datetime}-1.ndjson`, etc. #filename: auditbeat # Maximum size in kilobytes of each file. When this size is reached, and on @@ -1107,6 +1075,7 @@ output.elasticsearch: # Configure automatic file rotation on every startup. The default is true. #rotate_on_startup: true + # ------------------------------- Console Output ------------------------------- #output.console: # Boolean flag to enable or disable the output module. @@ -1205,19 +1174,13 @@ output.elasticsearch: # Set to false to disable template loading. #setup.template.enabled: true -# Select the kind of index template. From Elasticsearch 7.8, it is possible to -# use component templates. Available options: legacy, component, index. -# By default auditbeat uses the legacy index templates. -#setup.template.type: legacy - # Template name. By default the template name is "auditbeat-%{[agent.version]}" # The template name and pattern has to be set in case the Elasticsearch index pattern is modified. #setup.template.name: "auditbeat-%{[agent.version]}" -# Template pattern. By default the template pattern is "-%{[agent.version]}-*" to apply to the default index settings. -# The first part is the version of the beat and then -* is used to match all daily indices. +# Template pattern. By default the template pattern is "auditbeat-%{[agent.version]}" to apply to the default index settings. # The template name and pattern has to be set in case the Elasticsearch index pattern is modified. -#setup.template.pattern: "auditbeat-%{[agent.version]}-*" +#setup.template.pattern: "auditbeat-%{[agent.version]}" # Path to fields.yml file to generate the template #setup.template.fields: "${path.config}/fields.yml" @@ -1264,17 +1227,8 @@ setup.template.settings: # output.elasticsearch.index is ignored, and the write alias is used to set the # index name. -# Enable ILM support. Valid values are true, false, and auto. When set to auto -# (the default), the Beat uses index lifecycle management when it connects to a -# cluster that supports ILM; otherwise, it creates daily indices. -#setup.ilm.enabled: auto - -# Set the prefix used in the index lifecycle write alias name. The default alias -# name is 'auditbeat-%{[agent.version]}'. -#setup.ilm.rollover_alias: 'auditbeat' - -# Set the rollover index pattern. The default is "%{now/d}-000001". -#setup.ilm.pattern: "{now/d}-000001" +# Enable ILM support. Valid values are true, false. +#setup.ilm.enabled: true # Set the lifecycle policy name. The default policy name is # 'beatname'. @@ -1372,6 +1326,13 @@ setup.kibana: # The pin is a base64 encoded string of the SHA-256 fingerprint. #ssl.ca_sha256: "" + # A root CA HEX encoded fingerprint. During the SSL handshake if the + # fingerprint matches the root CA certificate, it will be added to + # the provided list of root CAs (`certificate_authorities`), if the + # list is empty or not defined, the matching certificate will be the + # only one in the list. Then the normal SSL validation happens. + #ssl.ca_trusted_fingerprint: "" + # ================================== Logging =================================== @@ -1443,11 +1404,6 @@ logging.files: # file. Defaults to true. # rotateonstartup: true - # Rotated files are either suffixed with a number e.g. auditbeat.1 when - # renamed during rotation. Or when set to date, the date is added to - # the end of the file. On rotation a new file is created, older files are untouched. - #suffix: count - # ============================= X-Pack Monitoring ============================== # Auditbeat can export internal metrics to a central Elasticsearch monitoring # cluster. This requires xpack monitoring to be enabled in Elasticsearch. The @@ -1575,6 +1531,13 @@ logging.files: # The pin is a base64 encoded string of the SHA-256 fingerprint. #ssl.ca_sha256: "" + # A root CA HEX encoded fingerprint. During the SSL handshake if the + # fingerprint matches the root CA certificate, it will be added to + # the provided list of root CAs (`certificate_authorities`), if the + # list is empty or not defined, the matching certificate will be the + # only one in the list. Then the normal SSL validation happens. + #ssl.ca_trusted_fingerprint: "" + # Enable Kerberos support. Kerberos is automatically enabled if any Kerberos setting is set. #kerberos.enabled: true diff --git a/auditbeat/cmd/root.go b/auditbeat/cmd/root.go index 35fa18ecad0..aa5b523e976 100644 --- a/auditbeat/cmd/root.go +++ b/auditbeat/cmd/root.go @@ -63,7 +63,7 @@ func AuditbeatSettings() instance.Settings { } } -// Initialize initializes the entrypoint commands for journalbeat +// Initialize initializes the entrypoint commands for auditbeat func Initialize(settings instance.Settings) *cmd.BeatsRootCmd { create := beater.Creator( beater.WithModuleOptions( diff --git a/auditbeat/docs/fields.asciidoc b/auditbeat/docs/fields.asciidoc index 57191196dea..646b9cb9f69 100644 --- a/auditbeat/docs/fields.asciidoc +++ b/auditbeat/docs/fields.asciidoc @@ -18222,47 +18222,16 @@ type: ip -- - -*`kubernetes.namespace.name`*:: +*`kubernetes.namespace`*:: + -- -Kubernetes namespace name +Kubernetes namespace type: keyword -- -*`kubernetes.namespace.uuid`*:: -+ --- -Kubernetes namespace uuid - - -type: keyword - --- - -*`kubernetes.namespace.labels.*`*:: -+ --- -Kubernetes namespace labels map - - -type: object - --- - -*`kubernetes.namespace.annotations.*`*:: -+ --- -Kubernetes namespace annotations map - - -type: object - --- - *`kubernetes.node.name`*:: + -- diff --git a/auditbeat/include/fields.go b/auditbeat/include/fields.go index 298c6653d6e..6d8c386ba38 100644 --- a/auditbeat/include/fields.go +++ b/auditbeat/include/fields.go @@ -32,5 +32,5 @@ func init() { // AssetFieldsYml returns asset data. // This is the base64 encoded zlib format compressed contents of fields.yml. func AssetFieldsYml() string { - return "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" + return "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" } diff --git a/auditbeat/tests/system/test_base.py b/auditbeat/tests/system/test_base.py index 3a007eb4f87..2f7f645c750 100644 --- a/auditbeat/tests/system/test_base.py +++ b/auditbeat/tests/system/test_base.py @@ -35,9 +35,9 @@ def test_start_stop(self): assert self.log_contains("auditbeat stopped") @unittest.skipUnless(INTEGRATION_TESTS, "integration test") - def test_template(self): + def test_index_management(self): """ - Test that the template can be loaded with `setup --template` + Test that the template can be loaded with `setup --index-management` """ dirs = [self.temp_dir("auditbeat_test")] with PathCleanup(dirs): @@ -51,7 +51,7 @@ def test_template(self): } }], elasticsearch={"host": self.get_elasticsearch_url()}) - self.run_beat(extra_args=["setup", "--template"], exit_code=0) + self.run_beat(extra_args=["setup", "--index-management"], exit_code=0) assert self.log_contains('Loaded index template') assert len(es.cat.templates(name='auditbeat-*', h='name')) > 0 diff --git a/deploy/docker/journalbeat.docker.yml b/deploy/docker/journalbeat.docker.yml deleted file mode 100644 index a1e67c0d961..00000000000 --- a/deploy/docker/journalbeat.docker.yml +++ /dev/null @@ -1,11 +0,0 @@ -journalbeat.inputs: -- paths: [] - seek: cursor - -processors: -- add_cloud_metadata: ~ - -output.elasticsearch: - hosts: '${ELASTICSEARCH_HOSTS:elasticsearch:9200}' - username: '${ELASTICSEARCH_USERNAME:}' - password: '${ELASTICSEARCH_PASSWORD:}' diff --git a/deploy/kubernetes/Jenkinsfile.yml b/deploy/kubernetes/Jenkinsfile.yml index 8b9dfcded5a..57dd8b5e52f 100644 --- a/deploy/kubernetes/Jenkinsfile.yml +++ b/deploy/kubernetes/Jenkinsfile.yml @@ -18,5 +18,5 @@ stages: make check-no-changes; stage: lint k8sTest: - k8sTest: "v1.21.1,v1.20.7,v1.19.11,v1.18.19,v1.17.17,v1.14.10" + k8sTest: "v1.23.0,v1.22.0,v1.21.1,v1.20.7,v1.19.11,v1.18.19" stage: mandatory diff --git a/deploy/kubernetes/elastic-agent-managed-kubernetes.yaml b/deploy/kubernetes/elastic-agent-managed-kubernetes.yaml index 12cc5badc69..9389489eed5 100644 --- a/deploy/kubernetes/elastic-agent-managed-kubernetes.yaml +++ b/deploy/kubernetes/elastic-agent-managed-kubernetes.yaml @@ -165,6 +165,8 @@ rules: - apiGroups: [ "batch" ] resources: - jobs + # Uncomment if need metadata for cronjob objects in versions >= v1.21 + #- cronjobs verbs: [ "get", "list", "watch" ] # required for apiserver - nonResourceURLs: diff --git a/deploy/kubernetes/elastic-agent-managed/elastic-agent-managed-role.yaml b/deploy/kubernetes/elastic-agent-managed/elastic-agent-managed-role.yaml index 37d159333cd..49d4bd12999 100644 --- a/deploy/kubernetes/elastic-agent-managed/elastic-agent-managed-role.yaml +++ b/deploy/kubernetes/elastic-agent-managed/elastic-agent-managed-role.yaml @@ -38,6 +38,8 @@ rules: - apiGroups: [ "batch" ] resources: - jobs + # Uncomment if need metadata for cronjob objects in versions >= v1.21 + #- cronjobs verbs: [ "get", "list", "watch" ] # required for apiserver - nonResourceURLs: diff --git a/deploy/kubernetes/elastic-agent-standalone-kubernetes.yaml b/deploy/kubernetes/elastic-agent-standalone-kubernetes.yaml index 6b306051eb2..a46d8e3f4f6 100644 --- a/deploy/kubernetes/elastic-agent-standalone-kubernetes.yaml +++ b/deploy/kubernetes/elastic-agent-standalone-kubernetes.yaml @@ -32,7 +32,7 @@ data: meta: package: name: kubernetes - version: 0.2.8 + version: 1.9.0 data_stream: namespace: default streams: @@ -72,6 +72,15 @@ data: hosts: - 'kube-state-metrics:8080' period: 10s + - data_stream: + dataset: kubernetes.state_daemonset + type: metrics + metricsets: + - state_daemonset + add_metadata: true + hosts: + - 'kube-state-metrics:8080' + period: 10s - data_stream: dataset: kubernetes.state_deployment type: metrics @@ -214,20 +223,73 @@ data: fields: ecs.version: 1.12.0 - name: container-log - type: logfile + type: filestream use_output: default meta: package: - name: log - version: 0.4.6 + name: kubernetes + version: 1.9.0 data_stream: namespace: default streams: - data_stream: - dataset: generic - symlinks: true + dataset: kubernetes.container_logs + type: logs + prospector.scanner.symlinks: true + parsers: + - container: ~ + # - ndjson: + # target: json + # - multiline: + # type: pattern + # pattern: '^\[' + # negate: true + # match: after paths: - /var/log/containers/*${kubernetes.container.id}.log + - name: audit-log + type: filestream + use_output: default + meta: + package: + name: kubernetes + version: 1.9.0 + data_stream: + namespace: default + streams: + - data_stream: + dataset: kubernetes.audit_logs + type: logs + exclude_files: + - .gz$ + parsers: + - ndjson: + add_error_key: true + target: kubernetes_audit + paths: + - /var/log/kubernetes/kube-apiserver-audit.log + processors: + - rename: + fields: + - from: kubernetes_audit + to: kubernetes.audit + - script: + id: dedot_annotations + lang: javascript + source: | + function process(event) { + var audit = event.Get("kubernetes.audit"); + for (var annotation in audit["annotations"]) { + var annotation_dedoted = annotation.replace(/\./g,'_') + event.Rename("kubernetes.audit.annotations."+annotation, "kubernetes.audit.annotations."+annotation_dedoted) + } + return event; + } function test() { + var event = process(new Event({ "kubernetes": { "audit": { "annotations": { "authorization.k8s.io/decision": "allow", "authorization.k8s.io/reason": "RBAC: allowed by ClusterRoleBinding \"system:kube-scheduler\" of ClusterRole \"system:kube-scheduler\" to User \"system:kube-scheduler\"" } } } })); + if (event.Get("kubernetes.audit.annotations.authorization_k8s_io/decision") !== "allow") { + throw "expected kubernetes.audit.annotations.authorization_k8s_io/decision === allow"; + } + } - name: system-metrics type: system/metrics use_output: default @@ -332,7 +394,7 @@ data: meta: package: name: kubernetes - version: 0.2.8 + version: 1.9.0 data_stream: namespace: default streams: @@ -609,6 +671,8 @@ rules: - apiGroups: ["batch"] resources: - jobs + # Uncomment if need metadata for cronjob objects in versions >= v1.21 + #- cronjobs verbs: ["get", "list", "watch"] - apiGroups: - "" diff --git a/deploy/kubernetes/elastic-agent-standalone/elastic-agent-standalone-daemonset-configmap.yaml b/deploy/kubernetes/elastic-agent-standalone/elastic-agent-standalone-daemonset-configmap.yaml index d3f290b2aab..0ad4f609883 100644 --- a/deploy/kubernetes/elastic-agent-standalone/elastic-agent-standalone-daemonset-configmap.yaml +++ b/deploy/kubernetes/elastic-agent-standalone/elastic-agent-standalone-daemonset-configmap.yaml @@ -32,7 +32,7 @@ data: meta: package: name: kubernetes - version: 0.2.8 + version: 1.9.0 data_stream: namespace: default streams: @@ -72,6 +72,15 @@ data: hosts: - 'kube-state-metrics:8080' period: 10s + - data_stream: + dataset: kubernetes.state_daemonset + type: metrics + metricsets: + - state_daemonset + add_metadata: true + hosts: + - 'kube-state-metrics:8080' + period: 10s - data_stream: dataset: kubernetes.state_deployment type: metrics @@ -214,20 +223,73 @@ data: fields: ecs.version: 1.12.0 - name: container-log - type: logfile + type: filestream use_output: default meta: package: - name: log - version: 0.4.6 + name: kubernetes + version: 1.9.0 data_stream: namespace: default streams: - data_stream: - dataset: generic - symlinks: true + dataset: kubernetes.container_logs + type: logs + prospector.scanner.symlinks: true + parsers: + - container: ~ + # - ndjson: + # target: json + # - multiline: + # type: pattern + # pattern: '^\[' + # negate: true + # match: after paths: - /var/log/containers/*${kubernetes.container.id}.log + - name: audit-log + type: filestream + use_output: default + meta: + package: + name: kubernetes + version: 1.9.0 + data_stream: + namespace: default + streams: + - data_stream: + dataset: kubernetes.audit_logs + type: logs + exclude_files: + - .gz$ + parsers: + - ndjson: + add_error_key: true + target: kubernetes_audit + paths: + - /var/log/kubernetes/kube-apiserver-audit.log + processors: + - rename: + fields: + - from: kubernetes_audit + to: kubernetes.audit + - script: + id: dedot_annotations + lang: javascript + source: | + function process(event) { + var audit = event.Get("kubernetes.audit"); + for (var annotation in audit["annotations"]) { + var annotation_dedoted = annotation.replace(/\./g,'_') + event.Rename("kubernetes.audit.annotations."+annotation, "kubernetes.audit.annotations."+annotation_dedoted) + } + return event; + } function test() { + var event = process(new Event({ "kubernetes": { "audit": { "annotations": { "authorization.k8s.io/decision": "allow", "authorization.k8s.io/reason": "RBAC: allowed by ClusterRoleBinding \"system:kube-scheduler\" of ClusterRole \"system:kube-scheduler\" to User \"system:kube-scheduler\"" } } } })); + if (event.Get("kubernetes.audit.annotations.authorization_k8s_io/decision") !== "allow") { + throw "expected kubernetes.audit.annotations.authorization_k8s_io/decision === allow"; + } + } - name: system-metrics type: system/metrics use_output: default @@ -332,7 +394,7 @@ data: meta: package: name: kubernetes - version: 0.2.8 + version: 1.9.0 data_stream: namespace: default streams: diff --git a/deploy/kubernetes/elastic-agent-standalone/elastic-agent-standalone-role.yaml b/deploy/kubernetes/elastic-agent-standalone/elastic-agent-standalone-role.yaml index 16ee4759acc..f0f6c2ca913 100644 --- a/deploy/kubernetes/elastic-agent-standalone/elastic-agent-standalone-role.yaml +++ b/deploy/kubernetes/elastic-agent-standalone/elastic-agent-standalone-role.yaml @@ -32,6 +32,8 @@ rules: - apiGroups: ["batch"] resources: - jobs + # Uncomment if need metadata for cronjob objects in versions >= v1.21 + #- cronjobs verbs: ["get", "list", "watch"] - apiGroups: - "" diff --git a/deploy/kubernetes/metricbeat-kubernetes.yaml b/deploy/kubernetes/metricbeat-kubernetes.yaml index ae81804a606..166c195d2f6 100644 --- a/deploy/kubernetes/metricbeat-kubernetes.yaml +++ b/deploy/kubernetes/metricbeat-kubernetes.yaml @@ -295,6 +295,8 @@ rules: - apiGroups: ["batch"] resources: - jobs + # Uncomment if need metadata for cronjob objects in versions >= v1.21 + #- cronjobs verbs: ["get", "list", "watch"] - apiGroups: - "" diff --git a/deploy/kubernetes/metricbeat/metricbeat-role.yaml b/deploy/kubernetes/metricbeat/metricbeat-role.yaml index 065c32c789c..26ed85ba619 100644 --- a/deploy/kubernetes/metricbeat/metricbeat-role.yaml +++ b/deploy/kubernetes/metricbeat/metricbeat-role.yaml @@ -31,6 +31,8 @@ rules: - apiGroups: ["batch"] resources: - jobs + # Uncomment if need metadata for cronjob objects in versions >= v1.21 + #- cronjobs verbs: ["get", "list", "watch"] - apiGroups: - "" diff --git a/dev-tools/cmd/update_go/update_go_version.go b/dev-tools/cmd/update_go/update_go_version.go index 9ab0fa8a4a4..f589abc756d 100644 --- a/dev-tools/cmd/update_go/update_go_version.go +++ b/dev-tools/cmd/update_go/update_go_version.go @@ -30,7 +30,6 @@ var files = []string{ "auditbeat/Dockerfile", "filebeat/Dockerfile", "heartbeat/Dockerfile", - "journalbeat/Dockerfile", "libbeat/Dockerfile", "libbeat/docs/version.asciidoc", "metricbeat/Dockerfile", diff --git a/dev-tools/ecs-migration.yml b/dev-tools/ecs-migration.yml index 39bc4950564..0ea295b2d7e 100644 --- a/dev-tools/ecs-migration.yml +++ b/dev-tools/ecs-migration.yml @@ -1954,20 +1954,6 @@ alias: true beat: heartbeat -# Journalbeat -- from: host.name - to: host.hostname - alias: false - beat: journalbeat - comment: This field should not be renamed as it would cause issue some Beats and Journalbeat does not have dashboards - # This field should not be renamed as it would cause issue some Beats and Journalbeat does not have dashboards - rename: false - -- from: read_timestamp - to: event.created - alias: true - beat: journalbeat - ## Winlogbeat # Alias to ECS fields diff --git a/dev-tools/mage/crossbuild.go b/dev-tools/mage/crossbuild.go index b2349310abc..9f56fd125c3 100644 --- a/dev-tools/mage/crossbuild.go +++ b/dev-tools/mage/crossbuild.go @@ -242,8 +242,8 @@ func CrossBuildImage(platform string) (string, error) { tagSuffix = "s390x" case strings.HasPrefix(platform, "linux"): // Use an older version of libc to gain greater OS compatibility. - // Debian 7 uses glibc 2.13. - tagSuffix = "main-debian7" + // Debian 8 uses glibc 2.19. + tagSuffix = "main-debian8" } goVersion, err := GoVersion() diff --git a/dev-tools/mage/integtest_docker.go b/dev-tools/mage/integtest_docker.go index e9767f68436..94d9288d1fa 100644 --- a/dev-tools/mage/integtest_docker.go +++ b/dev-tools/mage/integtest_docker.go @@ -81,7 +81,7 @@ func (d *DockerIntegrationTester) StepRequirements() IntegrationTestSteps { } // Test performs the tests with docker-compose. -func (d *DockerIntegrationTester) Test(_ string, mageTarget string, env map[string]string) error { +func (d *DockerIntegrationTester) Test(dir string, mageTarget string, env map[string]string) error { var err error d.buildImagesOnce.Do(func() { err = dockerComposeBuildImages() }) if err != nil { @@ -139,6 +139,12 @@ func (d *DockerIntegrationTester) Test(_ string, mageTarget string, env map[stri args..., ) + err = saveDockerComposeLogs(dir, mageTarget, composeEnv) + if err != nil && testErr == nil { + // saving docker-compose logs failed but the test didn't. + return err + } + // Docker-compose rm is noisy. So only pass through stderr when in verbose. out := ioutil.Discard if mg.Verbose() { @@ -160,6 +166,38 @@ func (d *DockerIntegrationTester) Test(_ string, mageTarget string, env map[stri return testErr } +func saveDockerComposeLogs(rootDir string, mageTarget string, composeEnv map[string]string) error { + var ( + composeLogDir = filepath.Join(rootDir, "build", "system-tests", "docker-logs") + composeLogFileName = filepath.Join(composeLogDir, "TEST-docker-compose-"+mageTarget+".log") + ) + + if err := os.MkdirAll(composeLogDir, os.ModeDir|os.ModePerm); err != nil { + return fmt.Errorf("creating docker log dir: %w", err) + } + + composeLogFile, err := os.Create(composeLogFileName) + if err != nil { + return fmt.Errorf("creating docker log file: %w", err) + } + defer composeLogFile.Close() + + _, err = sh.Exec( + composeEnv, + composeLogFile, // stdout + composeLogFile, // stderr + "docker-compose", + "-p", dockerComposeProjectName(), + "logs", + "--no-color", + ) + if err != nil { + return fmt.Errorf("executing docker-compose logs: %w", err) + } + + return nil +} + // InsideTest performs the tests inside of environment. func (d *DockerIntegrationTester) InsideTest(test func() error) error { // Fix file permissions after test is done writing files as root. diff --git a/dev-tools/mage/target/common/package.go b/dev-tools/mage/target/common/package.go index e8849adb26d..2054538df1f 100644 --- a/dev-tools/mage/target/common/package.go +++ b/dev-tools/mage/target/common/package.go @@ -30,8 +30,10 @@ import ( func PackageSystemTests() error { excludeds := []string{".ci", ".git", ".github", "vendor", "dev-tools"} - // include run as it's the directory we want to compress - systemTestsDir := filepath.Join("build", "system-tests", "run") + // include run and docker-logs as they are the directories we want to compress + systemTestsDir := filepath.Join("build", "system-tests") + systemTestsRunDir := filepath.Join(systemTestsDir, "run") + systemTestsLogDir := filepath.Join(systemTestsDir, "docker-logs") files, err := devtools.FindFilesRecursive(func(path string, _ os.FileInfo) bool { base := filepath.Base(path) for _, excluded := range excludeds { @@ -40,7 +42,7 @@ func PackageSystemTests() error { } } - return strings.HasPrefix(path, systemTestsDir) + return strings.HasPrefix(path, systemTestsRunDir) || strings.HasPrefix(path, systemTestsLogDir) }) if err != nil { return err diff --git a/dev-tools/packaging/packages.yml b/dev-tools/packaging/packages.yml index 4978d4ffb4d..9221f1ac0c0 100644 --- a/dev-tools/packaging/packages.yml +++ b/dev-tools/packaging/packages.yml @@ -94,6 +94,18 @@ shared: source: '{{.AgentDropPath}}/metricbeat-{{ beat_version }}{{if .Snapshot}}-SNAPSHOT{{end}}-{{.GOOS}}-{{.AgentArchName}}.tar.gz.asc' mode: 0644 skip_on_missing: true + /var/lib/{{.BeatName}}/data/{{.BeatName}}-{{ commit_short }}/downloads/osquerybeat-{{ beat_version }}{{if .Snapshot}}-SNAPSHOT{{end}}-{{.GOOS}}-{{.AgentArchName}}.tar.gz: + source: '{{.AgentDropPath}}/osquerybeat-{{ beat_version }}{{if .Snapshot}}-SNAPSHOT{{end}}-{{.GOOS}}-{{.AgentArchName}}.tar.gz' + mode: 0644 + skip_on_missing: true + /var/lib/{{.BeatName}}/data/{{.BeatName}}-{{ commit_short }}/downloads/osquerybeat-{{ beat_version }}{{if .Snapshot}}-SNAPSHOT{{end}}-{{.GOOS}}-{{.AgentArchName}}.tar.gz.sha512: + source: '{{.AgentDropPath}}/osquerybeat-{{ beat_version }}{{if .Snapshot}}-SNAPSHOT{{end}}-{{.GOOS}}-{{.AgentArchName}}.tar.gz.sha512' + mode: 0644 + skip_on_missing: true + /var/lib/{{.BeatName}}/data/{{.BeatName}}-{{ commit_short }}/downloads/osquerybeat-{{ beat_version }}{{if .Snapshot}}-SNAPSHOT{{end}}-{{.GOOS}}-{{.AgentArchName}}.tar.gz.asc: + source: '{{.AgentDropPath}}/osquerybeat-{{ beat_version }}{{if .Snapshot}}-SNAPSHOT{{end}}-{{.GOOS}}-{{.AgentArchName}}.tar.gz.asc' + mode: 0644 + skip_on_missing: true /var/lib/{{.BeatName}}/data/{{.BeatName}}-{{ commit_short }}/downloads/endpoint-security-{{ beat_version }}{{if .Snapshot}}-SNAPSHOT{{end}}-{{.GOOS}}-{{.AgentArchName}}.tar.gz: source: '{{.AgentDropPath}}/endpoint-security-{{ beat_version }}{{if .Snapshot}}-SNAPSHOT{{end}}-{{.GOOS}}-{{.AgentArchName}}.tar.gz' mode: 0644 @@ -210,6 +222,18 @@ shared: source: '{{.AgentDropPath}}/metricbeat-{{ beat_version }}{{if .Snapshot}}-SNAPSHOT{{end}}-{{.GOOS}}-{{.AgentArchName}}.tar.gz.asc' mode: 0644 skip_on_missing: true + /etc/{{.BeatName}}/data/{{.BeatName}}-{{ commit_short }}/downloads/osquerybeat-{{ beat_version }}{{if .Snapshot}}-SNAPSHOT{{end}}-{{.GOOS}}-{{.AgentArchName}}.tar.gz: + source: '{{.AgentDropPath}}/osquerybeat-{{ beat_version }}{{if .Snapshot}}-SNAPSHOT{{end}}-{{.GOOS}}-{{.AgentArchName}}.tar.gz' + mode: 0644 + skip_on_missing: true + /etc/{{.BeatName}}/data/{{.BeatName}}-{{ commit_short }}/downloads/osquerybeat-{{ beat_version }}{{if .Snapshot}}-SNAPSHOT{{end}}-{{.GOOS}}-{{.AgentArchName}}.tar.gz.sha512: + source: '{{.AgentDropPath}}/osquerybeat-{{ beat_version }}{{if .Snapshot}}-SNAPSHOT{{end}}-{{.GOOS}}-{{.AgentArchName}}.tar.gz.sha512' + mode: 0644 + skip_on_missing: true + /etc/{{.BeatName}}/data/{{.BeatName}}-{{ commit_short }}/downloads/osquerybeat-{{ beat_version }}{{if .Snapshot}}-SNAPSHOT{{end}}-{{.GOOS}}-{{.AgentArchName}}.tar.gz.asc: + source: '{{.AgentDropPath}}/osquerybeat-{{ beat_version }}{{if .Snapshot}}-SNAPSHOT{{end}}-{{.GOOS}}-{{.AgentArchName}}.tar.gz.asc' + mode: 0644 + skip_on_missing: true /etc/{{.BeatName}}/data/{{.BeatName}}-{{ commit_short }}/downloads/endpoint-security-{{ beat_version }}{{if .Snapshot}}-SNAPSHOT{{end}}-{{.GOOS}}-{{.AgentArchName}}.tar.gz: source: '{{.AgentDropPath}}/endpoint-security-{{ beat_version }}{{if .Snapshot}}-SNAPSHOT{{end}}-{{.GOOS}}-{{.AgentArchName}}.tar.gz' mode: 0644 @@ -314,6 +338,18 @@ shared: source: '{{.AgentDropPath}}/metricbeat-{{ beat_version }}{{if .Snapshot}}-SNAPSHOT{{end}}-{{.GOOS}}-{{.AgentArchName}}.tar.gz.asc' mode: 0644 skip_on_missing: true + 'data/{{.BeatName}}-{{ commit_short }}/downloads/osquerybeat-{{ beat_version }}{{if .Snapshot}}-SNAPSHOT{{end}}-{{.GOOS}}-{{.AgentArchName}}.tar.gz': + source: '{{.AgentDropPath}}/osquerybeat-{{ beat_version }}{{if .Snapshot}}-SNAPSHOT{{end}}-{{.GOOS}}-{{.AgentArchName}}.tar.gz' + mode: 0644 + skip_on_missing: true + 'data/{{.BeatName}}-{{ commit_short }}/downloads/osquerybeat-{{ beat_version }}{{if .Snapshot}}-SNAPSHOT{{end}}-{{.GOOS}}-{{.AgentArchName}}.tar.gz.sha512': + source: '{{.AgentDropPath}}/osquerybeat-{{ beat_version }}{{if .Snapshot}}-SNAPSHOT{{end}}-{{.GOOS}}-{{.AgentArchName}}.tar.gz.sha512' + mode: 0644 + skip_on_missing: true + 'data/{{.BeatName}}-{{ commit_short }}/downloads/osquerybeat-{{ beat_version }}{{if .Snapshot}}-SNAPSHOT{{end}}-{{.GOOS}}-{{.AgentArchName}}.tar.gz.asc': + source: '{{.AgentDropPath}}/osquerybeat-{{ beat_version }}{{if .Snapshot}}-SNAPSHOT{{end}}-{{.GOOS}}-{{.AgentArchName}}.tar.gz.asc' + mode: 0644 + skip_on_missing: true 'data/{{.BeatName}}-{{ commit_short }}/downloads/endpoint-security-{{ beat_version }}{{if .Snapshot}}-SNAPSHOT{{end}}-{{.GOOS}}-{{.AgentArchName}}.tar.gz': source: '{{.AgentDropPath}}/endpoint-security-{{ beat_version }}{{if .Snapshot}}-SNAPSHOT{{end}}-{{.GOOS}}-{{.AgentArchName}}.tar.gz' mode: 0644 @@ -387,6 +423,18 @@ shared: source: '{{.AgentDropPath}}/metricbeat-{{ beat_version }}{{if .Snapshot}}-SNAPSHOT{{end}}-{{.GOOS}}-{{.AgentArchName}}.zip.asc' mode: 0644 skip_on_missing: true + 'data/{{.BeatName}}-{{ commit_short }}/downloads/osquerybeat-{{ beat_version }}{{if .Snapshot}}-SNAPSHOT{{end}}-{{.GOOS}}-{{.AgentArchName}}.zip': + source: '{{.AgentDropPath}}/osquerybeat-{{ beat_version }}{{if .Snapshot}}-SNAPSHOT{{end}}-{{.GOOS}}-{{.AgentArchName}}.zip' + mode: 0644 + skip_on_missing: true + 'data/{{.BeatName}}-{{ commit_short }}/downloads/osquerybeat-{{ beat_version }}{{if .Snapshot}}-SNAPSHOT{{end}}-{{.GOOS}}-{{.AgentArchName}}.zip.sha512': + source: '{{.AgentDropPath}}/osquerybeat-{{ beat_version }}{{if .Snapshot}}-SNAPSHOT{{end}}-{{.GOOS}}-{{.AgentArchName}}.zip.sha512' + mode: 0644 + skip_on_missing: true + 'data/{{.BeatName}}-{{ commit_short }}/downloads/osquerybeat-{{ beat_version }}{{if .Snapshot}}-SNAPSHOT{{end}}-{{.GOOS}}-{{.AgentArchName}}.zip.asc': + source: '{{.AgentDropPath}}/osquerybeat-{{ beat_version }}{{if .Snapshot}}-SNAPSHOT{{end}}-{{.GOOS}}-{{.AgentArchName}}.zip.asc' + mode: 0644 + skip_on_missing: true 'data/{{.BeatName}}-{{ commit_short }}/downloads/endpoint-security-{{ beat_version }}{{if .Snapshot}}-SNAPSHOT{{end}}-{{.GOOS}}-{{.AgentArchName}}.zip': source: '{{.AgentDropPath}}/endpoint-security-{{ beat_version }}{{if .Snapshot}}-SNAPSHOT{{end}}-{{.GOOS}}-{{.AgentArchName}}.zip' mode: 0644 @@ -427,8 +475,8 @@ shared: - &agent_docker_spec <<: *agent_binary_spec extra_vars: - from: 'centos:7' - buildFrom: 'centos:7' + from: 'ubuntu:20.04' + buildFrom: 'ubuntu:20.04' dockerfile: 'Dockerfile.elastic-agent.tmpl' docker_entrypoint: 'docker-entrypoint.elastic-agent.tmpl' user: '{{ .BeatName }}' @@ -447,8 +495,8 @@ shared: - &agent_docker_arm_spec <<: *agent_docker_spec extra_vars: - from: 'arm64v8/centos:7' - buildFrom: 'arm64v8/centos:7' + from: 'arm64v8/ubuntu:20.04' + buildFrom: 'arm64v8/ubuntu:20.04' - &agent_docker_cloud_spec <<: *agent_docker_spec @@ -605,8 +653,8 @@ shared: - &docker_spec <<: *binary_spec extra_vars: - from: 'centos:7' - buildFrom: 'centos:7' + from: 'ubuntu:20.04' + buildFrom: 'ubuntu:20.04' user: '{{ .BeatName }}' linux_capabilities: '' files: @@ -618,8 +666,8 @@ shared: - &docker_arm_spec <<: *docker_spec extra_vars: - from: 'arm64v8/centos:7' - buildFrom: 'arm64v8/centos:7' + from: 'arm64v8/ubuntu:20.04' + buildFrom: 'arm64v8/ubuntu:20.04' - &docker_ubi_spec extra_vars: @@ -1182,4 +1230,4 @@ specs: <<: *elastic_license_for_binaries files: '{{.BeatName}}{{.BinaryExt}}': - source: ./build/golang-crossbuild/{{.BeatName}}-{{.GOOS}}-{{.Platform.Arch}}{{.BinaryExt}} \ No newline at end of file + source: ./build/golang-crossbuild/{{.BeatName}}-{{.GOOS}}-{{.Platform.Arch}}{{.BinaryExt}} diff --git a/dev-tools/packaging/templates/docker/Dockerfile.elastic-agent.tmpl b/dev-tools/packaging/templates/docker/Dockerfile.elastic-agent.tmpl index 38f7934a9d7..644df5bd73a 100644 --- a/dev-tools/packaging/templates/docker/Dockerfile.elastic-agent.tmpl +++ b/dev-tools/packaging/templates/docker/Dockerfile.elastic-agent.tmpl @@ -27,42 +27,51 @@ RUN mkdir -p {{ $beatHome }}/data {{ $beatHome }}/data/elastic-agent-{{ commit_s {{- end }} true -{{- if .linux_capabilities }} -# Since the beat is stored at the other end of a symlink we must follow the symlink first -# For security reasons setcap does not support symlinks. This is smart in the general case -# but in our specific case since we're building a trusted image from trusted binaries this is -# fine. Thus, we use readlink to follow the link and setcap on the actual binary -RUN readlink -f {{ $beatBinary }} | xargs setcap {{ .linux_capabilities }} -{{- end }} - FROM {{ .from }} ENV BEAT_SETUID_AS={{ .user }} {{- if contains .from "ubi-minimal" }} -RUN for iter in {1..10}; do microdnf update -y && microdnf install -y shadow-utils jq && microdnf clean all && exit_code=0 && break || exit_code=$? && echo "microdnf error: retry $iter in 10s" && sleep 10; done; (exit $exit_code) +RUN for iter in {1..10}; do microdnf update -y && microdnf install -y findutils shadow-utils && microdnf clean all && exit_code=0 && break || exit_code=$? && echo "microdnf error: retry $iter in 10s" && sleep 10; done; (exit $exit_code) {{- else }} -# Installing jq needs to be installed after epel-release and cannot be in the same yum install command. -RUN case $(arch) in aarch64) YUM_FLAGS="-x bind-license";; esac; \ - for iter in {1..10}; do \ - yum update -y $YUM_FLAGS && \ - yum install -y epel-release && \ - yum update -y $YUM_FLAGS && \ - yum install -y jq && \ - yum clean all && \ - exit_code=0 && break || exit_code=$? && echo "yum error: retry $iter in 10s" && sleep 10; \ + +RUN for iter in {1..10}; do \ + apt-get update -y && \ + DEBIAN_FRONTEND=noninteractive apt-get install --no-install-recommends --yes ca-certificates curl libcap2-bin xz-utils && \ + apt-get clean all && \ + exit_code=0 && break || exit_code=$? && echo "apt-get error: retry $iter in 10s" && sleep 10; \ done; \ (exit $exit_code) {{- end }} {{- if (and (contains .image_name "-complete") (not (contains .from "ubi-minimal"))) }} -RUN for iter in {1..10}; do \ - yum -y install atk gtk gdk xrandr pango libXcomposite libXcursor libXdamage \ - libXext libXi libXtst libXScrnSaver libXrandr GConf2 \ - alsa-lib atk gtk3 ipa-gothic-fonts xorg-x11-fonts-100dpi xorg-x11-fonts-75dpi xorg-x11-utils \ - xorg-x11-fonts-cyrillic xorg-x11-fonts-Type1 xorg-x11-fonts-misc \ - yum clean all && \ - exit_code=0 && break || exit_code=$? && echo "yum error: retry $iter in 10s" && sleep 10; \ +RUN apt-get update -y && \ + for iter in {1..10}; do \ + DEBIAN_FRONTEND=noninteractive apt-get install --no-install-recommends --yes \ + libglib2.0-0\ + libnss3\ + libnspr4\ + libatk1.0-0\ + libatk-bridge2.0-0\ + libcups2\ + libdrm2\ + libdbus-1-3\ + libxcb1\ + libxkbcommon0\ + libx11-6\ + libxcomposite1\ + libxdamage1\ + libxext6\ + libxfixes3\ + libxrandr2\ + libgbm1\ + libpango-1.0-0\ + libcairo2\ + libasound2\ + libatspi2.0-0\ + libxshmfence1 && \ + apt-get clean all && \ + exit_code=0 && break || exit_code=$? && echo "apt-get error: retry $iter in 10s" && sleep 10; \ done; \ (exit $exit_code) ENV NODE_PATH={{ $beatHome }}/.node @@ -145,6 +154,14 @@ COPY --from=home {{ $beatHome }}/NOTICE.txt /licenses COPY --from=home /opt /opt {{- end }} +{{- if .linux_capabilities }} +# Since the beat is stored at the other end of a symlink we must follow the symlink first +# For security reasons setcap does not support symlinks. This is smart in the general case +# but in our specific case since we're building a trusted image from trusted binaries this is +# fine. Thus, we use readlink to follow the link and setcap on the actual binary +RUN readlink -f {{ $beatBinary }} | xargs setcap {{ .linux_capabilities }} +{{- end }} + {{- if eq .user "root" }} {{- if contains .image_name "-cloud" }} # Generate folder for a stub command that will be overwritten at runtime @@ -213,3 +230,4 @@ RUN echo -e '#!/bin/sh\nexec /usr/local/bin/docker-entrypoint' > /app/apm.sh && {{- else }} ENTRYPOINT ["/usr/bin/tini", "--", "/usr/local/bin/docker-entrypoint"] {{- end }} + diff --git a/dev-tools/packaging/templates/docker/Dockerfile.tmpl b/dev-tools/packaging/templates/docker/Dockerfile.tmpl index 91a636f50b0..9309516bd80 100644 --- a/dev-tools/packaging/templates/docker/Dockerfile.tmpl +++ b/dev-tools/packaging/templates/docker/Dockerfile.tmpl @@ -18,36 +18,52 @@ RUN mkdir -p {{ $beatHome }}/data {{ $beatHome }}/logs && \ {{- end }} chmod 0775 {{ $beatHome }}/data {{ $beatHome }}/logs -{{- if .linux_capabilities }} -# Since the beat is stored at the other end of a symlink we must follow the symlink first -# For security reasons setcap does not support symlinks. This is smart in the general case -# but in our specific case since we're building a trusted image from trusted binaries this is -# fine. Thus, we use readlink to follow the link and setcap on the actual binary -RUN readlink -f {{ $beatBinary }} | xargs setcap {{ .linux_capabilities }} -{{- end }} - FROM {{ .from }} {{- if contains .from "ubi-minimal" }} RUN microdnf -y update && \ - microdnf install shadow-utils && \ + microdnf install findutils shadow-utils && \ microdnf clean all {{- else }} -# FIXME: Package bind-license failed to update in arm -RUN case $(arch) in aarch64) YUM_FLAGS="-x bind-license";; esac; \ - yum -y update $YUM_FLAGS \ - {{- if (eq .BeatName "heartbeat") }} - && yum -y install epel-release \ - && yum -y install atk gtk gdk xrandr pango libXcomposite libXcursor libXdamage \ - libXext libXi libXtst libXScrnSaver libXrandr GConf2 \ - alsa-lib atk gtk3 ipa-gothic-fonts xorg-x11-fonts-100dpi xorg-x11-fonts-75dpi xorg-x11-utils \ - xorg-x11-fonts-cyrillic xorg-x11-fonts-Type1 xorg-x11-fonts-misc \ - {{- end }} - && yum clean all && rm -rf /var/cache/yum - # See https://access.redhat.com/discussions/3195102 for why rm is needed +RUN for iter in {1..10}; do \ + apt-get update -y && \ + DEBIAN_FRONTEND=noninteractive apt-get install --no-install-recommends --yes ca-certificates curl libcap2-bin xz-utils && \ + apt-get clean all && \ + exit_code=0 && break || exit_code=$? && echo "apt-get error: retry $iter in 10s" && sleep 10; \ + done; \ + (exit $exit_code) {{- end }} {{- if (and (eq .BeatName "heartbeat") (not (contains .from "ubi-minimal"))) }} +RUN apt-get update -y && \ + for iter in {1..10}; do \ + DEBIAN_FRONTEND=noninteractive apt-get install --no-install-recommends --yes \ + libglib2.0-0\ + libnss3\ + libnspr4\ + libatk1.0-0\ + libatk-bridge2.0-0\ + libcups2\ + libdrm2\ + libdbus-1-3\ + libxcb1\ + libxkbcommon0\ + libx11-6\ + libxcomposite1\ + libxdamage1\ + libxext6\ + libxfixes3\ + libxrandr2\ + libgbm1\ + libpango-1.0-0\ + libcairo2\ + libasound2\ + libatspi2.0-0\ + libxshmfence1 && \ + apt-get clean all && \ + exit_code=0 && break || exit_code=$? && echo "apt-get error: retry $iter in 10s" && sleep 10; \ + done; \ + (exit $exit_code) ENV NODE_PATH={{ $beatHome }}/.node RUN echo \ $NODE_PATH \ @@ -93,6 +109,7 @@ RUN set -e ; \ TINI_BIN=""; \ TINI_SHA256=""; \ TINI_VERSION="v0.19.0"; \ + echo "The arch value is $(arch)"; \ case "$(arch)" in \ x86_64) \ TINI_BIN="tini-amd64"; \ @@ -120,6 +137,14 @@ RUN mkdir /licenses COPY --from=home {{ $beatHome }}/LICENSE.txt /licenses COPY --from=home {{ $beatHome }}/NOTICE.txt /licenses +{{- if .linux_capabilities }} +# Since the beat is stored at the other end of a symlink we must follow the symlink first +# For security reasons setcap does not support symlinks. This is smart in the general case +# but in our specific case since we're building a trusted image from trusted binaries this is +# fine. Thus, we use readlink to follow the link and setcap on the actual binary +RUN readlink -f {{ $beatBinary }} | xargs setcap {{ .linux_capabilities }} +{{- end }} + {{- if ne .user "root" }} RUN groupadd --gid 1000 {{ .BeatName }} RUN useradd -M --uid 1000 --gid 1000 --groups 0 --home {{ $beatHome }} {{ .user }} diff --git a/docs/devguide/create-metricset.asciidoc b/docs/devguide/create-metricset.asciidoc index a1540be2384..fd60e25dd3a 100644 --- a/docs/devguide/create-metricset.asciidoc +++ b/docs/devguide/create-metricset.asciidoc @@ -1,6 +1,8 @@ [[creating-metricsets]] === Creating a Metricset +include::generator-support-note.asciidoc[tag=metricset-generator] + A metricset is the part of a Metricbeat module that fetches and structures the data from the remote service. Each module can have multiple metricsets. In this guide, you learn how to create your own metricset. diff --git a/docs/devguide/generator-support-note.asciidoc b/docs/devguide/generator-support-note.asciidoc new file mode 100644 index 00000000000..25579798ed2 --- /dev/null +++ b/docs/devguide/generator-support-note.asciidoc @@ -0,0 +1,13 @@ +// tag::metricset-generator[] +IMPORTANT: Elastic provides no warranty or support for the code used to generate +metricsets. The generator is mainly offered as guidance for developers who want +to create their own data shippers. + +// end::metricset-generator[] + +// tag::filebeat-generator[] +IMPORTANT: Elastic provides no warranty or support for the code used to generate +modules and filesets. The generator is mainly offered as guidance for developers +who want to create their own data shippers. + +// end::filebeat-generator[] \ No newline at end of file diff --git a/docs/devguide/modules-dev-guide.asciidoc b/docs/devguide/modules-dev-guide.asciidoc index 0936438900e..03b3179c596 100644 --- a/docs/devguide/modules-dev-guide.asciidoc +++ b/docs/devguide/modules-dev-guide.asciidoc @@ -1,6 +1,8 @@ [[filebeat-modules-devguide]] == Creating a New Filebeat Module +include::generator-support-note.asciidoc[tag=filebeat-generator] + This guide will walk you through creating a new Filebeat module. All Filebeat modules currently live in the main diff --git a/filebeat/Dockerfile b/filebeat/Dockerfile index b4db2123456..3b17f95e998 100644 --- a/filebeat/Dockerfile +++ b/filebeat/Dockerfile @@ -1,8 +1,8 @@ -FROM golang:1.17.2 +FROM golang:1.17.5 RUN \ apt-get update \ - && apt-get install -y --no-install-recommends \ + && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \ libsystemd-dev \ netcat \ rsync \ diff --git a/filebeat/Jenkinsfile.yml b/filebeat/Jenkinsfile.yml index 758f0d496a0..f5843c43b18 100644 --- a/filebeat/Jenkinsfile.yml +++ b/filebeat/Jenkinsfile.yml @@ -55,7 +55,7 @@ stages: macos: mage: "mage build unitTest" platforms: ## override default label in this specific stage. - - "macosx&&x86_64" + - "orka && darwin && poc" when: ## Override the top-level when. comments: - "/test filebeat for macos" diff --git a/filebeat/_meta/config/filebeat.global.reference.yml.tmpl b/filebeat/_meta/config/filebeat.global.reference.yml.tmpl index dccfc790a7c..5686fe14f22 100644 --- a/filebeat/_meta/config/filebeat.global.reference.yml.tmpl +++ b/filebeat/_meta/config/filebeat.global.reference.yml.tmpl @@ -40,7 +40,7 @@ #reload.enabled: true #reload.period: 10s #modules: - #enabled: false + #enabled: true #path: modules.d/*.yml #reload.enabled: true #reload.period: 10s diff --git a/filebeat/_meta/config/filebeat.inputs.reference.yml.tmpl b/filebeat/_meta/config/filebeat.inputs.reference.yml.tmpl index a47e70d98c2..010e5e36e2f 100644 --- a/filebeat/_meta/config/filebeat.inputs.reference.yml.tmpl +++ b/filebeat/_meta/config/filebeat.inputs.reference.yml.tmpl @@ -94,7 +94,8 @@ filebeat.inputs: #max_bytes: 10485760 # Characters which separate the lines. Valid values: auto, line_feed, vertical_tab, form_feed, - # carriage_return, carriage_return_line_feed, next_line, line_separator, paragraph_separator. + # carriage_return, carriage_return_line_feed, next_line, line_separator, paragraph_separator, + # null_terminator #line_terminator: auto ### Recursive glob configuration @@ -348,7 +349,8 @@ filebeat.inputs: #message_max_bytes: 10485760 # Characters which separate the lines. Valid values: auto, line_feed, vertical_tab, form_feed, - # carriage_return, carriage_return_line_feed, next_line, line_separator, paragraph_separator. + # carriage_return, carriage_return_line_feed, next_line, line_separator, paragraph_separator, + # null_terminator #line_terminator: auto # The ingest pipeline ID associated with this input. If this is set, it @@ -557,3 +559,33 @@ filebeat.inputs: # Configure stream to filter to a specific stream: stdout, stderr or all (default) #stream: all +#------------------------------ Journald input -------------------------------- +# Journald input is experimental. +#- type: journald + #enabled: true + #id: service-foo + + # You may wish to have separate inputs for each service. You can use + # include_matches.or to specify a list of filter expressions that are + # applied as a logical OR. You may specify filter + #include_matches.or: + #- equals: + #- _SYSTEMD_UNIT=foo.service + + # List of syslog identifiers + #syslog_identifiers: ["audit"] + + # Collect events from the service and messages about the service, + # including coredumps. + #units: ["docker.service"] + + # The list of transports (_TRANSPORT field of journald entries) + #transports: ["audit"] + + # Parsers are also supported, here is an example of the multiline + # parser. + #parsers: + #- multiline: + #type: count + #count_lines: 3 + diff --git a/filebeat/docs/fields.asciidoc b/filebeat/docs/fields.asciidoc index d89839516fe..73d50ea649d 100644 --- a/filebeat/docs/fields.asciidoc +++ b/filebeat/docs/fields.asciidoc @@ -86641,47 +86641,16 @@ type: ip -- - -*`kubernetes.namespace.name`*:: -+ --- -Kubernetes namespace name - - -type: keyword - --- - -*`kubernetes.namespace.uuid`*:: +*`kubernetes.namespace`*:: + -- -Kubernetes namespace uuid +Kubernetes namespace type: keyword -- -*`kubernetes.namespace.labels.*`*:: -+ --- -Kubernetes namespace labels map - - -type: object - --- - -*`kubernetes.namespace.annotations.*`*:: -+ --- -Kubernetes namespace annotations map - - -type: object - --- - *`kubernetes.node.name`*:: + -- @@ -143309,6 +143278,16 @@ type: keyword The related XSS caught by the WAF +type: keyword + +-- + +*`sophos.xg.ether_type`*:: ++ +-- +The ethernet frame type + + type: keyword -- @@ -150641,385 +150620,8 @@ Threat intelligence Filebeat Module. -[float] -=== threatintel - -Fields from the threatintel Filebeat module. - - - -*`threatintel.indicator.first_seen`*:: -+ --- -The date and time when intelligence source first reported sighting this indicator. - - -type: date - --- - -*`threatintel.indicator.last_seen`*:: -+ --- -The date and time when intelligence source last reported sighting this indicator. - - -type: date - --- - -*`threatintel.indicator.sightings`*:: -+ --- -Number of times this indicator was observed conducting threat activity. - - -type: long - --- - -*`threatintel.indicator.type`*:: -+ --- -Type of indicator as represented by Cyber Observable in STIX 2.0. Expected values - * autonomous-system - * artifact - * directory - * domain-name - * email-addr - * file - * ipv4-addr - * ipv6-addr - * mac-addr - * mutex - * process - * software - * url - * user-account - * windows-registry-key - * x-509-certificate - - -type: keyword - --- - -*`threatintel.indicator.description`*:: -+ --- -Describes the type of action conducted by the threat. - - -type: keyword - --- - -*`threatintel.indicator.scanner_stats`*:: -+ --- -Count of AV/EDR vendors that successfully detected malicious file or URL. - - -type: long - --- - -*`threatintel.indicator.provider`*:: -+ --- -Identifies the name of the intelligence provider. - - -type: keyword - --- - -*`threatintel.indicator.confidence`*:: -+ --- -Identifies the confidence rating assigned by the provider using STIX confidence scales. Expected values - * Not Specified, None, Low, Medium, High - * 0-10 - * Admirality Scale (1-6) - * DNI Scale (5-95) - * WEP Scale (Impossible - Certain) - - -type: keyword - --- - -*`threatintel.indicator.module`*:: -+ --- -Identifies the name of specific module this data is coming from. - - -type: keyword - --- - -*`threatintel.indicator.dataset`*:: -+ --- -Identifies the name of specific dataset from the intelligence source. - - -type: keyword - --- - -*`threatintel.indicator.reference`*:: -+ --- -Reference URL linking to additional information about this indicator. - - -type: keyword - --- - -*`threatintel.indicator.ip`*:: -+ --- -Identifies a threat indicator as an IP address (irrespective of direction). - - -type: ip - --- - -*`threatintel.indicator.port`*:: -+ --- -Identifies a threat indicator as a port number (irrespective of direction). - - -type: long - --- - -*`threatintel.indicator.email.address`*:: -+ --- -Identifies a threat indicator as an email address (irrespective of direction). - - -type: keyword - --- - -*`threatintel.indicator.marking.tlp`*:: -+ --- -Traffic Light Protocol sharing markings. Expected values are: - * White - * Green - * Amber - * Red - - -type: keyword - --- - - -*`threatintel.indicator.matched.atomic`*:: -+ --- -Identifies the atomic indicator that matched a local environment endpoint or network event. - - -type: keyword - --- - -*`threatintel.indicator.matched.field`*:: -+ --- -Identifies the field of the atomic indicator that matched a local environment endpoint or network event. - - -type: keyword - --- - -*`threatintel.indicator.matched.type`*:: -+ --- -Identifies the type of the atomic indicator that matched a local environment endpoint or network event. - - -type: keyword - --- - - -*`threatintel.indicator.as.number`*:: -+ --- -Unique number allocated to the autonomous system. The autonomous system number (ASN) uniquely identifies each network on the Internet. - -type: long - -example: 15169 - --- - -*`threatintel.indicator.as.organization.name`*:: -+ --- -Organization name. - -type: keyword - -example: Google LLC - --- - -*`threatintel.indicator.as.organization.name.text`*:: -+ --- -type: text - --- - - -*`threatintel.indicator.registry.data.strings`*:: -+ --- -Content when writing string types. Populated as an array when writing string data to the registry. For single string registry types (REG_SZ, REG_EXPAND_SZ), this should be an array with one string. For sequences of string with REG_MULTI_SZ, this array will be variable length. For numeric data, such as REG_DWORD and REG_QWORD, this should be populated with the decimal representation (e.g `"1"`). - - -type: keyword - -example: ["C:\rta\red_ttp\bin\myapp.exe"] - --- - -*`threatintel.indicator.registry.path`*:: -+ --- -Full path, including hive, key and value - -type: keyword - -example: HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\winword.exe\Debugger - --- - -*`threatintel.indicator.registry.value`*:: -+ --- -Name of the value written. - -type: keyword - -example: Debugger - --- - -*`threatintel.indicator.registry.key`*:: -+ --- -Registry key value - -type: keyword - --- - - -*`threatintel.indicator.geo.city_name`*:: -+ --- -City name. - -type: keyword - -example: Montreal - --- - -*`threatintel.indicator.geo.continent_name`*:: -+ --- -Name of the continent. - -type: keyword - -example: North America - --- - -*`threatintel.indicator.geo.country_iso_code`*:: -+ --- -Country ISO code. - -type: keyword - -example: CA - --- - -*`threatintel.indicator.geo.country_name`*:: -+ --- -Country name. - -type: keyword - -example: Canada - --- - -*`threatintel.indicator.geo.location`*:: -+ --- -Longitude and latitude. - -type: geo_point - -example: { "lon": -73.614830, "lat": 45.505918 } - --- - -*`threatintel.indicator.geo.region_iso_code`*:: -+ --- -Region ISO code. - -type: keyword - -example: CA-QC - --- - -*`threatintel.indicator.geo.region_name`*:: -+ --- -Region name. - -type: keyword - -example: Quebec - --- -*`threatintel.indicator.file.pe.imphash`*:: -+ --- -A hash of the imports in a PE file. An imphash -- or import hash -- can be used to fingerprint binaries even after recompilation or other code-level transformations have occurred, which would change more traditional hash values. Learn more at https://www.fireeye.com/blog/threat-research/2014/01/tracking-malware-import-hashing.html. - -type: keyword - -example: 0c6803c4e922103c4dca5963aad36ddf - --- - - - -*`threatintel.indicator.file.hash.tlsh`*:: +*`threat.indicator.file.hash.tlsh`*:: + -- The file's import tlsh, if available. @@ -151029,47 +150631,7 @@ type: keyword -- -*`threatintel.indicator.file.hash.ssdeep`*:: -+ --- -The file's ssdeep hash, if available. - - -type: keyword - --- - -*`threatintel.indicator.file.hash.md5`*:: -+ --- -The file's md5 hash, if available. - - -type: keyword - --- - -*`threatintel.indicator.file.hash.sha1`*:: -+ --- -The file's sha1 hash, if available. - - -type: keyword - --- - -*`threatintel.indicator.file.hash.sha256`*:: -+ --- -The file's sha256 hash, if available. - - -type: keyword - --- - -*`threatintel.indicator.file.hash.sha384`*:: +*`threat.indicator.file.hash.sha384`*:: + -- The file's sha384 hash, if available. @@ -151079,272 +150641,28 @@ type: keyword -- -*`threatintel.indicator.file.hash.sha512`*:: -+ --- -The file's sha512 hash, if available. - - -type: keyword - --- - -*`threatintel.indicator.file.type`*:: -+ --- -The file type. - - -type: keyword - --- - -*`threatintel.indicator.file.size`*:: -+ --- -The file's total size. - - -type: long - --- - -*`threatintel.indicator.file.name`*:: -+ --- -The file's name. - - -type: keyword - --- - -*`threatintel.indicator.file.extension`*:: -+ --- -The file's extension. - - -type: keyword - --- - -*`threatintel.indicator.file.mime_type`*:: -+ --- -The file's MIME type. - - -type: keyword - --- - - -*`threatintel.indicator.url.domain`*:: -+ --- -Domain of the url, such as "www.elastic.co". - - -type: keyword - --- - -*`threatintel.indicator.url.extension`*:: +*`threat.feed.name`*:: + -- -The field contains the file extension from the original request - - -type: keyword - --- - -*`threatintel.indicator.url.fragment`*:: -+ --- -Portion of the url after the `#`, such as "top". - - -type: keyword - --- - -*`threatintel.indicator.url.full`*:: -+ --- -If full URLs are important to your use case, they should be stored in `url.full`, whether this field is reconstructed or present in the event source. - - -type: keyword - --- - -*`threatintel.indicator.url.original`*:: -+ --- -Unmodified original url as seen in the event source. Note that in network monitoring, the observed URL may be a full URL, whereas in access logs, the URL is often just represented as a path. This field is meant to represent the URL as it was observed, complete or not. - - -type: keyword - --- - -*`threatintel.indicator.url.password`*:: -+ --- -Password of the request. - - -type: keyword - --- - -*`threatintel.indicator.url.path`*:: -+ --- -Path of the request, such as "/search". - - -type: keyword - --- - -*`threatintel.indicator.url.port`*:: -+ --- -Port of the request, such as 443. - - -type: long - -format: string - --- - -*`threatintel.indicator.url.query`*:: -+ --- -The query field describes the query string of the request, such as "q=elasticsearch". The `?` is excluded from the query string. If a URL contains no `?`, there is no query field. If there is a `?` but no query, the query field exists with an empty string. The `exists` query can be used to differentiate between the two cases. - - -type: keyword - --- - -*`threatintel.indicator.url.registered_domain`*:: -+ --- -The highest registered url domain, stripped of the subdomain. For example, the registered domain for "foo.example.com" is "example.com". This value can be determined precisely with a list like the public suffix list (http://publicsuffix.org). Trying to approximate this by simply taking the last two labels will not work well for TLDs such as "co.uk". - - -type: keyword - --- - -*`threatintel.indicator.url.scheme`*:: -+ --- -Scheme of the request, such as "https". - - -type: keyword - --- - -*`threatintel.indicator.url.subdomain`*:: -+ --- -The subdomain portion of a fully qualified domain name includes all of the names except the host name under the registered_domain. In a partially qualified domain, or if the the qualification level of the full name cannot be determined, subdomain contains all of the names below the registered domain. For example the subdomain portion of "www.east.mydomain.co.uk" is "east". If the domain has multiple levels of subdomain, such as "sub2.sub1.example.com", the subdomain field should contain "sub2.sub1", with no trailing period. - - -type: keyword - --- - -*`threatintel.indicator.url.top_level_domain`*:: -+ --- -The effective top level domain (eTLD), also known as the domain suffix, is the last part of the domain name. For example, the top level domain for example.com is "com". This value can be determined precisely with a list like the public suffix list (http://publicsuffix.org). Trying to approximate this by simply taking the last label will not work well for effective TLDs such as "co.uk". - - -type: keyword - --- - -*`threatintel.indicator.url.username`*:: -+ --- -Username of the request. - - -type: keyword - --- - - -*`threatintel.indicator.x509.serial_number`*:: -+ --- -Unique serial number issued by the certificate authority. For consistency, if this value is alphanumeric, it should be formatted without colons and uppercase characters. - type: keyword -example: 55FBB9C7DEBF09809D12CCAA - -- -*`threatintel.indicator.x509.issuer`*:: +*`threat.feed.dashboard_id`*:: + -- -Name of issuing certificate authority. Could be either Distinguished Name (DN) or Common Name (CN), depending on source. - -type: keyword - -example: C=US, O=Example Inc, OU=www.example.com, CN=Example SHA2 High Assurance Server CA - --- - -*`threatintel.indicator.x509.subject`*:: -+ --- -Name of the certificate subject entity. Could be either Distinguished Name (DN) or Common Name (CN), depending on source. - -type: keyword - -example: C=US, ST=California, L=San Francisco, O=Example, Inc., CN=shared.global.example.net - --- - -*`threatintel.indicator.x509.alternative_names`*:: -+ --- -List of subject alternative names (SAN). Name types vary by certificate authority and certificate type but commonly contain IP addresses, DNS names (and wildcards), and email addresses. - -type: keyword - -example: *.elastic.co - --- - -*`threatintel.indicator.signature`*:: -+ --- -Malware family of sample (if available). - - type: keyword -- [float] -=== abusemalware +=== abusech.malware Fields for AbuseCH Malware Threat Intel -*`threatintel.abusemalware.file_type`*:: +*`abusech.malware.file_type`*:: + -- File type guessed by URLhaus. @@ -151354,7 +150672,7 @@ type: keyword -- -*`threatintel.abusemalware.signature`*:: +*`abusech.malware.signature`*:: + -- Malware familiy. @@ -151364,7 +150682,7 @@ type: keyword -- -*`threatintel.abusemalware.urlhaus_download`*:: +*`abusech.malware.urlhaus_download`*:: + -- Location (URL) where you can download a copy of this file. @@ -151374,7 +150692,7 @@ type: keyword -- -*`threatintel.abusemalware.virustotal.result`*:: +*`abusech.malware.virustotal.result`*:: + -- AV detection ration. @@ -151384,7 +150702,7 @@ type: keyword -- -*`threatintel.abusemalware.virustotal.percent`*:: +*`abusech.malware.virustotal.percent`*:: + -- AV detection in percent. @@ -151394,7 +150712,7 @@ type: float -- -*`threatintel.abusemalware.virustotal.link`*:: +*`abusech.malware.virustotal.link`*:: + -- Link to the Virustotal report. @@ -151405,13 +150723,13 @@ type: keyword -- [float] -=== abuseurl +=== abusech.url Fields for AbuseCH Malware Threat Intel -*`threatintel.abuseurl.id`*:: +*`abusech.url.id`*:: + -- The ID of the url. @@ -151421,7 +150739,7 @@ type: keyword -- -*`threatintel.abuseurl.urlhaus_reference`*:: +*`abusech.url.urlhaus_reference`*:: + -- Link to URLhaus entry. @@ -151431,7 +150749,7 @@ type: keyword -- -*`threatintel.abuseurl.url_status`*:: +*`abusech.url.url_status`*:: + -- The current status of the URL. Possible values are: online, offline and unknown. @@ -151441,7 +150759,7 @@ type: keyword -- -*`threatintel.abuseurl.threat`*:: +*`abusech.url.threat`*:: + -- The threat corresponding to this malware URL. @@ -151451,7 +150769,7 @@ type: keyword -- -*`threatintel.abuseurl.blacklists.surbl`*:: +*`abusech.url.blacklists.surbl`*:: + -- SURBL blacklist status. Possible values are: listed and not_listed @@ -151461,7 +150779,7 @@ type: keyword -- -*`threatintel.abuseurl.blacklists.spamhaus_dbl`*:: +*`abusech.url.blacklists.spamhaus_dbl`*:: + -- Spamhaus DBL blacklist status. @@ -151471,7 +150789,7 @@ type: keyword -- -*`threatintel.abuseurl.reporter`*:: +*`abusech.url.reporter`*:: + -- The Twitter handle of the reporter that has reported this malware URL (or anonymous). @@ -151481,7 +150799,7 @@ type: keyword -- -*`threatintel.abuseurl.larted`*:: +*`abusech.url.larted`*:: + -- Indicates whether the malware URL has been reported to the hosting provider (true or false) @@ -151491,7 +150809,7 @@ type: boolean -- -*`threatintel.abuseurl.tags`*:: +*`abusech.url.tags`*:: + -- A list of tags associated with the queried malware URL @@ -151502,13 +150820,13 @@ type: keyword -- [float] -=== anomali +=== anomali.limo Fields for Anomali Threat Intel -*`threatintel.anomali.id`*:: +*`anomali.limo.id`*:: + -- The ID of the indicator. @@ -151518,7 +150836,7 @@ type: keyword -- -*`threatintel.anomali.name`*:: +*`anomali.limo.name`*:: + -- The name of the indicator. @@ -151528,7 +150846,7 @@ type: keyword -- -*`threatintel.anomali.pattern`*:: +*`anomali.limo.pattern`*:: + -- The pattern ID of the indicator. @@ -151538,7 +150856,7 @@ type: keyword -- -*`threatintel.anomali.valid_from`*:: +*`anomali.limo.valid_from`*:: + -- When the indicator was first found or is considered valid. @@ -151548,7 +150866,7 @@ type: date -- -*`threatintel.anomali.modified`*:: +*`anomali.limo.modified`*:: + -- When the indicator was last modified @@ -151558,7 +150876,7 @@ type: date -- -*`threatintel.anomali.labels`*:: +*`anomali.limo.labels`*:: + -- The labels related to the indicator @@ -151568,7 +150886,7 @@ type: keyword -- -*`threatintel.anomali.indicator`*:: +*`anomali.limo.indicator`*:: + -- The value of the indicator, for example if the type is domain, this would be the value. @@ -151578,7 +150896,7 @@ type: keyword -- -*`threatintel.anomali.description`*:: +*`anomali.limo.description`*:: + -- A description of the indicator. @@ -151588,7 +150906,7 @@ type: keyword -- -*`threatintel.anomali.title`*:: +*`anomali.limo.title`*:: + -- Title describing the indicator. @@ -151598,7 +150916,7 @@ type: keyword -- -*`threatintel.anomali.content`*:: +*`anomali.limo.content`*:: + -- Extra text or descriptive content related to the indicator. @@ -151608,7 +150926,7 @@ type: keyword -- -*`threatintel.anomali.type`*:: +*`anomali.limo.type`*:: + -- The indicator type, can for example be "domain, email, FileHash-SHA256". @@ -151618,7 +150936,7 @@ type: keyword -- -*`threatintel.anomali.object_marking_refs`*:: +*`anomali.limo.object_marking_refs`*:: + -- The STIX reference object. @@ -151629,13 +150947,13 @@ type: keyword -- [float] -=== anomalithreatstream +=== anomali.threatstream Fields for Anomali ThreatStream -*`threatintel.anomalithreatstream.classification`*:: +*`anomali.threatstream.classification`*:: + -- Indicates whether an indicator is private or from a public feed and available publicly. Possible values: private, public. @@ -151647,7 +150965,7 @@ example: private -- -*`threatintel.anomalithreatstream.confidence`*:: +*`anomali.threatstream.confidence`*:: + -- The measure of the accuracy (from 0 to 100) assigned by ThreatStream's predictive analytics technology to indicators. @@ -151657,7 +150975,7 @@ type: short -- -*`threatintel.anomalithreatstream.detail2`*:: +*`anomali.threatstream.detail2`*:: + -- Detail text for indicator. @@ -151669,7 +150987,7 @@ example: Imported by user 42. -- -*`threatintel.anomalithreatstream.id`*:: +*`anomali.threatstream.id`*:: + -- The ID of the indicator. @@ -151679,7 +150997,7 @@ type: keyword -- -*`threatintel.anomalithreatstream.import_session_id`*:: +*`anomali.threatstream.import_session_id`*:: + -- ID of the import session that created the indicator on ThreatStream. @@ -151689,7 +151007,7 @@ type: keyword -- -*`threatintel.anomalithreatstream.itype`*:: +*`anomali.threatstream.itype`*:: + -- Indicator type. Possible values: "apt_domain", "apt_email", "apt_ip", "apt_url", "bot_ip", "c2_domain", "c2_ip", "c2_url", "i2p_ip", "mal_domain", "mal_email", "mal_ip", "mal_md5", "mal_url", "parked_ip", "phish_email", "phish_ip", "phish_url", "scan_ip", "spam_domain", "ssh_ip", "suspicious_domain", "tor_ip" and "torrent_tracker_url". @@ -151699,7 +151017,7 @@ type: keyword -- -*`threatintel.anomalithreatstream.maltype`*:: +*`anomali.threatstream.maltype`*:: + -- Information regarding a malware family, a CVE ID, or another attack or threat, associated with the indicator. @@ -151709,7 +151027,7 @@ type: wildcard -- -*`threatintel.anomalithreatstream.md5`*:: +*`anomali.threatstream.md5`*:: + -- Hash for the indicator. @@ -151719,7 +151037,7 @@ type: keyword -- -*`threatintel.anomalithreatstream.resource_uri`*:: +*`anomali.threatstream.resource_uri`*:: + -- Relative URI for the indicator details. @@ -151729,7 +151047,7 @@ type: keyword -- -*`threatintel.anomalithreatstream.severity`*:: +*`anomali.threatstream.severity`*:: + -- Criticality associated with the threat feed that supplied the indicator. Possible values: low, medium, high, very-high. @@ -151739,7 +151057,7 @@ type: keyword -- -*`threatintel.anomalithreatstream.source`*:: +*`anomali.threatstream.source`*:: + -- Source for the indicator. @@ -151751,7 +151069,7 @@ example: Analyst -- -*`threatintel.anomalithreatstream.source_feed_id`*:: +*`anomali.threatstream.source_feed_id`*:: + -- ID for the integrator source. @@ -151761,7 +151079,7 @@ type: keyword -- -*`threatintel.anomalithreatstream.state`*:: +*`anomali.threatstream.state`*:: + -- State for this indicator. @@ -151773,7 +151091,7 @@ example: active -- -*`threatintel.anomalithreatstream.trusted_circle_ids`*:: +*`anomali.threatstream.trusted_circle_ids`*:: + -- ID of the trusted circle that imported the indicator. @@ -151783,7 +151101,7 @@ type: keyword -- -*`threatintel.anomalithreatstream.update_id`*:: +*`anomali.threatstream.update_id`*:: + -- Update ID. @@ -151793,7 +151111,7 @@ type: keyword -- -*`threatintel.anomalithreatstream.url`*:: +*`anomali.threatstream.url`*:: + -- URL for the indicator. @@ -151803,7 +151121,7 @@ type: keyword -- -*`threatintel.anomalithreatstream.value_type`*:: +*`anomali.threatstream.value_type`*:: + -- Data type of the indicator. Possible values: ip, domain, url, email, md5. @@ -151814,13 +151132,13 @@ type: keyword -- [float] -=== malwarebazaar +=== abusech.malwarebazaar Fields for Malware Bazaar Threat Intel -*`threatintel.malwarebazaar.file_type`*:: +*`abusech.malwarebazaar.file_type`*:: + -- File type guessed by Malware Bazaar. @@ -151830,7 +151148,7 @@ type: keyword -- -*`threatintel.malwarebazaar.signature`*:: +*`abusech.malwarebazaar.signature`*:: + -- Malware familiy. @@ -151840,7 +151158,7 @@ type: keyword -- -*`threatintel.malwarebazaar.tags`*:: +*`abusech.malwarebazaar.tags`*:: + -- A list of tags associated with the queried malware sample. @@ -151851,7 +151169,7 @@ type: keyword -- -*`threatintel.malwarebazaar.intelligence.downloads`*:: +*`abusech.malwarebazaar.intelligence.downloads`*:: + -- Number of downloads from MalwareBazaar. @@ -151861,7 +151179,7 @@ type: long -- -*`threatintel.malwarebazaar.intelligence.uploads`*:: +*`abusech.malwarebazaar.intelligence.uploads`*:: + -- Number of uploads from MalwareBazaar. @@ -151872,7 +151190,7 @@ type: long -- -*`threatintel.malwarebazaar.intelligence.mail.Generic`*:: +*`abusech.malwarebazaar.intelligence.mail.Generic`*:: + -- Malware seen in generic spam traffic. @@ -151882,7 +151200,7 @@ type: keyword -- -*`threatintel.malwarebazaar.intelligence.mail.IT`*:: +*`abusech.malwarebazaar.intelligence.mail.IT`*:: + -- Malware seen in IT spam traffic. @@ -151892,7 +151210,7 @@ type: keyword -- -*`threatintel.malwarebazaar.anonymous`*:: +*`abusech.malwarebazaar.anonymous`*:: + -- Identifies if the sample was submitted anonymously. @@ -151902,7 +151220,7 @@ type: long -- -*`threatintel.malwarebazaar.code_sign`*:: +*`abusech.malwarebazaar.code_sign`*:: + -- Code signing information for the sample. @@ -151919,7 +151237,7 @@ Fields for MISP Threat Intel -*`threatintel.misp.id`*:: +*`misp.id`*:: + -- Attribute ID. @@ -151929,7 +151247,7 @@ type: keyword -- -*`threatintel.misp.orgc_id`*:: +*`misp.orgc_id`*:: + -- Organization Community ID of the event. @@ -151939,7 +151257,7 @@ type: keyword -- -*`threatintel.misp.org_id`*:: +*`misp.org_id`*:: + -- Organization ID of the event. @@ -151949,7 +151267,7 @@ type: keyword -- -*`threatintel.misp.threat_level_id`*:: +*`misp.threat_level_id`*:: + -- Threat level from 5 to 1, where 1 is the most critical. @@ -151959,7 +151277,7 @@ type: long -- -*`threatintel.misp.info`*:: +*`misp.info`*:: + -- Additional text or information related to the event. @@ -151969,7 +151287,7 @@ type: keyword -- -*`threatintel.misp.published`*:: +*`misp.published`*:: + -- When the event was published. @@ -151979,7 +151297,7 @@ type: boolean -- -*`threatintel.misp.uuid`*:: +*`misp.uuid`*:: + -- The UUID of the event object. @@ -151989,7 +151307,7 @@ type: keyword -- -*`threatintel.misp.date`*:: +*`misp.date`*:: + -- The date of when the event object was created. @@ -151999,7 +151317,7 @@ type: date -- -*`threatintel.misp.attribute_count`*:: +*`misp.attribute_count`*:: + -- How many attributes are included in a single event object. @@ -152009,7 +151327,7 @@ type: long -- -*`threatintel.misp.timestamp`*:: +*`misp.timestamp`*:: + -- The timestamp of when the event object was created. @@ -152019,7 +151337,7 @@ type: date -- -*`threatintel.misp.distribution`*:: +*`misp.distribution`*:: + -- Distribution type related to MISP. @@ -152029,7 +151347,7 @@ type: keyword -- -*`threatintel.misp.proposal_email_lock`*:: +*`misp.proposal_email_lock`*:: + -- Settings configured on MISP for email lock on this event object. @@ -152039,7 +151357,7 @@ type: boolean -- -*`threatintel.misp.locked`*:: +*`misp.locked`*:: + -- If the current MISP event object is locked or not. @@ -152049,7 +151367,7 @@ type: boolean -- -*`threatintel.misp.publish_timestamp`*:: +*`misp.publish_timestamp`*:: + -- At what time the event object was published @@ -152059,7 +151377,7 @@ type: date -- -*`threatintel.misp.sharing_group_id`*:: +*`misp.sharing_group_id`*:: + -- The ID of the grouped events or sources of the event. @@ -152069,7 +151387,7 @@ type: keyword -- -*`threatintel.misp.disable_correlation`*:: +*`misp.disable_correlation`*:: + -- If correlation is disabled on the MISP event object. @@ -152079,7 +151397,7 @@ type: boolean -- -*`threatintel.misp.extends_uuid`*:: +*`misp.extends_uuid`*:: + -- The UUID of the event object it might extend. @@ -152089,7 +151407,7 @@ type: keyword -- -*`threatintel.misp.org.id`*:: +*`misp.org.id`*:: + -- The organization ID related to the event object. @@ -152099,7 +151417,7 @@ type: keyword -- -*`threatintel.misp.org.name`*:: +*`misp.org.name`*:: + -- The organization name related to the event object. @@ -152109,7 +151427,7 @@ type: keyword -- -*`threatintel.misp.org.uuid`*:: +*`misp.org.uuid`*:: + -- The UUID of the organization related to the event object. @@ -152119,7 +151437,7 @@ type: keyword -- -*`threatintel.misp.org.local`*:: +*`misp.org.local`*:: + -- If the event object is local or from a remote source. @@ -152129,7 +151447,7 @@ type: boolean -- -*`threatintel.misp.orgc.id`*:: +*`misp.orgc.id`*:: + -- The Organization Community ID in which the event object was reported from. @@ -152139,7 +151457,7 @@ type: keyword -- -*`threatintel.misp.orgc.name`*:: +*`misp.orgc.name`*:: + -- The Organization Community name in which the event object was reported from. @@ -152149,7 +151467,7 @@ type: keyword -- -*`threatintel.misp.orgc.uuid`*:: +*`misp.orgc.uuid`*:: + -- The Organization Community UUID in which the event object was reported from. @@ -152159,7 +151477,7 @@ type: keyword -- -*`threatintel.misp.orgc.local`*:: +*`misp.orgc.local`*:: + -- If the Organization Community was local or synced from a remote source. @@ -152169,7 +151487,7 @@ type: boolean -- -*`threatintel.misp.attribute.id`*:: +*`misp.attribute.id`*:: + -- The ID of the attribute related to the event object. @@ -152179,7 +151497,7 @@ type: keyword -- -*`threatintel.misp.attribute.type`*:: +*`misp.attribute.type`*:: + -- The type of the attribute related to the event object. For example email, ipv4, sha1 and such. @@ -152189,7 +151507,7 @@ type: keyword -- -*`threatintel.misp.attribute.category`*:: +*`misp.attribute.category`*:: + -- The category of the attribute related to the event object. For example "Network Activity". @@ -152199,7 +151517,7 @@ type: keyword -- -*`threatintel.misp.attribute.to_ids`*:: +*`misp.attribute.to_ids`*:: + -- If the attribute should be automatically synced with an IDS. @@ -152209,7 +151527,7 @@ type: boolean -- -*`threatintel.misp.attribute.uuid`*:: +*`misp.attribute.uuid`*:: + -- The UUID of the attribute related to the event. @@ -152219,7 +151537,7 @@ type: keyword -- -*`threatintel.misp.attribute.event_id`*:: +*`misp.attribute.event_id`*:: + -- The local event ID of the attribute related to the event. @@ -152229,7 +151547,7 @@ type: keyword -- -*`threatintel.misp.attribute.distribution`*:: +*`misp.attribute.distribution`*:: + -- How the attribute has been distributed, represented by integer numbers. @@ -152239,7 +151557,7 @@ type: long -- -*`threatintel.misp.attribute.timestamp`*:: +*`misp.attribute.timestamp`*:: + -- The timestamp in which the attribute was attached to the event object. @@ -152249,7 +151567,7 @@ type: date -- -*`threatintel.misp.attribute.comment`*:: +*`misp.attribute.comment`*:: + -- Comments made to the attribute itself. @@ -152259,7 +151577,7 @@ type: keyword -- -*`threatintel.misp.attribute.sharing_group_id`*:: +*`misp.attribute.sharing_group_id`*:: + -- The group ID of the sharing group related to the specific attribute. @@ -152269,7 +151587,7 @@ type: keyword -- -*`threatintel.misp.attribute.deleted`*:: +*`misp.attribute.deleted`*:: + -- If the attribute has been removed from the event object. @@ -152279,7 +151597,7 @@ type: boolean -- -*`threatintel.misp.attribute.disable_correlation`*:: +*`misp.attribute.disable_correlation`*:: + -- If correlation has been enabled on the attribute related to the event object. @@ -152289,7 +151607,7 @@ type: boolean -- -*`threatintel.misp.attribute.object_id`*:: +*`misp.attribute.object_id`*:: + -- The ID of the Object in which the attribute is attached. @@ -152299,7 +151617,7 @@ type: keyword -- -*`threatintel.misp.attribute.object_relation`*:: +*`misp.attribute.object_relation`*:: + -- The type of relation the attribute has with the event object itself. @@ -152309,7 +151627,7 @@ type: keyword -- -*`threatintel.misp.attribute.value`*:: +*`misp.attribute.value`*:: + -- The value of the attribute, depending on the type like "url, sha1, email-src". @@ -152319,7 +151637,7 @@ type: keyword -- -*`threatintel.misp.context.attribute.id`*:: +*`misp.context.attribute.id`*:: + -- The ID of the secondary attribute related to the event object. @@ -152329,7 +151647,7 @@ type: keyword -- -*`threatintel.misp.context.attribute.type`*:: +*`misp.context.attribute.type`*:: + -- The type of the secondary attribute related to the event object. For example email, ipv4, sha1 and such. @@ -152339,7 +151657,7 @@ type: keyword -- -*`threatintel.misp.context.attribute.category`*:: +*`misp.context.attribute.category`*:: + -- The category of the secondary attribute related to the event object. For example "Network Activity". @@ -152349,7 +151667,7 @@ type: keyword -- -*`threatintel.misp.context.attribute.to_ids`*:: +*`misp.context.attribute.to_ids`*:: + -- If the secondary attribute should be automatically synced with an IDS. @@ -152359,7 +151677,7 @@ type: boolean -- -*`threatintel.misp.context.attribute.uuid`*:: +*`misp.context.attribute.uuid`*:: + -- The UUID of the secondary attribute related to the event. @@ -152369,7 +151687,7 @@ type: keyword -- -*`threatintel.misp.context.attribute.event_id`*:: +*`misp.context.attribute.event_id`*:: + -- The local event ID of the secondary attribute related to the event. @@ -152379,7 +151697,7 @@ type: keyword -- -*`threatintel.misp.context.attribute.distribution`*:: +*`misp.context.attribute.distribution`*:: + -- How the secondary attribute has been distributed, represented by integer numbers. @@ -152389,7 +151707,7 @@ type: long -- -*`threatintel.misp.context.attribute.timestamp`*:: +*`misp.context.attribute.timestamp`*:: + -- The timestamp in which the secondary attribute was attached to the event object. @@ -152399,7 +151717,7 @@ type: date -- -*`threatintel.misp.context.attribute.comment`*:: +*`misp.context.attribute.comment`*:: + -- Comments made to the secondary attribute itself. @@ -152409,7 +151727,7 @@ type: keyword -- -*`threatintel.misp.context.attribute.sharing_group_id`*:: +*`misp.context.attribute.sharing_group_id`*:: + -- The group ID of the sharing group related to the specific secondary attribute. @@ -152419,7 +151737,7 @@ type: keyword -- -*`threatintel.misp.context.attribute.deleted`*:: +*`misp.context.attribute.deleted`*:: + -- If the secondary attribute has been removed from the event object. @@ -152429,7 +151747,7 @@ type: boolean -- -*`threatintel.misp.context.attribute.disable_correlation`*:: +*`misp.context.attribute.disable_correlation`*:: + -- If correlation has been enabled on the secondary attribute related to the event object. @@ -152439,7 +151757,7 @@ type: boolean -- -*`threatintel.misp.context.attribute.object_id`*:: +*`misp.context.attribute.object_id`*:: + -- The ID of the Object in which the secondary attribute is attached. @@ -152449,7 +151767,7 @@ type: keyword -- -*`threatintel.misp.context.attribute.object_relation`*:: +*`misp.context.attribute.object_relation`*:: + -- The type of relation the secondary attribute has with the event object itself. @@ -152459,7 +151777,7 @@ type: keyword -- -*`threatintel.misp.context.attribute.value`*:: +*`misp.context.attribute.value`*:: + -- The value of the attribute, depending on the type like "url, sha1, email-src". @@ -152476,7 +151794,7 @@ Fields for OTX Threat Intel -*`threatintel.otx.id`*:: +*`otx.id`*:: + -- The ID of the indicator. @@ -152486,7 +151804,7 @@ type: keyword -- -*`threatintel.otx.indicator`*:: +*`otx.indicator`*:: + -- The value of the indicator, for example if the type is domain, this would be the value. @@ -152496,7 +151814,7 @@ type: keyword -- -*`threatintel.otx.description`*:: +*`otx.description`*:: + -- A description of the indicator. @@ -152506,7 +151824,7 @@ type: keyword -- -*`threatintel.otx.title`*:: +*`otx.title`*:: + -- Title describing the indicator. @@ -152516,7 +151834,7 @@ type: keyword -- -*`threatintel.otx.content`*:: +*`otx.content`*:: + -- Extra text or descriptive content related to the indicator. @@ -152526,7 +151844,7 @@ type: keyword -- -*`threatintel.otx.type`*:: +*`otx.type`*:: + -- The indicator type, can for example be "domain, email, FileHash-SHA256". @@ -152550,7 +151868,7 @@ Entity that represents a threat. -*`threatintel.recordedfuture.entity.id`*:: +*`recordedfuture.entity.id`*:: + -- Entity ID. @@ -152562,7 +151880,7 @@ example: ip:192.0.2.13 -- -*`threatintel.recordedfuture.entity.name`*:: +*`recordedfuture.entity.name`*:: + -- Entity name. Value for the entity. @@ -152574,7 +151892,7 @@ example: 192.0.2.13 -- -*`threatintel.recordedfuture.entity.type`*:: +*`recordedfuture.entity.type`*:: + -- Entity type. @@ -152586,7 +151904,7 @@ example: IpAddress -- -*`threatintel.recordedfuture.intelCard`*:: +*`recordedfuture.intelCard`*:: + -- Link to the Recorded Future Intelligence Card for to this indicator. @@ -152596,7 +151914,7 @@ type: keyword -- -*`threatintel.recordedfuture.ip_range`*:: +*`recordedfuture.ip_range`*:: + -- Range of IPs for this indicator. @@ -152615,7 +151933,7 @@ Risk fields. -*`threatintel.recordedfuture.risk.criticality`*:: +*`recordedfuture.risk.criticality`*:: + -- Risk criticality (0-4). @@ -152625,7 +151943,7 @@ type: byte -- -*`threatintel.recordedfuture.risk.criticalityLabel`*:: +*`recordedfuture.risk.criticalityLabel`*:: + -- Risk criticality label. One of None, Unusual, Suspicious, Malicious, Very Malicious. @@ -152635,7 +151953,7 @@ type: keyword -- -*`threatintel.recordedfuture.risk.evidenceDetails`*:: +*`recordedfuture.risk.evidenceDetails`*:: + -- Risk's evidence details. @@ -152645,7 +151963,7 @@ type: flattened -- -*`threatintel.recordedfuture.risk.score`*:: +*`recordedfuture.risk.score`*:: + -- Risk score (0-99). @@ -152655,7 +151973,7 @@ type: short -- -*`threatintel.recordedfuture.risk.riskString`*:: +*`recordedfuture.risk.riskString`*:: + -- Number of Risk Rules observed as a factor of total number of rules. @@ -152667,7 +151985,7 @@ example: 1/54 -- -*`threatintel.recordedfuture.risk.riskSummary`*:: +*`recordedfuture.risk.riskSummary`*:: + -- Risk summary. @@ -152679,14 +151997,14 @@ example: 1 of 54 Risk Rules currently observed. -- -*`threatintel.recordedfuture.risk.riskSummary.text`*:: +*`recordedfuture.risk.riskSummary.text`*:: + -- type: text -- -*`threatintel.recordedfuture.risk.rules`*:: +*`recordedfuture.risk.rules`*:: + -- Number of rules observed. @@ -152703,7 +152021,7 @@ Fields for ThreatQ Threat Library -*`threatintel.threatq.updated_at`*:: +*`threatq.updated_at`*:: + -- Last modification time @@ -152713,7 +152031,7 @@ type: date -- -*`threatintel.threatq.created_at`*:: +*`threatq.created_at`*:: + -- Object creation time @@ -152723,7 +152041,7 @@ type: date -- -*`threatintel.threatq.expires_at`*:: +*`threatq.expires_at`*:: + -- Expiration time @@ -152733,7 +152051,7 @@ type: date -- -*`threatintel.threatq.expires_calculated_at`*:: +*`threatq.expires_calculated_at`*:: + -- Expiration calculation time @@ -152743,7 +152061,7 @@ type: date -- -*`threatintel.threatq.published_at`*:: +*`threatq.published_at`*:: + -- Object publication time @@ -152753,7 +152071,7 @@ type: date -- -*`threatintel.threatq.status`*:: +*`threatq.status`*:: + -- Object status within the Threat Library @@ -152763,7 +152081,7 @@ type: keyword -- -*`threatintel.threatq.indicator_value`*:: +*`threatq.indicator_value`*:: + -- Original indicator value @@ -152773,7 +152091,7 @@ type: keyword -- -*`threatintel.threatq.adversaries`*:: +*`threatq.adversaries`*:: + -- Adversaries that are linked to the object @@ -152783,7 +152101,7 @@ type: keyword -- -*`threatintel.threatq.attributes`*:: +*`threatq.attributes`*:: + -- These provide additional context about an object diff --git a/filebeat/docs/filebeat-general-options.asciidoc b/filebeat/docs/filebeat-general-options.asciidoc index fc53057f4c2..d1bcdf2e545 100644 --- a/filebeat/docs/filebeat-general-options.asciidoc +++ b/filebeat/docs/filebeat-general-options.asciidoc @@ -41,14 +41,14 @@ That means in case there are some states where the TTL expired, these are only r The permissions mask to apply on registry data file. The default value is 0600. The permissions option must be a valid Unix-style file permissions mask expressed in octal notation. In Go, numbers in octal notation must start with 0. The most permissive mask allowed is 0640. If a higher permissions mask is -specified via this setting, it will be subject to a umask of 0027. +specified via this setting, it will be subject to an umask of 0027. This option is not supported on Windows. Examples: - 0640: give read and write access to the file owner, and read access to members of the group associated with the file. - 0600: give read and write access to the file owner, and no access to all others. +* 0640: give read and write access to the file owner, and read access to members of the group associated with the file. +* 0600: give read and write access to the file owner, and no access to all others. [source,yaml] ------------------------------------------------------------------------------------- diff --git a/filebeat/docs/filebeat-modules-options.asciidoc b/filebeat/docs/filebeat-modules-options.asciidoc index bf404588c03..8c39c56c9a6 100644 --- a/filebeat/docs/filebeat-modules-options.asciidoc +++ b/filebeat/docs/filebeat-modules-options.asciidoc @@ -1,4 +1,4 @@ -:modulename: system nginx mysql +:modulename: nginx [id="configuration-{beatname_lc}-modules"] == Configure modules diff --git a/filebeat/docs/getting-started.asciidoc b/filebeat/docs/getting-started.asciidoc index d51a267b91f..08f2bc311a5 100644 --- a/filebeat/docs/getting-started.asciidoc +++ b/filebeat/docs/getting-started.asciidoc @@ -1,4 +1,4 @@ -:modulename: system nginx mysql +:modulename: nginx //TODO: Remove release-state override before merging. @@ -20,6 +20,8 @@ You'll learn how to: [role="screenshot"] image::./images/kibana-system.png[{beatname_uc} System dashboard] +//TODO: We should replace this with an nginx dashboard rather than system + [float] === Before you begin @@ -79,14 +81,13 @@ include::{libbeat-dir}/tab-widgets/list-modules-widget.asciidoc[] -- . From the installation directory, enable one or more modules. For example, the -following command enables the `system`, `nginx`, and `mysql` module -configs: +following command enables the +{modulename}+ module config: + -- include::{libbeat-dir}/tab-widgets/enable-modules-widget.asciidoc[] -- -. In the module configs under `modules.d`, enable the desired datasets and +. In the module config under `modules.d`, enable the desired datasets and change the module settings to match your environment. + For example, log locations are set based on the OS. If your logs aren't in diff --git a/filebeat/docs/howto/override-config-settings.asciidoc b/filebeat/docs/howto/override-config-settings.asciidoc index cb69353f00b..63bcbfa784d 100644 --- a/filebeat/docs/howto/override-config-settings.asciidoc +++ b/filebeat/docs/howto/override-config-settings.asciidoc @@ -37,7 +37,7 @@ logging.files: path: /var/log/filebeat name: filebeat keepfiles: 7 - permissions: 0644 + permissions: 0640 ---- To override the logging level and send logging output to standard error instead diff --git a/filebeat/docs/inputs/input-journald.asciidoc b/filebeat/docs/inputs/input-journald.asciidoc index 32343def292..bbc4211b0c5 100644 --- a/filebeat/docs/inputs/input-journald.asciidoc +++ b/filebeat/docs/inputs/input-journald.asciidoc @@ -24,8 +24,8 @@ journal. ---- You may wish to have separate inputs for each service. You can use -`include_matches` to specify a list of filter expressions that are applied as a -logical OR. A good way to list the journald fields that are available for +`include_matches` to specify filtering expressions. +A good way to list the https://www.freedesktop.org/software/systemd/man/systemd.journal-fields.html[journald fields] that are available for filtering messages is to run `journalctl -o json` to output logs and metadata as JSON. This example collects logs from the `vault.service` systemd unit. @@ -34,7 +34,7 @@ JSON. This example collects logs from the `vault.service` systemd unit. {beatname_lc}.inputs: - type: journald id: service-vault - include_matches: + include_matches.match: - _SYSTEMD_UNIT=vault.service ---- @@ -48,7 +48,7 @@ possible. {beatname_lc}.inputs: - type: journald id: iptables - include_matches: + include_matches.match: - _TRANSPORT=kernel processors: - drop_event: @@ -133,14 +133,64 @@ If you have old log files and want to skip lines, start {beatname_uc} with `seek: tail` specified. Then stop {beatname_uc}, set `seek: cursor`, and restart {beatname_uc}. +[float] +[id="{beatname_lc}-input-{type}-units"] +==== `units` + +Iterate only the entries of the units specified in this option. The iterated entries include +messages from the units, messages about the units by authorized daemons and coredumps. However, +it does not match systemd user units. + +[float] +[id="{beatname_lc}-input-{type}-syslog-identifiers"] +==== `syslog_identifiers` + +Read only the entries with the selected syslog identifiers. + +[float] +[id="{beatname_lc}-input-{type}-transports"] +==== `transports` + +Collect the messages using the specified transports. Example: syslog. + +Valid transports: + +* audit: messages from the kernel audit subsystem +* driver: internally generated messages +* syslog: messages received via the local syslog socket with the syslog protocol +* journal: messages received via the native journal protocol +* stdout: messages from a service's standard output or error output +* kernel: messages from the kernel + [float] [id="{beatname_lc}-input-{type}-include-matches"] ==== `include_matches` -A list of filter expressions used to match fields. The format of the expression +A collection of filter expressions used to match fields. The format of the expression is `field=value`. {beatname_uc} fetches all events that exactly match the expressions. Pattern matching is not supported. +If you configured a filter expression, only entries with this field set will be iterated by the journald reader of Filebeat. +If the filter expressions apply to different fields, only entries with all fields set will be iterated. +If they apply to the same fields, only entries where the field takes one of the specified values will be iterated. + +`match`: List of filter expressions to match fields. +`or`: The filter expressions listed under `or` are connected with a disjunction (or). +`and`: The filter expressions listed under `and` are connected with a conjunction (and). + +Please note that these expressions are limited. You can build complex filtering, but full logical +expressions are not supported. + +The following include matches configuration reads all `systemd` syslog entries: + +["source","yaml",subs="attributes"] +---- +include_matches.and: +- match: + - "journald.process.name=systemd" + - "systemd.transport=syslog" +---- + To reference fields, use one of the following: * The field name used by the systemd journal. For example, diff --git a/filebeat/docs/modules/aws.asciidoc b/filebeat/docs/modules/aws.asciidoc index 097e22a741c..65bc668de05 100644 --- a/filebeat/docs/modules/aws.asciidoc +++ b/filebeat/docs/modules/aws.asciidoc @@ -61,6 +61,7 @@ Example config: #var.visibility_timeout: 300s #var.api_timeout: 120s #var.endpoint: amazonaws.com + #var.default_region: us-east-1 #var.role_arn: arn:aws:iam::123456789012:role/test-mb #var.proxy_url: http://proxy:8080 @@ -79,6 +80,7 @@ Example config: #var.visibility_timeout: 300s #var.api_timeout: 120s #var.endpoint: amazonaws.com + #var.default_region: us-east-1 #var.role_arn: arn:aws:iam::123456789012:role/test-mb #var.proxy_url: http://proxy:8080 @@ -97,6 +99,7 @@ Example config: #var.visibility_timeout: 300s #var.api_timeout: 120s #var.endpoint: amazonaws.com + #var.default_region: us-east-1 #var.role_arn: arn:aws:iam::123456789012:role/test-mb #var.proxy_url: http://proxy:8080 @@ -115,6 +118,7 @@ Example config: #var.visibility_timeout: 300s #var.api_timeout: 120s #var.endpoint: amazonaws.com + #var.default_region: us-east-1 #var.role_arn: arn:aws:iam::123456789012:role/test-mb #var.proxy_url: http://proxy:8080 @@ -133,6 +137,7 @@ Example config: #var.visibility_timeout: 300s #var.api_timeout: 120s #var.endpoint: amazonaws.com + #var.default_region: us-east-1 #var.role_arn: arn:aws:iam::123456789012:role/test-mb #var.proxy_url: http://proxy:8080 @@ -151,6 +156,7 @@ Example config: #var.visibility_timeout: 300s #var.api_timeout: 120s #var.endpoint: amazonaws.com + #var.default_region: us-east-1 #var.role_arn: arn:aws:iam::123456789012:role/test-mb #var.proxy_url: http://proxy:8080 ---- @@ -192,6 +198,10 @@ Prefix to apply for the list request to the S3 bucket. Default empty. Custom endpoint used to access AWS APIs. +*`var.default_region`*:: + +Default region to query if no other region is set. + *`var.shared_credential_file`*:: Filename of AWS credential file. diff --git a/filebeat/docs/modules/barracuda.asciidoc b/filebeat/docs/modules/barracuda.asciidoc index fc5529cf059..e1732beb061 100644 --- a/filebeat/docs/modules/barracuda.asciidoc +++ b/filebeat/docs/modules/barracuda.asciidoc @@ -33,7 +33,7 @@ NOTE: This was converted from RSA NetWitness log parser XML "barracudawaf" devic *`var.input`*:: -The input from which messages are read. One of `file`, `tcp` or `udp`. +The input from which messages are read. One of `file`, `tcp` or `udp`. Defaults to `udp`. *`var.syslog_host`*:: @@ -78,7 +78,7 @@ NOTE: This was converted from RSA NetWitness log parser XML "barracudasf" device *`var.input`*:: -The input from which messages are read. One of `file`, `tcp` or `udp`. +The input from which messages are read. One of `file`, `tcp` or `udp`. Defaults to `udp`. *`var.syslog_host`*:: diff --git a/filebeat/docs/modules/bluecoat.asciidoc b/filebeat/docs/modules/bluecoat.asciidoc index b6e1e23e50a..4f7c7e243b5 100644 --- a/filebeat/docs/modules/bluecoat.asciidoc +++ b/filebeat/docs/modules/bluecoat.asciidoc @@ -33,7 +33,7 @@ NOTE: This was converted from RSA NetWitness log parser XML "bluecoatdirector" d *`var.input`*:: -The input from which messages are read. One of `file`, `tcp` or `udp`. +The input from which messages are read. One of `file`, `tcp` or `udp`. Defaults to `udp`. *`var.syslog_host`*:: diff --git a/filebeat/docs/modules/cisco.asciidoc b/filebeat/docs/modules/cisco.asciidoc index e2a0a89acba..ae06741b09e 100644 --- a/filebeat/docs/modules/cisco.asciidoc +++ b/filebeat/docs/modules/cisco.asciidoc @@ -305,7 +305,7 @@ NOTE: This was converted from RSA NetWitness log parser XML "cisconxos" device r *`var.input`*:: -The input from which messages are read. One of `file`, `tcp` or `udp`. +The input from which messages are read. One of `file`, `tcp` or `udp`. Defaults to `udp`. *`var.syslog_host`*:: @@ -350,7 +350,7 @@ NOTE: This was converted from RSA NetWitness log parser XML "ciscomeraki" device *`var.input`*:: -The input from which messages are read. One of `file`, `tcp` or `udp`. +The input from which messages are read. One of `file`, `tcp` or `udp`. Defaults to `udp`. *`var.syslog_host`*:: diff --git a/filebeat/docs/modules/cylance.asciidoc b/filebeat/docs/modules/cylance.asciidoc index 641c369f4e5..3e70754430f 100644 --- a/filebeat/docs/modules/cylance.asciidoc +++ b/filebeat/docs/modules/cylance.asciidoc @@ -33,7 +33,7 @@ NOTE: This was converted from RSA NetWitness log parser XML "cylance" device rev *`var.input`*:: -The input from which messages are read. One of `file`, `tcp` or `udp`. +The input from which messages are read. One of `file`, `tcp` or `udp`. Defaults to `udp`. *`var.syslog_host`*:: diff --git a/filebeat/docs/modules/f5.asciidoc b/filebeat/docs/modules/f5.asciidoc index 5b886f8cae6..611239e2c21 100644 --- a/filebeat/docs/modules/f5.asciidoc +++ b/filebeat/docs/modules/f5.asciidoc @@ -37,7 +37,7 @@ NOTE: This was converted from RSA NetWitness log parser XML "bigipapm" device re *`var.input`*:: -The input from which messages are read. One of `file`, `tcp` or `udp`. +The input from which messages are read. One of `file`, `tcp` or `udp`. Defaults to `udp`. *`var.syslog_host`*:: @@ -82,7 +82,7 @@ NOTE: This was converted from RSA NetWitness log parser XML "bigipafm" device re *`var.input`*:: -The input from which messages are read. One of `file`, `tcp` or `udp`. +The input from which messages are read. One of `file`, `tcp` or `udp`. Defaults to `udp`. *`var.syslog_host`*:: diff --git a/filebeat/docs/modules/fortinet.asciidoc b/filebeat/docs/modules/fortinet.asciidoc index 8a5da7b80f7..9dc8c1e3f26 100644 --- a/filebeat/docs/modules/fortinet.asciidoc +++ b/filebeat/docs/modules/fortinet.asciidoc @@ -85,7 +85,7 @@ NOTE: This was converted from RSA NetWitness log parser XML "forticlientendpoint *`var.input`*:: -The input from which messages are read. One of `file`, `tcp` or `udp`. +The input from which messages are read. One of `file`, `tcp` or `udp`. Defaults to `udp`. *`var.syslog_host`*:: @@ -130,7 +130,7 @@ NOTE: This was converted from RSA NetWitness log parser XML "fortinetfortimail" *`var.input`*:: -The input from which messages are read. One of `file`, `tcp` or `udp`. +The input from which messages are read. One of `file`, `tcp` or `udp`. Defaults to `udp`. *`var.syslog_host`*:: @@ -175,7 +175,7 @@ NOTE: This was converted from RSA NetWitness log parser XML "fortinetmgr" device *`var.input`*:: -The input from which messages are read. One of `file`, `tcp` or `udp`. +The input from which messages are read. One of `file`, `tcp` or `udp`. Defaults to `udp`. *`var.syslog_host`*:: diff --git a/filebeat/docs/modules/imperva.asciidoc b/filebeat/docs/modules/imperva.asciidoc index bdbf16b0bec..480ed29d30d 100644 --- a/filebeat/docs/modules/imperva.asciidoc +++ b/filebeat/docs/modules/imperva.asciidoc @@ -33,7 +33,7 @@ NOTE: This was converted from RSA NetWitness log parser XML "impervawaf" device *`var.input`*:: -The input from which messages are read. One of `file`, `tcp` or `udp`. +The input from which messages are read. One of `file`, `tcp` or `udp`. Defaults to `udp`. *`var.syslog_host`*:: diff --git a/filebeat/docs/modules/infoblox.asciidoc b/filebeat/docs/modules/infoblox.asciidoc index 745a52e0c96..a830d765247 100644 --- a/filebeat/docs/modules/infoblox.asciidoc +++ b/filebeat/docs/modules/infoblox.asciidoc @@ -33,7 +33,7 @@ NOTE: This was converted from RSA NetWitness log parser XML "infobloxnios" devic *`var.input`*:: -The input from which messages are read. One of `file`, `tcp` or `udp`. +The input from which messages are read. One of `file`, `tcp` or `udp`. Defaults to `udp`. *`var.syslog_host`*:: diff --git a/filebeat/docs/modules/juniper.asciidoc b/filebeat/docs/modules/juniper.asciidoc index a97baa17de5..113fe33c513 100644 --- a/filebeat/docs/modules/juniper.asciidoc +++ b/filebeat/docs/modules/juniper.asciidoc @@ -146,7 +146,7 @@ NOTE: This was converted from RSA NetWitness log parser XML "junosrouter" device *`var.input`*:: -The input from which messages are read. One of `file`, `tcp` or `udp`. +The input from which messages are read. One of `file`, `tcp` or `udp`. Defaults to `udp`. *`var.syslog_host`*:: @@ -191,7 +191,7 @@ NOTE: This was converted from RSA NetWitness log parser XML "netscreen" device r *`var.input`*:: -The input from which messages are read. One of `file`, `tcp` or `udp`. +The input from which messages are read. One of `file`, `tcp` or `udp`. Defaults to `udp`. *`var.syslog_host`*:: diff --git a/filebeat/docs/modules/microsoft.asciidoc b/filebeat/docs/modules/microsoft.asciidoc index ff00507119f..7a1170c67d9 100644 --- a/filebeat/docs/modules/microsoft.asciidoc +++ b/filebeat/docs/modules/microsoft.asciidoc @@ -224,7 +224,7 @@ include::../include/var-paths.asciidoc[] *`var.input`*:: -The input from which messages are read. One of `file`, `tcp` or `udp`. +The input from which messages are read. One of `file`, `tcp` or `udp`. Defaults to `udp`. *`var.syslog_host`*:: diff --git a/filebeat/docs/modules/netscout.asciidoc b/filebeat/docs/modules/netscout.asciidoc index a1d4d3dcdd5..13e78e5b116 100644 --- a/filebeat/docs/modules/netscout.asciidoc +++ b/filebeat/docs/modules/netscout.asciidoc @@ -31,7 +31,7 @@ NOTE: This was converted from RSA NetWitness log parser XML "arborpeakflowsp" de *`var.input`*:: -The input from which messages are read. One of `file`, `tcp` or `udp`. +The input from which messages are read. One of `file`, `tcp` or `udp`. Defaults to `udp`. *`var.syslog_host`*:: diff --git a/filebeat/docs/modules/proofpoint.asciidoc b/filebeat/docs/modules/proofpoint.asciidoc index 905288fab3d..b5ebebc6ccd 100644 --- a/filebeat/docs/modules/proofpoint.asciidoc +++ b/filebeat/docs/modules/proofpoint.asciidoc @@ -33,7 +33,7 @@ NOTE: This was converted from RSA NetWitness log parser XML "proofpoint" device *`var.input`*:: -The input from which messages are read. One of `file`, `tcp` or `udp`. +The input from which messages are read. One of `file`, `tcp` or `udp`. Defaults to `udp`. *`var.syslog_host`*:: diff --git a/filebeat/docs/modules/radware.asciidoc b/filebeat/docs/modules/radware.asciidoc index 3d1dbc4dcbc..d76a5b96fe0 100644 --- a/filebeat/docs/modules/radware.asciidoc +++ b/filebeat/docs/modules/radware.asciidoc @@ -33,7 +33,7 @@ NOTE: This was converted from RSA NetWitness log parser XML "radwaredp" device r *`var.input`*:: -The input from which messages are read. One of `file`, `tcp` or `udp`. +The input from which messages are read. One of `file`, `tcp` or `udp`. Defaults to `udp`. *`var.syslog_host`*:: diff --git a/filebeat/docs/modules/snort.asciidoc b/filebeat/docs/modules/snort.asciidoc index ff9d5809ae8..aa6a08f8f26 100644 --- a/filebeat/docs/modules/snort.asciidoc +++ b/filebeat/docs/modules/snort.asciidoc @@ -31,7 +31,7 @@ NOTE: This was converted from RSA NetWitness log parser XML "snort" device revis *`var.input`*:: -The input from which messages are read. One of `file`, `tcp` or `udp`. +The input from which messages are read. One of `file`, `tcp` or `udp`. Defaults to `udp`. *`var.syslog_host`*:: diff --git a/filebeat/docs/modules/sonicwall.asciidoc b/filebeat/docs/modules/sonicwall.asciidoc index a50c6477307..17e953dcfc1 100644 --- a/filebeat/docs/modules/sonicwall.asciidoc +++ b/filebeat/docs/modules/sonicwall.asciidoc @@ -33,7 +33,7 @@ NOTE: This was converted from RSA NetWitness log parser XML "sonicwall" device r *`var.input`*:: -The input from which messages are read. One of `file`, `tcp` or `udp`. +The input from which messages are read. One of `file`, `tcp` or `udp`. Defaults to `udp`. *`var.syslog_host`*:: diff --git a/filebeat/docs/modules/sophos.asciidoc b/filebeat/docs/modules/sophos.asciidoc index 88572fee06a..4e8a2367424 100644 --- a/filebeat/docs/modules/sophos.asciidoc +++ b/filebeat/docs/modules/sophos.asciidoc @@ -156,7 +156,7 @@ NOTE: This was converted from RSA NetWitness log parser XML "astarosg" device re *`var.input`*:: -The input from which messages are read. One of `file`, `tcp` or `udp`. +The input from which messages are read. One of `file`, `tcp` or `udp`. Defaults to `udp`. *`var.syslog_host`*:: diff --git a/filebeat/docs/modules/squid.asciidoc b/filebeat/docs/modules/squid.asciidoc index b72a4412537..4bf202b262a 100644 --- a/filebeat/docs/modules/squid.asciidoc +++ b/filebeat/docs/modules/squid.asciidoc @@ -33,7 +33,7 @@ NOTE: This was converted from RSA NetWitness log parser XML "squid" device revis *`var.input`*:: -The input from which messages are read. One of `file`, `tcp` or `udp`. +The input from which messages are read. One of `file`, `tcp` or `udp`. Defaults to `udp`. *`var.syslog_host`*:: diff --git a/filebeat/docs/modules/threatintel.asciidoc b/filebeat/docs/modules/threatintel.asciidoc index a05384ff446..b8b5b6f950d 100644 --- a/filebeat/docs/modules/threatintel.asciidoc +++ b/filebeat/docs/modules/threatintel.asciidoc @@ -17,7 +17,7 @@ https://www.elastic.co/guide/en/security/current/rules-ui-create.html#create-ind Match rules], but is also compatible with other features like https://www.elastic.co/guide/en/elasticsearch/reference/current/enrich-processor.html[Enrich Processors]. The related threat intel attribute that is meant to be used for -matching incoming source data is stored under the `threatintel.indicator.*` +matching incoming source data is stored under the `threat.indicator.*` fields. The available filesets are: @@ -73,9 +73,9 @@ Abuse.ch URL Threat Intel is mapped to the following ECS fields. [options="header"] |============================================================== | URL Threat Intel Fields | ECS Fields -| url | threatintel.indicator.url.full +| url | threat.indicator.url.full | date_added | @timestamp -| host | threatintel.indicator.ip/domain +| host | threat.indicator.ip/domain |============================================================== [[abusemalware]] @@ -117,9 +117,9 @@ Abuse.ch Malware Threat Intel is mapped to the following ECS fields. [options="header"] |================================================================ | Malware Threat IntelFields | ECS Fields -| md5_hash | threatintel.indicator.file.hash.md5 -| sha256_hash | threatintel.indicator.file.hash.sha256 -| file_size | threatintel.indicator.file.size +| md5_hash | threat.indicator.file.hash.md5 +| sha256_hash | threat.indicator.file.hash.sha256 +| file_size | threat.indicator.file.size |================================================================ [[malwarebazaar]] @@ -161,24 +161,25 @@ Malware Bazaar Threat Intel is mapped to the following ECS fields. [options="header"] |================================================================ | Malware Threat IntelFields | ECS Fields -| md5_hash | threatintel.indicator.file.hash.md5 -| sha256_hash | threatintel.indicator.file.hash.sha256 -| tlsh | threatintel.indicator.file.hash.tlsh -| ssdeep | threatintel.indicator.file.hash.ssdeep -| imphash | threatintel.indicator.file.pe.imphash -| file_size | threatintel.indicator.file.size -| file_name | threatintel.indicator.file.name -| file_type_mime | threatintel.indicator.file.mime_type -| file_type | threatintel.indicator.file.type -| reporter | threatintel.indicator.provider -| origin_country | threatintel.indicator.geo.country_iso_code -| signature | threatintel.indicator.signature -| code_sign.subject_cn | threatintel.indicator.file.x509.subject.common_name -| code_sign.issuer_cn | threatintel.indicator.file.x509.issuer.common_name -| code_sign.algorithm | threatintel.indicator.file.x509.public_key_algorithm -| code_sign.valid_from | threatintel.indicator.file.x509.not_before -| code_sign.valid_to | threatintel.indicator.file.x509.not_after -| code_sign.serial_number | threatintel.indicator.file.x509.serial_number +| md5_hash | threat.indicator.file.hash.md5 +| sha256_hash | threat.indicator.file.hash.sha256 +| sha384_hash | threat.indicator.file.hash.sha384 +| tlsh | threat.indicator.file.hash.tlsh +| ssdeep | threat.indicator.file.hash.ssdeep +| imphash | threat.indicator.file.pe.imphash +| file_size | threat.indicator.file.size +| file_name | threat.indicator.file.name +| file_type_mime | threat.indicator.file.mime_type +| file_type | threat.indicator.file.type +| reporter | threat.indicator.provider +| origin_country | threat.indicator.geo.country_iso_code +| signature | threat.indicator.signature +| code_sign.subject_cn | threat.indicator.file.x509.subject.common_name +| code_sign.issuer_cn | threat.indicator.file.x509.issuer.common_name +| code_sign.algorithm | threat.indicator.file.x509.public_key_algorithm +| code_sign.valid_from | threat.indicator.file.x509.not_before +| code_sign.valid_to | threat.indicator.file.x509.not_after +| code_sign.serial_number | threat.indicator.file.x509.serial_number |================================================================ [[misp]] @@ -255,10 +256,10 @@ MISP Threat Intel is mapped to the following ECS fields. [options="header"] |============================================================== | Malware Threat IntelFields | ECS Fields -| misp.first_seen | threatintel.indicator.first_seen -| misp.last_seen | threatintel.indicator.last_seen +| misp.first_seen | threat.indicator.first_seen +| misp.last_seen | threat.indicator.last_seen | misp.tag | tag -| misp.value | threatintel.indicator.* +| misp.value | threat.indicator.* |============================================================== `misp.value` is mapped to the appropriate field dependent on attribute type. @@ -336,9 +337,9 @@ OTX Threat Intel is mapped to the following ECS fields. [options="header"] |============================================================ | Malware Threat Intel Fields | ECS Fields -| otx.type | threatintel.indicator.type -| otx.description | threatintel.indicator.description -| otx.indicator | threatintel.indicator.* +| otx.type | threat.indicator.type +| otx.description | threat.indicator.description +| otx.indicator | threat.indicator.* |============================================================ `otx.indicator` is mapped to the appropriate field dependent on attribute type. @@ -420,10 +421,10 @@ Anomali Threat Intel is mapped to the following ECS fields. [options="header"] |============================================================= | Malware Threat Intel Fields | ECS Fields -| anomali.description | threatintel.indicator.description -| anomali.created | threatintel.indicator.first_seen -| anomali.modified | threatintel.indicator.last_seen -| anomali.pattern | threatintel.indicator.* +| anomali.description | threat.indicator.description +| anomali.created | threat.indicator.first_seen +| anomali.modified | threat.indicator.last_seen +| anomali.pattern | threat.indicator.* | anomali.labels | tags |============================================================= @@ -491,24 +492,24 @@ Anomali ThreatStream fields are mapped to the following ECS fields: [options="header"] |============================================================= | ThreatStream fields | ECS Fields -| asn | threatintel.indicator.as.number -| classification<> | threatintel.indicator.marking.tlp -| confidence<> | threatintel.indicator.confidence -| country | threatintel.indicator.geo.country_iso_code -| date_first | threatintel.indicator.first_seen -| date_last | threatintel.indicator.last_seen +| asn | threat.indicator.as.number +| classification<> | threat.indicator.marking.tlp +| confidence<> | threat.indicator.confidence +| country | threat.indicator.geo.country_iso_code +| date_first | threat.indicator.first_seen +| date_last | threat.indicator.last_seen | detail | tags -| domain | threatintel.indicator.url.domain -| email | threatintel.indicator.email.address -| itype<> | threatintel.indicator.type -| lat | threatintel.indicator.geo.location.lat -| lon | threatintel.indicator.geo.location.lon -| md5 | threatintel.indicator.file.hash -| org | threatintel.indicator.as.organization.name +| domain | threat.indicator.url.domain +| email | threat.indicator.email.address +| itype<> | threat.indicator.type +| lat | threat.indicator.geo.location.lat +| lon | threat.indicator.geo.location.lon +| md5 | threat.indicator.file.hash +| org | threat.indicator.as.organization.name | severity<> | event.severity -| source | threatintel.indicator.provider -| srcip | threatintel.indicator.ip -| url | threatintel.indicator.url.original +| source | threat.indicator.provider +| srcip | threat.indicator.ip +| url | threat.indicator.url.original |============================================================= [[a]] @@ -590,16 +591,16 @@ Recorded Future fields are mapped to the following ECS fields: [options="header"] |============================================================= | Recorded Future fields | ECS Fields -| entity.name | threatintel.indicator.{url,ip,domain,file.hash} -| entity.type | threatintel.indicator.type -| fileHashes | threatintel.indicator.file.hash +| entity.name | threat.indicator.{url,ip,domain,file.hash} +| entity.type | threat.indicator.type +| fileHashes | threat.indicator.file.hash | intelCard | event.reference -| location.asn | threatintel.indicator.as.number -| location.location | threatintel.indicator.geo -| location.organization | threatintel.indicator.as.organization.name +| location.asn | threat.indicator.as.number +| location.location | threat.indicator.geo +| location.organization | threat.indicator.as.organization.name | risk.score | event.risk_score -| timestamps.firstSeen | threatintel.indicator.first_seen -| timestamps.lastSeen | threatintel.indicator.last_seen +| timestamps.firstSeen | threat.indicator.first_seen +| timestamps.lastSeen | threat.indicator.last_seen |============================================================= :has-dashboards!: @@ -707,11 +708,11 @@ Recorded Future fields are mapped to the following ECS fields: [options="header"] |============================================================= | ThreatQ fields | ECS Fields -| type.name | threatintel.indicator.type -| description | threatintel.indicator.description -| score | threatintel.indicator.confidence -| value | threatintel.indicator.{url,ip,domain,file.hash} -| sources | threatintel.indicator.provider +| type.name | threat.indicator.type +| description | threat.indicator.description +| score | threat.indicator.confidence +| value | threat.indicator.{url,ip,domain,file.hash} +| sources | threat.indicator.provider |============================================================= :has-dashboards!: diff --git a/filebeat/docs/modules/tomcat.asciidoc b/filebeat/docs/modules/tomcat.asciidoc index 7f80711b1c4..f3057c08be8 100644 --- a/filebeat/docs/modules/tomcat.asciidoc +++ b/filebeat/docs/modules/tomcat.asciidoc @@ -33,7 +33,7 @@ NOTE: This was converted from RSA NetWitness log parser XML "apachetomcat" devic *`var.input`*:: -The input from which messages are read. One of `file`, `tcp` or `udp`. +The input from which messages are read. One of `file`, `tcp` or `udp`. Defaults to `udp`. *`var.paths`*:: diff --git a/filebeat/docs/modules/zscaler.asciidoc b/filebeat/docs/modules/zscaler.asciidoc index 3586f16d6d1..0a09654200d 100644 --- a/filebeat/docs/modules/zscaler.asciidoc +++ b/filebeat/docs/modules/zscaler.asciidoc @@ -33,7 +33,7 @@ NOTE: This was converted from RSA NetWitness log parser XML "zscalernss" device *`var.input`*:: -The input from which messages are read. One of `file`, `tcp` or `udp`. +The input from which messages are read. One of `file`, `tcp` or `udp`. Defaults to `udp`. *`var.syslog_host`*:: diff --git a/filebeat/filebeat.reference.yml b/filebeat/filebeat.reference.yml index dc7250e402c..87a50f91a08 100644 --- a/filebeat/filebeat.reference.yml +++ b/filebeat/filebeat.reference.yml @@ -501,7 +501,8 @@ filebeat.inputs: #max_bytes: 10485760 # Characters which separate the lines. Valid values: auto, line_feed, vertical_tab, form_feed, - # carriage_return, carriage_return_line_feed, next_line, line_separator, paragraph_separator. + # carriage_return, carriage_return_line_feed, next_line, line_separator, paragraph_separator, + # null_terminator #line_terminator: auto ### Recursive glob configuration @@ -755,7 +756,8 @@ filebeat.inputs: #message_max_bytes: 10485760 # Characters which separate the lines. Valid values: auto, line_feed, vertical_tab, form_feed, - # carriage_return, carriage_return_line_feed, next_line, line_separator, paragraph_separator. + # carriage_return, carriage_return_line_feed, next_line, line_separator, paragraph_separator, + # null_terminator #line_terminator: auto # The ingest pipeline ID associated with this input. If this is set, it @@ -964,6 +966,36 @@ filebeat.inputs: # Configure stream to filter to a specific stream: stdout, stderr or all (default) #stream: all +#------------------------------ Journald input -------------------------------- +# Journald input is experimental. +#- type: journald + #enabled: true + #id: service-foo + + # You may wish to have separate inputs for each service. You can use + # include_matches.or to specify a list of filter expressions that are + # applied as a logical OR. You may specify filter + #include_matches.or: + #- equals: + #- _SYSTEMD_UNIT=foo.service + + # List of syslog identifiers + #syslog_identifiers: ["audit"] + + # Collect events from the service and messages about the service, + # including coredumps. + #units: ["docker.service"] + + # The list of transports (_TRANSPORT field of journald entries) + #transports: ["audit"] + + # Parsers are also supported, here is an example of the multiline + # parser. + #parsers: + #- multiline: + #type: count + #count_lines: 3 + # =========================== Filebeat autodiscover ============================ @@ -1024,7 +1056,7 @@ filebeat.inputs: #reload.enabled: true #reload.period: 10s #modules: - #enabled: false + #enabled: true #path: modules.d/*.yml #reload.enabled: true #reload.period: 10s @@ -1109,66 +1141,6 @@ filebeat.inputs: # length of its retry interval each time, up to this maximum. #max_retry_interval: 30s - # The spool queue will store events in a local spool file, before - # forwarding the events to the outputs. - # Note: the spool queue is deprecated and will be removed in the future. - # Use the disk queue instead. - # - # The spool file is a circular buffer, which blocks once the file/buffer is full. - # Events are put into a write buffer and flushed once the write buffer - # is full or the flush_timeout is triggered. - # Once ACKed by the output, events are removed immediately from the queue, - # making space for new events to be persisted. - #spool: - # The file namespace configures the file path and the file creation settings. - # Once the file exists, the `size`, `page_size` and `prealloc` settings - # will have no more effect. - #file: - # Location of spool file. The default value is ${path.data}/spool.dat. - #path: "${path.data}/spool.dat" - - # Configure file permissions if file is created. The default value is 0600. - #permissions: 0600 - - # File size hint. The spool blocks, once this limit is reached. The default value is 100 MiB. - #size: 100MiB - - # The files page size. A file is split into multiple pages of the same size. The default value is 4KiB. - #page_size: 4KiB - - # If prealloc is set, the required space for the file is reserved using - # truncate. The default value is true. - #prealloc: true - - # Spool writer settings - # Events are serialized into a write buffer. The write buffer is flushed if: - # - The buffer limit has been reached. - # - The configured limit of buffered events is reached. - # - The flush timeout is triggered. - #write: - # Sets the write buffer size. - #buffer_size: 1MiB - - # Maximum duration after which events are flushed if the write buffer - # is not full yet. The default value is 1s. - #flush.timeout: 1s - - # Number of maximum buffered events. The write buffer is flushed once the - # limit is reached. - #flush.events: 16384 - - # Configure the on-disk event encoding. The encoding can be changed - # between restarts. - # Valid encodings are: json, ubjson, and cbor. - #codec: cbor - #read: - # Reader flush timeout, waiting for more events to become available, so - # to fill a complete batch as required by the outputs. - # If flush_timeout is 0, all available events are forwarded to the - # outputs immediately. - # The default value is 0s. - #flush.timeout: 0s - # Sets the maximum number of CPUs that can be executing simultaneously. The # default is the number of logical CPUs available in the system. #max_procs: @@ -1485,6 +1457,13 @@ output.elasticsearch: # The pin is a base64 encoded string of the SHA-256 fingerprint. #ssl.ca_sha256: "" + # A root CA HEX encoded fingerprint. During the SSL handshake if the + # fingerprint matches the root CA certificate, it will be added to + # the provided list of root CAs (`certificate_authorities`), if the + # list is empty or not defined, the matching certificate will be the + # only one in the list. Then the normal SSL validation happens. + #ssl.ca_trusted_fingerprint: "" + # Enable Kerberos support. Kerberos is automatically enabled if any Kerberos setting is set. #kerberos.enabled: true @@ -1617,6 +1596,13 @@ output.elasticsearch: # The pin is a base64 encoded string of the SHA-256 fingerprint. #ssl.ca_sha256: "" + # A root CA HEX encoded fingerprint. During the SSL handshake if the + # fingerprint matches the root CA certificate, it will be added to + # the provided list of root CAs (`certificate_authorities`), if the + # list is empty or not defined, the matching certificate will be the + # only one in the list. Then the normal SSL validation happens. + #ssl.ca_trusted_fingerprint: "" + # The number of times to retry publishing an event after a publishing failure. # After the specified number of retries, the events are typically dropped. # Some Beats, such as Filebeat and Winlogbeat, ignore the max_retries setting @@ -1818,6 +1804,13 @@ output.elasticsearch: # The pin is a base64 encoded string of the SHA-256 fingerprint. #ssl.ca_sha256: "" + # A root CA HEX encoded fingerprint. During the SSL handshake if the + # fingerprint matches the root CA certificate, it will be added to + # the provided list of root CAs (`certificate_authorities`), if the + # list is empty or not defined, the matching certificate will be the + # only one in the list. Then the normal SSL validation happens. + #ssl.ca_trusted_fingerprint: "" + # Enable Kerberos support. Kerberos is automatically enabled if any Kerberos setting is set. #kerberos.enabled: true @@ -1982,6 +1975,13 @@ output.elasticsearch: # The pin is a base64 encoded string of the SHA-256 fingerprint. #ssl.ca_sha256: "" + # A root CA HEX encoded fingerprint. During the SSL handshake if the + # fingerprint matches the root CA certificate, it will be added to + # the provided list of root CAs (`certificate_authorities`), if the + # list is empty or not defined, the matching certificate will be the + # only one in the list. Then the normal SSL validation happens. + #ssl.ca_trusted_fingerprint: "" + # -------------------------------- File Output --------------------------------- #output.file: @@ -2001,7 +2001,7 @@ output.elasticsearch: #path: "/tmp/filebeat" # Name of the generated files. The default is `filebeat` and it generates - # files: `filebeat`, `filebeat.1`, `filebeat.2`, etc. + # files: `filebeat-{datetime}.ndjson`, `filebeat-{datetime}-1.ndjson`, etc. #filename: filebeat # Maximum size in kilobytes of each file. When this size is reached, and on @@ -2019,6 +2019,7 @@ output.elasticsearch: # Configure automatic file rotation on every startup. The default is true. #rotate_on_startup: true + # ------------------------------- Console Output ------------------------------- #output.console: # Boolean flag to enable or disable the output module. @@ -2117,19 +2118,13 @@ output.elasticsearch: # Set to false to disable template loading. #setup.template.enabled: true -# Select the kind of index template. From Elasticsearch 7.8, it is possible to -# use component templates. Available options: legacy, component, index. -# By default filebeat uses the legacy index templates. -#setup.template.type: legacy - # Template name. By default the template name is "filebeat-%{[agent.version]}" # The template name and pattern has to be set in case the Elasticsearch index pattern is modified. #setup.template.name: "filebeat-%{[agent.version]}" -# Template pattern. By default the template pattern is "-%{[agent.version]}-*" to apply to the default index settings. -# The first part is the version of the beat and then -* is used to match all daily indices. +# Template pattern. By default the template pattern is "filebeat-%{[agent.version]}" to apply to the default index settings. # The template name and pattern has to be set in case the Elasticsearch index pattern is modified. -#setup.template.pattern: "filebeat-%{[agent.version]}-*" +#setup.template.pattern: "filebeat-%{[agent.version]}" # Path to fields.yml file to generate the template #setup.template.fields: "${path.config}/fields.yml" @@ -2176,17 +2171,8 @@ setup.template.settings: # output.elasticsearch.index is ignored, and the write alias is used to set the # index name. -# Enable ILM support. Valid values are true, false, and auto. When set to auto -# (the default), the Beat uses index lifecycle management when it connects to a -# cluster that supports ILM; otherwise, it creates daily indices. -#setup.ilm.enabled: auto - -# Set the prefix used in the index lifecycle write alias name. The default alias -# name is 'filebeat-%{[agent.version]}'. -#setup.ilm.rollover_alias: 'filebeat' - -# Set the rollover index pattern. The default is "%{now/d}-000001". -#setup.ilm.pattern: "{now/d}-000001" +# Enable ILM support. Valid values are true, false. +#setup.ilm.enabled: true # Set the lifecycle policy name. The default policy name is # 'beatname'. @@ -2284,6 +2270,13 @@ setup.kibana: # The pin is a base64 encoded string of the SHA-256 fingerprint. #ssl.ca_sha256: "" + # A root CA HEX encoded fingerprint. During the SSL handshake if the + # fingerprint matches the root CA certificate, it will be added to + # the provided list of root CAs (`certificate_authorities`), if the + # list is empty or not defined, the matching certificate will be the + # only one in the list. Then the normal SSL validation happens. + #ssl.ca_trusted_fingerprint: "" + # ================================== Logging =================================== @@ -2355,11 +2348,6 @@ logging.files: # file. Defaults to true. # rotateonstartup: true - # Rotated files are either suffixed with a number e.g. filebeat.1 when - # renamed during rotation. Or when set to date, the date is added to - # the end of the file. On rotation a new file is created, older files are untouched. - #suffix: count - # ============================= X-Pack Monitoring ============================== # Filebeat can export internal metrics to a central Elasticsearch monitoring # cluster. This requires xpack monitoring to be enabled in Elasticsearch. The @@ -2487,6 +2475,13 @@ logging.files: # The pin is a base64 encoded string of the SHA-256 fingerprint. #ssl.ca_sha256: "" + # A root CA HEX encoded fingerprint. During the SSL handshake if the + # fingerprint matches the root CA certificate, it will be added to + # the provided list of root CAs (`certificate_authorities`), if the + # list is empty or not defined, the matching certificate will be the + # only one in the list. Then the normal SSL validation happens. + #ssl.ca_trusted_fingerprint: "" + # Enable Kerberos support. Kerberos is automatically enabled if any Kerberos setting is set. #kerberos.enabled: true diff --git a/filebeat/fileset/compatibility.go b/filebeat/fileset/compatibility.go index 8a38e6158cc..63631e86b88 100644 --- a/filebeat/fileset/compatibility.go +++ b/filebeat/fileset/compatibility.go @@ -211,7 +211,7 @@ func (p *Processor) String() string { // adaptPipelineForCompatibility iterates over all processors in the pipeline // and adapts them for version of Elasticsearch used. Adapt can mean modifying // processor options or removing the processor. -func adaptPipelineForCompatibility(esVersion common.Version, pipelineID string, content map[string]interface{}, log *logp.Logger) (err error) { +func AdaptPipelineForCompatibility(esVersion common.Version, pipelineID string, content map[string]interface{}, log *logp.Logger) (err error) { log = log.With("pipeline_id", pipelineID) // Adapt the main processors in the pipeline. if err = adaptProcessorsForCompatibility(esVersion, content, "processors", false, log); err != nil { diff --git a/filebeat/fileset/compatibility_test.go b/filebeat/fileset/compatibility_test.go index 82e584b046f..79b10eb263d 100644 --- a/filebeat/fileset/compatibility_test.go +++ b/filebeat/fileset/compatibility_test.go @@ -128,7 +128,7 @@ func TestAdaptPipelineForCompatibility(t *testing.T) { test := test t.Run(test.name, func(t *testing.T) { t.Parallel() - err := adaptPipelineForCompatibility(*test.esVersion, "foo-pipeline", test.content, logp.NewLogger(logName)) + err := AdaptPipelineForCompatibility(*test.esVersion, "foo-pipeline", test.content, logp.NewLogger(logName)) if test.isErrExpected { assert.Error(t, err) } else { @@ -305,7 +305,7 @@ func TestReplaceSetIgnoreEmptyValue(t *testing.T) { test := test t.Run(test.name, func(t *testing.T) { t.Parallel() - err := adaptPipelineForCompatibility(*test.esVersion, "foo-pipeline", test.content, logp.NewLogger(logName)) + err := AdaptPipelineForCompatibility(*test.esVersion, "foo-pipeline", test.content, logp.NewLogger(logName)) if test.isErrExpected { assert.Error(t, err) } else { @@ -507,7 +507,7 @@ func TestReplaceAppendAllowDuplicates(t *testing.T) { test := test t.Run(test.name, func(t *testing.T) { t.Parallel() - err := adaptPipelineForCompatibility(*test.esVersion, "foo-pipeline", test.content, logp.NewLogger(logName)) + err := AdaptPipelineForCompatibility(*test.esVersion, "foo-pipeline", test.content, logp.NewLogger(logName)) if test.isErrExpected { assert.Error(t, err) } else { @@ -632,7 +632,7 @@ func TestRemoveURIPartsProcessor(t *testing.T) { test := test t.Run(test.name, func(t *testing.T) { t.Parallel() - err := adaptPipelineForCompatibility(*test.esVersion, "foo-pipeline", test.content, logp.NewLogger(logName)) + err := AdaptPipelineForCompatibility(*test.esVersion, "foo-pipeline", test.content, logp.NewLogger(logName)) if test.isErrExpected { assert.Error(t, err) } else { @@ -767,7 +767,7 @@ func TestRemoveNetworkDirectionProcessor(t *testing.T) { test := test t.Run(test.name, func(t *testing.T) { t.Parallel() - err := adaptPipelineForCompatibility(*test.esVersion, "foo-pipeline", test.content, logp.NewLogger(logName)) + err := AdaptPipelineForCompatibility(*test.esVersion, "foo-pipeline", test.content, logp.NewLogger(logName)) if test.isErrExpected { assert.Error(t, err) } else { @@ -950,7 +950,7 @@ func TestReplaceConvertIPWithGrok(t *testing.T) { test := test t.Run(test.name, func(t *testing.T) { t.Parallel() - err := adaptPipelineForCompatibility(*test.esVersion, "foo-pipeline", test.content, logp.NewLogger(logName)) + err := AdaptPipelineForCompatibility(*test.esVersion, "foo-pipeline", test.content, logp.NewLogger(logName)) if test.isErrExpected { assert.Error(t, err) } else { @@ -1070,7 +1070,7 @@ func TestRemoveRegisteredDomainProcessor(t *testing.T) { test := test t.Run(test.name, func(t *testing.T) { t.Parallel() - err := adaptPipelineForCompatibility(*test.esVersion, "foo-pipeline", test.content, logp.NewLogger(logName)) + err := AdaptPipelineForCompatibility(*test.esVersion, "foo-pipeline", test.content, logp.NewLogger(logName)) if test.isErrExpected { assert.Error(t, err) } else { @@ -1331,7 +1331,7 @@ func TestReplaceAlternativeFlowProcessors(t *testing.T) { test := test t.Run(test.name, func(t *testing.T) { t.Parallel() - err := adaptPipelineForCompatibility(*test.esVersion, "foo-pipeline", test.content, logp.NewLogger(logName)) + err := AdaptPipelineForCompatibility(*test.esVersion, "foo-pipeline", test.content, logp.NewLogger(logName)) if test.isErrExpected { assert.Error(t, err) } else { @@ -1446,7 +1446,7 @@ func TestRemoveDescription(t *testing.T) { test := test t.Run(test.name, func(t *testing.T) { t.Parallel() - err := adaptPipelineForCompatibility(*test.esVersion, "foo-pipeline", test.content, logp.NewLogger(logName)) + err := AdaptPipelineForCompatibility(*test.esVersion, "foo-pipeline", test.content, logp.NewLogger(logName)) if test.isErrExpected { assert.Error(t, err) } else { diff --git a/filebeat/fileset/fileset.go b/filebeat/fileset/fileset.go index 09a2738bb17..dae801738f9 100644 --- a/filebeat/fileset/fileset.go +++ b/filebeat/fileset/fileset.go @@ -237,13 +237,13 @@ func (fs *Fileset) turnOffElasticsearchVars(vars map[string]interface{}, esVersi func resolveVariable(vars map[string]interface{}, value interface{}) (interface{}, error) { switch v := value.(type) { case string: - return applyTemplate(vars, v, false) + return ApplyTemplate(vars, v, false) case []interface{}: transformed := []interface{}{} for _, val := range v { s, ok := val.(string) if ok { - transf, err := applyTemplate(vars, s, false) + transf, err := ApplyTemplate(vars, s, false) if err != nil { return nil, fmt.Errorf("array: %v", err) } @@ -257,10 +257,10 @@ func resolveVariable(vars map[string]interface{}, value interface{}) (interface{ return value, nil } -// applyTemplate applies a Golang text/template. If specialDelims is set to true, +// ApplyTemplate applies a Golang text/template. If specialDelims is set to true, // the delimiters are set to `{<` and `>}` instead of `{{` and `}}`. These are easier to use // in pipeline definitions. -func applyTemplate(vars map[string]interface{}, templateString string, specialDelims bool) (string, error) { +func ApplyTemplate(vars map[string]interface{}, templateString string, specialDelims bool) (string, error) { tpl := template.New("text").Option("missingkey=error") if specialDelims { tpl = tpl.Delims("{<", ">}") @@ -307,7 +307,7 @@ func getTemplateFunctions(vars map[string]interface{}) (template.FuncMap, error) return buf.String(), err }, "IngestPipeline": func(shortID string) string { - return formatPipelineID( + return FormatPipelineID( builtinVars["prefix"].(string), builtinVars["module"].(string), builtinVars["fileset"].(string), @@ -343,7 +343,7 @@ func (fs *Fileset) getBuiltinVars(info beat.Info) (map[string]interface{}, error } func (fs *Fileset) getInputConfig() (*common.Config, error) { - path, err := applyTemplate(fs.vars, fs.manifest.Input, false) + path, err := ApplyTemplate(fs.vars, fs.manifest.Input, false) if err != nil { return nil, fmt.Errorf("Error expanding vars on the input path: %v", err) } @@ -352,7 +352,7 @@ func (fs *Fileset) getInputConfig() (*common.Config, error) { return nil, fmt.Errorf("Error reading input file %s: %v", path, err) } - yaml, err := applyTemplate(fs.vars, string(contents), false) + yaml, err := ApplyTemplate(fs.vars, string(contents), false) if err != nil { return nil, fmt.Errorf("Error interpreting the template of the input: %v", err) } @@ -409,12 +409,12 @@ func (fs *Fileset) getInputConfig() (*common.Config, error) { func (fs *Fileset) getPipelineIDs(info beat.Info) ([]string, error) { var pipelineIDs []string for _, ingestPipeline := range fs.manifest.IngestPipeline { - path, err := applyTemplate(fs.vars, ingestPipeline, false) + path, err := ApplyTemplate(fs.vars, ingestPipeline, false) if err != nil { return nil, fmt.Errorf("Error expanding vars on the ingest pipeline path: %v", err) } - pipelineIDs = append(pipelineIDs, formatPipelineID(info.IndexPrefix, fs.mcfg.Module, fs.name, path, info.Version)) + pipelineIDs = append(pipelineIDs, FormatPipelineID(info.IndexPrefix, fs.mcfg.Module, fs.name, path, info.Version)) } return pipelineIDs, nil @@ -428,7 +428,7 @@ func (fs *Fileset) GetPipelines(esVersion common.Version) (pipelines []pipeline, } for idx, ingestPipeline := range fs.manifest.IngestPipeline { - path, err := applyTemplate(fs.vars, ingestPipeline, false) + path, err := ApplyTemplate(fs.vars, ingestPipeline, false) if err != nil { return nil, fmt.Errorf("Error expanding vars on the ingest pipeline path: %v", err) } @@ -438,7 +438,7 @@ func (fs *Fileset) GetPipelines(esVersion common.Version) (pipelines []pipeline, return nil, fmt.Errorf("Error reading pipeline file %s: %v", path, err) } - encodedString, err := applyTemplate(vars, string(strContents), true) + encodedString, err := ApplyTemplate(vars, string(strContents), true) if err != nil { return nil, fmt.Errorf("Error interpreting the template of the ingest pipeline: %v", err) } @@ -453,7 +453,7 @@ func (fs *Fileset) GetPipelines(esVersion common.Version) (pipelines []pipeline, if err = yaml.Unmarshal([]byte(encodedString), &content); err != nil { return nil, fmt.Errorf("Error YAML decoding the pipeline file: %s: %v", path, err) } - newContent, err := fixYAMLMaps(content) + newContent, err := FixYAMLMaps(content) if err != nil { return nil, fmt.Errorf("Failed to sanitize the YAML pipeline file: %s: %v", path, err) } @@ -474,11 +474,11 @@ func (fs *Fileset) GetPipelines(esVersion common.Version) (pipelines []pipeline, return pipelines, nil } -// This function recursively converts maps with interface{} keys, as returned by +// FixYAMLMaps recursively converts maps with interface{} keys, as returned by // yaml.Unmarshal, to maps of string keys, as expected by the json encoder // that will be used when delivering the pipeline to Elasticsearch. // Will return an error when something other than a string is used as a key. -func fixYAMLMaps(elem interface{}) (_ interface{}, err error) { +func FixYAMLMaps(elem interface{}) (_ interface{}, err error) { switch v := elem.(type) { case map[interface{}]interface{}: result := make(map[string]interface{}, len(v)) @@ -487,20 +487,20 @@ func fixYAMLMaps(elem interface{}) (_ interface{}, err error) { if !ok { return nil, fmt.Errorf("key '%v' is not string but %T", key, key) } - if result[keyS], err = fixYAMLMaps(value); err != nil { + if result[keyS], err = FixYAMLMaps(value); err != nil { return nil, err } } return result, nil case map[string]interface{}: for key, value := range v { - if v[key], err = fixYAMLMaps(value); err != nil { + if v[key], err = FixYAMLMaps(value); err != nil { return nil, err } } case []interface{}: for idx, value := range v { - if v[idx], err = fixYAMLMaps(value); err != nil { + if v[idx], err = FixYAMLMaps(value); err != nil { return nil, err } } @@ -508,8 +508,11 @@ func fixYAMLMaps(elem interface{}) (_ interface{}, err error) { return elem, nil } -// formatPipelineID generates the ID to be used for the pipeline ID in Elasticsearch -func formatPipelineID(prefix, module, fileset, path, version string) string { +// FormatPipelineID generates the ID to be used for the pipeline ID in Elasticsearch +func FormatPipelineID(prefix, module, fileset, path, version string) string { + if module == "" && fileset == "" { + return fmt.Sprintf("%s-%s-%s", prefix, version, removeExt(filepath.Base(path))) + } return fmt.Sprintf("%s-%s-%s-%s-%s", prefix, version, module, fileset, removeExt(filepath.Base(path))) } diff --git a/filebeat/fileset/modules_integration_test.go b/filebeat/fileset/modules_integration_test.go index 6b9e86cac84..f17be7c8d73 100644 --- a/filebeat/fileset/modules_integration_test.go +++ b/filebeat/fileset/modules_integration_test.go @@ -62,7 +62,7 @@ func TestLoadPipeline(t *testing.T) { } log := logp.NewLogger(logName) - err := loadPipeline(client, "my-pipeline-id", content, false, log) + err := LoadPipeline(client, "my-pipeline-id", content, false, log) require.NoError(t, err) status, _, err := client.Request("GET", "/_ingest/pipeline/my-pipeline-id", "", nil, nil) @@ -71,12 +71,12 @@ func TestLoadPipeline(t *testing.T) { // loading again shouldn't actually update the pipeline content["description"] = "describe pipeline 2" - err = loadPipeline(client, "my-pipeline-id", content, false, log) + err = LoadPipeline(client, "my-pipeline-id", content, false, log) require.NoError(t, err) checkUploadedPipeline(t, client, "describe pipeline") // loading again updates the pipeline - err = loadPipeline(client, "my-pipeline-id", content, true, log) + err = LoadPipeline(client, "my-pipeline-id", content, true, log) require.NoError(t, err) checkUploadedPipeline(t, client, "describe pipeline 2") } diff --git a/filebeat/fileset/pipelines.go b/filebeat/fileset/pipelines.go index a3ce0b3de42..c93825ad09e 100644 --- a/filebeat/fileset/pipelines.go +++ b/filebeat/fileset/pipelines.go @@ -86,7 +86,7 @@ func (reg *ModuleRegistry) LoadPipelines(esClient PipelineLoader, overwrite bool var pipelineIDsLoaded []string for _, pipeline := range pipelines { - err = loadPipeline(esClient, pipeline.id, pipeline.contents, overwrite, reg.log.With("pipeline", pipeline.id)) + err = LoadPipeline(esClient, pipeline.id, pipeline.contents, overwrite, reg.log.With("pipeline", pipeline.id)) if err != nil { err = fmt.Errorf("error loading pipeline for fileset %s/%s: %v", module, name, err) break @@ -100,7 +100,7 @@ func (reg *ModuleRegistry) LoadPipelines(esClient PipelineLoader, overwrite bool // error, validate all pipelines before loading any of them. This requires https://github.com/elastic/elasticsearch/issues/35495. errs := multierror.Errors{err} for _, pipelineID := range pipelineIDsLoaded { - err = deletePipeline(esClient, pipelineID) + err = DeletePipeline(esClient, pipelineID) if err != nil { errs = append(errs, err) } @@ -112,7 +112,7 @@ func (reg *ModuleRegistry) LoadPipelines(esClient PipelineLoader, overwrite bool return nil } -func loadPipeline(esClient PipelineLoader, pipelineID string, content map[string]interface{}, overwrite bool, log *logp.Logger) error { +func LoadPipeline(esClient PipelineLoader, pipelineID string, content map[string]interface{}, overwrite bool, log *logp.Logger) error { path := makeIngestPipelinePath(pipelineID) if !overwrite { status, _, _ := esClient.Request("GET", path, "", nil, nil) @@ -122,7 +122,7 @@ func loadPipeline(esClient PipelineLoader, pipelineID string, content map[string } } - if err := adaptPipelineForCompatibility(esClient.GetVersion(), pipelineID, content, log); err != nil { + if err := AdaptPipelineForCompatibility(esClient.GetVersion(), pipelineID, content, log); err != nil { return fmt.Errorf("failed to adapt pipeline with backwards compatibility changes: %w", err) } @@ -134,7 +134,7 @@ func loadPipeline(esClient PipelineLoader, pipelineID string, content map[string return nil } -func deletePipeline(esClient PipelineLoader, pipelineID string) error { +func DeletePipeline(esClient PipelineLoader, pipelineID string) error { path := makeIngestPipelinePath(pipelineID) _, _, err := esClient.Request("DELETE", path, "", nil, nil) return err diff --git a/filebeat/include/fields.go b/filebeat/include/fields.go index 71cfa106bc2..920a6dc8e7e 100644 --- a/filebeat/include/fields.go +++ b/filebeat/include/fields.go @@ -32,5 +32,5 @@ func init() { // AssetFieldsYml returns asset data. // This is the base64 encoded zlib format compressed contents of fields.yml. func AssetFieldsYml() string { - return "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" + return "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" } diff --git a/filebeat/input/filestream/input.go b/filebeat/input/filestream/input.go index c1ba829d65f..654938869af 100644 --- a/filebeat/input/filestream/input.go +++ b/filebeat/input/filestream/input.go @@ -29,6 +29,7 @@ import ( input "github.com/elastic/beats/v7/filebeat/input/v2" "github.com/elastic/beats/v7/libbeat/common" "github.com/elastic/beats/v7/libbeat/common/cleanup" + "github.com/elastic/beats/v7/libbeat/common/file" "github.com/elastic/beats/v7/libbeat/common/match" "github.com/elastic/beats/v7/libbeat/feature" "github.com/elastic/beats/v7/libbeat/logp" @@ -244,7 +245,7 @@ func (inp *filestream) openFile(log *logp.Logger, path string, offset int64) (*o } ok := false - f, err := os.OpenFile(path, os.O_RDONLY, os.FileMode(0)) + f, err := file.ReadOpen(path) if err != nil { return nil, fmt.Errorf("failed opening %s: %s", path, err) } diff --git a/filebeat/input/journald/config.go b/filebeat/input/journald/config.go index 6704dabfc02..4e1c0b66da4 100644 --- a/filebeat/input/journald/config.go +++ b/filebeat/input/journald/config.go @@ -24,8 +24,9 @@ import ( "errors" "time" - "github.com/elastic/beats/v7/journalbeat/pkg/journalfield" - "github.com/elastic/beats/v7/journalbeat/pkg/journalread" + "github.com/elastic/beats/v7/filebeat/input/journald/pkg/journalfield" + "github.com/elastic/beats/v7/filebeat/input/journald/pkg/journalread" + "github.com/elastic/beats/v7/libbeat/reader/parser" ) // Config stores the options of a journald input. @@ -47,10 +48,22 @@ type config struct { CursorSeekFallback journalread.SeekMode `config:"cursor_seek_fallback"` // Matches store the key value pairs to match entries. - Matches []journalfield.Matcher `config:"include_matches"` + Matches journalfield.IncludeMatches `config:"include_matches"` + + // Units stores the units to monitor. + Units []string `config:"units"` + + // Transports stores the list of transports to include in the messages. + Transports []string `config:"transports"` + + // Identifiers stores the syslog identifiers to watch. + Identifiers []string `config:"syslog_identifiers"` // SaveRemoteHostname defines if the original source of the entry needs to be saved. SaveRemoteHostname bool `config:"save_remote_hostname"` + + // Parsers configuration + Parsers parser.Config `config:",inline"` } var errInvalidSeekFallback = errors.New("invalid setting for cursor_seek_fallback") diff --git a/filebeat/input/journald/conv.go b/filebeat/input/journald/conv.go index a9785cf49f6..a1bf52f3000 100644 --- a/filebeat/input/journald/conv.go +++ b/filebeat/input/journald/conv.go @@ -23,7 +23,7 @@ package journald import ( "time" - "github.com/elastic/beats/v7/journalbeat/pkg/journalfield" + "github.com/elastic/beats/v7/filebeat/input/journald/pkg/journalfield" "github.com/elastic/beats/v7/libbeat/beat" "github.com/elastic/beats/v7/libbeat/logp" ) diff --git a/filebeat/input/journald/environment_test.go b/filebeat/input/journald/environment_test.go new file mode 100644 index 00000000000..5c05759b2c2 --- /dev/null +++ b/filebeat/input/journald/environment_test.go @@ -0,0 +1,286 @@ +// Licensed to Elasticsearch B.V. under one or more contributor +// license agreements. See the NOTICE file distributed with +// this work for additional information regarding copyright +// ownership. Elasticsearch B.V. licenses this file to you 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. + +//go:build linux && cgo && withjournald +// +build linux,cgo,withjournald + +package journald + +import ( + "context" + "fmt" + "os" + "path/filepath" + "sync" + "testing" + "time" + + input "github.com/elastic/beats/v7/filebeat/input/v2" + v2 "github.com/elastic/beats/v7/filebeat/input/v2" + "github.com/elastic/beats/v7/libbeat/beat" + "github.com/elastic/beats/v7/libbeat/common" + "github.com/elastic/beats/v7/libbeat/common/acker" + "github.com/elastic/beats/v7/libbeat/logp" + "github.com/elastic/beats/v7/libbeat/statestore" + "github.com/elastic/beats/v7/libbeat/statestore/storetest" + "github.com/elastic/go-concert/unison" +) + +type inputTestingEnvironment struct { + t *testing.T + workingDir string + stateStore *testInputStore + pipeline *mockPipelineConnector + + pluginInitOnce sync.Once + plugin v2.Plugin + + wg sync.WaitGroup + grp unison.TaskGroup +} + +func newInputTestingEnvironment(t *testing.T) *inputTestingEnvironment { + return &inputTestingEnvironment{ + t: t, + workingDir: t.TempDir(), + stateStore: openTestStatestore(), + pipeline: &mockPipelineConnector{}, + } +} + +func (e *inputTestingEnvironment) getManager() v2.InputManager { + e.pluginInitOnce.Do(func() { + e.plugin = Plugin(logp.L(), e.stateStore) + }) + return e.plugin.Manager +} + +func (e *inputTestingEnvironment) mustCreateInput(config map[string]interface{}) v2.Input { + e.t.Helper() + e.grp = unison.TaskGroup{} + manager := e.getManager() + if err := manager.Init(&e.grp, v2.ModeRun); err != nil { + e.t.Fatalf("failed to initialise manager: %+v", err) + } + + c := common.MustNewConfigFrom(config) + inp, err := manager.Create(c) + if err != nil { + e.t.Fatalf("failed to create input using manager: %+v", err) + } + + return inp +} + +func (e *inputTestingEnvironment) startInput(ctx context.Context, inp v2.Input) { + e.wg.Add(1) + go func(wg *sync.WaitGroup, grp *unison.TaskGroup) { + defer wg.Done() + defer grp.Stop() + + inputCtx := input.Context{Logger: logp.L(), Cancelation: ctx} + inp.Run(inputCtx, e.pipeline) + }(&e.wg, &e.grp) +} + +// waitUntilEventCount waits until total count events arrive to the client. +func (e *inputTestingEnvironment) waitUntilEventCount(count int) { + e.t.Helper() + for { + sum := len(e.pipeline.GetAllEvents()) + if sum == count { + return + } + if count < sum { + e.t.Fatalf("too many events; expected: %d, actual: %d", count, sum) + } + time.Sleep(10 * time.Millisecond) + } +} + +func (e *inputTestingEnvironment) waitUntilInputStops() { + e.wg.Wait() +} + +func (e *inputTestingEnvironment) abspath(filename string) string { + return filepath.Join(e.workingDir, filename) +} + +func (e *inputTestingEnvironment) mustWriteFile(filename string, lines []byte) { + e.t.Helper() + path := e.abspath(filename) + if err := os.WriteFile(path, lines, 0644); err != nil { + e.t.Fatalf("failed to write file '%s': %+v", path, err) + } +} + +type testInputStore struct { + registry *statestore.Registry +} + +func openTestStatestore() *testInputStore { + return &testInputStore{ + registry: statestore.NewRegistry(storetest.NewMemoryStoreBackend()), + } +} + +func (s *testInputStore) Close() { + s.registry.Close() +} + +func (s *testInputStore) Access() (*statestore.Store, error) { + return s.registry.Get("filebeat") +} + +func (s *testInputStore) CleanupInterval() time.Duration { + return 24 * time.Hour +} + +type mockClient struct { + publishing []beat.Event + published []beat.Event + ackHandler beat.ACKer + closed bool + mtx sync.Mutex + canceler context.CancelFunc +} + +// GetEvents returns the published events +func (c *mockClient) GetEvents() []beat.Event { + c.mtx.Lock() + defer c.mtx.Unlock() + + return c.published +} + +// Publish mocks the Client Publish method +func (c *mockClient) Publish(e beat.Event) { + c.PublishAll([]beat.Event{e}) +} + +// PublishAll mocks the Client PublishAll method +func (c *mockClient) PublishAll(events []beat.Event) { + c.mtx.Lock() + defer c.mtx.Unlock() + + c.publishing = append(c.publishing, events...) + for _, event := range events { + c.ackHandler.AddEvent(event, true) + } + c.ackHandler.ACKEvents(len(events)) + + for _, event := range events { + c.published = append(c.published, event) + } +} + +func (c *mockClient) waitUntilPublishingHasStarted() { + for len(c.publishing) == 0 { + time.Sleep(10 * time.Millisecond) + } +} + +// Close mocks the Client Close method +func (c *mockClient) Close() error { + c.mtx.Lock() + defer c.mtx.Unlock() + + if c.closed { + return fmt.Errorf("mock client already closed") + } + + c.closed = true + return nil +} + +// mockPipelineConnector mocks the PipelineConnector interface +type mockPipelineConnector struct { + blocking bool + clients []*mockClient + mtx sync.Mutex +} + +// GetAllEvents returns all events associated with a pipeline +func (pc *mockPipelineConnector) GetAllEvents() []beat.Event { + pc.mtx.Lock() + defer pc.mtx.Unlock() + + var evList []beat.Event + for _, clientEvents := range pc.clients { + evList = append(evList, clientEvents.GetEvents()...) + } + + return evList +} + +// Connect mocks the PipelineConnector Connect method +func (pc *mockPipelineConnector) Connect() (beat.Client, error) { + return pc.ConnectWith(beat.ClientConfig{}) +} + +// ConnectWith mocks the PipelineConnector ConnectWith method +func (pc *mockPipelineConnector) ConnectWith(config beat.ClientConfig) (beat.Client, error) { + pc.mtx.Lock() + defer pc.mtx.Unlock() + + ctx, cancel := context.WithCancel(context.Background()) + c := &mockClient{ + canceler: cancel, + ackHandler: newMockACKHandler(ctx, pc.blocking, config), + } + + pc.clients = append(pc.clients, c) + + return c, nil + +} + +func (pc *mockPipelineConnector) cancelAllClients() { + pc.mtx.Lock() + defer pc.mtx.Unlock() + + for _, client := range pc.clients { + client.canceler() + } +} + +func (pc *mockPipelineConnector) cancelClient(i int) { + pc.mtx.Lock() + defer pc.mtx.Unlock() + + if len(pc.clients) < i+1 { + return + } + + pc.clients[i].canceler() +} + +func newMockACKHandler(starter context.Context, blocking bool, config beat.ClientConfig) beat.ACKer { + if !blocking { + return config.ACKHandler + } + + return acker.Combine(blockingACKer(starter), config.ACKHandler) + +} + +func blockingACKer(starter context.Context) beat.ACKer { + return acker.EventPrivateReporter(func(acked int, private []interface{}) { + for starter.Err() == nil { + } + }) +} diff --git a/filebeat/input/journald/input.go b/filebeat/input/journald/input.go index 74bd0983d23..41b6c649f90 100644 --- a/filebeat/input/journald/input.go +++ b/filebeat/input/journald/input.go @@ -26,14 +26,16 @@ import ( "github.com/coreos/go-systemd/v22/sdjournal" "github.com/urso/sderr" + "github.com/elastic/beats/v7/filebeat/input/journald/pkg/journalfield" + "github.com/elastic/beats/v7/filebeat/input/journald/pkg/journalread" input "github.com/elastic/beats/v7/filebeat/input/v2" cursor "github.com/elastic/beats/v7/filebeat/input/v2/input-cursor" - "github.com/elastic/beats/v7/journalbeat/pkg/journalfield" - "github.com/elastic/beats/v7/journalbeat/pkg/journalread" "github.com/elastic/beats/v7/libbeat/common" "github.com/elastic/beats/v7/libbeat/common/backoff" "github.com/elastic/beats/v7/libbeat/feature" "github.com/elastic/beats/v7/libbeat/logp" + "github.com/elastic/beats/v7/libbeat/reader" + "github.com/elastic/beats/v7/libbeat/reader/parser" ) type journald struct { @@ -41,8 +43,12 @@ type journald struct { MaxBackoff time.Duration Seek journalread.SeekMode CursorSeekFallback journalread.SeekMode - Matches []journalfield.Matcher + Matches journalfield.IncludeMatches + Units []string + Transports []string + Identifiers []string SaveRemoteHostname bool + Parsers parser.Config } type checkpoint struct { @@ -102,7 +108,11 @@ func configure(cfg *common.Config) ([]cursor.Source, cursor.Input, error) { Seek: config.Seek, CursorSeekFallback: config.CursorSeekFallback, Matches: config.Matches, + Units: config.Units, + Transports: config.Transports, + Identifiers: config.Identifiers, SaveRemoteHostname: config.SaveRemoteHostname, + Parsers: config.Parsers, }, nil } @@ -123,7 +133,7 @@ func (inp *journald) Run( publisher cursor.Publisher, ) error { log := ctx.Logger.With("path", src.Name()) - checkpoint := initCheckpoint(log, cursor) + currentCheckpoint := initCheckpoint(log, cursor) reader, err := inp.open(ctx.Logger, ctx.Cancelation, src) if err != nil { @@ -131,23 +141,20 @@ func (inp *journald) Run( } defer reader.Close() - if err := reader.Seek(seekBy(ctx.Logger, checkpoint, inp.Seek, inp.CursorSeekFallback)); err != nil { + if err := reader.Seek(seekBy(ctx.Logger, currentCheckpoint, inp.Seek, inp.CursorSeekFallback)); err != nil { log.Error("Continue from current position. Seek failed with: %v", err) } + parser := inp.Parsers.Create(&readerAdapter{r: reader, canceler: ctx.Cancelation}) + for { - entry, err := reader.Next(ctx.Cancelation) + entry, err := parser.Next() if err != nil { return err } - event := eventFromFields(ctx.Logger, entry.RealtimeTimestamp, entry.Fields, inp.SaveRemoteHostname) - - checkpoint.Position = entry.Cursor - checkpoint.RealtimeTimestamp = entry.RealtimeTimestamp - checkpoint.MonotonicTimestamp = entry.MonotonicTimestamp - - if err := publisher.Publish(event, checkpoint); err != nil { + event := entry.ToEvent() + if err := publisher.Publish(event, event.Private); err != nil { return err } } @@ -155,7 +162,8 @@ func (inp *journald) Run( func (inp *journald) open(log *logp.Logger, canceler input.Canceler, src cursor.Source) (*journalread.Reader, error) { backoff := backoff.NewExpBackoff(canceler.Done(), inp.Backoff, inp.MaxBackoff) - reader, err := journalread.Open(log, src.Name(), backoff, withFilters(inp.Matches)) + reader, err := journalread.Open(log, src.Name(), backoff, + withFilters(inp.Matches), withUnits(inp.Units), withTransports(inp.Transports), withSyslogIdentifiers(inp.Identifiers)) if err != nil { return nil, sderr.Wrap(err, "failed to create reader for %{path} journal", src.Name()) } @@ -183,9 +191,27 @@ func initCheckpoint(log *logp.Logger, c cursor.Cursor) checkpoint { return cp } -func withFilters(filters []journalfield.Matcher) func(*sdjournal.Journal) error { +func withFilters(filters journalfield.IncludeMatches) func(*sdjournal.Journal) error { + return func(j *sdjournal.Journal) error { + return journalfield.ApplyIncludeMatches(j, filters) + } +} + +func withUnits(units []string) func(*sdjournal.Journal) error { + return func(j *sdjournal.Journal) error { + return journalfield.ApplyUnitMatchers(j, units) + } +} + +func withTransports(transports []string) func(*sdjournal.Journal) error { + return func(j *sdjournal.Journal) error { + return journalfield.ApplyTransportMatcher(j, transports) + } +} + +func withSyslogIdentifiers(identifiers []string) func(*sdjournal.Journal) error { return func(j *sdjournal.Journal) error { - return journalfield.ApplyMatchersOr(j, filters) + return journalfield.ApplySyslogIdentifierMatcher(j, identifiers) } } @@ -204,3 +230,44 @@ func seekBy(log *logp.Logger, cp checkpoint, seek, defaultSeek journalread.SeekM } return mode, cp.Position } + +// readerAdapter is an adapter so journalread.Reader can +// behave like reader.Reader +type readerAdapter struct { + r *journalread.Reader + canceler input.Canceler +} + +func (r *readerAdapter) Close() error { + return r.r.Close() +} + +func (r *readerAdapter) Next() (reader.Message, error) { + data, err := r.r.Next(r.canceler) + if err != nil { + return reader.Message{}, err + } + + content := []byte(data.Fields["MESSAGE"]) + delete(data.Fields, "MESSAGE") + + fields := make(map[string]interface{}, len(data.Fields)) + for k, v := range data.Fields { + fields[k] = v + } + + m := reader.Message{ + Ts: time.UnixMicro(int64(data.RealtimeTimestamp)), + Content: content, + Bytes: len(content), + Fields: fields, + Private: checkpoint{ + Version: cursorVersion, + RealtimeTimestamp: data.RealtimeTimestamp, + MonotonicTimestamp: data.MonotonicTimestamp, + Position: data.Cursor, + }, + } + + return m, nil +} diff --git a/filebeat/input/journald/input_filtering_test.go b/filebeat/input/journald/input_filtering_test.go new file mode 100644 index 00000000000..75718b3e586 --- /dev/null +++ b/filebeat/input/journald/input_filtering_test.go @@ -0,0 +1,219 @@ +// Licensed to Elasticsearch B.V. under one or more contributor +// license agreements. See the NOTICE file distributed with +// this work for additional information regarding copyright +// ownership. Elasticsearch B.V. licenses this file to you 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. + +//go:build linux && cgo && withjournald +// +build linux,cgo,withjournald + +package journald + +import ( + "context" + "path" + "testing" + + "github.com/elastic/beats/v7/libbeat/common" +) + +func TestInputSyslogIdentifier(t *testing.T) { + tests := map[string]struct { + identifiers []string + expectedMessages []string + }{ + "one identifier": { + identifiers: []string{"sudo"}, + expectedMessages: []string{ + "pam_unix(sudo:session): session closed for user root", + }, + }, + "two identifiers": { + identifiers: []string{"sudo", "systemd"}, + expectedMessages: []string{ + "pam_unix(sudo:session): session closed for user root", + "Started Outputs some log lines.", + }, + }, + } + + for name, testCase := range tests { + t.Run(name, func(t *testing.T) { + env := newInputTestingEnvironment(t) + inp := env.mustCreateInput(common.MapStr{ + "paths": []string{path.Join("testdata", "input-multiline-parser.journal")}, + "syslog_identifiers": testCase.identifiers, + }) + + ctx, cancelInput := context.WithCancel(context.Background()) + env.startInput(ctx, inp) + defer cancelInput() + + env.waitUntilEventCount(len(testCase.expectedMessages)) + + for idx, event := range env.pipeline.clients[0].GetEvents() { + if got, expected := event.Fields["message"], testCase.expectedMessages[idx]; got != expected { + t.Fatalf("expecting event message %q, got %q", expected, got) + } + } + }) + } +} + +func TestInputUnits(t *testing.T) { + tests := map[string]struct { + units []string + kernel bool + expectedMessages []string + }{ + "one unit": { + units: []string{"session-1.scope"}, + kernel: true, + expectedMessages: []string{ + "pam_unix(sudo:session): session closed for user root", + }, + }, + "one unit with kernel": { + units: []string{"session-1.scope"}, + expectedMessages: []string{ + "pam_unix(sudo:session): session closed for user root", + }, + }, + "two units, all messages": { + units: []string{"session-1.scope", "user@1000.service"}, + expectedMessages: []string{ + "pam_unix(sudo:session): session closed for user root", + "Started Outputs some log lines.", + "1st line", + "2nd line", + "3rd line", + "4th line", + "5th line", + "6th line", + }, + }, + } + + for name, testCase := range tests { + t.Run(name, func(t *testing.T) { + env := newInputTestingEnvironment(t) + inp := env.mustCreateInput(common.MapStr{ + "paths": []string{path.Join("testdata", "input-multiline-parser.journal")}, + "units": testCase.units, + "kernel": testCase.kernel, + }) + + ctx, cancelInput := context.WithCancel(context.Background()) + env.startInput(ctx, inp) + defer cancelInput() + + env.waitUntilEventCount(len(testCase.expectedMessages)) + + for idx, event := range env.pipeline.clients[0].GetEvents() { + if got, expected := event.Fields["message"], testCase.expectedMessages[idx]; got != expected { + t.Fatalf("expecting event message %q, got %q", expected, got) + } + } + }) + } +} + +func TestInputIncludeMatches(t *testing.T) { + tests := map[string]struct { + includeMatches map[string]interface{} + expectedMessages []string + }{ + "single match condition": { + includeMatches: map[string]interface{}{ + "match": []string{ + "syslog.facility=3", + }, + }, + expectedMessages: []string{ + "Started Outputs some log lines.", + "1st line", + "2nd line", + "3rd line", + "4th line", + "5th line", + "6th line", + }, + }, + "multiple match condition": { + includeMatches: map[string]interface{}{ + "match": []string{ + "journald.process.name=systemd", + "syslog.facility=3", + }, + }, + expectedMessages: []string{ + "Started Outputs some log lines.", + }, + }, + "and condition": { + includeMatches: map[string]interface{}{ + "and": []map[string]interface{}{ + map[string]interface{}{ + "match": []string{ + "syslog.facility=3", + "message=6th line", + }, + }, + }, + }, + expectedMessages: []string{ + "6th line", + }, + }, + "or condition": { + includeMatches: map[string]interface{}{ + "or": []map[string]interface{}{ + map[string]interface{}{ + "match": []string{ + "message=5th line", + "message=6th line", + }, + }, + }, + }, + expectedMessages: []string{ + "5th line", + "6th line", + }, + }, + } + + for name, testCase := range tests { + t.Run(name, func(t *testing.T) { + env := newInputTestingEnvironment(t) + inp := env.mustCreateInput(common.MapStr{ + "paths": []string{path.Join("testdata", "input-multiline-parser.journal")}, + "include_matches": testCase.includeMatches, + }) + + ctx, cancelInput := context.WithCancel(context.Background()) + env.startInput(ctx, inp) + defer cancelInput() + + env.waitUntilEventCount(len(testCase.expectedMessages)) + + for idx, event := range env.pipeline.clients[0].GetEvents() { + if got, expected := event.Fields["message"], testCase.expectedMessages[idx]; got != expected { + t.Fatalf("expecting event message %q, got %q", expected, got) + } + } + }) + } + +} diff --git a/filebeat/input/journald/input_parsers_test.go b/filebeat/input/journald/input_parsers_test.go new file mode 100644 index 00000000000..3c6d1ad5780 --- /dev/null +++ b/filebeat/input/journald/input_parsers_test.go @@ -0,0 +1,62 @@ +// Licensed to Elasticsearch B.V. under one or more contributor +// license agreements. See the NOTICE file distributed with +// this work for additional information regarding copyright +// ownership. Elasticsearch B.V. licenses this file to you 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. + +//go:build linux && cgo && withjournald +// +build linux,cgo,withjournald + +package journald + +import ( + "context" + "path" + "testing" + + "github.com/elastic/beats/v7/libbeat/common" +) + +// TestInputParsers ensures journald input support parsers, +// it only tests a single parser, but that is enough to ensure +// we're correctly using the parsers +func TestInputParsers(t *testing.T) { + inputParsersExpected := []string{"1st line\n2nd line\n3rd line", "4th line\n5th line\n6th line"} + env := newInputTestingEnvironment(t) + + inp := env.mustCreateInput(common.MapStr{ + "paths": []string{path.Join("testdata", "input-multiline-parser.journal")}, + "include_matches.match": []string{"_SYSTEMD_USER_UNIT=log-service.service"}, + "parsers": []common.MapStr{ + { + "multiline": common.MapStr{ + "type": "count", + "count_lines": 3, + }, + }, + }, + }) + + ctx, cancelInput := context.WithCancel(context.Background()) + env.startInput(ctx, inp) + env.waitUntilEventCount(len(inputParsersExpected)) + + for idx, event := range env.pipeline.clients[0].GetEvents() { + if got, expected := event.Fields["message"], inputParsersExpected[idx]; got != expected { + t.Errorf("expecting event message %q, got %q", expected, got) + } + } + + cancelInput() +} diff --git a/journalbeat/pkg/journalfield/conv.go b/filebeat/input/journald/pkg/journalfield/conv.go similarity index 100% rename from journalbeat/pkg/journalfield/conv.go rename to filebeat/input/journald/pkg/journalfield/conv.go diff --git a/journalbeat/pkg/journalfield/conv_test.go b/filebeat/input/journald/pkg/journalfield/conv_test.go similarity index 100% rename from journalbeat/pkg/journalfield/conv_test.go rename to filebeat/input/journald/pkg/journalfield/conv_test.go diff --git a/journalbeat/pkg/journalfield/default.go b/filebeat/input/journald/pkg/journalfield/default.go similarity index 97% rename from journalbeat/pkg/journalfield/default.go rename to filebeat/input/journald/pkg/journalfield/default.go index 7573eb4156d..a72df0ce5c0 100644 --- a/journalbeat/pkg/journalfield/default.go +++ b/filebeat/input/journald/pkg/journalfield/default.go @@ -46,6 +46,7 @@ var journaldEventFields = FieldConversion{ "_UDEV_DEVLINK": text("journald.kernel.device_symlinks"), "_UDEV_DEVNODE": text("journald.kernel.device_node_path"), "_UDEV_SYSNAME": text("journald.kernel.device_name"), + "UNIT": text("journald.unit"), sdjournal.SD_JOURNAL_FIELD_AUDIT_LOGINUID: integer("journald.audit.login_uid"), sdjournal.SD_JOURNAL_FIELD_AUDIT_SESSION: text("journald.audit.session"), sdjournal.SD_JOURNAL_FIELD_BOOT_ID: text("journald.host.boot_id"), @@ -60,6 +61,7 @@ var journaldEventFields = FieldConversion{ sdjournal.SD_JOURNAL_FIELD_HOSTNAME: text("host.hostname"), sdjournal.SD_JOURNAL_FIELD_MACHINE_ID: text("host.id"), sdjournal.SD_JOURNAL_FIELD_MESSAGE: text("message"), + sdjournal.SD_JOURNAL_FIELD_MESSAGE_ID: text("message_id"), sdjournal.SD_JOURNAL_FIELD_PID: integer("journald.pid"), sdjournal.SD_JOURNAL_FIELD_PRIORITY: integer("syslog.priority", "log.syslog.priority"), sdjournal.SD_JOURNAL_FIELD_SYSLOG_FACILITY: integer("syslog.facility", "log.syslog.facility.code"), diff --git a/journalbeat/pkg/journalfield/default_other.go b/filebeat/input/journald/pkg/journalfield/default_other.go similarity index 100% rename from journalbeat/pkg/journalfield/default_other.go rename to filebeat/input/journald/pkg/journalfield/default_other.go diff --git a/filebeat/input/journald/pkg/journalfield/matcher.go b/filebeat/input/journald/pkg/journalfield/matcher.go new file mode 100644 index 00000000000..49d4e98fe1a --- /dev/null +++ b/filebeat/input/journald/pkg/journalfield/matcher.go @@ -0,0 +1,264 @@ +// Licensed to Elasticsearch B.V. under one or more contributor +// license agreements. See the NOTICE file distributed with +// this work for additional information regarding copyright +// ownership. Elasticsearch B.V. licenses this file to you 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 journalfield + +import ( + "fmt" + "strings" +) + +// Matcher is a single field condition for filtering journal entries. +// +// The Matcher type can be used as is with Beats configuration unpacking. The +// internal default conversion table will be used, similar to BuildMatcher. +type Matcher struct { + str string +} + +// MatcherBuilder can be used to create a custom builder for creating matchers +// based on a conversion table. +type MatcherBuilder struct { + Conversions map[string]Conversion +} + +// IncludeMatches stores the advanced matching configuratio +// provided by the user. +type IncludeMatches struct { + Matches []Matcher `config:"match"` + AND []IncludeMatches `config:"and"` + OR []IncludeMatches `config:"or"` +} + +type journal interface { + AddMatch(string) error + AddDisjunction() error + AddConjunction() error +} + +var ( + defaultBuilder = MatcherBuilder{Conversions: journaldEventFields} + coreDumpMsgID = MustBuildMatcher("message_id=fc2e22bc6ee647b6b90729ab34a250b1") // matcher for messages from coredumps + journaldUID = MustBuildMatcher("journald.uid=0") // matcher for messages from root (UID 0) + journaldPID = MustBuildMatcher("journald.pid=1") // matcher for messages from init process (PID 1) +) + +// Build creates a new Matcher using the configured conversion table. +// If no table has been configured the internal default table will be used. +func (b MatcherBuilder) Build(in string) (Matcher, error) { + elems := strings.Split(in, "=") + if len(elems) != 2 { + return Matcher{}, fmt.Errorf("invalid match format: %s", in) + } + + conversions := b.Conversions + if conversions == nil { + conversions = journaldEventFields + } + + for journalKey, eventField := range conversions { + for _, name := range eventField.Names { + if elems[0] == name { + return Matcher{journalKey + "=" + elems[1]}, nil + } + } + } + + // pass custom fields as is + return Matcher{in}, nil +} + +// BuildMatcher creates a Matcher from a field filter string. +func BuildMatcher(in string) (Matcher, error) { + return defaultBuilder.Build(in) +} + +func MustBuildMatcher(in string) Matcher { + m, err := BuildMatcher(in) + if err != nil { + panic(err) + } + return m +} + +// IsValid returns true if the matcher was initialized correctly. +func (m Matcher) IsValid() bool { return m.str != "" } + +// String returns the string representation of the field match. +func (m Matcher) String() string { return m.str } + +// Apply adds the field match to an open journal for filtering. +func (m Matcher) Apply(j journal) error { + if !m.IsValid() { + return fmt.Errorf("can not apply invalid matcher to a journal") + } + + err := j.AddMatch(m.str) + if err != nil { + return fmt.Errorf("error adding match '%s' to journal: %v", m.str, err) + } + return nil +} + +// Unpack initializes the Matcher from a given string representation. Unpack +// fails if the input string is invalid. +// Unpack can be used with Beats configuration loading. +func (m *Matcher) Unpack(value string) error { + tmp, err := BuildMatcher(value) + if err != nil { + return err + } + *m = tmp + return nil +} + +// ApplyMatchersOr adds a list of matchers to a journal, calling AddDisjunction after each matcher being added. +func ApplyMatchersOr(j journal, matchers []Matcher) error { + for _, m := range matchers { + if err := m.Apply(j); err != nil { + return err + } + + if err := j.AddDisjunction(); err != nil { + return fmt.Errorf("error adding disjunction to journal: %v", err) + } + } + + return nil +} + +// ApplyUnitMatchers adds unit based filtering to the journal reader. +// Filtering is similar to what systemd does here: +// https://github.com/systemd/systemd/blob/641e2124de6047e6010cd2925ea22fba29b25309/src/shared/logs-show.c#L1409-L1455 +func ApplyUnitMatchers(j journal, units []string) error { + for _, unit := range units { + systemdUnit, err := BuildMatcher("systemd.unit=" + unit) + if err != nil { + return fmt.Errorf("failed to build matcher for _SYSTEMD_UNIT: %+w", err) + } + coredumpUnit, err := BuildMatcher("journald.coredump.unit=" + unit) + if err != nil { + return fmt.Errorf("failed to build matcher for COREDUMP_UNIT: %+w", err) + } + journaldUnit, err := BuildMatcher("journald.unit=" + unit) + if err != nil { + return fmt.Errorf("failed to build matcher for UNIT: %+w", err) + } + journaldObjectUnit, err := BuildMatcher("journald.object.systemd.unit=" + unit) + if err != nil { + return fmt.Errorf("failed to build matcher for OBJECT_SYSTEMD_UNIT: %+w", err) + } + + matchers := [][]Matcher{ + // match for the messages of the service + []Matcher{ + systemdUnit, + }, + // match for the coredumps of the service + []Matcher{ + coreDumpMsgID, + journaldUID, + coredumpUnit, + }, + // match for messages about the service with PID value of 1 + []Matcher{ + journaldPID, + journaldUnit, + }, + // match for messages about the service from authorized daemons + []Matcher{ + journaldUID, + journaldObjectUnit, + }, + } + if strings.HasSuffix(unit, ".slice") { + if sliceMatcher, err := BuildMatcher("systemd.slice=" + unit); err != nil { + matchers = append(matchers, []Matcher{sliceMatcher}) + } + } + + for _, m := range matchers { + if err := ApplyMatchersOr(j, m); err != nil { + return fmt.Errorf("error while setting up unit matcher for %s: %+v", unit, err) + } + } + + } + + return nil + +} + +// ApplyTransportMatcher adds matchers for the configured transports. +func ApplyTransportMatcher(j journal, transports []string) error { + if len(transports) == 0 { + return nil + } + + transportMatchers := make([]Matcher, len(transports)) + for i, transport := range transports { + transportMatcher, err := BuildMatcher("_TRANSPORT=" + transport) + if err != nil { + return err + } + transportMatchers[i] = transportMatcher + } + if err := ApplyMatchersOr(j, transportMatchers); err != nil { + return fmt.Errorf("error while adding %+v transport to matchers: %+v", transports, err) + } + return nil + +} + +// ApplySyslogIdentifierMatcher adds syslog identifier filtering to the journal reader. +func ApplySyslogIdentifierMatcher(j journal, identifiers []string) error { + identifierMatchers := make([]Matcher, len(identifiers)) + for i, identifier := range identifiers { + identifierMatchers[i] = MustBuildMatcher("syslog.identifier=" + identifier) + } + + return ApplyMatchersOr(j, identifierMatchers) +} + +// ApplyIncludeMatches adds advanced filtering to journals. +func ApplyIncludeMatches(j journal, m IncludeMatches) error { + for _, or := range m.OR { + if err := ApplyIncludeMatches(j, or); err != nil { + return err + } + if err := j.AddDisjunction(); err != nil { + return fmt.Errorf("error adding disjunction to journal: %v", err) + } + } + + for _, and := range m.AND { + if err := ApplyIncludeMatches(j, and); err != nil { + return err + } + if err := j.AddConjunction(); err != nil { + return fmt.Errorf("error adding conjunction to journal: %v", err) + } + } + + for _, match := range m.Matches { + if err := match.Apply(j); err != nil { + return fmt.Errorf("failed to apply %s expression: %+v", match.str, err) + } + } + + return nil +} diff --git a/journalbeat/pkg/journalfield/matcher_test.go b/filebeat/input/journald/pkg/journalfield/matcher_test.go similarity index 79% rename from journalbeat/pkg/journalfield/matcher_test.go rename to filebeat/input/journald/pkg/journalfield/matcher_test.go index 82832f3297a..e1e896a7bf0 100644 --- a/journalbeat/pkg/journalfield/matcher_test.go +++ b/filebeat/input/journald/pkg/journalfield/matcher_test.go @@ -24,6 +24,7 @@ import ( "testing" "github.com/coreos/go-systemd/v22/sdjournal" + "github.com/stretchr/testify/require" ) func TestApplyMatchersOr(t *testing.T) { @@ -79,3 +80,25 @@ func TestApplyMatchersOr(t *testing.T) { }) } } + +func TestApplySyslogIdentifier(t *testing.T) { + journal, err := sdjournal.NewJournal() + if err != nil { + t.Fatalf("error while creating test journal: %v", err) + } + defer journal.Close() + + err = ApplySyslogIdentifierMatcher(journal, []string{"audit"}) + require.NoError(t, err) +} + +func TestApplyUnit(t *testing.T) { + journal, err := sdjournal.NewJournal() + if err != nil { + t.Fatalf("error while creating test journal: %v", err) + } + defer journal.Close() + + err = ApplyUnitMatchers(journal, []string{"docker.service"}) + require.NoError(t, err) +} diff --git a/journalbeat/pkg/journalread/mode.go b/filebeat/input/journald/pkg/journalread/mode.go similarity index 100% rename from journalbeat/pkg/journalread/mode.go rename to filebeat/input/journald/pkg/journalread/mode.go diff --git a/journalbeat/pkg/journalread/mode_test.go b/filebeat/input/journald/pkg/journalread/mode_test.go similarity index 100% rename from journalbeat/pkg/journalread/mode_test.go rename to filebeat/input/journald/pkg/journalread/mode_test.go diff --git a/journalbeat/pkg/journalread/reader.go b/filebeat/input/journald/pkg/journalread/reader.go similarity index 100% rename from journalbeat/pkg/journalread/reader.go rename to filebeat/input/journald/pkg/journalread/reader.go diff --git a/journalbeat/tests/system/input/test.journal b/filebeat/input/journald/testdata/input-multiline-parser.journal similarity index 99% rename from journalbeat/tests/system/input/test.journal rename to filebeat/input/journald/testdata/input-multiline-parser.journal index c42b825e62d..9aecfd442f0 100644 Binary files a/journalbeat/tests/system/input/test.journal and b/filebeat/input/journald/testdata/input-multiline-parser.journal differ diff --git a/filebeat/module/apache/error/ingest/pipeline.yml b/filebeat/module/apache/error/ingest/pipeline.yml index 4b8495dd9c8..ae35a6fb371 100644 --- a/filebeat/module/apache/error/ingest/pipeline.yml +++ b/filebeat/module/apache/error/ingest/pipeline.yml @@ -11,10 +11,12 @@ processors: patterns: - \[%{APACHE_TIME:apache.error.timestamp}\] \[%{LOGLEVEL:log.level}\]( \[client %{IPORHOST:source.address}(:%{POSINT:source.port})?\])? %{GREEDYDATA:message} - - \[%{APACHE_TIME:apache.error.timestamp}\] \[%{DATA:apache.error.module}:%{LOGLEVEL:log.level}\] + - \[%{APACHE_TIME:apache.error.timestamp}\] \[%{DATA:apache.error.module}:%{APACHE_LOGLEVEL:log.level}\] \[pid %{NUMBER:process.pid:long}(:tid %{NUMBER:process.thread.id:long})?\]( \[client %{IPORHOST:source.address}(:%{POSINT:source.port})?\])? %{GREEDYDATA:message} pattern_definitions: + # Apache log level can have numeric sub-levels such as trace1. + APACHE_LOGLEVEL: '%{LOGLEVEL}[0-9]*' APACHE_TIME: '%{DAY} %{MONTH} %{MONTHDAY} %{TIME} %{YEAR}' ignore_missing: true - grok: diff --git a/filebeat/module/apache/error/test/sublevel.log b/filebeat/module/apache/error/test/sublevel.log new file mode 100644 index 00000000000..e4ad2fbd87b --- /dev/null +++ b/filebeat/module/apache/error/test/sublevel.log @@ -0,0 +1,2 @@ +[Wed Oct 20 19:20:59.121211 2021] [rewrite:trace3] [pid 121591:tid 140413273032448] mod_rewrite.c(470): [client 10.121.192.8:38350] 10.121.192.8 - - [dev.elastic.co/sid#55a374e851c8][rid#7fb438083ac0/initial] applying pattern '^/import/?(.*)$' to uri '/' + diff --git a/filebeat/module/apache/error/test/sublevel.log-expected.json b/filebeat/module/apache/error/test/sublevel.log-expected.json new file mode 100644 index 00000000000..43ed49a67c5 --- /dev/null +++ b/filebeat/module/apache/error/test/sublevel.log-expected.json @@ -0,0 +1,21 @@ +[ + { + "@timestamp": "2021-10-20T19:20:59.121-02:00", + "apache.error.module": "rewrite", + "event.category": "web", + "event.dataset": "apache.error", + "event.kind": "event", + "event.module": "apache", + "event.original": "[Wed Oct 20 19:20:59.121211 2021] [rewrite:trace3] [pid 121591:tid 140413273032448] mod_rewrite.c(470): [client 10.121.192.8:38350] 10.121.192.8 - - [dev.elastic.co/sid#55a374e851c8][rid#7fb438083ac0/initial] applying pattern '^/import/?(.*)$' to uri '/'", + "event.timezone": "-02:00", + "event.type": "info", + "fileset.name": "error", + "input.type": "log", + "log.level": "trace3", + "log.offset": 0, + "message": "mod_rewrite.c(470): [client 10.121.192.8:38350] 10.121.192.8 - - [dev.elastic.co/sid#55a374e851c8][rid#7fb438083ac0/initial] applying pattern '^/import/?(.*)$' to uri '/'", + "process.pid": 121591, + "process.thread.id": 140413273032448, + "service.type": "apache" + } +] \ No newline at end of file diff --git a/filebeat/module/auditd/log/ingest/pipeline.yml b/filebeat/module/auditd/log/ingest/pipeline.yml index b5c6d56412a..b169fb4dd58 100644 --- a/filebeat/module/auditd/log/ingest/pipeline.yml +++ b/filebeat/module/auditd/log/ingest/pipeline.yml @@ -2102,6 +2102,29 @@ processors: ignore_failure: true field: auditd.log.msg target_field: message +- script: + lang: painless + description: Extracts process information from execve calls + if: 'ctx.process?.args_count != null && ctx.auditd?.log != null' + source: >- + long argc = ctx.process.args_count; + List args = new ArrayList(); + def[] fmt = new def[] {0}; + for (long i=0; i 0 - - @unittest.skipUnless(INTEGRATION_TESTS, "integration test") - def test_template_migration(self): - """ - Test that the template can be loaded with `setup --template` - """ - es = Elasticsearch([self.get_elasticsearch_url()]) - self.render_config_template( - elasticsearch={"host": self.get_elasticsearch_url()}, - ) - exit_code = self.run_beat(extra_args=["setup", "--template", - "-E", "setup.template.overwrite=true", "-E", "migration.6_to_7.enabled=true"]) + exit_code = self.run_beat(extra_args=["setup", "--index-management"]) assert exit_code == 0 assert self.log_contains('Loaded index template') diff --git a/filebeat/tests/system/test_harvester.py b/filebeat/tests/system/test_harvester.py index f56a51d0fe0..ecbb23fab77 100644 --- a/filebeat/tests/system/test_harvester.py +++ b/filebeat/tests/system/test_harvester.py @@ -493,11 +493,11 @@ def test_boms(self, fb_encoding, py_encoding, bom): filebeat = self.start_beat(output=fb_encoding + ".log") self.wait_until( - lambda: self.output_has(lines=1, output_file="output/" + fb_encoding), + lambda: self.output_has(lines=1, output_file="output/" + fb_encoding + "-" + self.today + ".ndjson"), max_timeout=10) # Verify that output does not contain bom - output = self.read_output_json(output_file="output/" + fb_encoding) + output = self.read_output_json(output_file="output/" + fb_encoding + "-" + self.today + ".ndjson") assert output[0]["message"] == message filebeat.kill_and_wait() diff --git a/filebeat/tests/system/test_input.py b/filebeat/tests/system/test_input.py index f9dbd138a2e..a4215587735 100644 --- a/filebeat/tests/system/test_input.py +++ b/filebeat/tests/system/test_input.py @@ -633,10 +633,10 @@ def test_restart_recursive_glob(self): with open(testfile_path, 'a') as testfile: testfile.write("entry2\n") - filebeat = self.start_beat(output="filebeat2.log") + filebeat = self.start_beat() self.wait_until( - lambda: self.output_has_message("entry2"), + lambda: self.output_has_message("entry2", output_file="output/filebeat-"+self.today+"-1.ndjson"), max_timeout=10, name="output contains 'entry2'") @@ -783,7 +783,7 @@ def test_inode_marker_based_identity_tracking_to_path_based(self): proc = self.start_beat() # on startup output is rotated - self.wait_until(lambda: self.output_has(lines=1, output_file="output/filebeat.1")) + self.wait_until(lambda: self.output_has(lines=1, output_file="output/filebeat-" + self.today + "-1.ndjson")) self.wait_until(lambda: self.output_has(lines=1)) proc.check_kill_and_wait() diff --git a/filebeat/tests/system/test_load.py b/filebeat/tests/system/test_load.py index 6a35a6ce250..b48b83e2659 100644 --- a/filebeat/tests/system/test_load.py +++ b/filebeat/tests/system/test_load.py @@ -72,7 +72,7 @@ def test_no_missing_events(self): entry_list = [] - with open(self.working_dir + "/output/filebeat") as f: + with open(self.working_dir + "/output/filebeat-" + self.today + ".ndjson") as f: for line in f: content = json.loads(line) v = int(content["message"]) diff --git a/filebeat/tests/system/test_modules.py b/filebeat/tests/system/test_modules.py index b552560f83c..96aed80cf15 100644 --- a/filebeat/tests/system/test_modules.py +++ b/filebeat/tests/system/test_modules.py @@ -11,6 +11,63 @@ from parameterized import parameterized from deepdiff import DeepDiff +# datasets for which @timestamp is removed due to date missing +remove_timestamp = { + "activemq.audit", + "barracuda.spamfirewall", + "barracuda.waf", + "bluecoat.director", + "cef.log", + "cisco.asa", + "cisco.ios", + "citrix.netscaler", + "cylance.protect", + "f5.bigipafm", + "fortinet.clientendpoint", + "haproxy.log", + "icinga.startup", + "imperva.securesphere", + "infoblox.nios", + "iptables.log", + "juniper.junos", + "juniper.netscreen", + "netscout.sightline", + "proofpoint.emailsecurity", + "redis.log", + "snort.log", + "symantec.endpointprotection", + "system.auth", + "system.syslog", + "crowdstrike.falcon_endpoint", + "crowdstrike.falcon_audit", + "zoom.webhook", + "threatintel.otx", + "threatintel.abuseurl", + "threatintel.abusemalware", + "threatintel.anomali", + "threatintel.anomalithreatstream", + "threatintel.malwarebazaar", + "threatintel.recordedfuture", + "snyk.vulnerabilities", + "snyk.audit", + "awsfargate.log", +} + +# dataset + log file pairs for which @timestamp is kept as an exception from above +remove_timestamp_exception = { + ('system.syslog', 'tz-offset.log'), + ('system.auth', 'timestamp.log'), + ('cisco.asa', 'asa.log'), + ('cisco.asa', 'hostnames.log'), + ('cisco.asa', 'not-ip.log'), + ('cisco.asa', 'sample.log') +} + +# array fields whose order is kept before comparison +array_fields_dont_sort = { + "process.args" +} + def load_fileset_test_cases(): """ @@ -104,7 +161,7 @@ def run_on_file(self, module, fileset, test_file, cfgfile): self.assert_explicit_ecs_version_set(module, fileset) try: - self.es.indices.delete(index=self.index_name) + self.es.indices.delete_data_stream(self.index_name) except BaseException: pass self.wait_until(lambda: not self.es.indices.exists(self.index_name)) @@ -198,7 +255,7 @@ def _test_expected_events(self, test_file, objects): objects[k] = self.flatten_object(obj, {}, "") clean_keys(objects[k]) for key in objects[k].keys(): - if isinstance(objects[k][key], list): + if isinstance(objects[k][key], list) and key not in array_fields_dont_sort: objects[k][key].sort(key=str) json.dump(objects, f, indent=4, separators=( @@ -247,56 +304,6 @@ def clean_keys(obj): other_keys = ["log.file.path", "agent.version"] # ECS versions change for any ECS release, large or small ecs_key = ["ecs.version"] - # datasets for which @timestamp is removed due to date missing - remove_timestamp = { - "activemq.audit", - "barracuda.spamfirewall", - "barracuda.waf", - "bluecoat.director", - "cef.log", - "cisco.asa", - "cisco.ios", - "citrix.netscaler", - "cylance.protect", - "f5.bigipafm", - "fortinet.clientendpoint", - "haproxy.log", - "icinga.startup", - "imperva.securesphere", - "infoblox.nios", - "iptables.log", - "juniper.junos", - "juniper.netscreen", - "netscout.sightline", - "proofpoint.emailsecurity", - "redis.log", - "snort.log", - "symantec.endpointprotection", - "system.auth", - "system.syslog", - "crowdstrike.falcon_endpoint", - "crowdstrike.falcon_audit", - "zoom.webhook", - "threatintel.otx", - "threatintel.abuseurl", - "threatintel.abusemalware", - "threatintel.anomali", - "threatintel.anomalithreatstream", - "threatintel.malwarebazaar", - "threatintel.recordedfuture", - "snyk.vulnerabilities", - "snyk.audit", - "awsfargate.log", - } - # dataset + log file pairs for which @timestamp is kept as an exception from above - remove_timestamp_exception = { - ('system.syslog', 'tz-offset.log'), - ('system.auth', 'timestamp.log'), - ('cisco.asa', 'asa.log'), - ('cisco.asa', 'hostnames.log'), - ('cisco.asa', 'not-ip.log'), - ('cisco.asa', 'sample.log') - } # Keep source log filename for exceptions filename = None diff --git a/filebeat/tests/system/test_multiline.py b/filebeat/tests/system/test_multiline.py index ee5384ef5ef..31d4f0258ca 100644 --- a/filebeat/tests/system/test_multiline.py +++ b/filebeat/tests/system/test_multiline.py @@ -148,11 +148,11 @@ def test_max_lines(self): # Checks line 3 is sent assert True == self.log_contains( - "MetaDataMappingService.java:388", "output/filebeat") + "MetaDataMappingService.java:388", "output/filebeat-" + self.today + ".ndjson") # Checks line 4 is not sent anymore assert False == self.log_contains( - "InternalClusterService.java:388", "output/filebeat") + "InternalClusterService.java:388", "output/filebeat-" + self.today + ".ndjson") # Check that output file has the same number of lines as the log file assert 20 == len(output) @@ -231,10 +231,10 @@ def test_max_bytes(self): output = self.read_output() # Check that first 60 chars are sent - assert True == self.log_contains("cluster.metadata", "output/filebeat") + assert True == self.log_contains("cluster.metadata", "output/filebeat-" + self.today + ".ndjson") # Checks that chars afterwards are not sent - assert False == self.log_contains("Zach", "output/filebeat") + assert False == self.log_contains("Zach", "output/filebeat-" + self.today + ".ndjson") # Check that output file has the same number of lines as the log file assert 20 == len(output) diff --git a/filebeat/tests/system/test_registrar.py b/filebeat/tests/system/test_registrar.py index 02d07a32446..bb55ef547b3 100644 --- a/filebeat/tests/system/test_registrar.py +++ b/filebeat/tests/system/test_registrar.py @@ -486,11 +486,11 @@ def test_restart_continue(self): # Output file was rotated self.wait_until( - lambda: self.output_has(lines=1, output_file="output/filebeat.1"), + lambda: self.output_has(lines=1, output_file="output/filebeat-" + self.today + ".ndjson"), max_timeout=10) self.wait_until( - lambda: self.output_has(lines=1), + lambda: self.output_has(lines=1, output_file="output/filebeat-" + self.today + "-1.ndjson"), max_timeout=10) filebeat.check_kill_and_wait() @@ -505,7 +505,7 @@ def test_restart_continue(self): # should never have been detected assert len(data) == 1 - output = self.read_output() + output = self.read_output(output_file="output/filebeat-" + self.today + "-1.ndjson") # Check that output file has the same number of lines as the log file assert len(output) == 1 @@ -592,15 +592,15 @@ def test_rotating_file_with_restart(self): with open(testfile_path, 'w') as testfile: testfile.write("entry3\n") - filebeat = self.start_beat(output="filebeat2.log") + filebeat = self.start_beat() # Output file was rotated self.wait_until( - lambda: self.output_has(lines=2, output_file="output/filebeat.1"), + lambda: self.output_has(lines=2), max_timeout=10) self.wait_until( - lambda: self.output_has(lines=1), + lambda: self.output_has(lines=1, output_file="output/filebeat-" + self.today + "-1.ndjson"), max_timeout=10) filebeat.check_kill_and_wait() @@ -951,8 +951,8 @@ def test_restart_state(self): clean_inactive="3s", ) - filebeat = self.start_beat(output="filebeat2.log") - logs = self.log_access("filebeat2.log") + filebeat = self.start_beat() + logs = self.log_access() # Write additional file for name in restart_files: diff --git a/go.mod b/go.mod index a06dd9e5d49..4cf5253b1a1 100644 --- a/go.mod +++ b/go.mod @@ -3,9 +3,9 @@ module github.com/elastic/beats/v7 go 1.17 require ( - cloud.google.com/go v0.83.0 cloud.google.com/go/bigquery v1.8.0 - cloud.google.com/go/pubsub v1.3.1 + cloud.google.com/go/monitoring v1.1.0 + cloud.google.com/go/pubsub v1.17.1 code.cloudfoundry.org/go-diodes v0.0.0-20190809170250-f77fb823c7ee // indirect code.cloudfoundry.org/go-loggregator v7.4.0+incompatible code.cloudfoundry.org/rfc5424 v0.0.0-20180905210152-236a6d29298a // indirect @@ -72,7 +72,6 @@ require ( github.com/elastic/go-seccomp-bpf v1.2.0 github.com/elastic/go-structform v0.0.9 github.com/elastic/go-sysinfo v1.7.1 - github.com/elastic/go-txfile v0.0.8 github.com/elastic/go-ucfg v0.8.3 github.com/elastic/go-windows v1.0.1 github.com/elastic/gosigar v0.14.2 @@ -96,10 +95,10 @@ require ( github.com/gomodule/redigo v1.8.3 github.com/google/flatbuffers v1.12.1 github.com/google/go-cmp v0.5.6 - github.com/google/gopacket v1.1.18-0.20191009163724-0ad7f2610e34 + github.com/google/gopacket v1.1.19 github.com/google/uuid v1.3.0 github.com/gorhill/cronexpr v0.0.0-20180427100037-88b0669f7d75 - github.com/gorilla/mux v1.7.3 + github.com/gorilla/mux v1.8.0 github.com/h2non/filetype v1.1.1 github.com/hashicorp/go-multierror v1.1.0 github.com/hashicorp/go-retryablehttp v0.6.6 @@ -149,9 +148,7 @@ require ( github.com/spf13/pflag v1.0.5 github.com/stretchr/testify v1.7.0 github.com/tsg/go-daemon v0.0.0-20200207173439-e704b93fd89b - github.com/tsg/gopacket v0.0.0-20200626092518-2ab8e397a786 github.com/ugorji/go/codec v1.1.8 - github.com/urso/magetools v0.0.0-20200125210132-c2e338f92f3a // indirect github.com/urso/sderr v0.0.0-20210525210834-52b04e8f5c71 github.com/vmware/govmomi v0.0.0-20170802214208-2cad15190b41 github.com/xdg/scram v1.0.3 @@ -165,16 +162,16 @@ require ( go.uber.org/atomic v1.8.0 go.uber.org/multierr v1.5.0 go.uber.org/zap v1.14.1 - golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e + golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 golang.org/x/net v0.0.0-20211020060615-d418f374d309 - golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c + golang.org/x/oauth2 v0.0.0-20211005180243-6b3c2da341f1 golang.org/x/sync v0.0.0-20210220032951-036812b2e83c golang.org/x/sys v0.0.0-20211102192858-4dd72447c267 golang.org/x/text v0.3.7 - golang.org/x/time v0.0.0-20210611083556-38a9dc6acbc6 + golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac golang.org/x/tools v0.1.7 - google.golang.org/api v0.48.0 + google.golang.org/api v0.58.0 google.golang.org/genproto v0.0.0-20211021150943-2b146023228c google.golang.org/grpc v1.41.0 google.golang.org/protobuf v1.27.1 @@ -189,13 +186,14 @@ require ( gotest.tools v2.2.0+incompatible gotest.tools/gotestsum v0.6.0 howett.net/plist v0.0.0-20181124034731-591f970eefbb - k8s.io/api v0.21.1 - k8s.io/apimachinery v0.21.1 - k8s.io/client-go v0.21.1 + k8s.io/api v0.23.0 + k8s.io/apimachinery v0.23.0 + k8s.io/client-go v0.23.0 kernel.org/pub/linux/libs/security/libcap/cap v1.2.57 ) require ( + cloud.google.com/go v0.97.0 // indirect code.cloudfoundry.org/gofileutils v0.0.0-20170111115228-4d0c80011a0f // indirect github.com/Azure/azure-amqp-common-go/v3 v3.2.1 // indirect github.com/Azure/azure-pipeline-go v0.2.1 // indirect @@ -218,9 +216,9 @@ require ( github.com/docker/distribution v2.7.1+incompatible // indirect github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21 // indirect github.com/eapache/queue v1.1.0 // indirect - github.com/evanphx/json-patch v4.9.0+incompatible // indirect + github.com/evanphx/json-patch v4.12.0+incompatible // indirect github.com/fearful-symmetry/gomsr v0.0.1 // indirect - github.com/go-logr/logr v0.4.0 // indirect + github.com/go-logr/logr v1.2.0 // indirect github.com/gobuffalo/here v0.6.0 // indirect github.com/godbus/dbus/v5 v5.0.5 // indirect github.com/golang-jwt/jwt/v4 v4.0.0 // indirect @@ -230,8 +228,8 @@ require ( github.com/google/gofuzz v1.1.0 // indirect github.com/google/licenseclassifier v0.0.0-20200402202327-879cb1424de0 // indirect github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect - github.com/googleapis/gax-go/v2 v2.0.5 // indirect - github.com/googleapis/gnostic v0.4.1 // indirect + github.com/googleapis/gax-go/v2 v2.1.1 // indirect + github.com/googleapis/gnostic v0.5.5 // indirect github.com/gorilla/websocket v1.4.2 // indirect github.com/hashicorp/cronexpr v1.1.0 // indirect github.com/hashicorp/errwrap v1.0.0 // indirect @@ -248,8 +246,7 @@ require ( github.com/jcmturner/rpc/v2 v2.0.3 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect github.com/josharian/intern v1.0.0 // indirect - github.com/json-iterator/go v1.1.11 // indirect - github.com/jstemmer/go-junit-report v0.9.1 // indirect + github.com/json-iterator/go v1.1.12 // indirect github.com/karrick/godirwalk v1.15.6 // indirect github.com/klauspost/compress v1.13.6 // indirect github.com/markbates/pkger v0.17.0 // indirect @@ -260,7 +257,7 @@ require ( github.com/moby/spdystream v0.2.0 // indirect github.com/moby/term v0.0.0-20201216013528-df9cb8a40635 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect - github.com/modern-go/reflect2 v1.0.1 // indirect + github.com/modern-go/reflect2 v1.0.2 // indirect github.com/pierrec/lz4 v2.6.0+incompatible // indirect github.com/sanathkr/go-yaml v0.0.0-20170819195128-ed9d249f429b // indirect github.com/santhosh-tekuri/jsonschema v1.2.4 // indirect @@ -268,20 +265,20 @@ require ( github.com/sirupsen/logrus v1.8.1 // indirect github.com/stretchr/objx v0.2.0 // indirect github.com/urso/diag v0.0.0-20200210123136-21b3cc8eb797 // indirect - github.com/urso/go-bin v0.0.0-20180220135811-781c575c9f0e // indirect github.com/xdg/stringprep v1.0.3 // indirect go.elastic.co/fastjson v1.1.0 // indirect go.opencensus.io v0.23.0 // indirect golang.org/x/mod v0.5.1 // indirect - golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d // indirect + golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b // indirect golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect google.golang.org/appengine v1.6.7 // indirect gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect - k8s.io/klog/v2 v2.9.0 // indirect - k8s.io/kube-openapi v0.0.0-20210305001622-591a79e4bda7 // indirect - k8s.io/utils v0.0.0-20201110183641-67b214c5f920 // indirect + k8s.io/klog/v2 v2.30.0 // indirect + k8s.io/kube-openapi v0.0.0-20211115234752-e816edb12b65 // indirect + k8s.io/utils v0.0.0-20210930125809-cb0fa318a74b // indirect kernel.org/pub/linux/libs/security/libcap/psx v1.2.57 // indirect - sigs.k8s.io/structured-merge-diff/v4 v4.1.0 // indirect + sigs.k8s.io/json v0.0.0-20211020170558-c049b76a60c6 // indirect + sigs.k8s.io/structured-merge-diff/v4 v4.1.2 // indirect sigs.k8s.io/yaml v1.2.0 // indirect ) @@ -295,7 +292,7 @@ replace ( github.com/fsnotify/fsevents => github.com/elastic/fsevents v0.0.0-20181029231046-e1d381a4d270 github.com/fsnotify/fsnotify => github.com/adriansr/fsnotify v1.4.8-0.20211018144411-a81f2b630e7c github.com/golang/glog => github.com/elastic/glog v1.0.1-0.20210831205241-7d8b5c89dfc4 - github.com/google/gopacket => github.com/adriansr/gopacket v1.1.18-0.20200327165309-dd62abfa8a41 + github.com/google/gopacket => github.com/elastic/gopacket v1.1.20-0.20211202005954-d412fca7f83a github.com/insomniacslk/dhcp => github.com/elastic/dhcp v0.0.0-20200227161230-57ec251c7eb3 // indirect github.com/tonistiigi/fifo => github.com/containerd/fifo v0.0.0-20190816180239-bda0ff6ed73c ) diff --git a/go.sum b/go.sum index 4ae1569e4da..49cf15709b8 100644 --- a/go.sum +++ b/go.sum @@ -21,8 +21,14 @@ cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmW cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg= cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8= cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0= -cloud.google.com/go v0.83.0 h1:bAMqZidYkmIsUqe6PtkEPT7Q+vfizScn+jfNA6jwK9c= cloud.google.com/go v0.83.0/go.mod h1:Z7MJUsANfY0pYPdw0lbnivPx4/vhy/e2FEkSkF7vAVY= +cloud.google.com/go v0.84.0/go.mod h1:RazrYuxIK6Kb7YrzzhPoLmCVzl7Sup4NrbKPg8KHSUM= +cloud.google.com/go v0.87.0/go.mod h1:TpDYlFy7vuLzZMMZ+B6iRiELaY7z/gJPaqbMx6mlWcY= +cloud.google.com/go v0.90.0/go.mod h1:kRX0mNRHe0e2rC6oNakvwQqzyDmg57xJ+SZU1eT2aDQ= +cloud.google.com/go v0.93.3/go.mod h1:8utlLll2EF5XMAV15woO4lSbWQlk8rer9aLOfLh7+YI= +cloud.google.com/go v0.94.1/go.mod h1:qAlAugsXlC+JWO+Bke5vCtc9ONxjQT3drlTTnAplMW4= +cloud.google.com/go v0.97.0 h1:3DXvAyifywvq64LfkKaMOmkWPS1CikIQdMe2lY9vxU8= +cloud.google.com/go v0.97.0/go.mod h1:GF7l59pYBVlXQIBLx3a761cZ41F9bBH3JUlihCt2Udc= cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= @@ -34,11 +40,16 @@ cloud.google.com/go/bigtable v1.2.0/go.mod h1:JcVAOl45lrTmQfLj7T6TxyMzIN/3FGGcFm cloud.google.com/go/bigtable v1.3.0/go.mod h1:z5EyKrPE8OQmeg4h5MNdKvuSnI9CCT49Ki3f23aBzio= cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= +cloud.google.com/go/kms v1.0.0 h1:YkIeqPXqTAlwXk3Z2/WG0d6h1tqJQjU354WftjEoP9E= +cloud.google.com/go/kms v1.0.0/go.mod h1:nhUehi+w7zht2XrUfvTRNpxrfayBHqP4lu2NSywui/0= +cloud.google.com/go/monitoring v1.1.0 h1:ZnyNdf/XRcynMmKzRSNTOdOyYPs6G7do1l2D2hIvIKo= +cloud.google.com/go/monitoring v1.1.0/go.mod h1:L81pzz7HKn14QCMaCs6NTQkdBnE87TElyanS95vIcl4= cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= -cloud.google.com/go/pubsub v1.3.1 h1:ukjixP1wl0LpnZ6LWtZJ0mX5tBmjp1f8Sqer8Z2OMUU= cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= +cloud.google.com/go/pubsub v1.17.1 h1:s2UGTTphpnUQ0Wppkp2OprR4pS3nlBpPvyL2GV9cqdc= +cloud.google.com/go/pubsub v1.17.1/go.mod h1:4qDxMr1WsM9+aQAz36ltDwCIM+R0QdlseyFjBuNvnss= cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= @@ -169,8 +180,6 @@ github.com/StackExchange/wmi v0.0.0-20170221213301-9f32b5905fd6/go.mod h1:3eOhrU github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g= github.com/adriansr/fsnotify v1.4.8-0.20211018144411-a81f2b630e7c h1:LpOCwE9oTg0+1Dm8rB06dKxQs7yu5tdnM6A/Zm/juQQ= github.com/adriansr/fsnotify v1.4.8-0.20211018144411-a81f2b630e7c/go.mod h1:onXS6zmTa1LJcurVsOkzywEV/Q3pdEqqu362/8OQzAI= -github.com/adriansr/gopacket v1.1.18-0.20200327165309-dd62abfa8a41 h1:9OmEpkkO4vm8Wz+JKWHDLZdzYrqXr4dovxIJDkTltKE= -github.com/adriansr/gopacket v1.1.18-0.20200327165309-dd62abfa8a41/go.mod h1:UdDNZ1OO62aGYVnPhxT1U6aI7ukYtA/kB8vaU0diBUM= github.com/aerospike/aerospike-client-go v1.27.1-0.20170612174108-0f3b54da6bdc h1:9iW/Fbn/R/nyUOiqo6AgwBe8uirqUIoTGF3vKG8qjoc= github.com/aerospike/aerospike-client-go v1.27.1-0.20170612174108-0f3b54da6bdc/go.mod h1:zj8LBEnWBDOVEIJt8LvaRvDG5ARAoa5dBeHaB472NRc= github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c= @@ -529,14 +538,14 @@ github.com/elastic/go-structform v0.0.9/go.mod h1:CZWf9aIRYY5SuKSmOhtXScE5uQiLZN github.com/elastic/go-sysinfo v1.1.1/go.mod h1:i1ZYdU10oLNfRzq4vq62BEwD2fH8KaWh6eh0ikPT9F0= github.com/elastic/go-sysinfo v1.7.1 h1:Wx4DSARcKLllpKT2TnFVdSUJOsybqMYCNQZq1/wO+s0= github.com/elastic/go-sysinfo v1.7.1/go.mod h1:i1ZYdU10oLNfRzq4vq62BEwD2fH8KaWh6eh0ikPT9F0= -github.com/elastic/go-txfile v0.0.8 h1:hqFMmLM+UCDMJeSyuCWe8YwS+HtoX7F+cz5fhPYRTn4= -github.com/elastic/go-txfile v0.0.8/go.mod h1:H0nCoFae0a4ga57apgxFsgmRjevNCsEaT6g56JoeKAE= github.com/elastic/go-ucfg v0.7.0/go.mod h1:iaiY0NBIYeasNgycLyTvhJftQlQEUO2hpF+FX0JKxzo= github.com/elastic/go-ucfg v0.8.3 h1:leywnFjzr2QneZZWhE6uWd+QN/UpP0sdJRHYyuFvkeo= github.com/elastic/go-ucfg v0.8.3/go.mod h1:iaiY0NBIYeasNgycLyTvhJftQlQEUO2hpF+FX0JKxzo= github.com/elastic/go-windows v1.0.0/go.mod h1:TsU0Nrp7/y3+VwE82FoZF8gC/XFg/Elz6CcloAxnPgU= github.com/elastic/go-windows v1.0.1 h1:AlYZOldA+UJ0/2nBuqWdo90GFCgG9xuyw9SYzGUtJm0= github.com/elastic/go-windows v1.0.1/go.mod h1:FoVvqWSun28vaDQPbj2Elfc0JahhPB7WQEGa3c814Ss= +github.com/elastic/gopacket v1.1.20-0.20211202005954-d412fca7f83a h1:8WfL/X6fK11iyX5t3Dd9dDMMNqPfEZNc//JsWGIhEgQ= +github.com/elastic/gopacket v1.1.20-0.20211202005954-d412fca7f83a/go.mod h1:riddUzxTSBpJXk3qBHtYr4qOhFhT6k/1c0E3qkQjQpA= github.com/elastic/gosigar v0.14.2 h1:Dg80n8cr90OZ7x+bAax/QjoW/XqTI11RmA79ZwIm9/4= github.com/elastic/gosigar v0.14.2/go.mod h1:iXRIGg2tLnu7LBdpqzyQfGDEidKCfWcCMS0WKyPWoMs= github.com/elastic/sarama v1.19.1-0.20210823122811-11c3ef800752 h1:5/RUNg7rkIvayjPhAIoI3v8p45NfWcfWs5DZSElycis= @@ -557,8 +566,9 @@ github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.m github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/evanphx/json-patch v4.2.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= -github.com/evanphx/json-patch v4.9.0+incompatible h1:kLcOMZeuLAJvL2BPWLMIj5oaZQobrkAqrL+WFZwQses= github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= +github.com/evanphx/json-patch v4.12.0+incompatible h1:4onqiflcdA9EOZ4RxV643DvftH5pOlLGNtQ5lPWQu84= +github.com/evanphx/json-patch v4.12.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/color v1.9.0 h1:8xPHl4/q1VyqGIPif1F+1V3Y3lSmrq01EabUW3CoW5s= github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= @@ -568,6 +578,7 @@ github.com/fearful-symmetry/gorapl v0.0.4 h1:TMn4fhhtIAd+C3NrAl638oaYlX1vgcKNVVd github.com/fearful-symmetry/gorapl v0.0.4/go.mod h1:XoeZ+5v0tJX9WMvzqdPaaKAdX7y17mDN3pxDGemINR0= github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= +github.com/form3tech-oss/jwt-go v3.2.3+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw= github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g= github.com/foxcpp/go-mockdns v0.0.0-20201212160233-ede2f9158d15/go.mod h1:tPg4cp4nseejPd+UKxtCVQ2hUxNTZ7qQZJa7CLriIeo= @@ -577,6 +588,7 @@ github.com/frankban/quicktest v1.11.3 h1:8sXhOn0uLys67V8EsXLc6eszDs8VXWxL3iRvebP github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k= github.com/fullsailor/pkcs7 v0.0.0-20190404230743-d7302db945fa/go.mod h1:KnogPXtdwXqoenmZCw6S+25EAm2MkxbG0deNDu4cbSA= github.com/garyburd/redigo v0.0.0-20150301180006-535138d7bcd7/go.mod h1:NR3MbYisc3/PwhQ00EMzDiPmrwpPxAn5GI05/YaO1SY= +github.com/getkin/kin-openapi v0.76.0/go.mod h1:660oXbgy5JFMKreazJaQTw7o+X00qeSyhcnluiMv+Xg= github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/globalsign/mgo v0.0.0-20180905125535-1ca0a4f7cbcb/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q= @@ -599,8 +611,9 @@ github.com/go-logfmt/logfmt v0.5.0 h1:TrB8swr/68K7m9CcGut2g3UOihhbcbiMAYiuTXdEih github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= -github.com/go-logr/logr v0.4.0 h1:K7/B1jt6fIBQVd4Owv2MqGQClcgf0R266+7C/QjRcLc= github.com/go-logr/logr v0.4.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= +github.com/go-logr/logr v1.2.0 h1:QK40JKJyMdUDz+h+xvCsru/bJhvG0UxvePV0ufL/AcE= +github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-martini/martini v0.0.0-20170121215854-22fa46961aab h1:xveKWz2iaueeTaUgdetzel+U7exyigDYBryyVfV/rZk= github.com/go-martini/martini v0.0.0-20170121215854-22fa46961aab/go.mod h1:/P9AEU963A2AYjv4d1V5eVL1CQbEJq6aCNHDDjibzu8= github.com/go-ole/go-ole v1.2.5-0.20190920104607-14974a1cf647 h1:whypLownH338a3Ork2w9t0KUKtVxbXYySuz7V1YGsJo= @@ -745,7 +758,6 @@ github.com/godbus/dbus/v5 v5.0.5 h1:9Eg0XUhQxtkV8ykTMKtMMYY72g4NgxtRq4jgh4Ih5YM= github.com/godbus/dbus/v5 v5.0.5/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/godror/godror v0.10.4 h1:44FcfzDPp/PJZzen5Hm59SZQBhgrbR6E1KwCjg6gnJo= github.com/godror/godror v0.10.4/go.mod h1:9MVLtu25FBJBMHkPs0m3Ngf/VmwGcLpM2HS8PlNGw9U= -github.com/gofrs/flock v0.7.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw= github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= github.com/gofrs/uuid v3.3.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= @@ -814,6 +826,7 @@ github.com/gomodule/redigo v1.8.3 h1:HR0kYDX2RJZvAup8CsiJwxB4dTCSC0AaUq6S4SiLwUc github.com/gomodule/redigo v1.8.3/go.mod h1:P9dn9mFrCBvWhGE1wpxx6fgq7BAeLBk+UUUzlpkBYO0= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA= github.com/google/flatbuffers v1.11.0/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= github.com/google/flatbuffers v1.12.0/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= github.com/google/flatbuffers v1.12.1 h1:MVlul7pQNoDzWRLTw5imwYsl+usrS1TXG2H4jg6ImGw= @@ -857,6 +870,7 @@ github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLe github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= @@ -867,12 +881,16 @@ github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+ github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= -github.com/googleapis/gax-go/v2 v2.0.5 h1:sjZBwGj9Jlw33ImPtvFviGYvseOtDM7hkSKB7+Tv3SM= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= +github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0= +github.com/googleapis/gax-go/v2 v2.1.1 h1:dp3bWCh+PPO1zjRRiCSczJav13sBvG4UhNyVTa1KqdU= +github.com/googleapis/gax-go/v2 v2.1.1/go.mod h1:hddJymUZASv3XPyGkUpKj8pPO47Rmb0eJc8R6ouapiM= github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= github.com/googleapis/gnostic v0.4.0/go.mod h1:on+2t9HRStVgn95RSsFWFz+6Q0Snyqv1awfrALZdbtU= -github.com/googleapis/gnostic v0.4.1 h1:DLJCy1n/vrD4HPjOvYcT8aYQXpPIzoRZONaYwyycI+I= github.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3ir6b65WBswg= +github.com/googleapis/gnostic v0.5.1/go.mod h1:6U4PtQXGIEt/Z3h5MAT7FNofLnw9vXk2cUuW7uA/OeU= +github.com/googleapis/gnostic v0.5.5 h1:9fHAtK0uDfpveeqqo1hkEZJcFvYXAiCN3UutL8F9xHw= +github.com/googleapis/gnostic v0.5.5/go.mod h1:7+EbHbldMins07ALC74bsA81Ovc97DwqyJO1AENw9kA= github.com/gophercloud/gophercloud v0.1.0/go.mod h1:vxM41WHh5uqHVBMZHzuwNOHh8XEoIEcSTewFxm1c5g8= github.com/gophercloud/gophercloud v0.10.0/go.mod h1:gmC5oQqMDOMO1t1gq5DquX/yAU808e/4mzjjDA76+Ss= github.com/gophercloud/gophercloud v0.18.0/go.mod h1:wRtmUelyIIv3CSSDI47aUwbs075O6i+LY+pXsKCBsb4= @@ -884,8 +902,9 @@ github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51 github.com/gorilla/handlers v0.0.0-20150720190736-60c7bfde3e33/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ= github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/mux v1.7.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= -github.com/gorilla/mux v1.7.3 h1:gnP5JzjVOuiZD07fKKToCAOjS0yOpj/qPETTXCCS6hw= github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= +github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= +github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4= github.com/gorilla/sessions v1.2.1/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM= github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= @@ -1043,10 +1062,10 @@ github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/u github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.11 h1:uVUAXhF2To8cbw/3xN3pxj6kk7TYKs98NIrTqPlMWAQ= github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= -github.com/jstemmer/go-junit-report v0.9.1 h1:6QPYqodiu3GuPL+7mfx+NwDdp2eTkp9IfEUpgAwUN0o= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/jsternberg/zap-logfmt v1.0.0/go.mod h1:uvPs/4X51zdkcm5jXl5SYoN+4RK21K8mysFmDaM/h+o= github.com/jsternberg/zap-logfmt v1.2.0/go.mod h1:kz+1CUmCutPWABnNkOu9hOHKdT2q3TDYCcsFy9hpqb0= @@ -1191,8 +1210,9 @@ github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc= github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= @@ -1230,14 +1250,16 @@ github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+W github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.12.1 h1:mFwc4LvZ0xpSvDZ3E+k8Yte0hLOMxXUlP+yXtJqkYfQ= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= +github.com/onsi/ginkgo v1.14.0 h1:2mOpI4JVVPBN+WQRa0WKH2eXR+Ey+uK4n7Zj0aYpIQA= +github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= github.com/onsi/gomega v0.0.0-20151007035656-2152b45fa28a/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v1.2.0/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= +github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/onsi/gomega v1.10.3 h1:gph6h/qe9GSUw1NhH1gp+qb+h8rXD8Cy60Z32Qw3ELA= github.com/onsi/gomega v1.10.3/go.mod h1:V9xEwhxec5O8UDM77eCW8vLymOMltsqPVYWrpDsH8xc= github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk= @@ -1469,6 +1491,7 @@ github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE= github.com/stefanberger/go-pkcs11uri v0.0.0-20201008174630-78d3cae3a980/go.mod h1:AO3tvPzVZ/ayst6UlUKUv6rcPQInYe3IknH3jYhAKu8= +github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8= github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI= @@ -1499,8 +1522,6 @@ github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1 github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tsg/go-daemon v0.0.0-20200207173439-e704b93fd89b h1:X/8hkb4rQq3+QuOxpJK7gWmAXmZucF0EI1s1BfBLq6U= github.com/tsg/go-daemon v0.0.0-20200207173439-e704b93fd89b/go.mod h1:jAqhj/JBVC1PwcLTWd6rjQyGyItxxrhpiBl8LSuAGmw= -github.com/tsg/gopacket v0.0.0-20200626092518-2ab8e397a786 h1:B/IVHYiI0d04dudYw+CvCAGqSMq8d0yWy56eD6p85BQ= -github.com/tsg/gopacket v0.0.0-20200626092518-2ab8e397a786/go.mod h1:RIkfovP3Y7my19aXEjjbNd9E5TlHozzAyt7B8AaEcwg= github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= github.com/uber-go/tally v3.3.15+incompatible/go.mod h1:YDTIBxdXyOU/sCWilKB4bgyufu1cEi0jdVnRdxvjnmU= github.com/uber/athenadriver v1.1.4/go.mod h1:tQjho4NzXw55LGfSZEcETuYydpY1vtmixUabHkC1K/E= @@ -1520,13 +1541,6 @@ github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtX github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/urso/diag v0.0.0-20200210123136-21b3cc8eb797 h1:OHNw/6pXODJAB32NujjdQO/KIYQ3KAbHQfCzH81XdCs= github.com/urso/diag v0.0.0-20200210123136-21b3cc8eb797/go.mod h1:pNWFTeQ+V1OYT/TzWpnWb6eQBdoXpdx+H+lrH97/Oyo= -github.com/urso/go-bin v0.0.0-20180220135811-781c575c9f0e h1:NiofbjIUI5gR+ybDsGSVH1fWyjSeDYiYVJHT1+kcsak= -github.com/urso/go-bin v0.0.0-20180220135811-781c575c9f0e/go.mod h1:6GfHrdWBQYjFRIznu7XuQH4lYB2w8nO4bnImVKkzPOM= -github.com/urso/magetools v0.0.0-20190919040553-290c89e0c230/go.mod h1:DFxTNgS/ExCGmmjVjSOgS2WjtfjKXgCyDzAFgbtovSA= -github.com/urso/magetools v0.0.0-20200125210132-c2e338f92f3a h1:jWAaRFnay3H2e6S0GGCl5nKrkgQNlarCE/kvcutzBmw= -github.com/urso/magetools v0.0.0-20200125210132-c2e338f92f3a/go.mod h1:DbaJnRzkGaWrMWm5Hz6QVnUj//x9/zjrfx8bF3J+GJY= -github.com/urso/qcgen v0.0.0-20180131103024-0b059e7db4f4 h1:hhA8EBThzz9PztawVTycKvfETVuBqxAQ5keFlAVtbAw= -github.com/urso/qcgen v0.0.0-20180131103024-0b059e7db4f4/go.mod h1:RspW+E2Yb7Fs7HclB2tiDaiu6Rp41BiIG4Wo1YaoXGc= github.com/urso/sderr v0.0.0-20210525210834-52b04e8f5c71 h1:CehQeKbysHV8J2V7AD0w8NL2x1h04kmmo/Ft5su4lU0= github.com/urso/sderr v0.0.0-20210525210834-52b04e8f5c71/go.mod h1:Wp40HwmjM59FkDIVFfcCb9LzBbnc0XAMp8++hJuWvSU= github.com/vbatts/tar-split v0.11.1/go.mod h1:LEuURwDEiWjRjwu46yU3KVGuUdVv/dcnpcEPSzR8z6g= @@ -1537,6 +1551,7 @@ github.com/vishvananda/netlink v1.1.1-0.20201029203352-d40f9887b852/go.mod h1:tw github.com/vishvananda/netns v0.0.0-20180720170159-13995c7128cc/go.mod h1:ZjcWmFBXmLKZu9Nxj3WKYEafiSqer2rnvPr0en9UNpI= github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU= github.com/vishvananda/netns v0.0.0-20200728191858-db3c7e526aae/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0= +github.com/vishvananda/netns v0.0.0-20210104183010-2eb08e3e575f/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0= github.com/vmware/govmomi v0.0.0-20170802214208-2cad15190b41 h1:NeNpIvfvaFOh0BH7nMEljE5Rk/VJlxhm58M41SeOD20= github.com/vmware/govmomi v0.0.0-20170802214208-2cad15190b41/go.mod h1:URlwyTFZX72RmxtxuaFL2Uj3fD1JTvZdx59bHWk6aFU= github.com/willf/bitset v1.1.3/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4= @@ -1671,8 +1686,9 @@ golang.org/x/crypto v0.0.0-20201208171446-5f87f3452ae9/go.mod h1:jdWPYTVW3xRLrWP golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= -golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e h1:gsTQYXdTw2Gq7RBsWvlQ91b+aEQ6bXFUngBGuR8sPpI= golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 h1:HWj/xjIHfjYU5nVXpTM0s39J9CbLn7Cc5a7IC5rwsMQ= +golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -1760,6 +1776,7 @@ golang.org/x/net v0.0.0-20200425230154-ff2c4b7c35a0/go.mod h1:qpuaurCH72eLCgpAm/ golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200602114024-627f9648deb9/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= @@ -1783,6 +1800,7 @@ golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qx golang.org/x/net v0.0.0-20210610132358-84b48f89b13b/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20210825183410-e898025ed96a/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211020060615-d418f374d309 h1:A0lJIi+hcTR6aajJH4YqKWwohY4aW9RO7oRMcdv+HKI= golang.org/x/net v0.0.0-20211020060615-d418f374d309/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -1797,8 +1815,12 @@ golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c h1:pkQiBZBvdos9qq4wBAHqlzuZHEXo07pqV06ef90u1WI= golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20211005180243-6b3c2da341f1 h1:B333XXssMuKQeBwiNODx4TupZy7bf4sxFZnN2ZOcvUE= +golang.org/x/oauth2 v0.0.0-20211005180243-6b3c2da341f1/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -1867,7 +1889,6 @@ golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20191210023423-ac6580df4449/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191220142924-d4481acd189f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200102141924-c96a22e43c9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200107162124-548cf772de50/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1886,6 +1907,7 @@ golang.org/x/sys v0.0.0-20200420163511-1957bb5e6d1f/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200622214017-ed371f2e16b4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1927,14 +1949,22 @@ golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210831042530-f4d43177bf5e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210917161153-d61c044b1678/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211102192858-4dd72447c267 h1:7zYaz3tjChtpayGDzu6H0hDAUM5zIGA2XW7kRNgQ0jc= golang.org/x/sys v0.0.0-20211102192858-4dd72447c267/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d h1:SZxvLBoTP5yHO3Frd4z4vrF+DBX9vMVanchswa69toE= golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b h1:9zKuko04nR4gjZ4+DNjHqRlAJqbJETHwiNKDqTfOjfE= +golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -1953,8 +1983,9 @@ golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxb golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20210611083556-38a9dc6acbc6 h1:Vv0JUPWTyeqUq42B2WJ1FeIDjjvGKoA2Ss+Ts0lAVbs= golang.org/x/time v0.0.0-20210611083556-38a9dc6acbc6/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac h1:7zkz7BUtwNFFqcowJ+RIgu2MaV/MapERkDIy+mwPyjs= +golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -2016,6 +2047,7 @@ golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjs golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= golang.org/x/tools v0.0.0-20200422205258-72e4a01eba43/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200505023115-26f46d2f7ef8/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200509030707-2212a7e161a5/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= @@ -2035,6 +2067,8 @@ golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.7 h1:6j8CgantCy3yc8JGBqkDLMKWqZ0RDU2g1HVgacojGWQ= golang.org/x/tools v0.1.7/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -2072,8 +2106,15 @@ google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjR google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU= google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94= google.golang.org/api v0.47.0/go.mod h1:Wbvgpq1HddcWVtzsVLyfLp8lDg6AA241LmgIL59tHXo= -google.golang.org/api v0.48.0 h1:RDAPWfNFY06dffEXfn7hZF5Fr1ZbnChzfQZAPyBd1+I= google.golang.org/api v0.48.0/go.mod h1:71Pr1vy+TAZRPkPs/xlCf5SsU8WjuAWv1Pfjbtukyy4= +google.golang.org/api v0.50.0/go.mod h1:4bNT5pAuq5ji4SRZm+5QIkjny9JAyVD/3gaSihNefaw= +google.golang.org/api v0.51.0/go.mod h1:t4HdrdoNgyN5cbEfm7Lum0lcLDLiise1F8qDKX00sOU= +google.golang.org/api v0.54.0/go.mod h1:7C4bFFOvVDGXjfDTAsgGwDgAxRDeQ4X8NvUedIt6z3k= +google.golang.org/api v0.55.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE= +google.golang.org/api v0.56.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE= +google.golang.org/api v0.57.0/go.mod h1:dVPlbZyBo2/OjBpmvNdpn2GRm6rPy75jyU7bmhdrMgI= +google.golang.org/api v0.58.0 h1:MDkAbYIB1JpSgCTOCYYoIec/coMlKK4oVbpnBLLcyT0= +google.golang.org/api v0.58.0/go.mod h1:cAbP2FsxoGVNwtgNAmmn3y5G1TWAiVYRmg4yku3lv+E= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= @@ -2122,6 +2163,7 @@ google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6D google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201019141844-1ed22bb0c154/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20201110150050-8816d57aaa9a/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= @@ -2135,6 +2177,23 @@ google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaE google.golang.org/genproto v0.0.0-20210513213006-bf773b8c8384/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A= google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= google.golang.org/genproto v0.0.0-20210604141403-392c879c8b08/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= +google.golang.org/genproto v0.0.0-20210608205507-b6d2f5bf0d7d/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= +google.golang.org/genproto v0.0.0-20210624195500-8bfb893ecb84/go.mod h1:SzzZ/N+nwJDaO1kznhnlzqS8ocJICar6hYhVyhi++24= +google.golang.org/genproto v0.0.0-20210713002101-d411969a0d9a/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k= +google.golang.org/genproto v0.0.0-20210716133855-ce7ef5c701ea/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k= +google.golang.org/genproto v0.0.0-20210728212813-7823e685a01f/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48= +google.golang.org/genproto v0.0.0-20210805201207-89edb61ffb67/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48= +google.golang.org/genproto v0.0.0-20210813162853-db860fec028c/go.mod h1:cFeNkxwySK631ADgubI+/XFU/xp8FD5KIVV4rj8UC5w= +google.golang.org/genproto v0.0.0-20210821163610-241b8fcbd6c8/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210828152312-66f60bf46e71/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210831024726-fe130286e0e2/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210903162649-d08c68adba83/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210909211513-a8c4777a87af/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210917145530-b395a37504d4/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210921142501-181ce0d877f6/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20210924002016-3dee208752a0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20211018162055-cf77aa76bad2/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20211019152133-63b7e35f4404/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/genproto v0.0.0-20211021150943-2b146023228c h1:FqrtZMB5Wr+/RecOM3uPJNPfWR8Upb5hAPnt7PU6i4k= google.golang.org/genproto v0.0.0-20211021150943-2b146023228c/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/grpc v0.0.0-20160317175043-d3ddb4469d5a/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= @@ -2167,6 +2226,8 @@ google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAG google.golang.org/grpc v1.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= google.golang.org/grpc v1.37.1/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= +google.golang.org/grpc v1.39.0/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= +google.golang.org/grpc v1.39.1/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= google.golang.org/grpc v1.41.0 h1:f+PlOh7QV4iIJkPrx5NQ7qaNGFQ3OTse67yaDHfju4E= google.golang.org/grpc v1.41.0/go.mod h1:U3l9uK9J0sini8mHphKoXyaqDA/8VyGnDee1zzIUK6k= @@ -2261,14 +2322,16 @@ k8s.io/api v0.17.5/go.mod h1:0zV5/ungglgy2Rlm3QK8fbxkXVs+BSJWpJP/+8gUVLY= k8s.io/api v0.20.1/go.mod h1:KqwcCVogGxQY3nBlRpwt+wpAMF/KjaCc7RpywacvqUo= k8s.io/api v0.20.4/go.mod h1:++lNL1AJMkDymriNniQsWRkMDzRaX2Y/POTUi8yvqYQ= k8s.io/api v0.20.6/go.mod h1:X9e8Qag6JV/bL5G6bU8sdVRltWKmdHsFUGS3eVndqE8= -k8s.io/api v0.21.1 h1:94bbZ5NTjdINJEdzOkpS4vdPhkb1VFpTYC9zh43f75c= k8s.io/api v0.21.1/go.mod h1:FstGROTmsSHBarKc8bylzXih8BLNYTiS3TZcsoEDg2s= +k8s.io/api v0.23.0 h1:WrL1gb73VSC8obi8cuYETJGXEoFNEh3LU0Pt+Sokgro= +k8s.io/api v0.23.0/go.mod h1:8wmDdLBHBNxtOIytwLstXt5E9PddnZb0GaMcqsvDBpg= k8s.io/apimachinery v0.17.5/go.mod h1:ioIo1G/a+uONV7Tv+ZmCbMG1/a3kVw5YcDdncd8ugQ0= k8s.io/apimachinery v0.20.1/go.mod h1:WlLqWAHZGg07AeltaI0MV5uk1Omp8xaN0JGLY6gkRpU= k8s.io/apimachinery v0.20.4/go.mod h1:WlLqWAHZGg07AeltaI0MV5uk1Omp8xaN0JGLY6gkRpU= k8s.io/apimachinery v0.20.6/go.mod h1:ejZXtW1Ra6V1O5H8xPBGz+T3+4gfkTCeExAHKU57MAc= -k8s.io/apimachinery v0.21.1 h1:Q6XuHGlj2xc+hlMCvqyYfbv3H7SRGn2c8NycxJquDVs= k8s.io/apimachinery v0.21.1/go.mod h1:jbreFvJo3ov9rj7eWT7+sYiRx+qZuCYXwWT1bcDswPY= +k8s.io/apimachinery v0.23.0 h1:mIfWRMjBuMdolAWJ3Fd+aPTMv3X9z+waiARMpvvb0HQ= +k8s.io/apimachinery v0.23.0/go.mod h1:fFCTTBKvKcwTPFzjlcxp91uPFZr+JA0FubU4fLzzFYc= k8s.io/apiserver v0.20.1/go.mod h1:ro5QHeQkgMS7ZGpvf4tSMx6bBOgPfE+f52KwvXfScaU= k8s.io/apiserver v0.20.4/go.mod h1:Mc80thBKOyy7tbvFtB4kJv1kbdD0eIH8k8vianJcbFM= k8s.io/apiserver v0.20.6/go.mod h1:QIJXNt6i6JB+0YQRNcS0hdRHJlMhflFmsBDeSgT1r8Q= @@ -2276,8 +2339,9 @@ k8s.io/client-go v0.17.5/go.mod h1:S8uZpBpjJJdEH/fEyxcqg7Rn0P5jH+ilkgBHjriSmNo= k8s.io/client-go v0.20.1/go.mod h1:/zcHdt1TeWSd5HoUe6elJmHSQ6uLLgp4bIJHVEuy+/Y= k8s.io/client-go v0.20.4/go.mod h1:LiMv25ND1gLUdBeYxBIwKpkSC5IsozMMmOOeSJboP+k= k8s.io/client-go v0.20.6/go.mod h1:nNQMnOvEUEsOzRRFIIkdmYOjAZrC8bgq0ExboWSU1I0= -k8s.io/client-go v0.21.1 h1:bhblWYLZKUu+pm50plvQF8WpY6TXdRRtcS/K9WauOj4= k8s.io/client-go v0.21.1/go.mod h1:/kEw4RgW+3xnBGzvp9IWxKSNA+lXn3A7AuH3gdOAzLs= +k8s.io/client-go v0.23.0 h1:vcsOqyPq7XV3QmQRCBH/t9BICJM9Q1M18qahjv+rebY= +k8s.io/client-go v0.23.0/go.mod h1:hrDnpnK1mSr65lHHcUuIZIXDgEbzc7/683c6hyG4jTA= k8s.io/component-base v0.20.1/go.mod h1:guxkoJnNoh8LNrbtiQOlyp2Y2XFCZQmrcg2n/DeYNLk= k8s.io/component-base v0.20.4/go.mod h1:t4p9EdiagbVCJKrQ1RsA5/V4rFQNDfRlevJajlGwgjI= k8s.io/component-base v0.20.6/go.mod h1:6f1MPBAeI+mvuts3sIdtpjljHWBQ2cIy38oBIWMYnrM= @@ -2287,24 +2351,30 @@ k8s.io/cri-api v0.20.4/go.mod h1:2JRbKt+BFLTjtrILYVqQK5jqhI+XNdF6UiGMgczeBCI= k8s.io/cri-api v0.20.6/go.mod h1:ew44AjNXwyn1s0U4xCKGodU7J1HzBeZ1MpGrpa5r8Yc= k8s.io/gengo v0.0.0-20190128074634-0689ccc1d7d6/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= +k8s.io/gengo v0.0.0-20210813121822-485abfe95c7c/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= k8s.io/klog v0.0.0-20181102134211-b9b56d5dfc92/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= k8s.io/klog v0.3.0/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= k8s.io/klog v1.0.0 h1:Pt+yjF5aB1xDSVbau4VsWe+dQNzA0qv1LlXdC2dF6Q8= k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I= k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE= +k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= k8s.io/klog/v2 v2.4.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= k8s.io/klog/v2 v2.8.0/go.mod h1:hy9LJ/NvuK+iVyP4Ehqva4HxZG/oXyIS3n3Jmire4Ec= -k8s.io/klog/v2 v2.9.0 h1:D7HV+n1V57XeZ0m6tdRkfknthUaM06VFbWldOFh8kzM= k8s.io/klog/v2 v2.9.0/go.mod h1:hy9LJ/NvuK+iVyP4Ehqva4HxZG/oXyIS3n3Jmire4Ec= +k8s.io/klog/v2 v2.30.0 h1:bUO6drIvCIsvZ/XFgfxoGFQU/a4Qkh0iAlvUR7vlHJw= +k8s.io/klog/v2 v2.30.0/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= k8s.io/kube-openapi v0.0.0-20200316234421-82d701f24f9d/go.mod h1:F+5wygcW0wmRTnM3cOgIqGivxkwSWIWT5YdsDbeAOaU= k8s.io/kube-openapi v0.0.0-20201113171705-d219536bb9fd/go.mod h1:WOJ3KddDSol4tAGcJo0Tvi+dK12EcqSLqcWsryKMpfM= -k8s.io/kube-openapi v0.0.0-20210305001622-591a79e4bda7 h1:vEx13qjvaZ4yfObSSXW7BrMc/KQBBT/Jyee8XtLf4x0= k8s.io/kube-openapi v0.0.0-20210305001622-591a79e4bda7/go.mod h1:wXW5VT87nVfh/iLV8FpR2uDvrFyomxbtb1KivDbvPTE= +k8s.io/kube-openapi v0.0.0-20211115234752-e816edb12b65 h1:E3J9oCLlaobFUqsjG9DfKbP2BmgwBL2p7pn0A3dG9W4= +k8s.io/kube-openapi v0.0.0-20211115234752-e816edb12b65/go.mod h1:sX9MT8g7NVZM5lVL/j8QyCCJe8YSMW30QvGZWaCIDIk= k8s.io/kubernetes v1.13.0/go.mod h1:ocZa8+6APFNC2tX1DZASIbocyYT5jHzqFVsY5aoB7Jk= k8s.io/utils v0.0.0-20191114184206-e782cd3c129f/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew= k8s.io/utils v0.0.0-20200414100711-2df71ebbae66/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= -k8s.io/utils v0.0.0-20201110183641-67b214c5f920 h1:CbnUZsM497iRC5QMVkHwyl8s2tB3g7yaSHkYPkpgelw= k8s.io/utils v0.0.0-20201110183641-67b214c5f920/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= +k8s.io/utils v0.0.0-20210802155522-efc7438f0176/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= +k8s.io/utils v0.0.0-20210930125809-cb0fa318a74b h1:wxEMGetGMur3J1xuGLQY7GEQYg9bZxKn3tKo5k/eYcs= +k8s.io/utils v0.0.0-20210930125809-cb0fa318a74b/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= kernel.org/pub/linux/libs/security/libcap/cap v1.2.57 h1:2nmqI+aw7EQZuelYktkQHBE4jESD2tOR+lOJEnv/Apo= kernel.org/pub/linux/libs/security/libcap/cap v1.2.57/go.mod h1:uI99C3r4SXvJeuqoEtx/eWt7UbmfqqZ80H8q+9t/A7I= kernel.org/pub/linux/libs/security/libcap/psx v1.2.57 h1:NOFATXSf5z/cMR3HIwQ3Xrd3nwnWl5xThmNr5U/F0pI= @@ -2315,11 +2385,14 @@ rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.14/go.mod h1:LEScyzhFmoF5pso/YSeBstl57mOzx9xlU9n85RGrDQg= sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.15/go.mod h1:LEScyzhFmoF5pso/YSeBstl57mOzx9xlU9n85RGrDQg= +sigs.k8s.io/json v0.0.0-20211020170558-c049b76a60c6 h1:fD1pz4yfdADVNfFmcP2aBEtudwUQ1AlLnRBALr33v3s= +sigs.k8s.io/json v0.0.0-20211020170558-c049b76a60c6/go.mod h1:p4QtZmO4uMYipTQNzagwnNoseA6OxSUutVw05NhYDRs= sigs.k8s.io/structured-merge-diff/v2 v2.0.1/go.mod h1:Wb7vfKAodbKgf6tn1Kl0VvGj7mRH6DGaRcixXEJXTsE= sigs.k8s.io/structured-merge-diff/v4 v4.0.2/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= sigs.k8s.io/structured-merge-diff/v4 v4.0.3/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= -sigs.k8s.io/structured-merge-diff/v4 v4.1.0 h1:C4r9BgJ98vrKnnVCjwCSXcWjWe0NKcUQkmzDXZXGwH8= sigs.k8s.io/structured-merge-diff/v4 v4.1.0/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= +sigs.k8s.io/structured-merge-diff/v4 v4.1.2 h1:Hr/htKFmJEbtMgS/UD0N+gtgctAqz81t3nu+sPzynno= +sigs.k8s.io/structured-merge-diff/v4 v4.1.2/go.mod h1:j/nl6xW8vLS49O8YvXW1ocPhZawJtm+Yrr7PPRQ0Vg4= sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q= sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= diff --git a/heartbeat/Dockerfile b/heartbeat/Dockerfile index 0108b788c35..f4a1faae369 100644 --- a/heartbeat/Dockerfile +++ b/heartbeat/Dockerfile @@ -1,8 +1,8 @@ -FROM golang:1.17.2 +FROM golang:1.17.5 RUN \ apt-get update \ - && apt-get install -y --no-install-recommends \ + && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \ netcat \ python3 \ python3-pip \ diff --git a/heartbeat/Jenkinsfile.yml b/heartbeat/Jenkinsfile.yml index 2eeaf486464..4eae0d100ef 100644 --- a/heartbeat/Jenkinsfile.yml +++ b/heartbeat/Jenkinsfile.yml @@ -49,7 +49,7 @@ stages: macos: mage: "mage build unitTest" platforms: ## override default label in this specific stage. - - "macosx&&x86_64" + - "orka && darwin && poc" when: ## Override the top-level when. comments: - "/test heartbeat for macos" @@ -79,11 +79,6 @@ stages: platforms: ## override default labels in this specific stage. - "windows-10" stage: extended - windows-2008: - mage: "mage build unitTest" - platforms: ## override default labels in this specific stage. - - "windows-2008-r2" - stage: extended windows-8: mage: "mage build unitTest" platforms: ## override default labels in this specific stage. diff --git a/heartbeat/README.md b/heartbeat/README.md index c7eb09fa52f..dad0c6d2bc1 100644 --- a/heartbeat/README.md +++ b/heartbeat/README.md @@ -1,8 +1,8 @@ -# Heartbeat (Experimental) +# Heartbeat Welcome to Heartbeat. -This is a new EXPERIMENTAL beat for testing service availability using PING based on ICMP, TCP or higher level protocols. +This is a beat for testing service availability using PING based on ICMP, TCP or higher level protocols. Ensure that this folder is at the following location: `${GOPATH}/src/github.com/elastic/beats` diff --git a/heartbeat/beater/heartbeat.go b/heartbeat/beater/heartbeat.go index f9623753d3a..0e499ce6f85 100644 --- a/heartbeat/beater/heartbeat.go +++ b/heartbeat/beater/heartbeat.go @@ -20,7 +20,6 @@ package beater import ( "errors" "fmt" - "sync" "syscall" "time" @@ -28,7 +27,6 @@ import ( "github.com/elastic/beats/v7/heartbeat/hbregistry" "github.com/elastic/beats/v7/heartbeat/monitors" "github.com/elastic/beats/v7/heartbeat/monitors/plugin" - "github.com/elastic/beats/v7/heartbeat/monitors/stdfields" "github.com/elastic/beats/v7/heartbeat/scheduler" "github.com/elastic/beats/v7/libbeat/autodiscover" "github.com/elastic/beats/v7/libbeat/beat" @@ -37,7 +35,6 @@ import ( "github.com/elastic/beats/v7/libbeat/common/reload" "github.com/elastic/beats/v7/libbeat/logp" "github.com/elastic/beats/v7/libbeat/management" - "github.com/elastic/beats/v7/x-pack/functionbeat/function/core" _ "github.com/elastic/beats/v7/heartbeat/security" _ "github.com/elastic/beats/v7/libbeat/processors/script" @@ -71,14 +68,14 @@ func New(b *beat.Beat, rawConfig *common.Config) (beat.Beater, error) { } jobConfig := parsedConfig.Jobs - scheduler := scheduler.NewWithLocation(limit, hbregistry.SchedulerRegistry, location, jobConfig) + scheduler := scheduler.Create(limit, hbregistry.SchedulerRegistry, location, jobConfig, parsedConfig.RunOnce) bt := &Heartbeat{ done: make(chan struct{}), config: parsedConfig, scheduler: scheduler, // dynamicFactory is the factory used for dynamic configs, e.g. autodiscover / reload - dynamicFactory: monitors.NewFactory(b.Info, scheduler), + dynamicFactory: monitors.NewFactory(b.Info, scheduler.Add, plugin.GlobalPluginsReg, parsedConfig.RunOnce), } return bt, nil } @@ -89,20 +86,21 @@ func (bt *Heartbeat) Run(b *beat.Beat) error { groups, _ := syscall.Getgroups() logp.Info("Effective user/group ids: %d/%d, with groups: %v", syscall.Geteuid(), syscall.Getegid(), groups) - if bt.config.RunOnce { - err := bt.runRunOnce(b) - if err != nil { - return err - } - return nil - } - + // It is important this appear before we check for run once mode + // In run once mode we depend on these monitors being loaded, but not other more + // dynamic types. stopStaticMonitors, err := bt.RunStaticMonitors(b) if err != nil { return err } defer stopStaticMonitors() + if bt.config.RunOnce { + bt.scheduler.WaitForRunOnce() + logp.Info("Ending run_once run") + return nil + } + if b.Manager.Enabled() { bt.RunCentralMgmtMonitors(b) } @@ -127,9 +125,6 @@ func (bt *Heartbeat) Run(b *beat.Beat) error { defer bt.autodiscover.Stop() } - if err := bt.scheduler.Start(); err != nil { - return err - } defer bt.scheduler.Stop() <-bt.done @@ -138,71 +133,11 @@ func (bt *Heartbeat) Run(b *beat.Beat) error { return nil } -// runRunOnce runs the given config then exits immediately after any queued events have been sent to ES -func (bt *Heartbeat) runRunOnce(b *beat.Beat) error { - logp.Info("Starting run_once run. This is an experimental feature and may be changed or removed in the future!") - - publishClient, err := core.NewSyncClient(logp.NewLogger("run_once mode"), b.Publisher, beat.ClientConfig{}) - if err != nil { - return fmt.Errorf("could not create sync client: %w", err) - } - defer publishClient.Close() - - wg := &sync.WaitGroup{} - for _, cfg := range bt.config.Monitors { - err := runRunOnceSingleConfig(cfg, publishClient, wg) - if err != nil { - logp.Warn("error running run_once config: %s", err) - } - } - - wg.Wait() - publishClient.Wait() - - logp.Info("Ending run_once run") - - return nil -} - -func runRunOnceSingleConfig(cfg *common.Config, publishClient *core.SyncClient, wg *sync.WaitGroup) (err error) { - sf, err := stdfields.ConfigToStdMonitorFields(cfg) - if err != nil { - return fmt.Errorf("could not get stdmon fields: %w", err) - } - pluginFactory, exists := plugin.GlobalPluginsReg.Get(sf.Type) - if !exists { - return fmt.Errorf("no plugin for type: %s", sf.Type) - } - plugin, err := pluginFactory.Make(sf.Type, cfg) - if err != nil { - return err - } - - results := plugin.RunWrapped(sf) - - wg.Add(1) - go func() { - defer wg.Done() - defer plugin.Close() - for { - event := <-results - if event == nil { - break - } - publishClient.Publish(*event) - } - }() - - return nil -} - // RunStaticMonitors runs the `heartbeat.monitors` portion of the yaml config if present. func (bt *Heartbeat) RunStaticMonitors(b *beat.Beat) (stop func(), err error) { - factory := monitors.NewFactory(b.Info, bt.scheduler) - var runners []cfgfile.Runner for _, cfg := range bt.config.Monitors { - created, err := factory.Create(b.Publisher, cfg) + created, err := bt.dynamicFactory.Create(b.Publisher, cfg) if err != nil { if errors.Is(err, monitors.ErrMonitorDisabled) { logp.Info("skipping disabled monitor: %s", err) diff --git a/heartbeat/cmd/root.go b/heartbeat/cmd/root.go index 5a99e97c56f..06f3961c279 100644 --- a/heartbeat/cmd/root.go +++ b/heartbeat/cmd/root.go @@ -18,7 +18,6 @@ package cmd import ( - "fmt" // include all heartbeat specific autodiscovery builders _ "github.com/elastic/beats/v7/heartbeat/autodiscover/builder/hints" @@ -80,10 +79,6 @@ func Initialize(settings instance.Settings) *cmd.BeatsRootCmd { ` setup.ResetFlags() setup.Flags().Bool(cmd.IndexManagementKey, false, "Setup all components related to Elasticsearch index management, including template, ilm policy and rollover alias") - setup.Flags().MarkDeprecated(cmd.TemplateKey, fmt.Sprintf("use --%s instead", cmd.IndexManagementKey)) - setup.Flags().MarkDeprecated(cmd.ILMPolicyKey, fmt.Sprintf("use --%s instead", cmd.IndexManagementKey)) - setup.Flags().Bool(cmd.TemplateKey, false, "Setup index template") - setup.Flags().Bool(cmd.ILMPolicyKey, false, "Setup ILM policy") return rootCmd } diff --git a/heartbeat/docs/fields.asciidoc b/heartbeat/docs/fields.asciidoc index ad0359e269f..1be13cd8827 100644 --- a/heartbeat/docs/fields.asciidoc +++ b/heartbeat/docs/fields.asciidoc @@ -15804,47 +15804,16 @@ type: ip -- - -*`kubernetes.namespace.name`*:: +*`kubernetes.namespace`*:: + -- -Kubernetes namespace name +Kubernetes namespace type: keyword -- -*`kubernetes.namespace.uuid`*:: -+ --- -Kubernetes namespace uuid - - -type: keyword - --- - -*`kubernetes.namespace.labels.*`*:: -+ --- -Kubernetes namespace labels map - - -type: object - --- - -*`kubernetes.namespace.annotations.*`*:: -+ --- -Kubernetes namespace annotations map - - -type: object - --- - *`kubernetes.node.name`*:: + -- diff --git a/heartbeat/heartbeat.reference.yml b/heartbeat/heartbeat.reference.yml index 1eb37188303..aca74cd9e63 100644 --- a/heartbeat/heartbeat.reference.yml +++ b/heartbeat/heartbeat.reference.yml @@ -343,66 +343,6 @@ heartbeat.jobs: # length of its retry interval each time, up to this maximum. #max_retry_interval: 30s - # The spool queue will store events in a local spool file, before - # forwarding the events to the outputs. - # Note: the spool queue is deprecated and will be removed in the future. - # Use the disk queue instead. - # - # The spool file is a circular buffer, which blocks once the file/buffer is full. - # Events are put into a write buffer and flushed once the write buffer - # is full or the flush_timeout is triggered. - # Once ACKed by the output, events are removed immediately from the queue, - # making space for new events to be persisted. - #spool: - # The file namespace configures the file path and the file creation settings. - # Once the file exists, the `size`, `page_size` and `prealloc` settings - # will have no more effect. - #file: - # Location of spool file. The default value is ${path.data}/spool.dat. - #path: "${path.data}/spool.dat" - - # Configure file permissions if file is created. The default value is 0600. - #permissions: 0600 - - # File size hint. The spool blocks, once this limit is reached. The default value is 100 MiB. - #size: 100MiB - - # The files page size. A file is split into multiple pages of the same size. The default value is 4KiB. - #page_size: 4KiB - - # If prealloc is set, the required space for the file is reserved using - # truncate. The default value is true. - #prealloc: true - - # Spool writer settings - # Events are serialized into a write buffer. The write buffer is flushed if: - # - The buffer limit has been reached. - # - The configured limit of buffered events is reached. - # - The flush timeout is triggered. - #write: - # Sets the write buffer size. - #buffer_size: 1MiB - - # Maximum duration after which events are flushed if the write buffer - # is not full yet. The default value is 1s. - #flush.timeout: 1s - - # Number of maximum buffered events. The write buffer is flushed once the - # limit is reached. - #flush.events: 16384 - - # Configure the on-disk event encoding. The encoding can be changed - # between restarts. - # Valid encodings are: json, ubjson, and cbor. - #codec: cbor - #read: - # Reader flush timeout, waiting for more events to become available, so - # to fill a complete batch as required by the outputs. - # If flush_timeout is 0, all available events are forwarded to the - # outputs immediately. - # The default value is 0s. - #flush.timeout: 0s - # Sets the maximum number of CPUs that can be executing simultaneously. The # default is the number of logical CPUs available in the system. #max_procs: @@ -719,6 +659,13 @@ output.elasticsearch: # The pin is a base64 encoded string of the SHA-256 fingerprint. #ssl.ca_sha256: "" + # A root CA HEX encoded fingerprint. During the SSL handshake if the + # fingerprint matches the root CA certificate, it will be added to + # the provided list of root CAs (`certificate_authorities`), if the + # list is empty or not defined, the matching certificate will be the + # only one in the list. Then the normal SSL validation happens. + #ssl.ca_trusted_fingerprint: "" + # Enable Kerberos support. Kerberos is automatically enabled if any Kerberos setting is set. #kerberos.enabled: true @@ -851,6 +798,13 @@ output.elasticsearch: # The pin is a base64 encoded string of the SHA-256 fingerprint. #ssl.ca_sha256: "" + # A root CA HEX encoded fingerprint. During the SSL handshake if the + # fingerprint matches the root CA certificate, it will be added to + # the provided list of root CAs (`certificate_authorities`), if the + # list is empty or not defined, the matching certificate will be the + # only one in the list. Then the normal SSL validation happens. + #ssl.ca_trusted_fingerprint: "" + # The number of times to retry publishing an event after a publishing failure. # After the specified number of retries, the events are typically dropped. # Some Beats, such as Filebeat and Winlogbeat, ignore the max_retries setting @@ -1052,6 +1006,13 @@ output.elasticsearch: # The pin is a base64 encoded string of the SHA-256 fingerprint. #ssl.ca_sha256: "" + # A root CA HEX encoded fingerprint. During the SSL handshake if the + # fingerprint matches the root CA certificate, it will be added to + # the provided list of root CAs (`certificate_authorities`), if the + # list is empty or not defined, the matching certificate will be the + # only one in the list. Then the normal SSL validation happens. + #ssl.ca_trusted_fingerprint: "" + # Enable Kerberos support. Kerberos is automatically enabled if any Kerberos setting is set. #kerberos.enabled: true @@ -1216,6 +1177,13 @@ output.elasticsearch: # The pin is a base64 encoded string of the SHA-256 fingerprint. #ssl.ca_sha256: "" + # A root CA HEX encoded fingerprint. During the SSL handshake if the + # fingerprint matches the root CA certificate, it will be added to + # the provided list of root CAs (`certificate_authorities`), if the + # list is empty or not defined, the matching certificate will be the + # only one in the list. Then the normal SSL validation happens. + #ssl.ca_trusted_fingerprint: "" + # -------------------------------- File Output --------------------------------- #output.file: @@ -1235,7 +1203,7 @@ output.elasticsearch: #path: "/tmp/heartbeat" # Name of the generated files. The default is `heartbeat` and it generates - # files: `heartbeat`, `heartbeat.1`, `heartbeat.2`, etc. + # files: `heartbeat-{datetime}.ndjson`, `heartbeat-{datetime}-1.ndjson`, etc. #filename: heartbeat # Maximum size in kilobytes of each file. When this size is reached, and on @@ -1253,6 +1221,7 @@ output.elasticsearch: # Configure automatic file rotation on every startup. The default is true. #rotate_on_startup: true + # ------------------------------- Console Output ------------------------------- #output.console: # Boolean flag to enable or disable the output module. @@ -1351,19 +1320,13 @@ output.elasticsearch: # Set to false to disable template loading. #setup.template.enabled: true -# Select the kind of index template. From Elasticsearch 7.8, it is possible to -# use component templates. Available options: legacy, component, index. -# By default heartbeat uses the legacy index templates. -#setup.template.type: legacy - # Template name. By default the template name is "heartbeat-%{[agent.version]}" # The template name and pattern has to be set in case the Elasticsearch index pattern is modified. #setup.template.name: "heartbeat-%{[agent.version]}" -# Template pattern. By default the template pattern is "-%{[agent.version]}-*" to apply to the default index settings. -# The first part is the version of the beat and then -* is used to match all daily indices. +# Template pattern. By default the template pattern is "heartbeat-%{[agent.version]}" to apply to the default index settings. # The template name and pattern has to be set in case the Elasticsearch index pattern is modified. -#setup.template.pattern: "heartbeat-%{[agent.version]}-*" +#setup.template.pattern: "heartbeat-%{[agent.version]}" # Path to fields.yml file to generate the template #setup.template.fields: "${path.config}/fields.yml" @@ -1410,17 +1373,8 @@ setup.template.settings: # output.elasticsearch.index is ignored, and the write alias is used to set the # index name. -# Enable ILM support. Valid values are true, false, and auto. When set to auto -# (the default), the Beat uses index lifecycle management when it connects to a -# cluster that supports ILM; otherwise, it creates daily indices. -#setup.ilm.enabled: auto - -# Set the prefix used in the index lifecycle write alias name. The default alias -# name is 'heartbeat-%{[agent.version]}'. -#setup.ilm.rollover_alias: 'heartbeat' - -# Set the rollover index pattern. The default is "%{now/d}-000001". -#setup.ilm.pattern: "{now/d}-000001" +# Enable ILM support. Valid values are true, false. +#setup.ilm.enabled: true # Set the lifecycle policy name. The default policy name is # 'beatname'. @@ -1518,6 +1472,13 @@ setup.kibana: # The pin is a base64 encoded string of the SHA-256 fingerprint. #ssl.ca_sha256: "" + # A root CA HEX encoded fingerprint. During the SSL handshake if the + # fingerprint matches the root CA certificate, it will be added to + # the provided list of root CAs (`certificate_authorities`), if the + # list is empty or not defined, the matching certificate will be the + # only one in the list. Then the normal SSL validation happens. + #ssl.ca_trusted_fingerprint: "" + # ================================== Logging =================================== @@ -1589,11 +1550,6 @@ logging.files: # file. Defaults to true. # rotateonstartup: true - # Rotated files are either suffixed with a number e.g. heartbeat.1 when - # renamed during rotation. Or when set to date, the date is added to - # the end of the file. On rotation a new file is created, older files are untouched. - #suffix: count - # ============================= X-Pack Monitoring ============================== # Heartbeat can export internal metrics to a central Elasticsearch monitoring # cluster. This requires xpack monitoring to be enabled in Elasticsearch. The @@ -1721,6 +1677,13 @@ logging.files: # The pin is a base64 encoded string of the SHA-256 fingerprint. #ssl.ca_sha256: "" + # A root CA HEX encoded fingerprint. During the SSL handshake if the + # fingerprint matches the root CA certificate, it will be added to + # the provided list of root CAs (`certificate_authorities`), if the + # list is empty or not defined, the matching certificate will be the + # only one in the list. Then the normal SSL validation happens. + #ssl.ca_trusted_fingerprint: "" + # Enable Kerberos support. Kerberos is automatically enabled if any Kerberos setting is set. #kerberos.enabled: true diff --git a/heartbeat/include/fields.go b/heartbeat/include/fields.go index d56c982c2e2..e512932b269 100644 --- a/heartbeat/include/fields.go +++ b/heartbeat/include/fields.go @@ -32,5 +32,5 @@ func init() { // AssetFieldsYml returns asset data. // This is the base64 encoded zlib format compressed contents of fields.yml. func AssetFieldsYml() string { - return "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" + return "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" } diff --git a/heartbeat/monitors/active/http/task.go b/heartbeat/monitors/active/http/task.go index f273b0a4cc7..9ee5f3fa1e8 100644 --- a/heartbeat/monitors/active/http/task.go +++ b/heartbeat/monitors/active/http/task.go @@ -45,6 +45,8 @@ import ( "github.com/elastic/beats/v7/libbeat/common/transport/tlscommon" ) +type requestFactory func() (*http.Request, error) + func newHTTPMonitorHostJob( addr string, config *Config, @@ -54,10 +56,7 @@ func newHTTPMonitorHostJob( validator multiValidator, ) (jobs.Job, error) { - request, err := buildRequest(addr, config, enc) - if err != nil { - return nil, err - } + var reqFactory requestFactory = func() (*http.Request, error) { return buildRequest(addr, config, enc) } return jobs.MakeSimpleJob(func(event *beat.Event) error { var redirects []string @@ -67,7 +66,13 @@ func newHTTPMonitorHostJob( Transport: transport, Timeout: config.Transport.Timeout, } - _, _, err := execPing(event, client, request, body, config.Transport.Timeout, validator, config.Response) + + req, err := reqFactory() + if err != nil { + return fmt.Errorf("could not make http request: %w", err) + } + + _, _, err = execPing(event, client, req, body, config.Transport.Timeout, validator, config.Response) if len(redirects) > 0 { event.PutValue("http.response.redirects", redirects) } @@ -84,17 +89,14 @@ func newHTTPMonitorIPsJob( validator multiValidator, ) (jobs.Job, error) { - req, err := buildRequest(addr, config, enc) - if err != nil { - return nil, err - } + var reqFactory requestFactory = func() (*http.Request, error) { return buildRequest(addr, config, enc) } - hostname, port, err := splitHostnamePort(req) + hostname, port, err := splitHostnamePort(addr) if err != nil { return nil, err } - pingFactory := createPingFactory(config, port, tls, req, body, validator) + pingFactory := createPingFactory(config, port, tls, reqFactory, body, validator) job, err := monitors.MakeByHostJob(hostname, config.Mode, monitors.NewStdResolver(), pingFactory) return job, err @@ -104,14 +106,19 @@ func createPingFactory( config *Config, port uint16, tls *tlscommon.TLSConfig, - request *http.Request, + reqFactory requestFactory, body []byte, validator multiValidator, ) func(*net.IPAddr) jobs.Job { timeout := config.Transport.Timeout - isTLS := request.URL.Scheme == "https" return monitors.MakePingIPFactory(func(event *beat.Event, ip *net.IPAddr) error { + req, err := reqFactory() + if err != nil { + return fmt.Errorf("could not create http request: %w", err) + } + isTLS := req.URL.Scheme == "https" + addr := net.JoinHostPort(ip.String(), strconv.Itoa(int(port))) d := &dialchain.DialerChain{ Net: dialchain.MakeConstAddrDialer(addr, dialchain.TCPDialer(timeout)), @@ -163,7 +170,7 @@ func createPingFactory( Transport: httpcommon.HeaderRoundTripper(transport, map[string]string{"User-Agent": userAgent}), } - _, end, err := execPing(event, client, request, body, timeout, validator, config.Response) + _, end, err := execPing(event, client, req, body, timeout, validator, config.Response) cbMutex.Lock() defer cbMutex.Unlock() @@ -313,11 +320,15 @@ func execRequest(client *http.Client, req *http.Request) (start time.Time, resp return start, resp, nil } -func splitHostnamePort(requ *http.Request) (string, uint16, error) { - host := requ.URL.Host +func splitHostnamePort(addr string) (string, uint16, error) { + u, err := url.Parse(addr) + if err != nil { + return "", 0, err + } + host := u.Host // Try to add a default port if needed if strings.LastIndex(host, ":") == -1 { - switch requ.URL.Scheme { + switch u.Scheme { case urlSchemaHTTP: host += ":80" case urlSchemaHTTPS: @@ -330,7 +341,7 @@ func splitHostnamePort(requ *http.Request) (string, uint16, error) { } p, err := strconv.ParseUint(port, 10, 16) if err != nil { - return "", 0, fmt.Errorf("'%v' is no valid port number in '%v'", port, requ.URL.Host) + return "", 0, fmt.Errorf("'%v' is no valid port number in '%v'", port, u.Host) } return host, uint16(p), nil } diff --git a/heartbeat/monitors/active/http/task_test.go b/heartbeat/monitors/active/http/task_test.go index 358a4a6ec2b..71b9720cbed 100644 --- a/heartbeat/monitors/active/http/task_test.go +++ b/heartbeat/monitors/active/http/task_test.go @@ -106,7 +106,7 @@ func TestSplitHostnamePort(t *testing.T) { request := &http.Request{ URL: url, } - host, port, err := splitHostnamePort(request) + host, port, err := splitHostnamePort(request.URL.String()) if err != nil { if test.expectedError == nil { diff --git a/heartbeat/monitors/factory.go b/heartbeat/monitors/factory.go index d2b013d3c01..11a3b2d9ecd 100644 --- a/heartbeat/monitors/factory.go +++ b/heartbeat/monitors/factory.go @@ -19,6 +19,7 @@ package monitors import ( "fmt" + "sync" "github.com/elastic/beats/v7/heartbeat/monitors/plugin" "github.com/elastic/beats/v7/heartbeat/monitors/stdfields" @@ -27,6 +28,7 @@ import ( "github.com/elastic/beats/v7/libbeat/cfgfile" "github.com/elastic/beats/v7/libbeat/common" "github.com/elastic/beats/v7/libbeat/common/fmtstr" + "github.com/elastic/beats/v7/libbeat/logp" "github.com/elastic/beats/v7/libbeat/processors" "github.com/elastic/beats/v7/libbeat/processors/actions" "github.com/elastic/beats/v7/libbeat/processors/add_data_stream" @@ -37,8 +39,13 @@ import ( // RunnerFactory that can be used to create cfg.Runner cast versions of Monitor // suitable for config reloading. type RunnerFactory struct { - info beat.Info - sched *scheduler.Scheduler + info beat.Info + addTask scheduler.AddTask + byId map[string]*Monitor + mtx *sync.Mutex + pluginsReg *plugin.PluginsReg + logger *logp.Logger + runOnce bool } type publishSettings struct { @@ -61,8 +68,16 @@ type publishSettings struct { } // NewFactory takes a scheduler and creates a RunnerFactory that can create cfgfile.Runner(Monitor) objects. -func NewFactory(info beat.Info, sched *scheduler.Scheduler) *RunnerFactory { - return &RunnerFactory{info, sched} +func NewFactory(info beat.Info, addTask scheduler.AddTask, pluginsReg *plugin.PluginsReg, runOnce bool) *RunnerFactory { + return &RunnerFactory{ + info: info, + addTask: addTask, + byId: map[string]*Monitor{}, + mtx: &sync.Mutex{}, + pluginsReg: pluginsReg, + logger: logp.NewLogger("monitor-factory"), + runOnce: runOnce, + } } // Create makes a new Runner for a new monitor with the given Config. @@ -78,8 +93,45 @@ func (f *RunnerFactory) Create(p beat.Pipeline, c *common.Config) (cfgfile.Runne } p = pipetool.WithClientConfigEdit(p, configEditor) - monitor, err := newMonitor(c, plugin.GlobalPluginsReg, p, f.sched) - return monitor, err + + f.mtx.Lock() + defer f.mtx.Unlock() + + // This is a callback executed on stop of a monitor, it ensures we delete the entry in + // byId. + // It's a little tricky, because it handles the problem of this function being + // occasionally invoked twice in one stack. + // f.mtx would be locked given that golang does not support reentrant locks. + // The important thing is clearing the map, not ensuring it stops exactly on time + // so we can defer its removal from the map with a goroutine, thus breaking out of the current stack + // and ensuring the cleanup happen soon enough. + safeStop := func(m *Monitor) { + go func() { + // We can safely relock now, since we're in a new goroutine. + f.mtx.Lock() + defer f.mtx.Unlock() + + // If this element hasn't already been removed or replaced with a new + // instance delete it from the map. Check monitor identity via pointer equality. + if curM, ok := f.byId[m.stdFields.ID]; ok && curM == m { + delete(f.byId, m.stdFields.ID) + } + }() + } + monitor, err := newMonitor(c, f.pluginsReg, p, f.addTask, safeStop, f.runOnce) + if err != nil { + return nil, err + } + + if mon, ok := f.byId[monitor.stdFields.ID]; ok { + f.logger.Warnf("monitor ID %s is configured for multiple monitors! IDs should be unique values, last seen config will win", monitor.stdFields.ID) + // Stop the old monitor, since we'll swap our new one in place + mon.Stop() + } + + f.byId[monitor.stdFields.ID] = monitor + + return monitor, nil } // CheckConfig checks to see if the given monitor config is valid. diff --git a/heartbeat/monitors/factory_test.go b/heartbeat/monitors/factory_test.go index 27b119392ee..c395050aaa1 100644 --- a/heartbeat/monitors/factory_test.go +++ b/heartbeat/monitors/factory_test.go @@ -20,22 +20,26 @@ package monitors import ( "regexp" "testing" + "time" "github.com/stretchr/testify/require" + "github.com/elastic/beats/v7/heartbeat/scheduler" "github.com/elastic/beats/v7/libbeat/beat" "github.com/elastic/beats/v7/libbeat/beat/events" "github.com/elastic/beats/v7/libbeat/common" "github.com/elastic/beats/v7/libbeat/common/fmtstr" + "github.com/elastic/beats/v7/libbeat/monitoring" "github.com/elastic/beats/v7/libbeat/processors/add_data_stream" ) +var binfo = beat.Info{ + Beat: "heartbeat", + IndexPrefix: "heartbeat", + Version: "8.0.0", +} + func TestPreProcessors(t *testing.T) { - binfo := beat.Info{ - Beat: "heartbeat", - IndexPrefix: "heartbeat", - Version: "8.0.0", - } tests := map[string]struct { settings publishSettings expectedIndex string @@ -143,3 +147,51 @@ func TestPreProcessors(t *testing.T) { }) } } + +func TestDuplicateMonitorIDs(t *testing.T) { + serverMonConf := mockPluginConf(t, "custom", "@every 1ms", "http://example.net") + badConf := mockBadPluginConf(t, "custom", "@every 1ms") + reg, built, closed := mockPluginsReg() + pipelineConnector := &MockPipelineConnector{} + + sched := scheduler.Create(1, monitoring.NewRegistry(), time.Local, nil, false) + defer sched.Stop() + + f := NewFactory(binfo, sched.Add, reg, false) + makeTestMon := func() (*Monitor, error) { + mIface, err := f.Create(pipelineConnector, serverMonConf) + if mIface == nil { + return nil, err + } else { + return mIface.(*Monitor), err + } + } + + // Ensure that an error is returned on a bad config + _, m0Err := newMonitor(badConf, reg, pipelineConnector, sched.Add, nil, false) + require.Error(t, m0Err) + + // Would fail if the previous newMonitor didn't free the monitor.id + m1, m1Err := makeTestMon() + require.NoError(t, m1Err) + m1.Start() + m2, m2Err := makeTestMon() + require.NoError(t, m2Err) + m2.Start() + // Change the name so we can ensure that this is the currently active monitor + m2.stdFields.Name = "mon2" + // This used to trigger an error, but shouldn't any longer, we just log + // the error, and ensure the last monitor wins + require.NoError(t, m2Err) + + m, ok := f.byId[m2.stdFields.ID] + require.True(t, ok) + require.Equal(t, m2.stdFields.Name, m.stdFields.Name) + m1.Stop() + m2.Stop() + + // 3 are counted as built, even the bad config + require.Equal(t, 3, built.Load()) + // Only 2 closes, because the bad config isn't closed + require.Equal(t, 2, closed.Load()) +} diff --git a/heartbeat/monitors/monitor.go b/heartbeat/monitors/monitor.go index f93483d7933..669579e31aa 100644 --- a/heartbeat/monitors/monitor.go +++ b/heartbeat/monitors/monitor.go @@ -32,22 +32,34 @@ import ( "github.com/elastic/beats/v7/libbeat/beat" "github.com/elastic/beats/v7/libbeat/common" "github.com/elastic/beats/v7/libbeat/logp" + "github.com/elastic/beats/v7/libbeat/publisher/pipeline" ) // ErrMonitorDisabled is returned when the monitor plugin is marked as disabled. var ErrMonitorDisabled = errors.New("monitor not loaded, plugin is disabled") +const ( + MON_INIT = iota + MON_STARTED + MON_STOPPED +) + +type WrappedClient struct { + Publish func(event beat.Event) + Close func() error + wait func() +} + // Monitor represents a configured recurring monitoring configuredJob loaded from a config file. Starting it // will cause it to run with the given scheduler until Stop() is called. type Monitor struct { stdFields stdfields.StdMonitorFields pluginName string config *common.Config - registrar *plugin.PluginsReg - uniqueName string - scheduler *scheduler.Scheduler + addTask scheduler.AddTask configuredJobs []*configuredJob enabled bool + state int // endpoints is a count of endpoints this monitor measures. endpoints int // internalsMtx is used to synchronize access to critical @@ -60,6 +72,8 @@ type Monitor struct { // stats is the countersRecorder used to record lifecycle events // for global metrics + telemetry stats plugin.RegistryRecorder + + runOnce bool } // String prints a description of the monitor in a threadsafe way. It is important that this use threadsafe @@ -69,32 +83,22 @@ func (m *Monitor) String() string { } func checkMonitorConfig(config *common.Config, registrar *plugin.PluginsReg) error { - m, err := newMonitor(config, registrar, nil, nil) - if m != nil { - m.Stop() // Stop the monitor to free up the ID from uniqueness checks - } - return err -} - -// uniqueMonitorIDs is used to keep track of explicitly configured monitor IDs and ensure no duplication within a -// given heartbeat instance. -var uniqueMonitorIDs sync.Map - -// ErrDuplicateMonitorID is returned when a monitor attempts to start using an ID already in use by another monitor. -type ErrDuplicateMonitorID struct{ ID string } + _, err := newMonitor(config, registrar, nil, nil, nil, false) -func (e ErrDuplicateMonitorID) Error() string { - return fmt.Sprintf("monitor ID %s is configured for multiple monitors! IDs must be unique values.", e.ID) + return err } -// newMonitor Creates a new monitor, without leaking resources in the event of an error. +// newMonitor creates a new monitor, without leaking resources in the event of an error. +// you do not need to call Stop(), it will be safely garbage collected unless Start is called. func newMonitor( config *common.Config, registrar *plugin.PluginsReg, pipelineConnector beat.PipelineConnector, - scheduler *scheduler.Scheduler, + taskAdder scheduler.AddTask, + onStop func(*Monitor), + runOnce bool, ) (*Monitor, error) { - m, err := newMonitorUnsafe(config, registrar, pipelineConnector, scheduler) + m, err := newMonitorUnsafe(config, registrar, pipelineConnector, taskAdder, onStop, runOnce) if m != nil && err != nil { m.Stop() } @@ -107,7 +111,9 @@ func newMonitorUnsafe( config *common.Config, registrar *plugin.PluginsReg, pipelineConnector beat.PipelineConnector, - scheduler *scheduler.Scheduler, + addTask scheduler.AddTask, + onStop func(*Monitor), + runOnce bool, ) (*Monitor, error) { // Extract just the Id, Type, and Enabled fields from the config // We'll parse things more precisely later once we know what exact type of @@ -129,20 +135,17 @@ func newMonitorUnsafe( m := &Monitor{ stdFields: standardFields, pluginName: pluginFactory.Name, - scheduler: scheduler, + addTask: addTask, configuredJobs: []*configuredJob{}, pipelineConnector: pipelineConnector, internalsMtx: sync.Mutex{}, config: config, stats: pluginFactory.Stats, + state: MON_INIT, + runOnce: runOnce, } - if m.stdFields.ID != "" { - // Ensure we don't have duplicate IDs - if _, loaded := uniqueMonitorIDs.LoadOrStore(m.stdFields.ID, m); loaded { - return m, ErrDuplicateMonitorID{m.stdFields.ID} - } - } else { + if m.stdFields.ID == "" { // If there's no explicit ID generate one hash, err := m.configHash() if err != nil { @@ -152,7 +155,14 @@ func newMonitorUnsafe( } p, err := pluginFactory.Create(config) - m.close = p.Close + + m.close = func() error { + if onStop != nil { + onStop(m) + } + return p.Close() + } + wrappedJobs := wrappers.WrapCommon(p.Jobs, m.stdFields) m.endpoints = p.Endpoints @@ -213,18 +223,46 @@ func (m *Monitor) Start() { defer m.internalsMtx.Unlock() for _, t := range m.configuredJobs { - t.Start() + if m.runOnce { + client, err := pipeline.NewSyncClient(logp.NewLogger("monitor_task"), t.monitor.pipelineConnector, beat.ClientConfig{}) + if err != nil { + logp.Err("could not start monitor: %v", err) + continue + } + t.Start(&WrappedClient{ + Publish: func(event beat.Event) { + client.Publish(event) + }, + Close: client.Close, + wait: client.Wait, + }) + } else { + client, err := m.pipelineConnector.Connect() + if err != nil { + logp.Err("could not start monitor: %v", err) + continue + } + t.Start(&WrappedClient{ + Publish: client.Publish, + Close: client.Close, + wait: func() {}, + }) + } } m.stats.StartMonitor(int64(m.endpoints)) + m.state = MON_STARTED } -// Stop stops the Monitor's execution in its configured scheduler. -// This is safe to call even if the Monitor was never started. +// Stop stops the monitor without freeing it in global dedup +// needed by dedup itself to avoid a reentrant lock. func (m *Monitor) Stop() { m.internalsMtx.Lock() defer m.internalsMtx.Unlock() - defer m.freeID() + + if m.state == MON_STOPPED { + return + } for _, t := range m.configuredJobs { t.Stop() @@ -238,9 +276,5 @@ func (m *Monitor) Stop() { } m.stats.StopMonitor(int64(m.endpoints)) -} - -func (m *Monitor) freeID() { - // Free up the monitor ID for reuse - uniqueMonitorIDs.Delete(m.stdFields.ID) + m.state = MON_STOPPED } diff --git a/heartbeat/monitors/monitor_test.go b/heartbeat/monitors/monitor_test.go index 0f00828bf9b..bbcd5b9b74c 100644 --- a/heartbeat/monitors/monitor_test.go +++ b/heartbeat/monitors/monitor_test.go @@ -34,12 +34,10 @@ func TestMonitor(t *testing.T) { reg, built, closed := mockPluginsReg() pipelineConnector := &MockPipelineConnector{} - sched := scheduler.New(1, monitoring.NewRegistry()) - err := sched.Start() - require.NoError(t, err) + sched := scheduler.Create(1, monitoring.NewRegistry(), time.Local, nil, false) defer sched.Stop() - mon, err := newMonitor(serverMonConf, reg, pipelineConnector, sched) + mon, err := newMonitor(serverMonConf, reg, pipelineConnector, sched.Add, nil, false) require.NoError(t, err) mon.Start() @@ -78,54 +76,16 @@ func TestMonitor(t *testing.T) { assert.Equal(t, true, pcClient.closed) } -func TestDuplicateMonitorIDs(t *testing.T) { - serverMonConf := mockPluginConf(t, "custom", "@every 1ms", "http://example.net") - badConf := mockBadPluginConf(t, "custom", "@every 1ms") - reg, built, closed := mockPluginsReg() - pipelineConnector := &MockPipelineConnector{} - - sched := scheduler.New(1, monitoring.NewRegistry()) - err := sched.Start() - require.NoError(t, err) - defer sched.Stop() - - makeTestMon := func() (*Monitor, error) { - return newMonitor(serverMonConf, reg, pipelineConnector, sched) - } - - // Ensure that an error is returned on a bad config - _, m0Err := newMonitor(badConf, reg, pipelineConnector, sched) - require.Error(t, m0Err) - - // Would fail if the previous newMonitor didn't free the monitor.id - m1, m1Err := makeTestMon() - require.NoError(t, m1Err) - _, m2Err := makeTestMon() - require.Error(t, m2Err) - m1.Stop() - m3, m3Err := makeTestMon() - require.NoError(t, m3Err) - m3.Stop() - - // We count 3 because built doesn't count successful builds, - // just attempted creations of monitors - require.Equal(t, 3, built.Load()) - // Only one stops because the others errored on create - require.Equal(t, 2, closed.Load()) - require.NoError(t, m3Err) -} - func TestCheckInvalidConfig(t *testing.T) { serverMonConf := mockInvalidPluginConf(t) reg, built, closed := mockPluginsReg() pipelineConnector := &MockPipelineConnector{} - sched := scheduler.New(1, monitoring.NewRegistry()) - err := sched.Start() - require.NoError(t, err) + sched := scheduler.Create(1, monitoring.NewRegistry(), time.Local, nil, false) defer sched.Stop() - m, err := newMonitor(serverMonConf, reg, pipelineConnector, sched) + m, err := newMonitor(serverMonConf, reg, pipelineConnector, sched.Add, nil, false) + require.Error(t, err) // This could change if we decide the contract for newMonitor should always return a monitor require.Nil(t, m, "For this test to work we need a nil value for the monitor.") diff --git a/heartbeat/monitors/task.go b/heartbeat/monitors/task.go index d9794da16d1..11b013a9871 100644 --- a/heartbeat/monitors/task.go +++ b/heartbeat/monitors/task.go @@ -37,7 +37,7 @@ type configuredJob struct { config jobConfig monitor *Monitor cancelFn context.CancelFunc - client beat.Client + client *WrappedClient } func newConfiguredJob(job jobs.Job, config jobConfig, monitor *Monitor) (*configuredJob, error) { @@ -74,17 +74,18 @@ func (t *configuredJob) makeSchedulerTaskFunc() scheduler.TaskFunc { } // Start schedules this configuredJob for execution. -func (t *configuredJob) Start() { +func (t *configuredJob) Start(client *WrappedClient) { var err error - t.client, err = t.monitor.pipelineConnector.Connect() + t.client = client + if err != nil { logp.Err("could not start monitor: %v", err) return } tf := t.makeSchedulerTaskFunc() - t.cancelFn, err = t.monitor.scheduler.Add(t.config.Schedule, t.monitor.stdFields.ID, tf, t.config.Type) + t.cancelFn, err = t.monitor.addTask(t.config.Schedule, t.monitor.stdFields.ID, tf, t.config.Type, client.wait) if err != nil { logp.Err("could not start monitor: %v", err) } @@ -100,7 +101,7 @@ func (t *configuredJob) Stop() { } } -func runPublishJob(job jobs.Job, client beat.Client) []scheduler.TaskFunc { +func runPublishJob(job jobs.Job, client *WrappedClient) []scheduler.TaskFunc { event := &beat.Event{ Fields: common.MapStr{}, } diff --git a/heartbeat/monitors/task_test.go b/heartbeat/monitors/task_test.go index dc0aa7ab23c..64e86b35b88 100644 --- a/heartbeat/monitors/task_test.go +++ b/heartbeat/monitors/task_test.go @@ -96,7 +96,11 @@ func Test_runPublishJob(t *testing.T) { for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { client := &MockBeatClient{} - queue := runPublishJob(tc.job, client) + queue := runPublishJob(tc.job, &WrappedClient{ + Publish: client.Publish, + Close: client.Close, + wait: func() {}, + }) for { if len(queue) == 0 { break diff --git a/heartbeat/monitors/wrappers/monitors.go b/heartbeat/monitors/wrappers/wrappers.go similarity index 96% rename from heartbeat/monitors/wrappers/monitors.go rename to heartbeat/monitors/wrappers/wrappers.go index dca3a8b70de..c9e0c79c105 100644 --- a/heartbeat/monitors/wrappers/monitors.go +++ b/heartbeat/monitors/wrappers/wrappers.go @@ -51,7 +51,7 @@ func WrapLightweight(js []jobs.Job, stdMonFields stdfields.StdMonitorFields) []j jobs.WrapAll( js, addMonitorMeta(stdMonFields, len(js) > 1), - addMonitorStatus(stdMonFields.Type), + addMonitorStatus(stdMonFields.Type, false), addMonitorDuration, ), func() jobs.JobWrapper { @@ -66,7 +66,7 @@ func WrapBrowser(js []jobs.Job, stdMonFields stdfields.StdMonitorFields) []jobs. return jobs.WrapAll( js, addMonitorMeta(stdMonFields, len(js) > 1), - addMonitorStatus(stdMonFields.Type), + addMonitorStatus(stdMonFields.Type, true), ) } @@ -142,12 +142,18 @@ func timespan(started time.Time, sched *schedule.Schedule, timeout time.Duration // by the original Job will be set as a field. The original error will not be // passed through as a return value. Errors may still be present but only if there // is an actual error wrapping the error. - -func addMonitorStatus(monitorType string) jobs.JobWrapper { +func addMonitorStatus(monitorType string, summaryOnly bool) jobs.JobWrapper { return func(origJob jobs.Job) jobs.Job { return func(event *beat.Event) ([]jobs.Job, error) { cont, err := origJob(event) + if summaryOnly { + hasSummary, _ := event.Fields.HasKey("summary.up") + if !hasSummary { + return cont, nil + } + } + fields := common.MapStr{ "monitor": common.MapStr{ "status": look.Status(err), diff --git a/heartbeat/monitors/wrappers/monitors_test.go b/heartbeat/monitors/wrappers/wrappers_test.go similarity index 87% rename from heartbeat/monitors/wrappers/monitors_test.go rename to heartbeat/monitors/wrappers/wrappers_test.go index 88e6fd76997..b84b18f65a9 100644 --- a/heartbeat/monitors/wrappers/monitors_test.go +++ b/heartbeat/monitors/wrappers/wrappers_test.go @@ -428,7 +428,6 @@ func TestInlineBrowserJob(t *testing.T) { "id": testMonFields.ID, "name": testMonFields.Name, "type": fields.Type, - "status": "up", "check_group": "inline-check-group", }, }), @@ -450,7 +449,7 @@ var suiteBrowserJobValues = struct { checkGroup: "journey-1-check-group", } -func makeSuiteBrowserJob(t *testing.T, u string) jobs.Job { +func makeSuiteBrowserJob(t *testing.T, u string, summary bool, suiteErr error) jobs.Job { parsed, err := url.Parse(u) require.NoError(t, err) return func(event *beat.Event) (i []jobs.Job, e error) { @@ -462,7 +461,18 @@ func makeSuiteBrowserJob(t *testing.T, u string) jobs.Job { "check_group": suiteBrowserJobValues.checkGroup, }, }) - return nil, nil + if summary { + sumFields := common.MapStr{"up": 0, "down": 0} + if suiteErr == nil { + sumFields["up"] = 1 + } else { + sumFields["down"] = 1 + } + eventext.MergeEventFields(event, common.MapStr{ + "summary": sumFields, + }) + } + return nil, suiteErr } } @@ -470,30 +480,65 @@ func TestSuiteBrowserJob(t *testing.T) { fields := testBrowserMonFields urlStr := "http://foo.com" urlU, _ := url.Parse(urlStr) + expectedMonFields := lookslike.MustCompile(map[string]interface{}{ + "monitor": map[string]interface{}{ + "id": fmt.Sprintf("%s-%s", testMonFields.ID, suiteBrowserJobValues.id), + "name": fmt.Sprintf("%s - %s", testMonFields.Name, suiteBrowserJobValues.name), + "type": fields.Type, + "check_group": suiteBrowserJobValues.checkGroup, + "timespan": common.MapStr{ + "gte": hbtestllext.IsTime, + "lt": hbtestllext.IsTime, + }, + }, + "url": URLFields(urlU), + }) testCommonWrap(t, testDef{ - "simple", + "simple", // has no summary fields! fields, - []jobs.Job{makeSuiteBrowserJob(t, urlStr)}, + []jobs.Job{makeSuiteBrowserJob(t, urlStr, false, nil)}, []validator.Validator{ - lookslike.Compose( - urlValidator(t, urlStr), - lookslike.Strict( + lookslike.Strict( + lookslike.Compose( + urlValidator(t, urlStr), + expectedMonFields, + ))}, + nil, + }) + testCommonWrap(t, testDef{ + "with up summary", + fields, + []jobs.Job{makeSuiteBrowserJob(t, urlStr, true, nil)}, + []validator.Validator{ + lookslike.Strict( + lookslike.Compose( + urlValidator(t, urlStr), + expectedMonFields, lookslike.MustCompile(map[string]interface{}{ - "monitor": map[string]interface{}{ - "id": fmt.Sprintf("%s-%s", testMonFields.ID, suiteBrowserJobValues.id), - "name": fmt.Sprintf("%s - %s", testMonFields.Name, suiteBrowserJobValues.name), - "type": fields.Type, - "check_group": suiteBrowserJobValues.checkGroup, - "status": "up", - "timespan": common.MapStr{ - "gte": hbtestllext.IsTime, - "lt": hbtestllext.IsTime, - }, + "monitor": map[string]interface{}{"status": "up"}, + "summary": map[string]interface{}{"up": 1, "down": 0}, + }), + ))}, + nil, + }) + testCommonWrap(t, testDef{ + "with down summary", + fields, + []jobs.Job{makeSuiteBrowserJob(t, urlStr, true, fmt.Errorf("testerr"))}, + []validator.Validator{ + lookslike.Strict( + lookslike.Compose( + urlValidator(t, urlStr), + expectedMonFields, + lookslike.MustCompile(map[string]interface{}{ + "monitor": map[string]interface{}{"status": "down"}, + "summary": map[string]interface{}{"up": 0, "down": 1}, + "error": map[string]interface{}{ + "type": isdef.IsString, + "message": "testerr", }, - "url": URLFields(urlU), }), - ), - )}, + ))}, nil, }) } diff --git a/heartbeat/scheduler/schedjob_test.go b/heartbeat/scheduler/schedjob_test.go index 48f4bf5a18b..4a6f5e892af 100644 --- a/heartbeat/scheduler/schedjob_test.go +++ b/heartbeat/scheduler/schedjob_test.go @@ -63,7 +63,7 @@ func TestSchedJobRun(t *testing.T) { for _, testCase := range testCases { t.Run(testCase.name, func(t *testing.T) { limit := int64(100) - s := NewWithLocation(limit, monitoring.NewRegistry(), tarawaTime(), nil) + s := Create(limit, monitoring.NewRegistry(), tarawaTime(), nil, false) if testCase.overLimit { s.limitSem.Acquire(context.Background(), limit) @@ -98,9 +98,9 @@ func TestSchedJobRun(t *testing.T) { // testRecursiveForkingJob tests that a schedJob that splits into multiple parallel pieces executes without error func TestRecursiveForkingJob(t *testing.T) { - s := NewWithLocation(1000, monitoring.NewRegistry(), tarawaTime(), map[string]config.JobLimit{ + s := Create(1000, monitoring.NewRegistry(), tarawaTime(), map[string]config.JobLimit{ "atype": {Limit: 1}, - }) + }, false) ran := batomic.NewInt(0) var terminalTf TaskFunc = func(ctx context.Context) []TaskFunc { diff --git a/heartbeat/scheduler/scheduler.go b/heartbeat/scheduler/scheduler.go index 3b6d34fa579..8de2d5760d6 100644 --- a/heartbeat/scheduler/scheduler.go +++ b/heartbeat/scheduler/scheduler.go @@ -22,23 +22,17 @@ import ( "errors" "fmt" "math" + "sync" "time" "golang.org/x/sync/semaphore" "github.com/elastic/beats/v7/heartbeat/config" "github.com/elastic/beats/v7/heartbeat/scheduler/timerqueue" - "github.com/elastic/beats/v7/libbeat/common/atomic" "github.com/elastic/beats/v7/libbeat/logp" "github.com/elastic/beats/v7/libbeat/monitoring" ) -const ( - statePreRunning int = iota + 1 - stateRunning - stateStopped -) - var debugf = logp.MakeDebug("scheduler") // ErrInvalidTransition is returned from start/stop when making an invalid state transition, say from preRunning to stopped @@ -48,20 +42,20 @@ var ErrInvalidTransition = fmt.Errorf("invalid state transition") type Scheduler struct { limit int64 limitSem *semaphore.Weighted - state atomic.Int location *time.Location timerQueue *timerqueue.TimerQueue ctx context.Context cancelCtx context.CancelFunc stats schedulerStats jobLimitSem map[string]*semaphore.Weighted + runOnce bool + runOnceWg *sync.WaitGroup } type schedulerStats struct { activeJobs *monitoring.Uint // gauge showing number of active jobs activeTasks *monitoring.Uint // gauge showing number of active tasks waitingTasks *monitoring.Uint // number of tasks waiting to run, but constrained by scheduler limit - jobsPerSecond *monitoring.Uint // rate of job processing computed over the past hour jobsMissedDeadline *monitoring.Uint // counter for number of jobs that missed start deadline } @@ -88,13 +82,8 @@ func getJobLimitSem(jobLimitByType map[string]config.JobLimit) map[string]*semap return jobLimitSem } -// New creates a new Scheduler -func New(limit int64, registry *monitoring.Registry) *Scheduler { - return NewWithLocation(limit, registry, time.Local, nil) -} - // NewWithLocation creates a new Scheduler using the given runAt zone. -func NewWithLocation(limit int64, registry *monitoring.Registry, location *time.Location, jobLimitByType map[string]config.JobLimit) *Scheduler { +func Create(limit int64, registry *monitoring.Registry, location *time.Location, jobLimitByType map[string]config.JobLimit, runOnce bool) *Scheduler { ctx, cancelCtx := context.WithCancel(context.Background()) if limit < 1 { @@ -109,12 +98,13 @@ func NewWithLocation(limit int64, registry *monitoring.Registry, location *time. sched := &Scheduler{ limit: limit, location: location, - state: atomic.MakeInt(statePreRunning), ctx: ctx, cancelCtx: cancelCtx, limitSem: semaphore.NewWeighted(limit), jobLimitSem: getJobLimitSem(jobLimitByType), timerQueue: timerqueue.NewTimerQueue(ctx), + runOnce: runOnce, + runOnceWg: &sync.WaitGroup{}, stats: schedulerStats{ activeJobs: activeJobsGauge, @@ -124,24 +114,10 @@ func NewWithLocation(limit int64, registry *monitoring.Registry, location *time. }, } - return sched -} - -// Start the scheduler. Starting a stopped scheduler returns an error. -func (s *Scheduler) Start() error { - if s.state.Load() == stateStopped { - return ErrInvalidTransition - } - if !s.state.CAS(statePreRunning, stateRunning) { - return nil // we already running, just exit - } - - s.timerQueue.Start() + sched.timerQueue.Start() + go sched.missedDeadlineReporter() - // Missed deadline reporter - go s.missedDeadlineReporter() - - return nil + return sched } func (s *Scheduler) missedDeadlineReporter() { @@ -160,7 +136,7 @@ func (s *Scheduler) missedDeadlineReporter() { missingNow := s.stats.jobsMissedDeadline.Get() missedDelta := missingNow - missedAtLastCheck if missedDelta > 0 { - logp.Warn("%d tasks have missed their schedule deadlines in the last %s.", missedDelta, interval) + logp.Warn("%d tasks have missed their schedule deadlines by more than 1 second in the last %s.", missedDelta, interval) } missedAtLastCheck = missingNow } @@ -168,25 +144,28 @@ func (s *Scheduler) missedDeadlineReporter() { } // Stop all executing tasks in the scheduler. Cannot be restarted after Stop. -func (s *Scheduler) Stop() error { - if s.state.CAS(stateRunning, stateStopped) { - s.cancelCtx() - return nil - } else if s.state.Load() == stateStopped { - return nil - } +func (s *Scheduler) Stop() { + s.cancelCtx() +} - return ErrInvalidTransition +// Wait until all tasks are done if run in runOnce mode. Will block forever +// if this scheduler does not have the runOnce option set. +// Adding new tasks after this method is invoked is not supported. +func (s *Scheduler) WaitForRunOnce() { + s.runOnceWg.Wait() + s.Stop() } // ErrAlreadyStopped is returned when an Add operation is attempted after the scheduler // has already stopped. var ErrAlreadyStopped = errors.New("attempted to add job to already stopped scheduler") +type AddTask func(sched Schedule, id string, entrypoint TaskFunc, jobType string, waitForPublish func()) (removeFn context.CancelFunc, err error) + // Add adds the given TaskFunc to the current scheduler. Will return an error if the scheduler // is done. -func (s *Scheduler) Add(sched Schedule, id string, entrypoint TaskFunc, jobType string) (removeFn context.CancelFunc, err error) { - if s.state.Load() == stateStopped { +func (s *Scheduler) Add(sched Schedule, id string, entrypoint TaskFunc, jobType string, waitForPublish func()) (removeFn context.CancelFunc, err error) { + if errors.Is(s.ctx.Err(), context.Canceled) { return nil, ErrAlreadyStopped } @@ -207,20 +186,31 @@ func (s *Scheduler) Add(sched Schedule, id string, entrypoint TaskFunc, jobType } s.stats.activeJobs.Inc() debugf("Job '%s' started", id) - lastRanAt := newSchedJob(jobCtx, s, id, jobType, entrypoint).run() + sj := newSchedJob(jobCtx, s, id, jobType, entrypoint) + + lastRanAt := sj.run() s.stats.activeJobs.Dec() - s.runOnce(sched.Next(lastRanAt), taskFn) + + if s.runOnce { + waitForPublish() + s.runOnceWg.Done() + } else { + // Schedule the next run + s.runTaskOnce(sched.Next(lastRanAt), taskFn, true) + } debugf("Job '%v' returned at %v", id, time.Now()) } - // We skip using the scheduler to execute the initial tasks for jobs that have RunOnInit returning true. - // You might think it'd be simpler to just invoke runOnce in either case with 0 as a lastRanAt value, - // however, that would caused the missed deadline stats to be incremented. Given that, it's easier - // and slightly more efficient to simply run these tasks immediately in a goroutine. - if sched.RunOnInit() { - go taskFn(time.Now()) + if s.runOnce { + s.runOnceWg.Add(1) + } + + // Run non-cron tasks immediately, or run all tasks immediately if we're + // in RunOnce mode + if s.runOnce || sched.RunOnInit() { + s.runTaskOnce(time.Now(), taskFn, false) } else { - s.runOnce(sched.Next(lastRanAt), taskFn) + s.runTaskOnce(sched.Next(lastRanAt), taskFn, true) } return func() { @@ -229,15 +219,18 @@ func (s *Scheduler) Add(sched Schedule, id string, entrypoint TaskFunc, jobType }, nil } -func (s *Scheduler) runOnce(runAt time.Time, taskFn timerqueue.TimerTaskFn) { +// runTaskOnce runs the given task exactly once at the given time. Set deadlineCheck +// to false if this is the first invocation of this, otherwise the deadline checker +// will complain about a missed task +func (s *Scheduler) runTaskOnce(runAt time.Time, taskFn timerqueue.TimerTaskFn, deadlineCheck bool) { now := time.Now().In(s.location) - if runAt.Before(now) { - // Our last invocation went long! + // Check if the task is more than 1 second late + if deadlineCheck && runAt.Sub(now) < time.Second { s.stats.jobsMissedDeadline.Inc() } // Schedule task to run sometime in the future. Wrap the task in a go-routine so it doesn't - // block the timer thread. + // blocks the timer thread. asyncTask := func(now time.Time) { go taskFn(now) } s.timerQueue.Push(runAt, asyncTask) } diff --git a/heartbeat/scheduler/scheduler_test.go b/heartbeat/scheduler/scheduler_test.go index 61c062184a4..371be5f69ef 100644 --- a/heartbeat/scheduler/scheduler_test.go +++ b/heartbeat/scheduler/scheduler_test.go @@ -44,14 +44,8 @@ func tarawaTime() *time.Location { return loc } -func TestNew(t *testing.T) { - scheduler := New(123, monitoring.NewRegistry()) - assert.Equal(t, int64(123), scheduler.limit) - assert.Equal(t, time.Local, scheduler.location) -} - func TestNewWithLocation(t *testing.T) { - scheduler := NewWithLocation(123, monitoring.NewRegistry(), tarawaTime(), nil) + scheduler := Create(123, monitoring.NewRegistry(), tarawaTime(), nil, false) assert.Equal(t, int64(123), scheduler.limit) assert.Equal(t, tarawaTime(), scheduler.location) } @@ -83,23 +77,23 @@ func testTaskTimes(limit uint32, fn TaskFunc) TaskFunc { } } -func TestScheduler_Start(t *testing.T) { +func TestSchedulerRun(t *testing.T) { // We use tarawa runAt because it could expose some weird runAt math if by accident some code // relied on the local TZ. - s := NewWithLocation(10, monitoring.NewRegistry(), tarawaTime(), nil) + s := Create(10, monitoring.NewRegistry(), tarawaTime(), nil, false) defer s.Stop() executed := make(chan string) - preAddEvents := uint32(10) - s.Add(testSchedule{0}, "preAdd", testTaskTimes(preAddEvents, func(_ context.Context) []TaskFunc { - executed <- "preAdd" + initialEvents := uint32(10) + s.Add(testSchedule{0}, "add", testTaskTimes(initialEvents, func(_ context.Context) []TaskFunc { + executed <- "initial" cont := func(_ context.Context) []TaskFunc { - executed <- "preAddCont" + executed <- "initialCont" return nil } return []TaskFunc{cont} - }), "http") + }), "http", nil) removedEvents := uint32(1) // This function will be removed after being invoked once @@ -114,28 +108,26 @@ func TestScheduler_Start(t *testing.T) { } // Attempt to execute this twice to see if remove() had any effect removeMtx.Lock() - remove, err := s.Add(testSchedule{}, "removed", testTaskTimes(removedEvents+1, testFn), "http") + remove, err := s.Add(testSchedule{}, "removed", testTaskTimes(removedEvents+1, testFn), "http", nil) require.NoError(t, err) require.NotNil(t, remove) removeMtx.Unlock() - s.Start() - - postAddEvents := uint32(10) - s.Add(testSchedule{}, "postAdd", testTaskTimes(postAddEvents, func(_ context.Context) []TaskFunc { - executed <- "postAdd" + postRemoveEvents := uint32(10) + s.Add(testSchedule{}, "postRemove", testTaskTimes(postRemoveEvents, func(_ context.Context) []TaskFunc { + executed <- "postRemove" cont := func(_ context.Context) []TaskFunc { - executed <- "postAddCont" + executed <- "postRemoveCont" return nil } return []TaskFunc{cont} - }), "http") + }), "http", nil) received := make([]string, 0) // We test for a good number of events in this loop because we want to ensure that the remove() took effect - // Otherwise, we might only do 1 preAdd and 1 postAdd event + // Otherwise, we might only do 1 preAdd and 1 postRemove event // We double the number of pre/post add events to account for their continuations - totalExpected := preAddEvents*2 + removedEvents + postAddEvents*2 + totalExpected := initialEvents*2 + removedEvents + postRemoveEvents*2 for uint32(len(received)) < totalExpected { select { case got := <-executed: @@ -147,31 +139,53 @@ func TestScheduler_Start(t *testing.T) { } // The removed callback should only have been executed once - counts := map[string]uint32{"preAdd": 0, "postAdd": 0, "preAddCont": 0, "postAddcont": 0, "removed": 0} + counts := map[string]uint32{"initial": 0, "initialCont": 0, "removed": 0, "postRemove": 0, "postRemoveCont": 0} for _, s := range received { counts[s]++ } // convert with int() because the printed output is nicer than hex - assert.Equal(t, int(preAddEvents), int(counts["preAdd"])) - assert.Equal(t, int(preAddEvents), int(counts["preAddCont"])) - assert.Equal(t, int(postAddEvents), int(counts["postAdd"])) - assert.Equal(t, int(postAddEvents), int(counts["postAddCont"])) + assert.Equal(t, int(initialEvents), int(counts["initial"])) + assert.Equal(t, int(initialEvents), int(counts["initialCont"])) assert.Equal(t, int(removedEvents), int(counts["removed"])) + assert.Equal(t, int(postRemoveEvents), int(counts["postRemove"])) + assert.Equal(t, int(postRemoveEvents), int(counts["postRemoveCont"])) +} + +func TestScheduler_WaitForRunOnce(t *testing.T) { + s := Create(10, monitoring.NewRegistry(), tarawaTime(), nil, true) + + defer s.Stop() + + executed := new(uint32) + waits := new(uint32) + + s.Add(testSchedule{0}, "runOnce", func(_ context.Context) []TaskFunc { + cont := func(_ context.Context) []TaskFunc { + // Make sure we actually wait for the task! + time.Sleep(time.Millisecond * 250) + atomic.AddUint32(executed, 1) + return nil + } + return []TaskFunc{cont} + }, "http", func() { atomic.AddUint32(waits, 1) }) + + s.WaitForRunOnce() + require.Equal(t, uint32(1), atomic.LoadUint32(executed)) + require.Equal(t, uint32(1), atomic.LoadUint32(waits)) } func TestScheduler_Stop(t *testing.T) { - s := NewWithLocation(10, monitoring.NewRegistry(), tarawaTime(), nil) + s := Create(10, monitoring.NewRegistry(), tarawaTime(), nil, false) executed := make(chan struct{}) - require.NoError(t, s.Start()) - require.NoError(t, s.Stop()) + s.Stop() _, err := s.Add(testSchedule{}, "testPostStop", testTaskTimes(1, func(_ context.Context) []TaskFunc { executed <- struct{}{} return nil - }), "http") + }), "http", nil) assert.Equal(t, ErrAlreadyStopped, err) } @@ -235,7 +249,7 @@ func TestSchedTaskLimits(t *testing.T) { jobType: {Limit: tt.limit}, } } - s := NewWithLocation(math.MaxInt64, monitoring.NewRegistry(), tarawaTime(), jobConfigByType) + s := Create(math.MaxInt64, monitoring.NewRegistry(), tarawaTime(), jobConfigByType, false) var taskArr []int wg := sync.WaitGroup{} wg.Add(tt.numJobs) @@ -257,7 +271,7 @@ func TestSchedTaskLimits(t *testing.T) { } func BenchmarkScheduler(b *testing.B) { - s := NewWithLocation(0, monitoring.NewRegistry(), tarawaTime(), nil) + s := Create(0, monitoring.NewRegistry(), tarawaTime(), nil, false) sched := testSchedule{0} @@ -266,13 +280,11 @@ func BenchmarkScheduler(b *testing.B) { _, err := s.Add(sched, "testPostStop", func(_ context.Context) []TaskFunc { executed <- struct{}{} return nil - }, "http") + }, "http", nil) assert.NoError(b, err) } - err := s.Start() defer s.Stop() - assert.NoError(b, err) count := 0 for count < b.N { diff --git a/heartbeat/scheduler/timerqueue/queue.go b/heartbeat/scheduler/timerqueue/queue.go index 61d4e0ac933..760dd353f38 100644 --- a/heartbeat/scheduler/timerqueue/queue.go +++ b/heartbeat/scheduler/timerqueue/queue.go @@ -88,7 +88,7 @@ func (tq *TimerQueue) Start() { if tq.th.Len() > 0 { nr := tq.th[0].runAt tq.nextRunAt = &nr - tq.timer = time.NewTimer(time.Until(nr)) + tq.timer.Reset(time.Until(nr)) } else { tq.timer.Stop() tq.nextRunAt = nil @@ -107,18 +107,7 @@ func (tq *TimerQueue) pushInternal(tt *timerTask) { if tq.nextRunAt != nil && !tq.timer.Stop() { <-tq.timer.C } - // Originally the line below this comment was - // - // tq.timer.Reset(time.Until(tt.runAt)) - // - // however this broke in go1.16rc1, specifically on the commit b4b014465216790e01aa66f9120d03230e4aff46 - //, specifically on this line: - // https://github.com/golang/go/commit/b4b014465216790e01aa66f9120d03230e4aff46#diff-73699b6edfe5dbb3f6824e66bb3566bce9405e9a8c810cac55c8199459f0ac19R652 - // where some nice new optimizations don't actually work reliably - // This can be worked around by instantiating a new timer rather than resetting the timer. - // since that internally calls deltimer in runtime/timer.go rather than modtimer, - // I suspect that the problem is in modtimer's setting of &pp.timerModifiedEarliest - tq.timer = time.NewTimer(time.Until(tt.runAt)) + tq.timer.Reset(time.Until(tt.runAt)) tq.nextRunAt = &tt.runAt } } diff --git a/heartbeat/tests/system/test_base.py b/heartbeat/tests/system/test_base.py index 141658049fb..172960209d3 100644 --- a/heartbeat/tests/system/test_base.py +++ b/heartbeat/tests/system/test_base.py @@ -194,9 +194,9 @@ def run_fields(self, expected, local=None, top=None): return doc @unittest.skipUnless(INTEGRATION_TESTS, "integration test") - def test_template(self): + def test_index_management(self): """ - Test that the template can be loaded with `setup --template` + Test that the template can be loaded with `setup --index-management` """ es = Elasticsearch([self.get_elasticsearch_url()]) self.render_config_template( @@ -206,7 +206,7 @@ def test_template(self): }], elasticsearch={"host": self.get_elasticsearch_url()}, ) - exit_code = self.run_beat(extra_args=["setup", "--template"]) + exit_code = self.run_beat(extra_args=["setup", "--index-management"]) assert exit_code == 0 assert self.log_contains('Loaded index template') diff --git a/journalbeat/.gitignore b/journalbeat/.gitignore deleted file mode 100644 index 504279e50ee..00000000000 --- a/journalbeat/.gitignore +++ /dev/null @@ -1,9 +0,0 @@ -/.idea -/build -.DS_Store -.journalbeat_position -/journalbeat -/journalbeat.test -*.pyc -data/meta.json -/*.journal diff --git a/journalbeat/Dockerfile b/journalbeat/Dockerfile deleted file mode 100644 index 6c461fcb01a..00000000000 --- a/journalbeat/Dockerfile +++ /dev/null @@ -1,23 +0,0 @@ -FROM golang:1.17.2 - -RUN \ - apt-get update \ - && apt-get install -y --no-install-recommends \ - libsystemd-dev \ - libc6-dev-i386 \ - gcc-arm-linux-gnueabi \ - python3 \ - python3-pip \ - python3-venv \ - && rm -rf /var/lib/apt/lists/* - -RUN pip3 install --upgrade pip==20.1.1 -RUN pip3 install --upgrade setuptools==47.3.2 -RUN pip3 install --upgrade docker-compose==1.23.2 - -# Setup work environment -ENV JOURNALBEAT_PATH /go/src/github.com/elastic/beats/journalbeat - -RUN mkdir -p $JOURNALBEAT_PATH/build/coverage -WORKDIR $JOURNALBEAT_PATH -HEALTHCHECK CMD exit 0 diff --git a/journalbeat/Makefile b/journalbeat/Makefile deleted file mode 100644 index 85049183d4e..00000000000 --- a/journalbeat/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -BEAT_NAME=journalbeat -BEAT_TITLE=Journalbeat -SYSTEM_TESTS=true -TEST_ENVIRONMENT=false -ES_BEATS?=.. - -# Path to the libbeat Makefile --include $(ES_BEATS)/libbeat/scripts/Makefile - -.PHONY: before-build -before-build: - -# Collects all dependencies and then calls update -.PHONY: collect -collect: diff --git a/journalbeat/README.md b/journalbeat/README.md deleted file mode 100644 index 69fccb38f90..00000000000 --- a/journalbeat/README.md +++ /dev/null @@ -1,5 +0,0 @@ -# Journalbeat - -Journalbeat is an open source data collector to read and forward journal entries from Linuxes with systemd. - -## Getting started diff --git a/journalbeat/_meta/config/beat.docker.yml.tmpl b/journalbeat/_meta/config/beat.docker.yml.tmpl deleted file mode 100644 index 20ae6ee130d..00000000000 --- a/journalbeat/_meta/config/beat.docker.yml.tmpl +++ /dev/null @@ -1,3 +0,0 @@ -journalbeat.inputs: -- paths: [] - seek: cursor diff --git a/journalbeat/_meta/config/beat.reference.yml.tmpl b/journalbeat/_meta/config/beat.reference.yml.tmpl deleted file mode 100644 index 8da73b6bf07..00000000000 --- a/journalbeat/_meta/config/beat.reference.yml.tmpl +++ /dev/null @@ -1,62 +0,0 @@ -###################### Journalbeat Configuration Example ######################### - -# This file is an example configuration file highlighting only the most common -# options. The journalbeat.reference.yml file from the same directory contains all the -# supported options with more comments. You can use it as a reference. -# -# You can find the full configuration reference here: -# https://www.elastic.co/guide/en/beats/journalbeat/index.html - -# For more available modules and options, please see the journalbeat.reference.yml sample -# configuration file. - -{{header "Journalbeat inputs"}} - -journalbeat.inputs: - # Paths that should be crawled and fetched. Possible values files and directories. - # When setting a directory, all journals under it are merged. - # When empty starts to read from local journal. -- paths: [] - - # An optional unique identifier for the input. By providing a unique `id` you - # can operate multiple inputs on the same journal. This allows each input's - # cursor to be persisted independently in the registry file. - #id: "" - - # The number of seconds to wait before trying to read again from journals. - #backoff: 1s - # The maximum number of seconds to wait before attempting to read again from journals. - #max_backoff: 20s - - # Position to start reading from journal. Valid values: head, tail, cursor - seek: cursor - # Fallback position if no cursor data is available. - #cursor_seek_fallback: head - - # Exact matching for field values of events. - # Matching for nginx entries: "systemd.unit=nginx" - #include_matches: [] - - # Set the option to preserve the remote hostname in entries from a remote journal. - # It is only needed when used with add_host_metadata, so the original host name - # does not get overwritten by the processor. - #save_remote_hostname: false - - # Optional fields that you can specify to add additional information to the - # output. Fields can be scalar values, arrays, dictionaries, or any nested - # combination of these. - #fields: - # env: staging - - -{{header "Journalbeat global options"}} -#journalbeat: - # Name of the registry file. If a relative path is used, it is considered relative to the - # data path. - #registry_file: registry - -{{header "Elasticsearch template setting"}} -setup.template.settings: - index.number_of_shards: 1 - #index.codec: best_compression - #_source.enabled: false diff --git a/journalbeat/_meta/config/beat.yml.tmpl b/journalbeat/_meta/config/beat.yml.tmpl deleted file mode 100644 index a4f7d5d4c31..00000000000 --- a/journalbeat/_meta/config/beat.yml.tmpl +++ /dev/null @@ -1,57 +0,0 @@ -###################### Journalbeat Configuration Example ######################### - -# This file is an example configuration file highlighting only the most common -# options. The journalbeat.reference.yml file from the same directory contains all the -# supported options with more comments. You can use it as a reference. -# -# You can find the full configuration reference here: -# https://www.elastic.co/guide/en/beats/journalbeat/index.html - -# For more available modules and options, please see the journalbeat.reference.yml sample -# configuration file. - -{{header "Journalbeat inputs"}} - -journalbeat.inputs: - # Paths that should be crawled and fetched. Possible values files and directories. - # When setting a directory, all journals under it are merged. - # When empty starts to read from local journal. -- paths: [] - - # An optional unique identifier for the input. By providing a unique `id` you - # can operate multiple inputs on the same journal. This allows each input's - # cursor to be persisted independently in the registry file. - #id: "" - - # The number of seconds to wait before trying to read again from journals. - #backoff: 1s - # The maximum number of seconds to wait before attempting to read again from journals. - #max_backoff: 20s - - # Position to start reading from journal. Valid values: head, tail, cursor - seek: cursor - # Fallback position if no cursor data is available. - #cursor_seek_fallback: head - - # Exact matching for field values of events. - # Matching for nginx entries: "systemd.unit=nginx" - #include_matches: [] - - # Optional fields that you can specify to add additional information to the - # output. Fields can be scalar values, arrays, dictionaries, or any nested - # combination of these. - #fields: - # env: staging - - -{{header "Journalbeat global options"}} -#journalbeat: - # Name of the registry file. If a relative path is used, it is considered relative to the - # data path. - #registry_file: registry - -{{header "Elasticsearch template setting"}} -setup.template.settings: - index.number_of_shards: 1 - #index.codec: best_compression - #_source.enabled: false diff --git a/journalbeat/_meta/fields.common.yml b/journalbeat/_meta/fields.common.yml deleted file mode 100644 index b06081ae19b..00000000000 --- a/journalbeat/_meta/fields.common.yml +++ /dev/null @@ -1,329 +0,0 @@ -- key: common - title: "Common Journalbeat" - description: > - Contains common fields available in all event types. - fields: - - name: coredump - type: group - description: > - Fields used by systemd-coredump kernel helper. - fields: - - name: unit - type: keyword - description: > - Annotations of messages containing coredumps from system units. - - name: user_unit - type: keyword - description: > - Annotations of messages containing coredumps from user units. - - name: journald - type: group - description: > - Fields provided by journald. - fields: - - name: object - type: group - description: > - Fields to log on behalf of a different program. - fields: - - name: audit - type: group - description: > - Audit fields of event. - fields: - - name: login_uid - type: long - required: false - example: 1000 - description: > - The login UID of the object process. - - name: session - type: long - required: false - example: 3 - description: > - The audit session of the object process. - - name: process.command_line - type: keyword - required: false - example: "/lib/systemd/systemd --user" - description: > - The command line of the process. - - name: process.name - type: keyword - required: false - example: "/lib/systemd/systemd" - description: > - Name of the executable. - - name: process.executable - type: keyword - required: false - description: > - Path to the the executable. - example: "/lib/systemd/systemd" - - name: uid - type: long - required: false - description: > - UID of the object process. - - name: gid - type: long - required: false - description: > - GID of the object process. - - name: pid - type: long - required: false - description: > - PID of the object process. - - name: systemd - type: group - description: > - Systemd fields of event. - fields: - - name: owner_uid - type: long - required: false - description: > - The UID of the owner. - - name: session - type: keyword - required: false - description: > - The ID of the systemd session. - - name: unit - type: keyword - required: false - description: > - The name of the systemd unit. - - name: user_unit - type: keyword - required: false - description: > - The name of the systemd user unit. - - name: kernel - type: group - description: > - Fields to log on behalf of a different program. - fields: - - name: device - type: keyword - required: false - description: > - The kernel device name. - - name: subsystem - type: keyword - required: false - description: > - The kernel subsystem name. - - name: device_symlinks - type: keyword - required: false - description: > - Additional symlink names pointing to the device node in /dev. - - name: device_node_path - type: keyword - required: false - description: > - The device node path of this device in /dev. - - name: device_name - type: keyword - required: false - description: > - The kernel device name as it shows up in the device tree below /sys. - - name: code - type: group - description: > - Fields of the code generating the event. - fields: - - name: file - type: keyword - required: false - example: "../src/core/manager.c" - description: > - The name of the source file where the log is generated. - - name: function - type: keyword - required: false - example: "job_log_status_message" - description: > - The name of the function which generated the log message. - - name: line - type: long - required: false - example: 123 - description: > - The line number of the code which generated the log message. - - name: process - type: group - description: > - Fields to log on behalf of a different program. - fields: - - name: audit - type: group - description: > - Audit fields of event. - fields: - - name: loginuid - type: long - required: false - example: 1000 - description: > - The login UID of the source process. - - name: session - type: long - required: false - example: 3 - description: > - The audit session of the source process. - - name: command_line - type: keyword - required: false - example: "/lib/systemd/systemd --user" - description: > - The command line of the process. - - name: name - type: keyword - required: false - example: "/lib/systemd/systemd" - description: > - Name of the executable. - - name: executable - type: keyword - required: false - description: > - Path to the the executable. - example: "/lib/systemd/systemd" - - name: pid - type: long - required: false - example: 1 - description: > - The ID of the process which logged the message. - - name: gid - type: long - required: false - example: 1 - description: > - The ID of the group which runs the process. - - name: uid - type: long - required: false - example: 1 - description: > - The ID of the user which runs the process. - - name: capabilities - required: false - description: > - The effective capabilities of the process. - - name: systemd - type: group - description: > - Fields of systemd. - fields: - - name: invocation_id - type: keyword - required: false - example: "8450f1672de646c88cd133aadd4f2d70" - description: > - The invocation ID for the runtime cycle of the unit the message was generated in. - - name: cgroup - type: keyword - required: false - example: "/user.slice/user-1234.slice/session-2.scope" - description: > - The control group path in the systemd hierarchy. - - name: owner_uid - type: long - required: false - description: > - The owner UID of the systemd user unit or systemd session. - - name: session - type: keyword - required: false - description: > - The ID of the systemd session. - - name: slice - type: keyword - required: false - example: "user-1234.slice" - description: > - The systemd slice unit. - - name: user_slice - type: keyword - required: false - description: > - The systemd user slice unit. - - name: unit - type: keyword - required: false - example: "nginx.service" - description: > - The name of the systemd unit. - - name: user_unit - type: keyword - required: false - example: "user-1234.slice" - description: > - The name of the systemd user unit. - - name: transport - type: keyword - required: true - example: "syslog" - description: > - How the log message was received by journald. - - name: host - type: group - description: > - Fields of the host. - fields: - - name: boot_id - type: keyword - required: false - example: "dd8c974asdf01dbe2ef26d7fasdf264c9" - description: > - The boot ID for the boot the log was generated in. - - name: syslog - type: group - description: > - Fields of the code generating the event. - fields: - - name: priority - type: long - required: false - example: 1 - description: > - The priority of the message. A syslog compatibility field. - - name: facility - type: long - required: false - example: 1 - description: > - The facility of the message. A syslog compatibility field. - - name: identifier - type: keyword - required: false - example: "su" - description: > - The identifier of the message. A syslog compatibility field. - - name: custom - type: nested - required: false - description: > - Arbitrary fields coming from processes. - - - name: read_timestamp - type: alias - path: event.created - migration: true - - - name: container - type: group - fields: - - name: log - type: group - fields: - - name: tag - type: keyword - description: > - User defined tag of a container. diff --git a/journalbeat/_meta/kibana/default/index-pattern/journalbeat.json b/journalbeat/_meta/kibana/default/index-pattern/journalbeat.json deleted file mode 100644 index 55e70bd81d1..00000000000 --- a/journalbeat/_meta/kibana/default/index-pattern/journalbeat.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "version": "7.0.0-alpha1", - "objects": [ - { - "attributes": { - "fields": "[{\"count\": 0, \"analyzed\": false, \"aggregatable\": true, \"name\": \"beat.name\", \"searchable\": true, \"indexed\": true, \"doc_values\": true, \"type\": \"string\", \"scripted\": false}, {\"count\": 0, \"analyzed\": false, \"aggregatable\": true, \"name\": \"beat.hostname\", \"searchable\": true, \"indexed\": true, \"doc_values\": true, \"type\": \"string\", \"scripted\": false}, {\"count\": 0, \"analyzed\": false, \"aggregatable\": true, \"name\": \"beat.timezone\", \"searchable\": true, \"indexed\": true, \"doc_values\": true, \"type\": \"string\", \"scripted\": false}, {\"count\": 0, \"analyzed\": false, \"aggregatable\": true, \"name\": \"beat.version\", \"searchable\": true, \"indexed\": true, \"doc_values\": true, \"type\": \"string\", \"scripted\": false}, {\"count\": 0, \"analyzed\": false, \"aggregatable\": true, \"name\": \"@timestamp\", \"searchable\": true, \"indexed\": true, \"doc_values\": true, \"type\": \"date\", \"scripted\": false}, {\"count\": 0, \"analyzed\": false, \"aggregatable\": true, \"name\": \"tags\", \"searchable\": true, \"indexed\": true, \"doc_values\": true, \"type\": \"string\", \"scripted\": false}, {\"count\": 0, \"analyzed\": false, \"aggregatable\": true, \"name\": \"fields\", \"searchable\": true, \"indexed\": true, \"doc_values\": true, \"scripted\": false}, {\"count\": 0, \"analyzed\": false, \"aggregatable\": false, \"name\": \"error.message\", \"searchable\": true, \"indexed\": true, \"doc_values\": true, \"type\": \"string\", \"scripted\": false}, {\"count\": 0, \"analyzed\": false, \"aggregatable\": true, \"name\": \"error.code\", \"searchable\": true, \"indexed\": true, \"doc_values\": true, \"type\": \"number\", \"scripted\": false}, {\"count\": 0, \"analyzed\": false, \"aggregatable\": true, \"name\": \"error.type\", \"searchable\": true, \"indexed\": true, \"doc_values\": true, \"type\": \"string\", \"scripted\": false}, {\"count\": 0, \"analyzed\": false, \"aggregatable\": true, \"name\": \"meta.cloud.provider\", \"searchable\": true, \"indexed\": true, \"doc_values\": true, \"type\": \"string\", \"scripted\": false}, {\"count\": 0, \"analyzed\": false, \"aggregatable\": true, \"name\": \"meta.cloud.instance_id\", \"searchable\": true, \"indexed\": true, \"doc_values\": true, \"type\": \"string\", \"scripted\": false}, {\"count\": 0, \"analyzed\": false, \"aggregatable\": true, \"name\": \"meta.cloud.instance_name\", \"searchable\": true, \"indexed\": true, \"doc_values\": true, \"type\": \"string\", \"scripted\": false}, {\"count\": 0, \"analyzed\": false, \"aggregatable\": true, \"name\": \"meta.cloud.machine_type\", \"searchable\": true, \"indexed\": true, \"doc_values\": true, \"type\": \"string\", \"scripted\": false}, {\"count\": 0, \"analyzed\": false, \"aggregatable\": true, \"name\": \"meta.cloud.availability_zone\", \"searchable\": true, \"indexed\": true, \"doc_values\": true, \"type\": \"string\", \"scripted\": false}, {\"count\": 0, \"analyzed\": false, \"aggregatable\": true, \"name\": \"meta.cloud.project_id\", \"searchable\": true, \"indexed\": true, \"doc_values\": true, \"type\": \"string\", \"scripted\": false}, {\"count\": 0, \"analyzed\": false, \"aggregatable\": true, \"name\": \"meta.cloud.region\", \"searchable\": true, \"indexed\": true, \"doc_values\": true, \"type\": \"string\", \"scripted\": false}, {\"count\": 0, \"analyzed\": false, \"aggregatable\": true, \"name\": \"docker.container.id\", \"searchable\": true, \"indexed\": true, \"doc_values\": true, \"type\": \"string\", \"scripted\": false}, {\"count\": 0, \"analyzed\": false, \"aggregatable\": true, \"name\": \"docker.container.image\", \"searchable\": true, \"indexed\": true, \"doc_values\": true, \"type\": \"string\", \"scripted\": false}, {\"count\": 0, \"analyzed\": false, \"aggregatable\": true, \"name\": \"docker.container.name\", \"searchable\": true, \"indexed\": true, \"doc_values\": true, \"type\": \"string\", \"scripted\": false}, {\"count\": 0, \"analyzed\": false, \"aggregatable\": true, \"name\": \"docker.container.labels\", \"searchable\": true, \"indexed\": true, \"doc_values\": true, \"scripted\": false}, {\"count\": 0, \"analyzed\": false, \"aggregatable\": true, \"name\": \"kubernetes.pod.name\", \"searchable\": true, \"indexed\": true, \"doc_values\": true, \"type\": \"string\", \"scripted\": false}, {\"count\": 0, \"analyzed\": false, \"aggregatable\": true, \"name\": \"kubernetes.namespace\", \"searchable\": true, \"indexed\": true, \"doc_values\": true, \"type\": \"string\", \"scripted\": false}, {\"count\": 0, \"analyzed\": false, \"aggregatable\": true, \"name\": \"kubernetes.labels\", \"searchable\": true, \"indexed\": true, \"doc_values\": true, \"scripted\": false}, {\"count\": 0, \"analyzed\": false, \"aggregatable\": true, \"name\": \"kubernetes.annotations\", \"searchable\": true, \"indexed\": true, \"doc_values\": true, \"scripted\": false}, {\"count\": 0, \"analyzed\": false, \"aggregatable\": true, \"name\": \"kubernetes.container.name\", \"searchable\": true, \"indexed\": true, \"doc_values\": true, \"type\": \"string\", \"scripted\": false}, {\"count\": 0, \"analyzed\": false, \"aggregatable\": true, \"name\": \"kubernetes.container.image\", \"searchable\": true, \"indexed\": true, \"doc_values\": true, \"type\": \"string\", \"scripted\": false}, {\"count\": 0, \"analyzed\": false, \"aggregatable\": true, \"name\": \"counter\", \"searchable\": true, \"indexed\": true, \"doc_values\": true, \"type\": \"number\", \"scripted\": false}, {\"count\": 0, \"analyzed\": false, \"aggregatable\": false, \"name\": \"_id\", \"searchable\": false, \"indexed\": false, \"doc_values\": false, \"type\": \"string\", \"scripted\": false}, {\"count\": 0, \"analyzed\": false, \"aggregatable\": true, \"name\": \"_type\", \"searchable\": true, \"indexed\": false, \"doc_values\": false, \"type\": \"string\", \"scripted\": false}, {\"count\": 0, \"analyzed\": false, \"aggregatable\": false, \"name\": \"_index\", \"searchable\": false, \"indexed\": false, \"doc_values\": false, \"type\": \"string\", \"scripted\": false}, {\"count\": 0, \"analyzed\": false, \"aggregatable\": false, \"name\": \"_score\", \"searchable\": false, \"indexed\": false, \"doc_values\": false, \"type\": \"number\", \"scripted\": false}]", - "fieldFormatMap": "{\"@timestamp\": {\"id\": \"date\"}}", - "timeFieldName": "@timestamp", - "title": "journalbeat-*" - }, - "version": 1, - "type": "index-pattern", - "id": "journalbeat-*" - } - ] -} \ No newline at end of file diff --git a/journalbeat/beater/journalbeat.go b/journalbeat/beater/journalbeat.go deleted file mode 100644 index 6694dbd8a9a..00000000000 --- a/journalbeat/beater/journalbeat.go +++ /dev/null @@ -1,126 +0,0 @@ -// Licensed to Elasticsearch B.V. under one or more contributor -// license agreements. See the NOTICE file distributed with -// this work for additional information regarding copyright -// ownership. Elasticsearch B.V. licenses this file to you 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 beater - -import ( - "fmt" - "sync" - "time" - - "github.com/elastic/beats/v7/journalbeat/checkpoint" - "github.com/elastic/beats/v7/journalbeat/cmd/instance" - "github.com/elastic/beats/v7/journalbeat/input" - "github.com/elastic/beats/v7/libbeat/beat" - "github.com/elastic/beats/v7/libbeat/common" - "github.com/elastic/beats/v7/libbeat/common/acker" - "github.com/elastic/beats/v7/libbeat/common/cfgwarn" - "github.com/elastic/beats/v7/libbeat/logp" - "github.com/elastic/beats/v7/libbeat/publisher/pipetool" - - "github.com/elastic/beats/v7/journalbeat/config" - _ "github.com/elastic/beats/v7/journalbeat/include" - - // Add dedicated processors - _ "github.com/elastic/beats/v7/libbeat/processors/decode_csv_fields" -) - -// Journalbeat instance -type Journalbeat struct { - inputs []*input.Input - done chan struct{} - config config.Config - - pipeline beat.Pipeline - checkpoint *checkpoint.Checkpoint - logger *logp.Logger -} - -// New returns a new Journalbeat instance -func New(b *beat.Beat, cfg *common.Config) (beat.Beater, error) { - cfgwarn.Experimental("Journalbeat is experimental.") - - config := config.DefaultConfig - if err := cfg.Unpack(&config); err != nil { - return nil, fmt.Errorf("error reading config file: %v", err) - } - - done := make(chan struct{}) - cp, err := checkpoint.NewCheckpoint(config.RegistryFile, 10, 1*time.Second) - if err != nil { - return nil, err - } - - instance.SetupJournalMetrics() - - var inputs []*input.Input - for _, c := range config.Inputs { - i, err := input.New(c, b.Info, done, cp.States()) - if err != nil { - return nil, err - } - inputs = append(inputs, i) - } - - bt := &Journalbeat{ - inputs: inputs, - done: done, - config: config, - pipeline: b.Publisher, - checkpoint: cp, - logger: logp.NewLogger("journalbeat"), - } - - return bt, nil -} - -// Run sets up the ACK handler and starts inputs to read and forward events to outputs. -func (bt *Journalbeat) Run(b *beat.Beat) error { - bt.logger.Info("journalbeat is running! Hit CTRL-C to stop it.") - defer bt.logger.Info("journalbeat is stopping") - - defer bt.checkpoint.Shutdown() - - pipeline := pipetool.WithACKer(b.Publisher, acker.LastEventPrivateReporter(func(_ int, private interface{}) { - if st, ok := private.(checkpoint.JournalState); ok { - bt.checkpoint.PersistState(st) - } - })) - - var wg sync.WaitGroup - for _, i := range bt.inputs { - wg.Add(1) - go bt.runInput(i, &wg, pipeline) - } - - wg.Wait() - - return nil -} - -func (bt *Journalbeat) runInput(i *input.Input, wg *sync.WaitGroup, pipeline beat.Pipeline) { - defer wg.Done() - i.Run(pipeline) -} - -// Stop stops the beat and its inputs. -func (bt *Journalbeat) Stop() { - close(bt.done) - for _, i := range bt.inputs { - i.Stop() - } -} diff --git a/journalbeat/checkpoint/checkpoint.go b/journalbeat/checkpoint/checkpoint.go deleted file mode 100644 index 2ba4140182a..00000000000 --- a/journalbeat/checkpoint/checkpoint.go +++ /dev/null @@ -1,352 +0,0 @@ -// Licensed to Elasticsearch B.V. under one or more contributor -// license agreements. See the NOTICE file distributed with -// this work for additional information regarding copyright -// ownership. Elasticsearch B.V. licenses this file to you 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 checkpoint persists event log state information to disk so that -// event log monitoring can resume from the last read event in the case of a -// restart or unexpected interruption. -package checkpoint - -import ( - "fmt" - "io" - "io/ioutil" - "os" - "path/filepath" - "sort" - "sync" - "time" - - "gopkg.in/yaml.v2" - - "github.com/elastic/beats/v7/libbeat/logp" - "github.com/elastic/beats/v7/libbeat/paths" -) - -// Checkpoint persists event log state information to disk. -type Checkpoint struct { - wg sync.WaitGroup // WaitGroup used to wait on the shutdown of the checkpoint worker. - done chan struct{} // Channel for shutting down the checkpoint worker. - once sync.Once // Used to guarantee shutdown happens once. - file string // File where the state is persisted. - fileLock sync.RWMutex // Lock that protects concurrent reads/writes to file. - numUpdates int // Number of updates received since last persisting to disk. - maxUpdates int // Maximum number of updates to buffer before persisting to disk. - flushInterval time.Duration // Maximum time interval that can pass before persisting to disk. - sort []string // Slice used for sorting states map (store to save on mallocs). - - lock sync.RWMutex - states map[string]JournalState - - save chan JournalState -} - -// PersistedState represents the format of the data persisted to disk. -type PersistedState struct { - UpdateTime time.Time `yaml:"update_time"` - States []JournalState `yaml:"journal_entries"` -} - -// JournalState represents the state of an individual event log. -type JournalState struct { - Path string `yaml:"path"` - Cursor string `yaml:"cursor"` - RealtimeTimestamp uint64 `yaml:"realtime_timestamp"` - MonotonicTimestamp uint64 `yaml:"monotonic_timestamp"` -} - -// NewCheckpoint creates and returns a new Checkpoint. This method loads state -// information from disk if it exists and starts a goroutine for persisting -// state information to disk. Shutdown should be called when finished to -// guarantee any in-memory state information is flushed to disk. -// -// file is the name of the file where event log state is persisted as YAML. -// maxUpdates is the maximum number of updates checkpoint will accept before -// triggering a flush to disk. interval is maximum amount of time that can -// pass since the last flush before triggering a flush to disk (minimum value -// is 1s). -func NewCheckpoint(file string, maxUpdates int, interval time.Duration) (*Checkpoint, error) { - c := &Checkpoint{ - done: make(chan struct{}), - file: file, - maxUpdates: maxUpdates, - flushInterval: interval, - sort: make([]string, 0, 10), - states: make(map[string]JournalState), - save: make(chan JournalState, 1), - } - - err := c.findRegistryFile() - if err != nil { - return nil, fmt.Errorf("error locating the proper registry file: %+v", err) - } - - // Minimum batch size. - if c.maxUpdates < 1 { - c.maxUpdates = 1 - } - - // Minimum flush interval. - if c.flushInterval < time.Second { - c.flushInterval = time.Second - } - - // Read existing state information: - ps, err := c.read() - if err != nil { - return nil, err - } - - if ps != nil { - for _, state := range ps.States { - c.states[state.Path] = state - } - } - - // Write the state file to verify we have have permissions. - err = c.flush() - if err != nil { - return nil, err - } - - c.wg.Add(1) - go c.run() - return c, nil -} - -// Previously the registry file was written to the root folder. It was fixed on -// 7.x but not on 6.x. Thus, migration is needed, so users avoid losing state info. -func (c *Checkpoint) findRegistryFile() error { - migratedPath := paths.Resolve(paths.Data, c.file) - - fs, err := os.Stat(c.file) - if os.IsNotExist(err) { - c.file = migratedPath - return nil - } else if err != nil { - return fmt.Errorf("error accessing previous registry file: %+v", err) - } - - // if two files are the same, do not do anything - migratedFs, err := os.Stat(migratedPath) - if err == nil { - if os.SameFile(fs, migratedFs) { - return nil - } - } - - f, err := os.Open(c.file) - if err != nil { - return err - } - defer f.Close() - - target, err := os.OpenFile(migratedPath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, fs.Mode()) - if err != nil { - return err - } - defer target.Close() - - if _, err := io.Copy(target, f); err != nil { - return err - } - - err = target.Sync() - if err != nil { - return fmt.Errorf("error while syncing new registry file to disk: %+v", err) - } - - c.file = migratedPath - - p := filepath.Dir(migratedPath) - pf, err := os.Open(p) - if err != nil { - return nil - } - defer pf.Close() - pf.Sync() - - return nil -} - -// run is worker loop that reads incoming state information from the save -// channel and persists it when the number of changes reaches maxEvents or -// the amount of time since the last disk write reaches flushInterval. -func (c *Checkpoint) run() { - defer c.wg.Done() - defer c.persist() - - flushTimer := time.NewTimer(c.flushInterval) - defer flushTimer.Stop() -loop: - for { - select { - case <-c.done: - break loop - case s := <-c.save: - c.lock.Lock() - c.states[s.Path] = s - c.lock.Unlock() - c.numUpdates++ - if c.numUpdates < c.maxUpdates { - continue - } - case <-flushTimer.C: - } - - c.persist() - flushTimer.Reset(c.flushInterval) - } -} - -// Shutdown stops the checkpoint worker (which persists any state to disk as -// it stops). This method blocks until the checkpoint worker shutdowns. Calling -// this method more once is safe and has no effect. -func (c *Checkpoint) Shutdown() { - c.once.Do(func() { - close(c.done) - c.wg.Wait() - }) -} - -// States returns the current in-memory event log state. This state information -// is bootstrapped with any data found on disk at creation time. -func (c *Checkpoint) States() map[string]JournalState { - c.lock.RLock() - defer c.lock.RUnlock() - - copy := make(map[string]JournalState) - for k, v := range c.states { - copy[k] = v - } - - return copy -} - -// Persist queues the given event log state information to be written to disk. -func (c *Checkpoint) Persist(path, cursor string, realTs, monotonicTs uint64) { - c.PersistState(JournalState{ - Path: path, - Cursor: cursor, - RealtimeTimestamp: realTs, - MonotonicTimestamp: monotonicTs, - }) -} - -// PersistState queues the given event log state to be written to disk. -func (c *Checkpoint) PersistState(st JournalState) { - c.save <- st -} - -// persist writes the current state to disk if the in-memory state is dirty. -func (c *Checkpoint) persist() bool { - if c.numUpdates == 0 { - return false - } - - err := c.flush() - if err != nil { - return false - } - - logp.Debug("checkpoint", "Checkpoint saved to disk. numUpdates=%d", - c.numUpdates) - c.numUpdates = 0 - return true -} - -// flush writes the current state to disk. -func (c *Checkpoint) flush() error { - c.fileLock.Lock() - defer c.fileLock.Unlock() - - tempFile := c.file + ".new" - file, err := create(tempFile) - if os.IsNotExist(err) { - // Try to create directory if it does not exist. - if createDirErr := c.createDir(); createDirErr == nil { - file, err = create(tempFile) - } - } - - if err != nil { - return fmt.Errorf("Failed to flush state to disk. %v", err) - } - - // Sort persisted eventLogs by name. - c.sort = c.sort[:0] - for k := range c.states { - c.sort = append(c.sort, k) - } - sort.Strings(c.sort) - - ps := PersistedState{ - UpdateTime: time.Now().UTC(), - States: make([]JournalState, len(c.sort)), - } - for i, name := range c.sort { - ps.States[i] = c.states[name] - } - - data, err := yaml.Marshal(ps) - if err != nil { - file.Close() - return fmt.Errorf("Failed to flush state to disk. Could not marshal "+ - "data to YAML. %v", err) - } - - _, err = file.Write(data) - if err != nil { - file.Close() - return fmt.Errorf("Failed to flush state to disk. Could not write to "+ - "%s. %v", tempFile, err) - } - - file.Close() - err = os.Rename(tempFile, c.file) - return err -} - -// read loads the persisted state from disk. If the file does not exists then -// the method returns nil and no error. -func (c *Checkpoint) read() (*PersistedState, error) { - c.fileLock.RLock() - defer c.fileLock.RUnlock() - - contents, err := ioutil.ReadFile(c.file) - if err != nil { - if os.IsNotExist(err) { - err = nil - } - return nil, err - } - - ps := &PersistedState{} - err = yaml.Unmarshal(contents, ps) - if err != nil { - return nil, err - } - - return ps, nil -} - -// createDir creates the directory in which the state file will reside if the -// directory does not already exist. -func (c *Checkpoint) createDir() error { - dir := filepath.Dir(c.file) - logp.Info("Creating %s if it does not exist.", dir) - return os.MkdirAll(dir, os.FileMode(0750)) -} diff --git a/journalbeat/checkpoint/checkpoint_test.go b/journalbeat/checkpoint/checkpoint_test.go deleted file mode 100644 index 6f6aa780d9a..00000000000 --- a/journalbeat/checkpoint/checkpoint_test.go +++ /dev/null @@ -1,223 +0,0 @@ -// Licensed to Elasticsearch B.V. under one or more contributor -// license agreements. See the NOTICE file distributed with -// this work for additional information regarding copyright -// ownership. Elasticsearch B.V. licenses this file to you 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. - -//go:build !integration -// +build !integration - -package checkpoint - -import ( - "io/ioutil" - "os" - "path/filepath" - "runtime" - "testing" - "time" - - "github.com/stretchr/testify/assert" -) - -func eventually(t *testing.T, predicate func() (bool, error), timeout time.Duration) { - const minInterval = time.Millisecond * 5 - const maxInterval = time.Millisecond * 500 - - checkInterval := timeout / 100 - if checkInterval < minInterval { - checkInterval = minInterval - } - if checkInterval > maxInterval { - checkInterval = maxInterval - } - for deadline, first := time.Now().Add(timeout), true; first || time.Now().Before(deadline); first = false { - ok, err := predicate() - if err != nil { - t.Fatal("predicate failed with error:", err) - return - } - if ok { - return - } - time.Sleep(checkInterval) - } - t.Fatal("predicate is not true after", timeout) -} - -// Test that a write is triggered when the maximum number of updates is reached. -func TestWriteMaxUpdates(t *testing.T) { - t.Skip("Duplicate of winlogbeat/checkpoint") - dir, err := ioutil.TempDir("", "wlb-checkpoint-test") - if err != nil { - t.Fatal(err) - } - defer func() { - err := os.RemoveAll(dir) - if err != nil { - t.Fatal(err) - } - }() - - file := filepath.Join(dir, "some", "new", "dir", ".winlogbeat.yml") - if !assert.False(t, fileExists(file), "%s should not exist", file) { - return - } - - cp, err := NewCheckpoint(file, 2, time.Hour) - if err != nil { - t.Fatal(err) - } - defer cp.Shutdown() - - // Send update - it's not written to disk but it's in memory. - cp.Persist("", "", 123456, 123456) - found := false - eventually(t, func() (bool, error) { - _, found = cp.States()[""] - return found, nil - }, time.Second*15) - assert.True(t, found) - - ps, err := cp.read() - if err != nil { - t.Fatal("read failed", err) - } - assert.Len(t, ps.States, 0) - - // Send update - it is written to disk. - cp.Persist("", "", 123456, 123456) - eventually(t, func() (bool, error) { - ps, err = cp.read() - return ps != nil && len(ps.States) > 0, err - }, time.Second*15) - - if assert.Len(t, ps.States, 1, "state not written, could be a flush timing issue, retry") { - assert.Equal(t, "", ps.States[0].Path) - assert.Equal(t, "", ps.States[0].Cursor) - } -} - -// Test that a write is triggered when the maximum time period since the last -// write is reached. -func TestWriteTimedFlush(t *testing.T) { - t.Skip("Duplicate of winlogbeat/checkpoint") - dir, err := ioutil.TempDir("", "wlb-checkpoint-test") - if err != nil { - t.Fatal(err) - } - defer func() { - err := os.RemoveAll(dir) - if err != nil { - t.Fatal(err) - } - }() - - file := filepath.Join(dir, ".winlogbeat.yml") - if !assert.False(t, fileExists(file), "%s should not exist", file) { - return - } - - cp, err := NewCheckpoint(file, 100, time.Second) - if err != nil { - t.Fatal(err) - } - defer cp.Shutdown() - - // Send update then wait longer than the flush interval and it should be - // on disk. - cp.Persist("", "cursor", 123456, 123456) - eventually(t, func() (bool, error) { - ps, err := cp.read() - return ps != nil && len(ps.States) > 0, err - }, time.Second*15) - - ps, err := cp.read() - if err != nil { - t.Fatal("read failed", err) - } - if assert.Len(t, ps.States, 1) { - assert.Equal(t, "", ps.States[0].Path) - assert.Equal(t, "cursor", ps.States[0].Cursor) - } -} - -// Test that createDir creates the directory with 0750 permissions. -func TestCreateDir(t *testing.T) { - t.Skip("Duplicate of winlogbeat/checkpoint") - dir, err := ioutil.TempDir("", "wlb-checkpoint-test") - if err != nil { - t.Fatal(err) - } - defer func() { - err := os.RemoveAll(dir) - if err != nil { - t.Fatal(err) - } - }() - - stateDir := filepath.Join(dir, "state", "dir", "does", "not", "exists") - file := filepath.Join(stateDir, ".winlogbeat.yml") - cp := &Checkpoint{file: file} - - if !assert.False(t, fileExists(file), "%s should not exist", file) { - return - } - if err = cp.createDir(); err != nil { - t.Fatal("createDir", err) - } - if !assert.True(t, fileExists(stateDir), "%s should exist", file) { - return - } - - // mkdir on Windows does not pass the POSIX mode to the CreateDirectory - // syscall so doesn't test the mode. - if runtime.GOOS != "windows" { - fileInfo, err := os.Stat(stateDir) - if assert.NoError(t, err) { - assert.Equal(t, true, fileInfo.IsDir()) - assert.Equal(t, os.FileMode(0750), fileInfo.Mode().Perm()) - } - } -} - -// Test createDir when the directory already exists to verify that no error is -// returned. -func TestCreateDirAlreadyExists(t *testing.T) { - t.Skip("Duplicate of winlogbeat/checkpoint") - dir, err := ioutil.TempDir("", "wlb-checkpoint-test") - if err != nil { - t.Fatal(err) - } - defer func() { - err := os.RemoveAll(dir) - if err != nil { - t.Fatal(err) - } - }() - - file := filepath.Join(dir, ".winlogbeat.yml") - cp := &Checkpoint{file: file} - - if !assert.True(t, fileExists(dir), "%s should exist", file) { - return - } - assert.NoError(t, cp.createDir()) -} - -// fileExists returns true if the specified file exists. -func fileExists(file string) bool { - _, err := os.Stat(file) - return !os.IsNotExist(err) -} diff --git a/journalbeat/checkpoint/file_unix.go b/journalbeat/checkpoint/file_unix.go deleted file mode 100644 index 248b5301955..00000000000 --- a/journalbeat/checkpoint/file_unix.go +++ /dev/null @@ -1,27 +0,0 @@ -// Licensed to Elasticsearch B.V. under one or more contributor -// license agreements. See the NOTICE file distributed with -// this work for additional information regarding copyright -// ownership. Elasticsearch B.V. licenses this file to you 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. - -//go:build !windows -// +build !windows - -package checkpoint - -import "os" - -func create(path string) (*os.File, error) { - return os.OpenFile(path, os.O_RDWR|os.O_CREATE|os.O_TRUNC|os.O_SYNC, 0600) -} diff --git a/journalbeat/checkpoint/file_windows.go b/journalbeat/checkpoint/file_windows.go deleted file mode 100644 index 267086398f3..00000000000 --- a/journalbeat/checkpoint/file_windows.go +++ /dev/null @@ -1,54 +0,0 @@ -// Licensed to Elasticsearch B.V. under one or more contributor -// license agreements. See the NOTICE file distributed with -// this work for additional information regarding copyright -// ownership. Elasticsearch B.V. licenses this file to you 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 checkpoint - -import ( - "os" - "syscall" -) - -const ( - _FILE_FLAG_WRITE_THROUGH = 0x80000000 -) - -func create(path string) (*os.File, error) { - return createWriteThroughFile(path) -} - -// createWriteThroughFile creates a file whose write operations do not go -// through any intermediary cache, they go directly to disk. -func createWriteThroughFile(path string) (*os.File, error) { - if len(path) == 0 { - return nil, syscall.ERROR_FILE_NOT_FOUND - } - pathp, err := syscall.UTF16PtrFromString(path) - if err != nil { - return nil, err - } - - h, err := syscall.CreateFile( - pathp, // Path - syscall.GENERIC_READ|syscall.GENERIC_WRITE, // Access Mode - uint32(syscall.FILE_SHARE_READ|syscall.FILE_SHARE_WRITE), // Share Mode - nil, // Security Attributes - syscall.CREATE_ALWAYS, // Create Mode - uint32(syscall.FILE_ATTRIBUTE_NORMAL|_FILE_FLAG_WRITE_THROUGH), // Flags and Attributes - 0) // Template File - - return os.NewFile(uintptr(h), path), err -} diff --git a/journalbeat/cmd/instance/metrics.go b/journalbeat/cmd/instance/metrics.go deleted file mode 100644 index 3d75426c809..00000000000 --- a/journalbeat/cmd/instance/metrics.go +++ /dev/null @@ -1,69 +0,0 @@ -// Licensed to Elasticsearch B.V. under one or more contributor -// license agreements. See the NOTICE file distributed with -// this work for additional information regarding copyright -// ownership. Elasticsearch B.V. licenses this file to you 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. - -//go:build linux && cgo -// +build linux,cgo - -package instance - -import ( - "fmt" - - "github.com/coreos/go-systemd/v22/sdjournal" - - "github.com/elastic/beats/v7/libbeat/monitoring" -) - -var ( - metrics *monitoring.Registry - journals map[string]*sdjournal.Journal -) - -// SetupJournalMetrics initializes and registers monitoring functions. -func SetupJournalMetrics() { - metrics = monitoring.Default.NewRegistry("journalbeat") - journals = make(map[string]*sdjournal.Journal) - - monitoring.NewFunc(metrics, "journals", reportJournalSizes, monitoring.Report) -} - -// AddJournalToMonitor adds a new journal which has to be monitored. -func AddJournalToMonitor(path string, journal *sdjournal.Journal) { - journals[path] = journal -} - -// StopMonitoringJournal stops monitoring the journal under the path. -func StopMonitoringJournal(path string) { - delete(journals, path) -} - -func reportJournalSizes(m monitoring.Mode, V monitoring.Visitor) { - i := 0 - for path, journal := range journals { - s, err := journal.GetUsage() - if err != nil { - continue - } - - ns := fmt.Sprintf("journal_%d", i) - monitoring.ReportNamespace(V, ns, func() { - monitoring.ReportString(V, "path", path) - monitoring.ReportInt(V, "size_in_bytes", int64(s)) - }) - i++ - } -} diff --git a/journalbeat/cmd/instance/metrics_other.go b/journalbeat/cmd/instance/metrics_other.go deleted file mode 100644 index 990d5f06b09..00000000000 --- a/journalbeat/cmd/instance/metrics_other.go +++ /dev/null @@ -1,27 +0,0 @@ -// Licensed to Elasticsearch B.V. under one or more contributor -// license agreements. See the NOTICE file distributed with -// this work for additional information regarding copyright -// ownership. Elasticsearch B.V. licenses this file to you 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. - -//go:build !linux || !cgo -// +build !linux !cgo - -package instance - -// SetupJournalMetrics initializes and registers monitoring functions. -func SetupJournalMetrics() {} - -// StopMonitoringJournal stops monitoring the journal under the path. -func StopMonitoringJournal(path string) {} diff --git a/journalbeat/cmd/root.go b/journalbeat/cmd/root.go deleted file mode 100644 index a7a2d8ddcaa..00000000000 --- a/journalbeat/cmd/root.go +++ /dev/null @@ -1,64 +0,0 @@ -// Licensed to Elasticsearch B.V. under one or more contributor -// license agreements. See the NOTICE file distributed with -// this work for additional information regarding copyright -// ownership. Elasticsearch B.V. licenses this file to you 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 cmd - -import ( - "github.com/elastic/beats/v7/journalbeat/beater" - "github.com/elastic/beats/v7/libbeat/cmd" - "github.com/elastic/beats/v7/libbeat/cmd/instance" - "github.com/elastic/beats/v7/libbeat/common" - "github.com/elastic/beats/v7/libbeat/ecs" - "github.com/elastic/beats/v7/libbeat/publisher/processing" - - // Import processors. - _ "github.com/elastic/beats/v7/libbeat/processors/script" - _ "github.com/elastic/beats/v7/libbeat/processors/timestamp" -) - -const ( - // Name of this beat. - Name = "journalbeat" -) - -// withECSVersion is a modifier that adds ecs.version to events. -var withECSVersion = processing.WithFields(common.MapStr{ - "ecs": common.MapStr{ - "version": ecs.Version, - }, -}) - -// RootCmd to handle beats cli -var RootCmd *cmd.BeatsRootCmd - -// JournalbeatSettings contains the default settings for journalbeat -func JournalbeatSettings() instance.Settings { - return instance.Settings{ - Name: Name, - HasDashboards: false, - Processing: processing.MakeDefaultSupport(true, withECSVersion, processing.WithHost, processing.WithAgentMeta()), - } -} - -// Initialize initializes the entrypoint commands for journalbeat -func Initialize(settings instance.Settings) *cmd.BeatsRootCmd { - return cmd.GenRootCmdWithSettings(beater.New, settings) -} - -func init() { - RootCmd = Initialize(JournalbeatSettings()) -} diff --git a/journalbeat/conftest.py b/journalbeat/conftest.py deleted file mode 100644 index 2f3f8199559..00000000000 --- a/journalbeat/conftest.py +++ /dev/null @@ -1,4 +0,0 @@ -import os -import sys - -sys.path.append(os.path.join(os.path.dirname(__file__), '../libbeat/tests/system')) diff --git a/journalbeat/docs/config-options.asciidoc b/journalbeat/docs/config-options.asciidoc deleted file mode 100644 index 106318ceb6d..00000000000 --- a/journalbeat/docs/config-options.asciidoc +++ /dev/null @@ -1,251 +0,0 @@ -[id="configuration-{beatname_lc}-options"] -== Configure inputs - -++++ -Inputs -++++ - -By default, {beatname_uc} reads log events from the default systemd journals. To -specify other journal files, set the <<{beatname_lc}-paths,`paths`>> option in -the +{beatname_lc}.inputs+ section of the +{beatname_lc}.yml+ file. Each path -can be a directory path (to collect events from all journals in a directory), or -a file path. For example: - -["source","sh",subs="attributes"] ----- -{beatname_lc}.inputs: -- paths: - - "/dev/log" - - "/var/log/messages/my-journal-file.journal" ----- - -Within the configuration file, you can also specify options that control how -{beatname_uc} reads the journal files and which fields are sent to the -configured output. See <<{beatname_lc}-options>> for a list of available -options. - -The following examples show how to configure {beatname_uc} for some common use -cases. - -[[monitor-multiple-journals]] -.Example 1: Monitor multiple journals under the same directory -This example configures {beatname_uc} to read from multiple journals that are -stored under the same directory. {beatname_uc} merges all journals under the -directory into a single event stream and reads the events. With `seek` set to -`cursor`, {beatname_uc} starts reading at the beginning of the journal, but will -continue reading at the last known position after a reload or restart. -["source","sh",subs="attributes"] ----- -{beatname_lc}.inputs: -- paths: ["/path/to/journal/directory"] - seek: cursor ----- - -[[filter-using-field-names]] -.Example 2: Fetch log events for Redis running on Docker (uses field names from systemd) -This example configures {beatname_uc} to fetch log events for Redis running in a -Docker container. The fields are matched using field names from the systemd -journal. -["source","sh",subs="attributes"] ----- -{beatname_lc}.inputs: -- paths: [] - include_matches: - - "CONTAINER_TAG=redis" - - "_COMM=redis" ----- - -[[filter-using-translated-names]] -.Example 3: Fetch log events for Redis running on Docker (uses translated field names) -This example also configures {beatname_uc} to fetch log events for Redis running -in a Docker container. However, in this example the fields are matched using the -<> provided by {beatname_uc}. -["source","sh",subs="attributes"] ----- -{beatname_lc}.inputs: -- paths: [] - include_matches: - - "container.image.tag=redis" - - "process.name=redis" ----- - -[id="{beatname_lc}-options"] -[float] -=== Configuration options -You can specify the following options to configure how {beatname_uc} reads the -journal files. - -[float] -[id="{beatname_lc}-id"] -==== `id` - -An optional unique identifier for the input. By providing a unique `id` you can -operate multiple inputs on the same journal. This allows each input's cursor -to be persisted independently in the registry file. - ----- -{beatname_lc}.inputs: -- id: consul.service - paths: [] - include_matches: - - _SYSTEMD_UNIT=consul.service - -- id: vault.service - paths: [] - include_matches: - - _SYSTEMD_UNIT=vault.service ----- - -[float] -[id="{beatname_lc}-paths"] -==== `paths` - -A list of paths that will be crawled and fetched. Each path can be a directory -path (to collect events from all journals in a directory), or a file path. If -you specify a directory, {beatname_uc} merges all journals under the directory -into a single journal and reads them. - -If no paths are specified, {beatname_uc} reads from the default journal. - -[float] -[id="{beatname_lc}-backoff"] -==== `backoff` - -The number of seconds to wait before trying to read again from journals. The -default is 1s. - -[float] -[id="{beatname_lc}-max-backoff"] -==== `max_backoff` - -The maximum number of seconds to wait before attempting to read again from -journals. The default is 60s. - -[float] -[id="seek"] -==== `seek` - -The position to start reading the journal from. Valid settings are: - -* `head`: Starts reading at the beginning of the journal. After a restart, -{beatname_uc} resends all log messages in the journal. -* `tail`: Starts reading at the end of the journal. After a restart, -{beatname_uc} resends the last message, which might result in duplicates. If -multiple log messages are written to a journal while {beatname_uc} is down, -only the last log message is sent on restart. -* `cursor`: On first read, starts reading at the beginning of the journal. After a -reload or restart, continues reading at the last known position. - -When specified under `paths`, the `seek` setting applies to all journals under -the configured paths. When specified directly under the +{beatname_lc}+ -namespace, the setting applies to all journals read by {beatname_uc}. - -If you have old log files and want to skip lines, start {beatname_uc} with -`seek: tail` specified. Then stop {beatname_uc}, set `seek: cursor`, and restart -{beatname_uc}. - -[float] -[id="include-matches"] -==== `include_matches` - -A list of filter expressions used to match fields. The format of the expression -is `field=value`. {beatname_uc} fetches all events that exactly match the -expressions. Pattern matching is not supported. - -To reference fields, use one of the following: - -* The field name used by the systemd journal. For example, -`CONTAINER_TAG=redis` (<>). -* The <> used by -{beatname_uc}. For example, `container.image.tag=redis` -(<>). {beatname_uc} -does not translate all fields from the journal. For custom fields, use the name -specified in the systemd journal. - -When specified under `paths`, the `include_matches` filter is applied to all -journals under the configured paths. When specified directly under the -+{beatname_lc}+ namespace, the setting applies to all journals read by -{beatname_uc}. - -[float] -[[translated-fields]] -=== Translated field names - -You can use the following translated names in filter expressions to reference -journald fields: - -[horizontal] -*Journald field name*:: *Translated name* -`COREDUMP_UNIT`:: `journald.coredump.unit` -`COREDUMP_USER_UNIT`:: `journald.coredump.user_unit` -`OBJECT_AUDIT_LOGINUID`:: `journald.object.audit.login_uid` -`OBJECT_AUDIT_SESSION`:: `journald.object.audit.session` -`OBJECT_CMDLINE`:: `journald.object.cmd` -`OBJECT_COMM`:: `journald.object.name` -`OBJECT_EXE`:: `journald.object.executable` -`OBJECT_GID`:: `journald.object.gid` -`OBJECT_PID`:: `journald.object.pid` -`OBJECT_SYSTEMD_OWNER_UID`:: `journald.object.systemd.owner_uid` -`OBJECT_SYSTEMD_SESSION`:: `journald.object.systemd.session` -`OBJECT_SYSTEMD_UNIT`:: `journald.object.systemd.unit` -`OBJECT_SYSTEMD_USER_UNIT`:: `journald.object.systemd.user_unit` -`OBJECT_UID`:: `journald.object.uid` -`_AUDIT_LOGINUID`:: `process.audit.login_uid` -`_AUDIT_SESSION`:: `process.audit.session` -`_BOOT_ID`:: `host.boot_id` -`_CAP_EFFECTIVE`:: `process.capabilites` -`_CMDLINE`:: `process.cmd` -`_CODE_FILE`:: `journald.code.file` -`_CODE_FUNC`:: `journald.code.func` -`_CODE_LINE`:: `journald.code.line` -`_COMM`:: `process.name` -`_EXE`:: `process.executable` -`_GID`:: `process.uid` -`_HOSTNAME`:: `host.name` -`_KERNEL_DEVICE`:: `journald.kernel.device` -`_KERNEL_SUBSYSTEM`:: `journald.kernel.subsystem` -`_MACHINE_ID`:: `host.id` -`_MESSAGE`:: `message` -`_PID`:: `process.pid` -`_PRIORITY`:: `syslog.priority` -`_SYSLOG_FACILITY`:: `syslog.facility` -`_SYSLOG_IDENTIFIER`:: `syslog.identifier` -`_SYSLOG_PID`:: `syslog.pid` -`_SYSTEMD_CGROUP`:: `systemd.cgroup` -`_SYSTEMD_INVOCATION_ID`:: `systemd.invocation_id` -`_SYSTEMD_OWNER_UID`:: `systemd.owner_uid` -`_SYSTEMD_SESSION`:: `systemd.session` -`_SYSTEMD_SLICE`:: `systemd.slice` -`_SYSTEMD_UNIT`:: `systemd.unit` -`_SYSTEMD_USER_SLICE`:: `systemd.user_slice` -`_SYSTEMD_USER_UNIT`:: `systemd.user_unit` -`_TRANSPORT`:: `systemd.transport` -`_UDEV_DEVLINK`:: `journald.kernel.device_symlinks` -`_UDEV_DEVNODE`:: `journald.kernel.device_node_path` -`_UDEV_SYSNAME`:: `journald.kernel.device_name` -`_UID`:: `process.uid` - - -The following translated fields for -https://docs.docker.com/config/containers/logging/journald/[Docker] are also -available: - -[horizontal] -`CONTAINER_ID`:: `container.id_truncated` -`CONTAINER_ID_FULL`:: `container.id` -`CONTAINER_NAME`:: `container.name` -`CONTAINER_PARTIAL_MESSAGE`:: `container.partial` -`CONTAINER_TAG`:: `container.image.tag` - -[float] -[id="index"] -==== `index` - -If present, this formatted string overrides the index for events from this input -(for elasticsearch outputs), or sets the `raw_index` field of the event's -metadata (for other outputs). This string can only refer to the agent name and -version and the event timestamp; for access to dynamic fields, use -`output.elasticsearch.index` or a processor. - -Example value: `"%{[agent.name]}-myindex-%{+yyyy.MM.dd}"` might -expand to `"journalbeat-myindex-2019.12.13"`. diff --git a/journalbeat/docs/configuring-howto.asciidoc b/journalbeat/docs/configuring-howto.asciidoc deleted file mode 100644 index 246880468e3..00000000000 --- a/journalbeat/docs/configuring-howto.asciidoc +++ /dev/null @@ -1,59 +0,0 @@ -[id="configuring-howto-{beatname_lc}"] -= Configure {beatname_uc} - -[partintro] --- -++++ -Configure -++++ - -include::{libbeat-dir}/shared/configuring-intro.asciidoc[] - -* <> -* <> -* <> -* <> -* <> -* <> -* <> -* <> -* <> -* <> -* <> -* <> -* <> -* <<{beatname_lc}-reference-yml>> - --- - -include::./config-options.asciidoc[] - -include::./general-options.asciidoc[] - -include::{libbeat-dir}/shared-path-config.asciidoc[] - -include::{libbeat-dir}/outputconfig.asciidoc[] - -ifndef::no_kerberos[] -include::{libbeat-dir}/shared-kerberos-config.asciidoc[] -endif::[] - -include::{libbeat-dir}/shared-ssl-config.asciidoc[] - -include::{libbeat-dir}/shared-ilm.asciidoc[] - -include::{libbeat-dir}/setup-config.asciidoc[] - -include::./filtering.asciidoc[] - -include::{libbeat-dir}/queueconfig.asciidoc[] - -include::{libbeat-dir}/loggingconfig.asciidoc[] - -include::{libbeat-dir}/http-endpoint.asciidoc[] - -include::{libbeat-dir}/regexp.asciidoc[] - -include::{libbeat-dir}/shared-instrumentation.asciidoc[] - -include::{libbeat-dir}/reference-yml.asciidoc[] diff --git a/journalbeat/docs/faq.asciidoc b/journalbeat/docs/faq.asciidoc deleted file mode 100644 index bbe89a61c72..00000000000 --- a/journalbeat/docs/faq.asciidoc +++ /dev/null @@ -1,10 +0,0 @@ -[[faq]] -== Common problems - -This section describes common problems you might encounter with -{beatname_uc}. Also check out the -https://discuss.elastic.co/c/beats/{beatname_lc}[{beatname_uc} discussion forum]. - -include::{libbeat-dir}/faq-limit-bandwidth.asciidoc[] - -include::{libbeat-dir}/shared-faq.asciidoc[] diff --git a/journalbeat/docs/fields.asciidoc b/journalbeat/docs/fields.asciidoc deleted file mode 100644 index d0900854735..00000000000 --- a/journalbeat/docs/fields.asciidoc +++ /dev/null @@ -1,16332 +0,0 @@ - -//// -This file is generated! See _meta/fields.yml and scripts/generate_fields_docs.py -//// - -[[exported-fields]] -= Exported fields - -[partintro] - --- -This document describes the fields that are exported by Journalbeat. They are -grouped in the following categories: - -* <> -* <> -* <> -* <> -* <> -* <> -* <> -* <> -* <> - --- -[[exported-fields-beat-common]] -== Beat fields - -Contains common beat fields available in all event types. - - - -*`agent.hostname`*:: -+ --- -Deprecated - use agent.name or agent.id to identify an agent. - - -type: alias - -alias to: agent.name - --- - -*`beat.timezone`*:: -+ --- -type: alias - -alias to: event.timezone - --- - -*`fields`*:: -+ --- -Contains user configurable fields. - - -type: object - --- - -*`beat.name`*:: -+ --- -type: alias - -alias to: host.name - --- - -*`beat.hostname`*:: -+ --- -type: alias - -alias to: agent.name - --- - -*`timeseries.instance`*:: -+ --- -Time series instance id - -type: keyword - --- - -[[exported-fields-cloud]] -== Cloud provider metadata fields - -Metadata from cloud providers added by the add_cloud_metadata processor. - - - -*`cloud.image.id`*:: -+ --- -Image ID for the cloud instance. - - -example: ami-abcd1234 - --- - -*`meta.cloud.provider`*:: -+ --- -type: alias - -alias to: cloud.provider - --- - -*`meta.cloud.instance_id`*:: -+ --- -type: alias - -alias to: cloud.instance.id - --- - -*`meta.cloud.instance_name`*:: -+ --- -type: alias - -alias to: cloud.instance.name - --- - -*`meta.cloud.machine_type`*:: -+ --- -type: alias - -alias to: cloud.machine.type - --- - -*`meta.cloud.availability_zone`*:: -+ --- -type: alias - -alias to: cloud.availability_zone - --- - -*`meta.cloud.project_id`*:: -+ --- -type: alias - -alias to: cloud.project.id - --- - -*`meta.cloud.region`*:: -+ --- -type: alias - -alias to: cloud.region - --- - -[[exported-fields-common]] -== Common Journalbeat fields - -Contains common fields available in all event types. - - - -[float] -=== coredump - -Fields used by systemd-coredump kernel helper. - - - -*`coredump.unit`*:: -+ --- -Annotations of messages containing coredumps from system units. - - -type: keyword - --- - -*`coredump.user_unit`*:: -+ --- -Annotations of messages containing coredumps from user units. - - -type: keyword - --- - -[float] -=== journald - -Fields provided by journald. - - - -[float] -=== object - -Fields to log on behalf of a different program. - - - -[float] -=== audit - -Audit fields of event. - - - -*`journald.object.audit.login_uid`*:: -+ --- -The login UID of the object process. - - -type: long - -example: 1000 - -required: False - --- - -*`journald.object.audit.session`*:: -+ --- -The audit session of the object process. - - -type: long - -example: 3 - -required: False - --- - -*`journald.object.process.command_line`*:: -+ --- -The command line of the process. - - -type: keyword - -example: /lib/systemd/systemd --user - -required: False - --- - -*`journald.object.process.name`*:: -+ --- -Name of the executable. - - -type: keyword - -example: /lib/systemd/systemd - -required: False - --- - -*`journald.object.process.executable`*:: -+ --- -Path to the the executable. - - -type: keyword - -example: /lib/systemd/systemd - -required: False - --- - -*`journald.object.uid`*:: -+ --- -UID of the object process. - - -type: long - -required: False - --- - -*`journald.object.gid`*:: -+ --- -GID of the object process. - - -type: long - -required: False - --- - -*`journald.object.pid`*:: -+ --- -PID of the object process. - - -type: long - -required: False - --- - -[float] -=== systemd - -Systemd fields of event. - - - -*`journald.object.systemd.owner_uid`*:: -+ --- -The UID of the owner. - - -type: long - -required: False - --- - -*`journald.object.systemd.session`*:: -+ --- -The ID of the systemd session. - - -type: keyword - -required: False - --- - -*`journald.object.systemd.unit`*:: -+ --- -The name of the systemd unit. - - -type: keyword - -required: False - --- - -*`journald.object.systemd.user_unit`*:: -+ --- -The name of the systemd user unit. - - -type: keyword - -required: False - --- - -[float] -=== kernel - -Fields to log on behalf of a different program. - - - -*`journald.kernel.device`*:: -+ --- -The kernel device name. - - -type: keyword - -required: False - --- - -*`journald.kernel.subsystem`*:: -+ --- -The kernel subsystem name. - - -type: keyword - -required: False - --- - -*`journald.kernel.device_symlinks`*:: -+ --- -Additional symlink names pointing to the device node in /dev. - - -type: keyword - -required: False - --- - -*`journald.kernel.device_node_path`*:: -+ --- -The device node path of this device in /dev. - - -type: keyword - -required: False - --- - -*`journald.kernel.device_name`*:: -+ --- -The kernel device name as it shows up in the device tree below /sys. - - -type: keyword - -required: False - --- - -[float] -=== code - -Fields of the code generating the event. - - - -*`journald.code.file`*:: -+ --- -The name of the source file where the log is generated. - - -type: keyword - -example: ../src/core/manager.c - -required: False - --- - -*`journald.code.function`*:: -+ --- -The name of the function which generated the log message. - - -type: keyword - -example: job_log_status_message - -required: False - --- - -*`journald.code.line`*:: -+ --- -The line number of the code which generated the log message. - - -type: long - -example: 123 - -required: False - --- - -[float] -=== process - -Fields to log on behalf of a different program. - - - -[float] -=== audit - -Audit fields of event. - - - -*`journald.process.audit.loginuid`*:: -+ --- -The login UID of the source process. - - -type: long - -example: 1000 - -required: False - --- - -*`journald.process.audit.session`*:: -+ --- -The audit session of the source process. - - -type: long - -example: 3 - -required: False - --- - -*`journald.process.command_line`*:: -+ --- -The command line of the process. - - -type: keyword - -example: /lib/systemd/systemd --user - -required: False - --- - -*`journald.process.name`*:: -+ --- -Name of the executable. - - -type: keyword - -example: /lib/systemd/systemd - -required: False - --- - -*`journald.process.executable`*:: -+ --- -Path to the the executable. - - -type: keyword - -example: /lib/systemd/systemd - -required: False - --- - -*`journald.process.pid`*:: -+ --- -The ID of the process which logged the message. - - -type: long - -example: 1 - -required: False - --- - -*`journald.process.gid`*:: -+ --- -The ID of the group which runs the process. - - -type: long - -example: 1 - -required: False - --- - -*`journald.process.uid`*:: -+ --- -The ID of the user which runs the process. - - -type: long - -example: 1 - -required: False - --- - -*`journald.process.capabilities`*:: -+ --- -The effective capabilities of the process. - - -required: False - --- - -[float] -=== systemd - -Fields of systemd. - - - -*`systemd.invocation_id`*:: -+ --- -The invocation ID for the runtime cycle of the unit the message was generated in. - - -type: keyword - -example: 8450f1672de646c88cd133aadd4f2d70 - -required: False - --- - -*`systemd.cgroup`*:: -+ --- -The control group path in the systemd hierarchy. - - -type: keyword - -example: /user.slice/user-1234.slice/session-2.scope - -required: False - --- - -*`systemd.owner_uid`*:: -+ --- -The owner UID of the systemd user unit or systemd session. - - -type: long - -required: False - --- - -*`systemd.session`*:: -+ --- -The ID of the systemd session. - - -type: keyword - -required: False - --- - -*`systemd.slice`*:: -+ --- -The systemd slice unit. - - -type: keyword - -example: user-1234.slice - -required: False - --- - -*`systemd.user_slice`*:: -+ --- -The systemd user slice unit. - - -type: keyword - -required: False - --- - -*`systemd.unit`*:: -+ --- -The name of the systemd unit. - - -type: keyword - -example: nginx.service - -required: False - --- - -*`systemd.user_unit`*:: -+ --- -The name of the systemd user unit. - - -type: keyword - -example: user-1234.slice - -required: False - --- - -*`systemd.transport`*:: -+ --- -How the log message was received by journald. - - -type: keyword - -example: syslog - -required: True - --- - -[float] -=== host - -Fields of the host. - - - -*`host.boot_id`*:: -+ --- -The boot ID for the boot the log was generated in. - - -type: keyword - -example: dd8c974asdf01dbe2ef26d7fasdf264c9 - -required: False - --- - -[float] -=== syslog - -Fields of the code generating the event. - - - -*`syslog.priority`*:: -+ --- -The priority of the message. A syslog compatibility field. - - -type: long - -example: 1 - -required: False - --- - -*`syslog.facility`*:: -+ --- -The facility of the message. A syslog compatibility field. - - -type: long - -example: 1 - -required: False - --- - -*`syslog.identifier`*:: -+ --- -The identifier of the message. A syslog compatibility field. - - -type: keyword - -example: su - -required: False - --- - -*`custom`*:: -+ --- -Arbitrary fields coming from processes. - - -type: nested - -required: False - --- - -*`read_timestamp`*:: -+ --- -type: alias - -alias to: event.created - --- - - - -*`container.log.tag`*:: -+ --- -User defined tag of a container. - - -type: keyword - --- - -[[exported-fields-docker-processor]] -== Docker fields - -Docker stats collected from Docker. - - - - -*`docker.container.id`*:: -+ --- -type: alias - -alias to: container.id - --- - -*`docker.container.image`*:: -+ --- -type: alias - -alias to: container.image.name - --- - -*`docker.container.name`*:: -+ --- -type: alias - -alias to: container.name - --- - -*`docker.container.labels`*:: -+ --- -Image labels. - - -type: object - --- - -[[exported-fields-ecs]] -== ECS fields - - -This section defines Elastic Common Schema (ECS) fields—a common set of fields -to be used when storing event data in {es}. - -This is an exhaustive list, and fields listed here are not necessarily used by {beatname_uc}. -The goal of ECS is to enable and encourage users of {es} to normalize their event data, -so that they can better analyze, visualize, and correlate the data represented in their events. - -See the {ecs-ref}[ECS reference] for more information. - -*`@timestamp`*:: -+ --- -Date/time when the event originated. -This is the date/time extracted from the event, typically representing when the event was generated by the source. -If the event source has no original timestamp, this value is typically populated by the first time the event was received by the pipeline. -Required field for all events. - -type: date - -example: 2016-05-23T08:05:34.853Z - -required: True - --- - -*`labels`*:: -+ --- -Custom key/value pairs. -Can be used to add meta information to events. Should not contain nested objects. All values are stored as keyword. -Example: `docker` and `k8s` labels. - -type: object - -example: {"application": "foo-bar", "env": "production"} - --- - -*`message`*:: -+ --- -For log events the message field contains the log message, optimized for viewing in a log viewer. -For structured logs without an original message field, other fields can be concatenated to form a human-readable summary of the event. -If multiple messages exist, they can be combined into one message. - -type: match_only_text - -example: Hello World - --- - -*`tags`*:: -+ --- -List of keywords used to tag each event. - -type: keyword - -example: ["production", "env2"] - --- - -[float] -=== agent - -The agent fields contain the data about the software entity, if any, that collects, detects, or observes events on a host, or takes measurements on a host. -Examples include Beats. Agents may also run on observers. ECS agent.* fields shall be populated with details of the agent running on the host or observer where the event happened or the measurement was taken. - - -*`agent.build.original`*:: -+ --- -Extended build information for the agent. -This field is intended to contain any build information that a data source may provide, no specific formatting is required. - -type: keyword - -example: metricbeat version 7.6.0 (amd64), libbeat 7.6.0 [6a23e8f8f30f5001ba344e4e54d8d9cb82cb107c built 2020-02-05 23:10:10 +0000 UTC] - --- - -*`agent.ephemeral_id`*:: -+ --- -Ephemeral identifier of this agent (if one exists). -This id normally changes across restarts, but `agent.id` does not. - -type: keyword - -example: 8a4f500f - --- - -*`agent.id`*:: -+ --- -Unique identifier of this agent (if one exists). -Example: For Beats this would be beat.id. - -type: keyword - -example: 8a4f500d - --- - -*`agent.name`*:: -+ --- -Custom name of the agent. -This is a name that can be given to an agent. This can be helpful if for example two Filebeat instances are running on the same host but a human readable separation is needed on which Filebeat instance data is coming from. -If no name is given, the name is often left empty. - -type: keyword - -example: foo - --- - -*`agent.type`*:: -+ --- -Type of the agent. -The agent type always stays the same and should be given by the agent used. In case of Filebeat the agent would always be Filebeat also if two Filebeat instances are run on the same machine. - -type: keyword - -example: filebeat - --- - -*`agent.version`*:: -+ --- -Version of the agent. - -type: keyword - -example: 6.0.0-rc2 - --- - -[float] -=== as - -An autonomous system (AS) is a collection of connected Internet Protocol (IP) routing prefixes under the control of one or more network operators on behalf of a single administrative entity or domain that presents a common, clearly defined routing policy to the internet. - - -*`as.number`*:: -+ --- -Unique number allocated to the autonomous system. The autonomous system number (ASN) uniquely identifies each network on the Internet. - -type: long - -example: 15169 - --- - -*`as.organization.name`*:: -+ --- -Organization name. - -type: keyword - -example: Google LLC - --- - -*`as.organization.name.text`*:: -+ --- -type: match_only_text - --- - -[float] -=== client - -A client is defined as the initiator of a network connection for events regarding sessions, connections, or bidirectional flow records. -For TCP events, the client is the initiator of the TCP connection that sends the SYN packet(s). For other protocols, the client is generally the initiator or requestor in the network transaction. Some systems use the term "originator" to refer the client in TCP connections. The client fields describe details about the system acting as the client in the network event. Client fields are usually populated in conjunction with server fields. Client fields are generally not populated for packet-level events. -Client / server representations can add semantic context to an exchange, which is helpful to visualize the data in certain situations. If your context falls in that category, you should still ensure that source and destination are filled appropriately. - - -*`client.address`*:: -+ --- -Some event client addresses are defined ambiguously. The event will sometimes list an IP, a domain or a unix socket. You should always store the raw address in the `.address` field. -Then it should be duplicated to `.ip` or `.domain`, depending on which one it is. - -type: keyword - --- - -*`client.as.number`*:: -+ --- -Unique number allocated to the autonomous system. The autonomous system number (ASN) uniquely identifies each network on the Internet. - -type: long - -example: 15169 - --- - -*`client.as.organization.name`*:: -+ --- -Organization name. - -type: keyword - -example: Google LLC - --- - -*`client.as.organization.name.text`*:: -+ --- -type: match_only_text - --- - -*`client.bytes`*:: -+ --- -Bytes sent from the client to the server. - -type: long - -example: 184 - -format: bytes - --- - -*`client.domain`*:: -+ --- -Client domain. - -type: keyword - --- - -*`client.geo.city_name`*:: -+ --- -City name. - -type: keyword - -example: Montreal - --- - -*`client.geo.continent_code`*:: -+ --- -Two-letter code representing continent's name. - -type: keyword - -example: NA - --- - -*`client.geo.continent_name`*:: -+ --- -Name of the continent. - -type: keyword - -example: North America - --- - -*`client.geo.country_iso_code`*:: -+ --- -Country ISO code. - -type: keyword - -example: CA - --- - -*`client.geo.country_name`*:: -+ --- -Country name. - -type: keyword - -example: Canada - --- - -*`client.geo.location`*:: -+ --- -Longitude and latitude. - -type: geo_point - -example: { "lon": -73.614830, "lat": 45.505918 } - --- - -*`client.geo.name`*:: -+ --- -User-defined description of a location, at the level of granularity they care about. -Could be the name of their data centers, the floor number, if this describes a local physical entity, city names. -Not typically used in automated geolocation. - -type: keyword - -example: boston-dc - --- - -*`client.geo.postal_code`*:: -+ --- -Postal code associated with the location. -Values appropriate for this field may also be known as a postcode or ZIP code and will vary widely from country to country. - -type: keyword - -example: 94040 - --- - -*`client.geo.region_iso_code`*:: -+ --- -Region ISO code. - -type: keyword - -example: CA-QC - --- - -*`client.geo.region_name`*:: -+ --- -Region name. - -type: keyword - -example: Quebec - --- - -*`client.geo.timezone`*:: -+ --- -The time zone of the location, such as IANA time zone name. - -type: keyword - -example: America/Argentina/Buenos_Aires - --- - -*`client.ip`*:: -+ --- -IP address of the client (IPv4 or IPv6). - -type: ip - --- - -*`client.mac`*:: -+ --- -MAC address of the client. -The notation format from RFC 7042 is suggested: Each octet (that is, 8-bit byte) is represented by two [uppercase] hexadecimal digits giving the value of the octet as an unsigned integer. Successive octets are separated by a hyphen. - -type: keyword - -example: 00-00-5E-00-53-23 - --- - -*`client.nat.ip`*:: -+ --- -Translated IP of source based NAT sessions (e.g. internal client to internet). -Typically connections traversing load balancers, firewalls, or routers. - -type: ip - --- - -*`client.nat.port`*:: -+ --- -Translated port of source based NAT sessions (e.g. internal client to internet). -Typically connections traversing load balancers, firewalls, or routers. - -type: long - -format: string - --- - -*`client.packets`*:: -+ --- -Packets sent from the client to the server. - -type: long - -example: 12 - --- - -*`client.port`*:: -+ --- -Port of the client. - -type: long - -format: string - --- - -*`client.registered_domain`*:: -+ --- -The highest registered client domain, stripped of the subdomain. -For example, the registered domain for "foo.example.com" is "example.com". -This value can be determined precisely with a list like the public suffix list (http://publicsuffix.org). Trying to approximate this by simply taking the last two labels will not work well for TLDs such as "co.uk". - -type: keyword - -example: example.com - --- - -*`client.subdomain`*:: -+ --- -The subdomain portion of a fully qualified domain name includes all of the names except the host name under the registered_domain. In a partially qualified domain, or if the the qualification level of the full name cannot be determined, subdomain contains all of the names below the registered domain. -For example the subdomain portion of "www.east.mydomain.co.uk" is "east". If the domain has multiple levels of subdomain, such as "sub2.sub1.example.com", the subdomain field should contain "sub2.sub1", with no trailing period. - -type: keyword - -example: east - --- - -*`client.top_level_domain`*:: -+ --- -The effective top level domain (eTLD), also known as the domain suffix, is the last part of the domain name. For example, the top level domain for example.com is "com". -This value can be determined precisely with a list like the public suffix list (http://publicsuffix.org). Trying to approximate this by simply taking the last label will not work well for effective TLDs such as "co.uk". - -type: keyword - -example: co.uk - --- - -*`client.user.domain`*:: -+ --- -Name of the directory the user is a member of. -For example, an LDAP or Active Directory domain name. - -type: keyword - --- - -*`client.user.email`*:: -+ --- -User email address. - -type: keyword - --- - -*`client.user.full_name`*:: -+ --- -User's full name, if available. - -type: keyword - -example: Albert Einstein - --- - -*`client.user.full_name.text`*:: -+ --- -type: match_only_text - --- - -*`client.user.group.domain`*:: -+ --- -Name of the directory the group is a member of. -For example, an LDAP or Active Directory domain name. - -type: keyword - --- - -*`client.user.group.id`*:: -+ --- -Unique identifier for the group on the system/platform. - -type: keyword - --- - -*`client.user.group.name`*:: -+ --- -Name of the group. - -type: keyword - --- - -*`client.user.hash`*:: -+ --- -Unique user hash to correlate information for a user in anonymized form. -Useful if `user.id` or `user.name` contain confidential information and cannot be used. - -type: keyword - --- - -*`client.user.id`*:: -+ --- -Unique identifier of the user. - -type: keyword - -example: S-1-5-21-202424912787-2692429404-2351956786-1000 - --- - -*`client.user.name`*:: -+ --- -Short name or login of the user. - -type: keyword - -example: a.einstein - --- - -*`client.user.name.text`*:: -+ --- -type: match_only_text - --- - -*`client.user.roles`*:: -+ --- -Array of user roles at the time of the event. - -type: keyword - -example: ["kibana_admin", "reporting_user"] - --- - -[float] -=== cloud - -Fields related to the cloud or infrastructure the events are coming from. - - -*`cloud.account.id`*:: -+ --- -The cloud account or organization id used to identify different entities in a multi-tenant environment. -Examples: AWS account id, Google Cloud ORG Id, or other unique identifier. - -type: keyword - -example: 666777888999 - --- - -*`cloud.account.name`*:: -+ --- -The cloud account name or alias used to identify different entities in a multi-tenant environment. -Examples: AWS account name, Google Cloud ORG display name. - -type: keyword - -example: elastic-dev - --- - -*`cloud.availability_zone`*:: -+ --- -Availability zone in which this host, resource, or service is located. - -type: keyword - -example: us-east-1c - --- - -*`cloud.instance.id`*:: -+ --- -Instance ID of the host machine. - -type: keyword - -example: i-1234567890abcdef0 - --- - -*`cloud.instance.name`*:: -+ --- -Instance name of the host machine. - -type: keyword - --- - -*`cloud.machine.type`*:: -+ --- -Machine type of the host machine. - -type: keyword - -example: t2.medium - --- - -*`cloud.origin.account.id`*:: -+ --- -The cloud account or organization id used to identify different entities in a multi-tenant environment. -Examples: AWS account id, Google Cloud ORG Id, or other unique identifier. - -type: keyword - -example: 666777888999 - --- - -*`cloud.origin.account.name`*:: -+ --- -The cloud account name or alias used to identify different entities in a multi-tenant environment. -Examples: AWS account name, Google Cloud ORG display name. - -type: keyword - -example: elastic-dev - --- - -*`cloud.origin.availability_zone`*:: -+ --- -Availability zone in which this host, resource, or service is located. - -type: keyword - -example: us-east-1c - --- - -*`cloud.origin.instance.id`*:: -+ --- -Instance ID of the host machine. - -type: keyword - -example: i-1234567890abcdef0 - --- - -*`cloud.origin.instance.name`*:: -+ --- -Instance name of the host machine. - -type: keyword - --- - -*`cloud.origin.machine.type`*:: -+ --- -Machine type of the host machine. - -type: keyword - -example: t2.medium - --- - -*`cloud.origin.project.id`*:: -+ --- -The cloud project identifier. -Examples: Google Cloud Project id, Azure Project id. - -type: keyword - -example: my-project - --- - -*`cloud.origin.project.name`*:: -+ --- -The cloud project name. -Examples: Google Cloud Project name, Azure Project name. - -type: keyword - -example: my project - --- - -*`cloud.origin.provider`*:: -+ --- -Name of the cloud provider. Example values are aws, azure, gcp, or digitalocean. - -type: keyword - -example: aws - --- - -*`cloud.origin.region`*:: -+ --- -Region in which this host, resource, or service is located. - -type: keyword - -example: us-east-1 - --- - -*`cloud.origin.service.name`*:: -+ --- -The cloud service name is intended to distinguish services running on different platforms within a provider, eg AWS EC2 vs Lambda, GCP GCE vs App Engine, Azure VM vs App Server. -Examples: app engine, app service, cloud run, fargate, lambda. - -type: keyword - -example: lambda - --- - -*`cloud.project.id`*:: -+ --- -The cloud project identifier. -Examples: Google Cloud Project id, Azure Project id. - -type: keyword - -example: my-project - --- - -*`cloud.project.name`*:: -+ --- -The cloud project name. -Examples: Google Cloud Project name, Azure Project name. - -type: keyword - -example: my project - --- - -*`cloud.provider`*:: -+ --- -Name of the cloud provider. Example values are aws, azure, gcp, or digitalocean. - -type: keyword - -example: aws - --- - -*`cloud.region`*:: -+ --- -Region in which this host, resource, or service is located. - -type: keyword - -example: us-east-1 - --- - -*`cloud.service.name`*:: -+ --- -The cloud service name is intended to distinguish services running on different platforms within a provider, eg AWS EC2 vs Lambda, GCP GCE vs App Engine, Azure VM vs App Server. -Examples: app engine, app service, cloud run, fargate, lambda. - -type: keyword - -example: lambda - --- - -*`cloud.target.account.id`*:: -+ --- -The cloud account or organization id used to identify different entities in a multi-tenant environment. -Examples: AWS account id, Google Cloud ORG Id, or other unique identifier. - -type: keyword - -example: 666777888999 - --- - -*`cloud.target.account.name`*:: -+ --- -The cloud account name or alias used to identify different entities in a multi-tenant environment. -Examples: AWS account name, Google Cloud ORG display name. - -type: keyword - -example: elastic-dev - --- - -*`cloud.target.availability_zone`*:: -+ --- -Availability zone in which this host, resource, or service is located. - -type: keyword - -example: us-east-1c - --- - -*`cloud.target.instance.id`*:: -+ --- -Instance ID of the host machine. - -type: keyword - -example: i-1234567890abcdef0 - --- - -*`cloud.target.instance.name`*:: -+ --- -Instance name of the host machine. - -type: keyword - --- - -*`cloud.target.machine.type`*:: -+ --- -Machine type of the host machine. - -type: keyword - -example: t2.medium - --- - -*`cloud.target.project.id`*:: -+ --- -The cloud project identifier. -Examples: Google Cloud Project id, Azure Project id. - -type: keyword - -example: my-project - --- - -*`cloud.target.project.name`*:: -+ --- -The cloud project name. -Examples: Google Cloud Project name, Azure Project name. - -type: keyword - -example: my project - --- - -*`cloud.target.provider`*:: -+ --- -Name of the cloud provider. Example values are aws, azure, gcp, or digitalocean. - -type: keyword - -example: aws - --- - -*`cloud.target.region`*:: -+ --- -Region in which this host, resource, or service is located. - -type: keyword - -example: us-east-1 - --- - -*`cloud.target.service.name`*:: -+ --- -The cloud service name is intended to distinguish services running on different platforms within a provider, eg AWS EC2 vs Lambda, GCP GCE vs App Engine, Azure VM vs App Server. -Examples: app engine, app service, cloud run, fargate, lambda. - -type: keyword - -example: lambda - --- - -[float] -=== code_signature - -These fields contain information about binary code signatures. - - -*`code_signature.digest_algorithm`*:: -+ --- -The hashing algorithm used to sign the process. -This value can distinguish signatures when a file is signed multiple times by the same signer but with a different digest algorithm. - -type: keyword - -example: sha256 - --- - -*`code_signature.exists`*:: -+ --- -Boolean to capture if a signature is present. - -type: boolean - -example: true - --- - -*`code_signature.signing_id`*:: -+ --- -The identifier used to sign the process. -This is used to identify the application manufactured by a software vendor. The field is relevant to Apple *OS only. - -type: keyword - -example: com.apple.xpc.proxy - --- - -*`code_signature.status`*:: -+ --- -Additional information about the certificate status. -This is useful for logging cryptographic errors with the certificate validity or trust status. Leave unpopulated if the validity or trust of the certificate was unchecked. - -type: keyword - -example: ERROR_UNTRUSTED_ROOT - --- - -*`code_signature.subject_name`*:: -+ --- -Subject name of the code signer - -type: keyword - -example: Microsoft Corporation - --- - -*`code_signature.team_id`*:: -+ --- -The team identifier used to sign the process. -This is used to identify the team or vendor of a software product. The field is relevant to Apple *OS only. - -type: keyword - -example: EQHXZ8M8AV - --- - -*`code_signature.timestamp`*:: -+ --- -Date and time when the code signature was generated and signed. - -type: date - -example: 2021-01-01T12:10:30Z - --- - -*`code_signature.trusted`*:: -+ --- -Stores the trust status of the certificate chain. -Validating the trust of the certificate chain may be complicated, and this field should only be populated by tools that actively check the status. - -type: boolean - -example: true - --- - -*`code_signature.valid`*:: -+ --- -Boolean to capture if the digital signature is verified against the binary content. -Leave unpopulated if a certificate was unchecked. - -type: boolean - -example: true - --- - -[float] -=== container - -Container fields are used for meta information about the specific container that is the source of information. -These fields help correlate data based containers from any runtime. - - -*`container.id`*:: -+ --- -Unique container id. - -type: keyword - --- - -*`container.image.name`*:: -+ --- -Name of the image the container was built on. - -type: keyword - --- - -*`container.image.tag`*:: -+ --- -Container image tags. - -type: keyword - --- - -*`container.labels`*:: -+ --- -Image labels. - -type: object - --- - -*`container.name`*:: -+ --- -Container name. - -type: keyword - --- - -*`container.runtime`*:: -+ --- -Runtime managing this container. - -type: keyword - -example: docker - --- - -[float] -=== data_stream - -The data_stream fields take part in defining the new data stream naming scheme. -In the new data stream naming scheme the value of the data stream fields combine to the name of the actual data stream in the following manner: `{data_stream.type}-{data_stream.dataset}-{data_stream.namespace}`. This means the fields can only contain characters that are valid as part of names of data streams. More details about this can be found in this https://www.elastic.co/blog/an-introduction-to-the-elastic-data-stream-naming-scheme[blog post]. -An Elasticsearch data stream consists of one or more backing indices, and a data stream name forms part of the backing indices names. Due to this convention, data streams must also follow index naming restrictions. For example, data stream names cannot include `\`, `/`, `*`, `?`, `"`, `<`, `>`, `|`, ` ` (space character), `,`, or `#`. Please see the Elasticsearch reference for additional https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-create-index.html#indices-create-api-path-params[restrictions]. - - -*`data_stream.dataset`*:: -+ --- -The field can contain anything that makes sense to signify the source of the data. -Examples include `nginx.access`, `prometheus`, `endpoint` etc. For data streams that otherwise fit, but that do not have dataset set we use the value "generic" for the dataset value. `event.dataset` should have the same value as `data_stream.dataset`. -Beyond the Elasticsearch data stream naming criteria noted above, the `dataset` value has additional restrictions: - * Must not contain `-` - * No longer than 100 characters - -type: constant_keyword - -example: nginx.access - --- - -*`data_stream.namespace`*:: -+ --- -A user defined namespace. Namespaces are useful to allow grouping of data. -Many users already organize their indices this way, and the data stream naming scheme now provides this best practice as a default. Many users will populate this field with `default`. If no value is used, it falls back to `default`. -Beyond the Elasticsearch index naming criteria noted above, `namespace` value has the additional restrictions: - * Must not contain `-` - * No longer than 100 characters - -type: constant_keyword - -example: production - --- - -*`data_stream.type`*:: -+ --- -An overarching type for the data stream. -Currently allowed values are "logs" and "metrics". We expect to also add "traces" and "synthetics" in the near future. - -type: constant_keyword - -example: logs - --- - -[float] -=== destination - -Destination fields capture details about the receiver of a network exchange/packet. These fields are populated from a network event, packet, or other event containing details of a network transaction. -Destination fields are usually populated in conjunction with source fields. The source and destination fields are considered the baseline and should always be filled if an event contains source and destination details from a network transaction. If the event also contains identification of the client and server roles, then the client and server fields should also be populated. - - -*`destination.address`*:: -+ --- -Some event destination addresses are defined ambiguously. The event will sometimes list an IP, a domain or a unix socket. You should always store the raw address in the `.address` field. -Then it should be duplicated to `.ip` or `.domain`, depending on which one it is. - -type: keyword - --- - -*`destination.as.number`*:: -+ --- -Unique number allocated to the autonomous system. The autonomous system number (ASN) uniquely identifies each network on the Internet. - -type: long - -example: 15169 - --- - -*`destination.as.organization.name`*:: -+ --- -Organization name. - -type: keyword - -example: Google LLC - --- - -*`destination.as.organization.name.text`*:: -+ --- -type: match_only_text - --- - -*`destination.bytes`*:: -+ --- -Bytes sent from the destination to the source. - -type: long - -example: 184 - -format: bytes - --- - -*`destination.domain`*:: -+ --- -Destination domain. - -type: keyword - --- - -*`destination.geo.city_name`*:: -+ --- -City name. - -type: keyword - -example: Montreal - --- - -*`destination.geo.continent_code`*:: -+ --- -Two-letter code representing continent's name. - -type: keyword - -example: NA - --- - -*`destination.geo.continent_name`*:: -+ --- -Name of the continent. - -type: keyword - -example: North America - --- - -*`destination.geo.country_iso_code`*:: -+ --- -Country ISO code. - -type: keyword - -example: CA - --- - -*`destination.geo.country_name`*:: -+ --- -Country name. - -type: keyword - -example: Canada - --- - -*`destination.geo.location`*:: -+ --- -Longitude and latitude. - -type: geo_point - -example: { "lon": -73.614830, "lat": 45.505918 } - --- - -*`destination.geo.name`*:: -+ --- -User-defined description of a location, at the level of granularity they care about. -Could be the name of their data centers, the floor number, if this describes a local physical entity, city names. -Not typically used in automated geolocation. - -type: keyword - -example: boston-dc - --- - -*`destination.geo.postal_code`*:: -+ --- -Postal code associated with the location. -Values appropriate for this field may also be known as a postcode or ZIP code and will vary widely from country to country. - -type: keyword - -example: 94040 - --- - -*`destination.geo.region_iso_code`*:: -+ --- -Region ISO code. - -type: keyword - -example: CA-QC - --- - -*`destination.geo.region_name`*:: -+ --- -Region name. - -type: keyword - -example: Quebec - --- - -*`destination.geo.timezone`*:: -+ --- -The time zone of the location, such as IANA time zone name. - -type: keyword - -example: America/Argentina/Buenos_Aires - --- - -*`destination.ip`*:: -+ --- -IP address of the destination (IPv4 or IPv6). - -type: ip - --- - -*`destination.mac`*:: -+ --- -MAC address of the destination. -The notation format from RFC 7042 is suggested: Each octet (that is, 8-bit byte) is represented by two [uppercase] hexadecimal digits giving the value of the octet as an unsigned integer. Successive octets are separated by a hyphen. - -type: keyword - -example: 00-00-5E-00-53-23 - --- - -*`destination.nat.ip`*:: -+ --- -Translated ip of destination based NAT sessions (e.g. internet to private DMZ) -Typically used with load balancers, firewalls, or routers. - -type: ip - --- - -*`destination.nat.port`*:: -+ --- -Port the source session is translated to by NAT Device. -Typically used with load balancers, firewalls, or routers. - -type: long - -format: string - --- - -*`destination.packets`*:: -+ --- -Packets sent from the destination to the source. - -type: long - -example: 12 - --- - -*`destination.port`*:: -+ --- -Port of the destination. - -type: long - -format: string - --- - -*`destination.registered_domain`*:: -+ --- -The highest registered destination domain, stripped of the subdomain. -For example, the registered domain for "foo.example.com" is "example.com". -This value can be determined precisely with a list like the public suffix list (http://publicsuffix.org). Trying to approximate this by simply taking the last two labels will not work well for TLDs such as "co.uk". - -type: keyword - -example: example.com - --- - -*`destination.subdomain`*:: -+ --- -The subdomain portion of a fully qualified domain name includes all of the names except the host name under the registered_domain. In a partially qualified domain, or if the the qualification level of the full name cannot be determined, subdomain contains all of the names below the registered domain. -For example the subdomain portion of "www.east.mydomain.co.uk" is "east". If the domain has multiple levels of subdomain, such as "sub2.sub1.example.com", the subdomain field should contain "sub2.sub1", with no trailing period. - -type: keyword - -example: east - --- - -*`destination.top_level_domain`*:: -+ --- -The effective top level domain (eTLD), also known as the domain suffix, is the last part of the domain name. For example, the top level domain for example.com is "com". -This value can be determined precisely with a list like the public suffix list (http://publicsuffix.org). Trying to approximate this by simply taking the last label will not work well for effective TLDs such as "co.uk". - -type: keyword - -example: co.uk - --- - -*`destination.user.domain`*:: -+ --- -Name of the directory the user is a member of. -For example, an LDAP or Active Directory domain name. - -type: keyword - --- - -*`destination.user.email`*:: -+ --- -User email address. - -type: keyword - --- - -*`destination.user.full_name`*:: -+ --- -User's full name, if available. - -type: keyword - -example: Albert Einstein - --- - -*`destination.user.full_name.text`*:: -+ --- -type: match_only_text - --- - -*`destination.user.group.domain`*:: -+ --- -Name of the directory the group is a member of. -For example, an LDAP or Active Directory domain name. - -type: keyword - --- - -*`destination.user.group.id`*:: -+ --- -Unique identifier for the group on the system/platform. - -type: keyword - --- - -*`destination.user.group.name`*:: -+ --- -Name of the group. - -type: keyword - --- - -*`destination.user.hash`*:: -+ --- -Unique user hash to correlate information for a user in anonymized form. -Useful if `user.id` or `user.name` contain confidential information and cannot be used. - -type: keyword - --- - -*`destination.user.id`*:: -+ --- -Unique identifier of the user. - -type: keyword - -example: S-1-5-21-202424912787-2692429404-2351956786-1000 - --- - -*`destination.user.name`*:: -+ --- -Short name or login of the user. - -type: keyword - -example: a.einstein - --- - -*`destination.user.name.text`*:: -+ --- -type: match_only_text - --- - -*`destination.user.roles`*:: -+ --- -Array of user roles at the time of the event. - -type: keyword - -example: ["kibana_admin", "reporting_user"] - --- - -[float] -=== dll - -These fields contain information about code libraries dynamically loaded into processes. - -Many operating systems refer to "shared code libraries" with different names, but this field set refers to all of the following: -* Dynamic-link library (`.dll`) commonly used on Windows -* Shared Object (`.so`) commonly used on Unix-like operating systems -* Dynamic library (`.dylib`) commonly used on macOS - - -*`dll.code_signature.digest_algorithm`*:: -+ --- -The hashing algorithm used to sign the process. -This value can distinguish signatures when a file is signed multiple times by the same signer but with a different digest algorithm. - -type: keyword - -example: sha256 - --- - -*`dll.code_signature.exists`*:: -+ --- -Boolean to capture if a signature is present. - -type: boolean - -example: true - --- - -*`dll.code_signature.signing_id`*:: -+ --- -The identifier used to sign the process. -This is used to identify the application manufactured by a software vendor. The field is relevant to Apple *OS only. - -type: keyword - -example: com.apple.xpc.proxy - --- - -*`dll.code_signature.status`*:: -+ --- -Additional information about the certificate status. -This is useful for logging cryptographic errors with the certificate validity or trust status. Leave unpopulated if the validity or trust of the certificate was unchecked. - -type: keyword - -example: ERROR_UNTRUSTED_ROOT - --- - -*`dll.code_signature.subject_name`*:: -+ --- -Subject name of the code signer - -type: keyword - -example: Microsoft Corporation - --- - -*`dll.code_signature.team_id`*:: -+ --- -The team identifier used to sign the process. -This is used to identify the team or vendor of a software product. The field is relevant to Apple *OS only. - -type: keyword - -example: EQHXZ8M8AV - --- - -*`dll.code_signature.timestamp`*:: -+ --- -Date and time when the code signature was generated and signed. - -type: date - -example: 2021-01-01T12:10:30Z - --- - -*`dll.code_signature.trusted`*:: -+ --- -Stores the trust status of the certificate chain. -Validating the trust of the certificate chain may be complicated, and this field should only be populated by tools that actively check the status. - -type: boolean - -example: true - --- - -*`dll.code_signature.valid`*:: -+ --- -Boolean to capture if the digital signature is verified against the binary content. -Leave unpopulated if a certificate was unchecked. - -type: boolean - -example: true - --- - -*`dll.hash.md5`*:: -+ --- -MD5 hash. - -type: keyword - --- - -*`dll.hash.sha1`*:: -+ --- -SHA1 hash. - -type: keyword - --- - -*`dll.hash.sha256`*:: -+ --- -SHA256 hash. - -type: keyword - --- - -*`dll.hash.sha512`*:: -+ --- -SHA512 hash. - -type: keyword - --- - -*`dll.hash.ssdeep`*:: -+ --- -SSDEEP hash. - -type: keyword - --- - -*`dll.name`*:: -+ --- -Name of the library. -This generally maps to the name of the file on disk. - -type: keyword - -example: kernel32.dll - --- - -*`dll.path`*:: -+ --- -Full file path of the library. - -type: keyword - -example: C:\Windows\System32\kernel32.dll - --- - -*`dll.pe.architecture`*:: -+ --- -CPU architecture target for the file. - -type: keyword - -example: x64 - --- - -*`dll.pe.company`*:: -+ --- -Internal company name of the file, provided at compile-time. - -type: keyword - -example: Microsoft Corporation - --- - -*`dll.pe.description`*:: -+ --- -Internal description of the file, provided at compile-time. - -type: keyword - -example: Paint - --- - -*`dll.pe.file_version`*:: -+ --- -Internal version of the file, provided at compile-time. - -type: keyword - -example: 6.3.9600.17415 - --- - -*`dll.pe.imphash`*:: -+ --- -A hash of the imports in a PE file. An imphash -- or import hash -- can be used to fingerprint binaries even after recompilation or other code-level transformations have occurred, which would change more traditional hash values. -Learn more at https://www.fireeye.com/blog/threat-research/2014/01/tracking-malware-import-hashing.html. - -type: keyword - -example: 0c6803c4e922103c4dca5963aad36ddf - --- - -*`dll.pe.original_file_name`*:: -+ --- -Internal name of the file, provided at compile-time. - -type: keyword - -example: MSPAINT.EXE - --- - -*`dll.pe.product`*:: -+ --- -Internal product name of the file, provided at compile-time. - -type: keyword - -example: Microsoft® Windows® Operating System - --- - -[float] -=== dns - -Fields describing DNS queries and answers. -DNS events should either represent a single DNS query prior to getting answers (`dns.type:query`) or they should represent a full exchange and contain the query details as well as all of the answers that were provided for this query (`dns.type:answer`). - - -*`dns.answers`*:: -+ --- -An array containing an object for each answer section returned by the server. -The main keys that should be present in these objects are defined by ECS. Records that have more information may contain more keys than what ECS defines. -Not all DNS data sources give all details about DNS answers. At minimum, answer objects must contain the `data` key. If more information is available, map as much of it to ECS as possible, and add any additional fields to the answer objects as custom fields. - -type: object - --- - -*`dns.answers.class`*:: -+ --- -The class of DNS data contained in this resource record. - -type: keyword - -example: IN - --- - -*`dns.answers.data`*:: -+ --- -The data describing the resource. -The meaning of this data depends on the type and class of the resource record. - -type: keyword - -example: 10.10.10.10 - --- - -*`dns.answers.name`*:: -+ --- -The domain name to which this resource record pertains. -If a chain of CNAME is being resolved, each answer's `name` should be the one that corresponds with the answer's `data`. It should not simply be the original `question.name` repeated. - -type: keyword - -example: www.example.com - --- - -*`dns.answers.ttl`*:: -+ --- -The time interval in seconds that this resource record may be cached before it should be discarded. Zero values mean that the data should not be cached. - -type: long - -example: 180 - --- - -*`dns.answers.type`*:: -+ --- -The type of data contained in this resource record. - -type: keyword - -example: CNAME - --- - -*`dns.header_flags`*:: -+ --- -Array of 2 letter DNS header flags. -Expected values are: AA, TC, RD, RA, AD, CD, DO. - -type: keyword - -example: ["RD", "RA"] - --- - -*`dns.id`*:: -+ --- -The DNS packet identifier assigned by the program that generated the query. The identifier is copied to the response. - -type: keyword - -example: 62111 - --- - -*`dns.op_code`*:: -+ --- -The DNS operation code that specifies the kind of query in the message. This value is set by the originator of a query and copied into the response. - -type: keyword - -example: QUERY - --- - -*`dns.question.class`*:: -+ --- -The class of records being queried. - -type: keyword - -example: IN - --- - -*`dns.question.name`*:: -+ --- -The name being queried. -If the name field contains non-printable characters (below 32 or above 126), those characters should be represented as escaped base 10 integers (\DDD). Back slashes and quotes should be escaped. Tabs, carriage returns, and line feeds should be converted to \t, \r, and \n respectively. - -type: keyword - -example: www.example.com - --- - -*`dns.question.registered_domain`*:: -+ --- -The highest registered domain, stripped of the subdomain. -For example, the registered domain for "foo.example.com" is "example.com". -This value can be determined precisely with a list like the public suffix list (http://publicsuffix.org). Trying to approximate this by simply taking the last two labels will not work well for TLDs such as "co.uk". - -type: keyword - -example: example.com - --- - -*`dns.question.subdomain`*:: -+ --- -The subdomain is all of the labels under the registered_domain. -If the domain has multiple levels of subdomain, such as "sub2.sub1.example.com", the subdomain field should contain "sub2.sub1", with no trailing period. - -type: keyword - -example: www - --- - -*`dns.question.top_level_domain`*:: -+ --- -The effective top level domain (eTLD), also known as the domain suffix, is the last part of the domain name. For example, the top level domain for example.com is "com". -This value can be determined precisely with a list like the public suffix list (http://publicsuffix.org). Trying to approximate this by simply taking the last label will not work well for effective TLDs such as "co.uk". - -type: keyword - -example: co.uk - --- - -*`dns.question.type`*:: -+ --- -The type of record being queried. - -type: keyword - -example: AAAA - --- - -*`dns.resolved_ip`*:: -+ --- -Array containing all IPs seen in `answers.data`. -The `answers` array can be difficult to use, because of the variety of data formats it can contain. Extracting all IP addresses seen in there to `dns.resolved_ip` makes it possible to index them as IP addresses, and makes them easier to visualize and query for. - -type: ip - -example: ["10.10.10.10", "10.10.10.11"] - --- - -*`dns.response_code`*:: -+ --- -The DNS response code. - -type: keyword - -example: NOERROR - --- - -*`dns.type`*:: -+ --- -The type of DNS event captured, query or answer. -If your source of DNS events only gives you DNS queries, you should only create dns events of type `dns.type:query`. -If your source of DNS events gives you answers as well, you should create one event per query (optionally as soon as the query is seen). And a second event containing all query details as well as an array of answers. - -type: keyword - -example: answer - --- - -[float] -=== ecs - -Meta-information specific to ECS. - - -*`ecs.version`*:: -+ --- -ECS version this event conforms to. `ecs.version` is a required field and must exist in all events. -When querying across multiple indices -- which may conform to slightly different ECS versions -- this field lets integrations adjust to the schema version of the events. - -type: keyword - -example: 1.0.0 - -required: True - --- - -[float] -=== elf - -These fields contain Linux Executable Linkable Format (ELF) metadata. - - -*`elf.architecture`*:: -+ --- -Machine architecture of the ELF file. - -type: keyword - -example: x86-64 - --- - -*`elf.byte_order`*:: -+ --- -Byte sequence of ELF file. - -type: keyword - -example: Little Endian - --- - -*`elf.cpu_type`*:: -+ --- -CPU type of the ELF file. - -type: keyword - -example: Intel - --- - -*`elf.creation_date`*:: -+ --- -Extracted when possible from the file's metadata. Indicates when it was built or compiled. It can also be faked by malware creators. - -type: date - --- - -*`elf.exports`*:: -+ --- -List of exported element names and types. - -type: flattened - --- - -*`elf.header.abi_version`*:: -+ --- -Version of the ELF Application Binary Interface (ABI). - -type: keyword - --- - -*`elf.header.class`*:: -+ --- -Header class of the ELF file. - -type: keyword - --- - -*`elf.header.data`*:: -+ --- -Data table of the ELF header. - -type: keyword - --- - -*`elf.header.entrypoint`*:: -+ --- -Header entrypoint of the ELF file. - -type: long - -format: string - --- - -*`elf.header.object_version`*:: -+ --- -"0x1" for original ELF files. - -type: keyword - --- - -*`elf.header.os_abi`*:: -+ --- -Application Binary Interface (ABI) of the Linux OS. - -type: keyword - --- - -*`elf.header.type`*:: -+ --- -Header type of the ELF file. - -type: keyword - --- - -*`elf.header.version`*:: -+ --- -Version of the ELF header. - -type: keyword - --- - -*`elf.imports`*:: -+ --- -List of imported element names and types. - -type: flattened - --- - -*`elf.sections`*:: -+ --- -An array containing an object for each section of the ELF file. -The keys that should be present in these objects are defined by sub-fields underneath `elf.sections.*`. - -type: nested - --- - -*`elf.sections.chi2`*:: -+ --- -Chi-square probability distribution of the section. - -type: long - -format: number - --- - -*`elf.sections.entropy`*:: -+ --- -Shannon entropy calculation from the section. - -type: long - -format: number - --- - -*`elf.sections.flags`*:: -+ --- -ELF Section List flags. - -type: keyword - --- - -*`elf.sections.name`*:: -+ --- -ELF Section List name. - -type: keyword - --- - -*`elf.sections.physical_offset`*:: -+ --- -ELF Section List offset. - -type: keyword - --- - -*`elf.sections.physical_size`*:: -+ --- -ELF Section List physical size. - -type: long - -format: bytes - --- - -*`elf.sections.type`*:: -+ --- -ELF Section List type. - -type: keyword - --- - -*`elf.sections.virtual_address`*:: -+ --- -ELF Section List virtual address. - -type: long - -format: string - --- - -*`elf.sections.virtual_size`*:: -+ --- -ELF Section List virtual size. - -type: long - -format: string - --- - -*`elf.segments`*:: -+ --- -An array containing an object for each segment of the ELF file. -The keys that should be present in these objects are defined by sub-fields underneath `elf.segments.*`. - -type: nested - --- - -*`elf.segments.sections`*:: -+ --- -ELF object segment sections. - -type: keyword - --- - -*`elf.segments.type`*:: -+ --- -ELF object segment type. - -type: keyword - --- - -*`elf.shared_libraries`*:: -+ --- -List of shared libraries used by this ELF object. - -type: keyword - --- - -*`elf.telfhash`*:: -+ --- -telfhash symbol hash for ELF file. - -type: keyword - --- - -[float] -=== error - -These fields can represent errors of any kind. -Use them for errors that happen while fetching events or in cases where the event itself contains an error. - - -*`error.code`*:: -+ --- -Error code describing the error. - -type: keyword - --- - -*`error.id`*:: -+ --- -Unique identifier for the error. - -type: keyword - --- - -*`error.message`*:: -+ --- -Error message. - -type: match_only_text - --- - -*`error.stack_trace`*:: -+ --- -The stack trace of this error in plain text. - -type: wildcard - --- - -*`error.stack_trace.text`*:: -+ --- -type: match_only_text - --- - -*`error.type`*:: -+ --- -The type of the error, for example the class name of the exception. - -type: keyword - -example: java.lang.NullPointerException - --- - -[float] -=== event - -The event fields are used for context information about the log or metric event itself. -A log is defined as an event containing details of something that happened. Log events must include the time at which the thing happened. Examples of log events include a process starting on a host, a network packet being sent from a source to a destination, or a network connection between a client and a server being initiated or closed. A metric is defined as an event containing one or more numerical measurements and the time at which the measurement was taken. Examples of metric events include memory pressure measured on a host and device temperature. See the `event.kind` definition in this section for additional details about metric and state events. - - -*`event.action`*:: -+ --- -The action captured by the event. -This describes the information in the event. It is more specific than `event.category`. Examples are `group-add`, `process-started`, `file-created`. The value is normally defined by the implementer. - -type: keyword - -example: user-password-change - --- - -*`event.agent_id_status`*:: -+ --- -Agents are normally responsible for populating the `agent.id` field value. If the system receiving events is capable of validating the value based on authentication information for the client then this field can be used to reflect the outcome of that validation. -For example if the agent's connection is authenticated with mTLS and the client cert contains the ID of the agent to which the cert was issued then the `agent.id` value in events can be checked against the certificate. If the values match then `event.agent_id_status: verified` is added to the event, otherwise one of the other allowed values should be used. -If no validation is performed then the field should be omitted. -The allowed values are: -`verified` - The `agent.id` field value matches expected value obtained from auth metadata. -`mismatch` - The `agent.id` field value does not match the expected value obtained from auth metadata. -`missing` - There was no `agent.id` field in the event to validate. -`auth_metadata_missing` - There was no auth metadata or it was missing information about the agent ID. - -type: keyword - -example: verified - --- - -*`event.category`*:: -+ --- -This is one of four ECS Categorization Fields, and indicates the second level in the ECS category hierarchy. -`event.category` represents the "big buckets" of ECS categories. For example, filtering on `event.category:process` yields all events relating to process activity. This field is closely related to `event.type`, which is used as a subcategory. -This field is an array. This will allow proper categorization of some events that fall in multiple categories. - -type: keyword - -example: authentication - --- - -*`event.code`*:: -+ --- -Identification code for this event, if one exists. -Some event sources use event codes to identify messages unambiguously, regardless of message language or wording adjustments over time. An example of this is the Windows Event ID. - -type: keyword - -example: 4648 - --- - -*`event.created`*:: -+ --- -event.created contains the date/time when the event was first read by an agent, or by your pipeline. -This field is distinct from @timestamp in that @timestamp typically contain the time extracted from the original event. -In most situations, these two timestamps will be slightly different. The difference can be used to calculate the delay between your source generating an event, and the time when your agent first processed it. This can be used to monitor your agent's or pipeline's ability to keep up with your event source. -In case the two timestamps are identical, @timestamp should be used. - -type: date - -example: 2016-05-23T08:05:34.857Z - --- - -*`event.dataset`*:: -+ --- -Name of the dataset. -If an event source publishes more than one type of log or events (e.g. access log, error log), the dataset is used to specify which one the event comes from. -It's recommended but not required to start the dataset name with the module name, followed by a dot, then the dataset name. - -type: keyword - -example: apache.access - --- - -*`event.duration`*:: -+ --- -Duration of the event in nanoseconds. -If event.start and event.end are known this value should be the difference between the end and start time. - -type: long - -format: duration - --- - -*`event.end`*:: -+ --- -event.end contains the date when the event ended or when the activity was last observed. - -type: date - --- - -*`event.hash`*:: -+ --- -Hash (perhaps logstash fingerprint) of raw field to be able to demonstrate log integrity. - -type: keyword - -example: 123456789012345678901234567890ABCD - --- - -*`event.id`*:: -+ --- -Unique ID to describe the event. - -type: keyword - -example: 8a4f500d - --- - -*`event.ingested`*:: -+ --- -Timestamp when an event arrived in the central data store. -This is different from `@timestamp`, which is when the event originally occurred. It's also different from `event.created`, which is meant to capture the first time an agent saw the event. -In normal conditions, assuming no tampering, the timestamps should chronologically look like this: `@timestamp` < `event.created` < `event.ingested`. - -type: date - -example: 2016-05-23T08:05:35.101Z - --- - -*`event.kind`*:: -+ --- -This is one of four ECS Categorization Fields, and indicates the highest level in the ECS category hierarchy. -`event.kind` gives high-level information about what type of information the event contains, without being specific to the contents of the event. For example, values of this field distinguish alert events from metric events. -The value of this field can be used to inform how these kinds of events should be handled. They may warrant different retention, different access control, it may also help understand whether the data coming in at a regular interval or not. - -type: keyword - -example: alert - --- - -*`event.module`*:: -+ --- -Name of the module this data is coming from. -If your monitoring agent supports the concept of modules or plugins to process events of a given source (e.g. Apache logs), `event.module` should contain the name of this module. - -type: keyword - -example: apache - --- - -*`event.original`*:: -+ --- -Raw text message of entire event. Used to demonstrate log integrity or where the full log message (before splitting it up in multiple parts) may be required, e.g. for reindex. -This field is not indexed and doc_values are disabled. It cannot be searched, but it can be retrieved from `_source`. If users wish to override this and index this field, please see `Field data types` in the `Elasticsearch Reference`. - -type: keyword - -example: Sep 19 08:26:10 host CEF:0|Security| threatmanager|1.0|100| worm successfully stopped|10|src=10.0.0.1 dst=2.1.2.2spt=1232 - -Field is not indexed. - --- - -*`event.outcome`*:: -+ --- -This is one of four ECS Categorization Fields, and indicates the lowest level in the ECS category hierarchy. -`event.outcome` simply denotes whether the event represents a success or a failure from the perspective of the entity that produced the event. -Note that when a single transaction is described in multiple events, each event may populate different values of `event.outcome`, according to their perspective. -Also note that in the case of a compound event (a single event that contains multiple logical events), this field should be populated with the value that best captures the overall success or failure from the perspective of the event producer. -Further note that not all events will have an associated outcome. For example, this field is generally not populated for metric events, events with `event.type:info`, or any events for which an outcome does not make logical sense. - -type: keyword - -example: success - --- - -*`event.provider`*:: -+ --- -Source of the event. -Event transports such as Syslog or the Windows Event Log typically mention the source of an event. It can be the name of the software that generated the event (e.g. Sysmon, httpd), or of a subsystem of the operating system (kernel, Microsoft-Windows-Security-Auditing). - -type: keyword - -example: kernel - --- - -*`event.reason`*:: -+ --- -Reason why this event happened, according to the source. -This describes the why of a particular action or outcome captured in the event. Where `event.action` captures the action from the event, `event.reason` describes why that action was taken. For example, a web proxy with an `event.action` which denied the request may also populate `event.reason` with the reason why (e.g. `blocked site`). - -type: keyword - -example: Terminated an unexpected process - --- - -*`event.reference`*:: -+ --- -Reference URL linking to additional information about this event. -This URL links to a static definition of this event. Alert events, indicated by `event.kind:alert`, are a common use case for this field. - -type: keyword - -example: https://system.example.com/event/#0001234 - --- - -*`event.risk_score`*:: -+ --- -Risk score or priority of the event (e.g. security solutions). Use your system's original value here. - -type: float - --- - -*`event.risk_score_norm`*:: -+ --- -Normalized risk score or priority of the event, on a scale of 0 to 100. -This is mainly useful if you use more than one system that assigns risk scores, and you want to see a normalized value across all systems. - -type: float - --- - -*`event.sequence`*:: -+ --- -Sequence number of the event. -The sequence number is a value published by some event sources, to make the exact ordering of events unambiguous, regardless of the timestamp precision. - -type: long - -format: string - --- - -*`event.severity`*:: -+ --- -The numeric severity of the event according to your event source. -What the different severity values mean can be different between sources and use cases. It's up to the implementer to make sure severities are consistent across events from the same source. -The Syslog severity belongs in `log.syslog.severity.code`. `event.severity` is meant to represent the severity according to the event source (e.g. firewall, IDS). If the event source does not publish its own severity, you may optionally copy the `log.syslog.severity.code` to `event.severity`. - -type: long - -example: 7 - -format: string - --- - -*`event.start`*:: -+ --- -event.start contains the date when the event started or when the activity was first observed. - -type: date - --- - -*`event.timezone`*:: -+ --- -This field should be populated when the event's timestamp does not include timezone information already (e.g. default Syslog timestamps). It's optional otherwise. -Acceptable timezone formats are: a canonical ID (e.g. "Europe/Amsterdam"), abbreviated (e.g. "EST") or an HH:mm differential (e.g. "-05:00"). - -type: keyword - --- - -*`event.type`*:: -+ --- -This is one of four ECS Categorization Fields, and indicates the third level in the ECS category hierarchy. -`event.type` represents a categorization "sub-bucket" that, when used along with the `event.category` field values, enables filtering events down to a level appropriate for single visualization. -This field is an array. This will allow proper categorization of some events that fall in multiple event types. - -type: keyword - --- - -*`event.url`*:: -+ --- -URL linking to an external system to continue investigation of this event. -This URL links to another system where in-depth investigation of the specific occurrence of this event can take place. Alert events, indicated by `event.kind:alert`, are a common use case for this field. - -type: keyword - -example: https://mysystem.example.com/alert/5271dedb-f5b0-4218-87f0-4ac4870a38fe - --- - -[float] -=== faas - -The user fields describe information about the function as a service that is relevant to the event. - - -*`faas.coldstart`*:: -+ --- -Boolean value indicating a cold start of a function. - -type: boolean - --- - -*`faas.execution`*:: -+ --- -The execution ID of the current function execution. - -type: keyword - -example: af9d5aa4-a685-4c5f-a22b-444f80b3cc28 - --- - -*`faas.trigger`*:: -+ --- -Details about the function trigger. - -type: nested - --- - -*`faas.trigger.request_id`*:: -+ --- -The ID of the trigger request , message, event, etc. - -type: keyword - -example: 123456789 - --- - -*`faas.trigger.type`*:: -+ --- -The trigger for the function execution. -Expected values are: - * http - * pubsub - * datasource - * timer - * other - -type: keyword - -example: http - --- - -[float] -=== file - -A file is defined as a set of information that has been created on, or has existed on a filesystem. -File objects can be associated with host events, network events, and/or file events (e.g., those produced by File Integrity Monitoring [FIM] products or services). File fields provide details about the affected file associated with the event or metric. - - -*`file.accessed`*:: -+ --- -Last time the file was accessed. -Note that not all filesystems keep track of access time. - -type: date - --- - -*`file.attributes`*:: -+ --- -Array of file attributes. -Attributes names will vary by platform. Here's a non-exhaustive list of values that are expected in this field: archive, compressed, directory, encrypted, execute, hidden, read, readonly, system, write. - -type: keyword - -example: ["readonly", "system"] - --- - -*`file.code_signature.digest_algorithm`*:: -+ --- -The hashing algorithm used to sign the process. -This value can distinguish signatures when a file is signed multiple times by the same signer but with a different digest algorithm. - -type: keyword - -example: sha256 - --- - -*`file.code_signature.exists`*:: -+ --- -Boolean to capture if a signature is present. - -type: boolean - -example: true - --- - -*`file.code_signature.signing_id`*:: -+ --- -The identifier used to sign the process. -This is used to identify the application manufactured by a software vendor. The field is relevant to Apple *OS only. - -type: keyword - -example: com.apple.xpc.proxy - --- - -*`file.code_signature.status`*:: -+ --- -Additional information about the certificate status. -This is useful for logging cryptographic errors with the certificate validity or trust status. Leave unpopulated if the validity or trust of the certificate was unchecked. - -type: keyword - -example: ERROR_UNTRUSTED_ROOT - --- - -*`file.code_signature.subject_name`*:: -+ --- -Subject name of the code signer - -type: keyword - -example: Microsoft Corporation - --- - -*`file.code_signature.team_id`*:: -+ --- -The team identifier used to sign the process. -This is used to identify the team or vendor of a software product. The field is relevant to Apple *OS only. - -type: keyword - -example: EQHXZ8M8AV - --- - -*`file.code_signature.timestamp`*:: -+ --- -Date and time when the code signature was generated and signed. - -type: date - -example: 2021-01-01T12:10:30Z - --- - -*`file.code_signature.trusted`*:: -+ --- -Stores the trust status of the certificate chain. -Validating the trust of the certificate chain may be complicated, and this field should only be populated by tools that actively check the status. - -type: boolean - -example: true - --- - -*`file.code_signature.valid`*:: -+ --- -Boolean to capture if the digital signature is verified against the binary content. -Leave unpopulated if a certificate was unchecked. - -type: boolean - -example: true - --- - -*`file.created`*:: -+ --- -File creation time. -Note that not all filesystems store the creation time. - -type: date - --- - -*`file.ctime`*:: -+ --- -Last time the file attributes or metadata changed. -Note that changes to the file content will update `mtime`. This implies `ctime` will be adjusted at the same time, since `mtime` is an attribute of the file. - -type: date - --- - -*`file.device`*:: -+ --- -Device that is the source of the file. - -type: keyword - -example: sda - --- - -*`file.directory`*:: -+ --- -Directory where the file is located. It should include the drive letter, when appropriate. - -type: keyword - -example: /home/alice - --- - -*`file.drive_letter`*:: -+ --- -Drive letter where the file is located. This field is only relevant on Windows. -The value should be uppercase, and not include the colon. - -type: keyword - -example: C - --- - -*`file.elf.architecture`*:: -+ --- -Machine architecture of the ELF file. - -type: keyword - -example: x86-64 - --- - -*`file.elf.byte_order`*:: -+ --- -Byte sequence of ELF file. - -type: keyword - -example: Little Endian - --- - -*`file.elf.cpu_type`*:: -+ --- -CPU type of the ELF file. - -type: keyword - -example: Intel - --- - -*`file.elf.creation_date`*:: -+ --- -Extracted when possible from the file's metadata. Indicates when it was built or compiled. It can also be faked by malware creators. - -type: date - --- - -*`file.elf.exports`*:: -+ --- -List of exported element names and types. - -type: flattened - --- - -*`file.elf.header.abi_version`*:: -+ --- -Version of the ELF Application Binary Interface (ABI). - -type: keyword - --- - -*`file.elf.header.class`*:: -+ --- -Header class of the ELF file. - -type: keyword - --- - -*`file.elf.header.data`*:: -+ --- -Data table of the ELF header. - -type: keyword - --- - -*`file.elf.header.entrypoint`*:: -+ --- -Header entrypoint of the ELF file. - -type: long - -format: string - --- - -*`file.elf.header.object_version`*:: -+ --- -"0x1" for original ELF files. - -type: keyword - --- - -*`file.elf.header.os_abi`*:: -+ --- -Application Binary Interface (ABI) of the Linux OS. - -type: keyword - --- - -*`file.elf.header.type`*:: -+ --- -Header type of the ELF file. - -type: keyword - --- - -*`file.elf.header.version`*:: -+ --- -Version of the ELF header. - -type: keyword - --- - -*`file.elf.imports`*:: -+ --- -List of imported element names and types. - -type: flattened - --- - -*`file.elf.sections`*:: -+ --- -An array containing an object for each section of the ELF file. -The keys that should be present in these objects are defined by sub-fields underneath `elf.sections.*`. - -type: nested - --- - -*`file.elf.sections.chi2`*:: -+ --- -Chi-square probability distribution of the section. - -type: long - -format: number - --- - -*`file.elf.sections.entropy`*:: -+ --- -Shannon entropy calculation from the section. - -type: long - -format: number - --- - -*`file.elf.sections.flags`*:: -+ --- -ELF Section List flags. - -type: keyword - --- - -*`file.elf.sections.name`*:: -+ --- -ELF Section List name. - -type: keyword - --- - -*`file.elf.sections.physical_offset`*:: -+ --- -ELF Section List offset. - -type: keyword - --- - -*`file.elf.sections.physical_size`*:: -+ --- -ELF Section List physical size. - -type: long - -format: bytes - --- - -*`file.elf.sections.type`*:: -+ --- -ELF Section List type. - -type: keyword - --- - -*`file.elf.sections.virtual_address`*:: -+ --- -ELF Section List virtual address. - -type: long - -format: string - --- - -*`file.elf.sections.virtual_size`*:: -+ --- -ELF Section List virtual size. - -type: long - -format: string - --- - -*`file.elf.segments`*:: -+ --- -An array containing an object for each segment of the ELF file. -The keys that should be present in these objects are defined by sub-fields underneath `elf.segments.*`. - -type: nested - --- - -*`file.elf.segments.sections`*:: -+ --- -ELF object segment sections. - -type: keyword - --- - -*`file.elf.segments.type`*:: -+ --- -ELF object segment type. - -type: keyword - --- - -*`file.elf.shared_libraries`*:: -+ --- -List of shared libraries used by this ELF object. - -type: keyword - --- - -*`file.elf.telfhash`*:: -+ --- -telfhash symbol hash for ELF file. - -type: keyword - --- - -*`file.extension`*:: -+ --- -File extension, excluding the leading dot. -Note that when the file name has multiple extensions (example.tar.gz), only the last one should be captured ("gz", not "tar.gz"). - -type: keyword - -example: png - --- - -*`file.fork_name`*:: -+ --- -A fork is additional data associated with a filesystem object. -On Linux, a resource fork is used to store additional data with a filesystem object. A file always has at least one fork for the data portion, and additional forks may exist. -On NTFS, this is analogous to an Alternate Data Stream (ADS), and the default data stream for a file is just called $DATA. Zone.Identifier is commonly used by Windows to track contents downloaded from the Internet. An ADS is typically of the form: `C:\path\to\filename.extension:some_fork_name`, and `some_fork_name` is the value that should populate `fork_name`. `filename.extension` should populate `file.name`, and `extension` should populate `file.extension`. The full path, `file.path`, will include the fork name. - -type: keyword - -example: Zone.Identifer - --- - -*`file.gid`*:: -+ --- -Primary group ID (GID) of the file. - -type: keyword - -example: 1001 - --- - -*`file.group`*:: -+ --- -Primary group name of the file. - -type: keyword - -example: alice - --- - -*`file.hash.md5`*:: -+ --- -MD5 hash. - -type: keyword - --- - -*`file.hash.sha1`*:: -+ --- -SHA1 hash. - -type: keyword - --- - -*`file.hash.sha256`*:: -+ --- -SHA256 hash. - -type: keyword - --- - -*`file.hash.sha512`*:: -+ --- -SHA512 hash. - -type: keyword - --- - -*`file.hash.ssdeep`*:: -+ --- -SSDEEP hash. - -type: keyword - --- - -*`file.inode`*:: -+ --- -Inode representing the file in the filesystem. - -type: keyword - -example: 256383 - --- - -*`file.mime_type`*:: -+ --- -MIME type should identify the format of the file or stream of bytes using https://www.iana.org/assignments/media-types/media-types.xhtml[IANA official types], where possible. When more than one type is applicable, the most specific type should be used. - -type: keyword - --- - -*`file.mode`*:: -+ --- -Mode of the file in octal representation. - -type: keyword - -example: 0640 - --- - -*`file.mtime`*:: -+ --- -Last time the file content was modified. - -type: date - --- - -*`file.name`*:: -+ --- -Name of the file including the extension, without the directory. - -type: keyword - -example: example.png - --- - -*`file.owner`*:: -+ --- -File owner's username. - -type: keyword - -example: alice - --- - -*`file.path`*:: -+ --- -Full path to the file, including the file name. It should include the drive letter, when appropriate. - -type: keyword - -example: /home/alice/example.png - --- - -*`file.path.text`*:: -+ --- -type: match_only_text - --- - -*`file.pe.architecture`*:: -+ --- -CPU architecture target for the file. - -type: keyword - -example: x64 - --- - -*`file.pe.company`*:: -+ --- -Internal company name of the file, provided at compile-time. - -type: keyword - -example: Microsoft Corporation - --- - -*`file.pe.description`*:: -+ --- -Internal description of the file, provided at compile-time. - -type: keyword - -example: Paint - --- - -*`file.pe.file_version`*:: -+ --- -Internal version of the file, provided at compile-time. - -type: keyword - -example: 6.3.9600.17415 - --- - -*`file.pe.imphash`*:: -+ --- -A hash of the imports in a PE file. An imphash -- or import hash -- can be used to fingerprint binaries even after recompilation or other code-level transformations have occurred, which would change more traditional hash values. -Learn more at https://www.fireeye.com/blog/threat-research/2014/01/tracking-malware-import-hashing.html. - -type: keyword - -example: 0c6803c4e922103c4dca5963aad36ddf - --- - -*`file.pe.original_file_name`*:: -+ --- -Internal name of the file, provided at compile-time. - -type: keyword - -example: MSPAINT.EXE - --- - -*`file.pe.product`*:: -+ --- -Internal product name of the file, provided at compile-time. - -type: keyword - -example: Microsoft® Windows® Operating System - --- - -*`file.size`*:: -+ --- -File size in bytes. -Only relevant when `file.type` is "file". - -type: long - -example: 16384 - --- - -*`file.target_path`*:: -+ --- -Target path for symlinks. - -type: keyword - --- - -*`file.target_path.text`*:: -+ --- -type: match_only_text - --- - -*`file.type`*:: -+ --- -File type (file, dir, or symlink). - -type: keyword - -example: file - --- - -*`file.uid`*:: -+ --- -The user ID (UID) or security identifier (SID) of the file owner. - -type: keyword - -example: 1001 - --- - -*`file.x509.alternative_names`*:: -+ --- -List of subject alternative names (SAN). Name types vary by certificate authority and certificate type but commonly contain IP addresses, DNS names (and wildcards), and email addresses. - -type: keyword - -example: *.elastic.co - --- - -*`file.x509.issuer.common_name`*:: -+ --- -List of common name (CN) of issuing certificate authority. - -type: keyword - -example: Example SHA2 High Assurance Server CA - --- - -*`file.x509.issuer.country`*:: -+ --- -List of country (C) codes - -type: keyword - -example: US - --- - -*`file.x509.issuer.distinguished_name`*:: -+ --- -Distinguished name (DN) of issuing certificate authority. - -type: keyword - -example: C=US, O=Example Inc, OU=www.example.com, CN=Example SHA2 High Assurance Server CA - --- - -*`file.x509.issuer.locality`*:: -+ --- -List of locality names (L) - -type: keyword - -example: Mountain View - --- - -*`file.x509.issuer.organization`*:: -+ --- -List of organizations (O) of issuing certificate authority. - -type: keyword - -example: Example Inc - --- - -*`file.x509.issuer.organizational_unit`*:: -+ --- -List of organizational units (OU) of issuing certificate authority. - -type: keyword - -example: www.example.com - --- - -*`file.x509.issuer.state_or_province`*:: -+ --- -List of state or province names (ST, S, or P) - -type: keyword - -example: California - --- - -*`file.x509.not_after`*:: -+ --- -Time at which the certificate is no longer considered valid. - -type: date - -example: 2020-07-16 03:15:39+00:00 - --- - -*`file.x509.not_before`*:: -+ --- -Time at which the certificate is first considered valid. - -type: date - -example: 2019-08-16 01:40:25+00:00 - --- - -*`file.x509.public_key_algorithm`*:: -+ --- -Algorithm used to generate the public key. - -type: keyword - -example: RSA - --- - -*`file.x509.public_key_curve`*:: -+ --- -The curve used by the elliptic curve public key algorithm. This is algorithm specific. - -type: keyword - -example: nistp521 - --- - -*`file.x509.public_key_exponent`*:: -+ --- -Exponent used to derive the public key. This is algorithm specific. - -type: long - -example: 65537 - -Field is not indexed. - --- - -*`file.x509.public_key_size`*:: -+ --- -The size of the public key space in bits. - -type: long - -example: 2048 - --- - -*`file.x509.serial_number`*:: -+ --- -Unique serial number issued by the certificate authority. For consistency, if this value is alphanumeric, it should be formatted without colons and uppercase characters. - -type: keyword - -example: 55FBB9C7DEBF09809D12CCAA - --- - -*`file.x509.signature_algorithm`*:: -+ --- -Identifier for certificate signature algorithm. We recommend using names found in Go Lang Crypto library. See https://github.com/golang/go/blob/go1.14/src/crypto/x509/x509.go#L337-L353. - -type: keyword - -example: SHA256-RSA - --- - -*`file.x509.subject.common_name`*:: -+ --- -List of common names (CN) of subject. - -type: keyword - -example: shared.global.example.net - --- - -*`file.x509.subject.country`*:: -+ --- -List of country (C) code - -type: keyword - -example: US - --- - -*`file.x509.subject.distinguished_name`*:: -+ --- -Distinguished name (DN) of the certificate subject entity. - -type: keyword - -example: C=US, ST=California, L=San Francisco, O=Example, Inc., CN=shared.global.example.net - --- - -*`file.x509.subject.locality`*:: -+ --- -List of locality names (L) - -type: keyword - -example: San Francisco - --- - -*`file.x509.subject.organization`*:: -+ --- -List of organizations (O) of subject. - -type: keyword - -example: Example, Inc. - --- - -*`file.x509.subject.organizational_unit`*:: -+ --- -List of organizational units (OU) of subject. - -type: keyword - --- - -*`file.x509.subject.state_or_province`*:: -+ --- -List of state or province names (ST, S, or P) - -type: keyword - -example: California - --- - -*`file.x509.version_number`*:: -+ --- -Version of x509 format. - -type: keyword - -example: 3 - --- - -[float] -=== geo - -Geo fields can carry data about a specific location related to an event. -This geolocation information can be derived from techniques such as Geo IP, or be user-supplied. - - -*`geo.city_name`*:: -+ --- -City name. - -type: keyword - -example: Montreal - --- - -*`geo.continent_code`*:: -+ --- -Two-letter code representing continent's name. - -type: keyword - -example: NA - --- - -*`geo.continent_name`*:: -+ --- -Name of the continent. - -type: keyword - -example: North America - --- - -*`geo.country_iso_code`*:: -+ --- -Country ISO code. - -type: keyword - -example: CA - --- - -*`geo.country_name`*:: -+ --- -Country name. - -type: keyword - -example: Canada - --- - -*`geo.location`*:: -+ --- -Longitude and latitude. - -type: geo_point - -example: { "lon": -73.614830, "lat": 45.505918 } - --- - -*`geo.name`*:: -+ --- -User-defined description of a location, at the level of granularity they care about. -Could be the name of their data centers, the floor number, if this describes a local physical entity, city names. -Not typically used in automated geolocation. - -type: keyword - -example: boston-dc - --- - -*`geo.postal_code`*:: -+ --- -Postal code associated with the location. -Values appropriate for this field may also be known as a postcode or ZIP code and will vary widely from country to country. - -type: keyword - -example: 94040 - --- - -*`geo.region_iso_code`*:: -+ --- -Region ISO code. - -type: keyword - -example: CA-QC - --- - -*`geo.region_name`*:: -+ --- -Region name. - -type: keyword - -example: Quebec - --- - -*`geo.timezone`*:: -+ --- -The time zone of the location, such as IANA time zone name. - -type: keyword - -example: America/Argentina/Buenos_Aires - --- - -[float] -=== group - -The group fields are meant to represent groups that are relevant to the event. - - -*`group.domain`*:: -+ --- -Name of the directory the group is a member of. -For example, an LDAP or Active Directory domain name. - -type: keyword - --- - -*`group.id`*:: -+ --- -Unique identifier for the group on the system/platform. - -type: keyword - --- - -*`group.name`*:: -+ --- -Name of the group. - -type: keyword - --- - -[float] -=== hash - -The hash fields represent different bitwise hash algorithms and their values. -Field names for common hashes (e.g. MD5, SHA1) are predefined. Add fields for other hashes by lowercasing the hash algorithm name and using underscore separators as appropriate (snake case, e.g. sha3_512). -Note that this fieldset is used for common hashes that may be computed over a range of generic bytes. Entity-specific hashes such as ja3 or imphash are placed in the fieldsets to which they relate (tls and pe, respectively). - - -*`hash.md5`*:: -+ --- -MD5 hash. - -type: keyword - --- - -*`hash.sha1`*:: -+ --- -SHA1 hash. - -type: keyword - --- - -*`hash.sha256`*:: -+ --- -SHA256 hash. - -type: keyword - --- - -*`hash.sha512`*:: -+ --- -SHA512 hash. - -type: keyword - --- - -*`hash.ssdeep`*:: -+ --- -SSDEEP hash. - -type: keyword - --- - -[float] -=== host - -A host is defined as a general computing instance. -ECS host.* fields should be populated with details about the host on which the event happened, or from which the measurement was taken. Host types include hardware, virtual machines, Docker containers, and Kubernetes nodes. - - -*`host.architecture`*:: -+ --- -Operating system architecture. - -type: keyword - -example: x86_64 - --- - -*`host.cpu.usage`*:: -+ --- -Percent CPU used which is normalized by the number of CPU cores and it ranges from 0 to 1. -Scaling factor: 1000. -For example: For a two core host, this value should be the average of the two cores, between 0 and 1. - -type: scaled_float - --- - -*`host.disk.read.bytes`*:: -+ --- -The total number of bytes (gauge) read successfully (aggregated from all disks) since the last metric collection. - -type: long - --- - -*`host.disk.write.bytes`*:: -+ --- -The total number of bytes (gauge) written successfully (aggregated from all disks) since the last metric collection. - -type: long - --- - -*`host.domain`*:: -+ --- -Name of the domain of which the host is a member. -For example, on Windows this could be the host's Active Directory domain or NetBIOS domain name. For Linux this could be the domain of the host's LDAP provider. - -type: keyword - -example: CONTOSO - --- - -*`host.geo.city_name`*:: -+ --- -City name. - -type: keyword - -example: Montreal - --- - -*`host.geo.continent_code`*:: -+ --- -Two-letter code representing continent's name. - -type: keyword - -example: NA - --- - -*`host.geo.continent_name`*:: -+ --- -Name of the continent. - -type: keyword - -example: North America - --- - -*`host.geo.country_iso_code`*:: -+ --- -Country ISO code. - -type: keyword - -example: CA - --- - -*`host.geo.country_name`*:: -+ --- -Country name. - -type: keyword - -example: Canada - --- - -*`host.geo.location`*:: -+ --- -Longitude and latitude. - -type: geo_point - -example: { "lon": -73.614830, "lat": 45.505918 } - --- - -*`host.geo.name`*:: -+ --- -User-defined description of a location, at the level of granularity they care about. -Could be the name of their data centers, the floor number, if this describes a local physical entity, city names. -Not typically used in automated geolocation. - -type: keyword - -example: boston-dc - --- - -*`host.geo.postal_code`*:: -+ --- -Postal code associated with the location. -Values appropriate for this field may also be known as a postcode or ZIP code and will vary widely from country to country. - -type: keyword - -example: 94040 - --- - -*`host.geo.region_iso_code`*:: -+ --- -Region ISO code. - -type: keyword - -example: CA-QC - --- - -*`host.geo.region_name`*:: -+ --- -Region name. - -type: keyword - -example: Quebec - --- - -*`host.geo.timezone`*:: -+ --- -The time zone of the location, such as IANA time zone name. - -type: keyword - -example: America/Argentina/Buenos_Aires - --- - -*`host.hostname`*:: -+ --- -Hostname of the host. -It normally contains what the `hostname` command returns on the host machine. - -type: keyword - --- - -*`host.id`*:: -+ --- -Unique host id. -As hostname is not always unique, use values that are meaningful in your environment. -Example: The current usage of `beat.name`. - -type: keyword - --- - -*`host.ip`*:: -+ --- -Host ip addresses. - -type: ip - --- - -*`host.mac`*:: -+ --- -Host MAC addresses. -The notation format from RFC 7042 is suggested: Each octet (that is, 8-bit byte) is represented by two [uppercase] hexadecimal digits giving the value of the octet as an unsigned integer. Successive octets are separated by a hyphen. - -type: keyword - -example: ["00-00-5E-00-53-23", "00-00-5E-00-53-24"] - --- - -*`host.name`*:: -+ --- -Name of the host. -It can contain what `hostname` returns on Unix systems, the fully qualified domain name, or a name specified by the user. The sender decides which value to use. - -type: keyword - --- - -*`host.network.egress.bytes`*:: -+ --- -The number of bytes (gauge) sent out on all network interfaces by the host since the last metric collection. - -type: long - --- - -*`host.network.egress.packets`*:: -+ --- -The number of packets (gauge) sent out on all network interfaces by the host since the last metric collection. - -type: long - --- - -*`host.network.ingress.bytes`*:: -+ --- -The number of bytes received (gauge) on all network interfaces by the host since the last metric collection. - -type: long - --- - -*`host.network.ingress.packets`*:: -+ --- -The number of packets (gauge) received on all network interfaces by the host since the last metric collection. - -type: long - --- - -*`host.os.family`*:: -+ --- -OS family (such as redhat, debian, freebsd, windows). - -type: keyword - -example: debian - --- - -*`host.os.full`*:: -+ --- -Operating system name, including the version or code name. - -type: keyword - -example: Mac OS Mojave - --- - -*`host.os.full.text`*:: -+ --- -type: match_only_text - --- - -*`host.os.kernel`*:: -+ --- -Operating system kernel version as a raw string. - -type: keyword - -example: 4.4.0-112-generic - --- - -*`host.os.name`*:: -+ --- -Operating system name, without the version. - -type: keyword - -example: Mac OS X - --- - -*`host.os.name.text`*:: -+ --- -type: match_only_text - --- - -*`host.os.platform`*:: -+ --- -Operating system platform (such centos, ubuntu, windows). - -type: keyword - -example: darwin - --- - -*`host.os.type`*:: -+ --- -Use the `os.type` field to categorize the operating system into one of the broad commercial families. -One of these following values should be used (lowercase): linux, macos, unix, windows. -If the OS you're dealing with is not in the list, the field should not be populated. Please let us know by opening an issue with ECS, to propose its addition. - -type: keyword - -example: macos - --- - -*`host.os.version`*:: -+ --- -Operating system version as a raw string. - -type: keyword - -example: 10.14.1 - --- - -*`host.type`*:: -+ --- -Type of host. -For Cloud providers this can be the machine type like `t2.medium`. If vm, this could be the container, for example, or other information meaningful in your environment. - -type: keyword - --- - -*`host.uptime`*:: -+ --- -Seconds the host has been up. - -type: long - -example: 1325 - --- - -[float] -=== http - -Fields related to HTTP activity. Use the `url` field set to store the url of the request. - - -*`http.request.body.bytes`*:: -+ --- -Size in bytes of the request body. - -type: long - -example: 887 - -format: bytes - --- - -*`http.request.body.content`*:: -+ --- -The full HTTP request body. - -type: wildcard - -example: Hello world - --- - -*`http.request.body.content.text`*:: -+ --- -type: match_only_text - --- - -*`http.request.bytes`*:: -+ --- -Total size in bytes of the request (body and headers). - -type: long - -example: 1437 - -format: bytes - --- - -*`http.request.id`*:: -+ --- -A unique identifier for each HTTP request to correlate logs between clients and servers in transactions. -The id may be contained in a non-standard HTTP header, such as `X-Request-ID` or `X-Correlation-ID`. - -type: keyword - -example: 123e4567-e89b-12d3-a456-426614174000 - --- - -*`http.request.method`*:: -+ --- -HTTP request method. -The value should retain its casing from the original event. For example, `GET`, `get`, and `GeT` are all considered valid values for this field. - -type: keyword - -example: POST - --- - -*`http.request.mime_type`*:: -+ --- -Mime type of the body of the request. -This value must only be populated based on the content of the request body, not on the `Content-Type` header. Comparing the mime type of a request with the request's Content-Type header can be helpful in detecting threats or misconfigured clients. - -type: keyword - -example: image/gif - --- - -*`http.request.referrer`*:: -+ --- -Referrer for this HTTP request. - -type: keyword - -example: https://blog.example.com/ - --- - -*`http.response.body.bytes`*:: -+ --- -Size in bytes of the response body. - -type: long - -example: 887 - -format: bytes - --- - -*`http.response.body.content`*:: -+ --- -The full HTTP response body. - -type: wildcard - -example: Hello world - --- - -*`http.response.body.content.text`*:: -+ --- -type: match_only_text - --- - -*`http.response.bytes`*:: -+ --- -Total size in bytes of the response (body and headers). - -type: long - -example: 1437 - -format: bytes - --- - -*`http.response.mime_type`*:: -+ --- -Mime type of the body of the response. -This value must only be populated based on the content of the response body, not on the `Content-Type` header. Comparing the mime type of a response with the response's Content-Type header can be helpful in detecting misconfigured servers. - -type: keyword - -example: image/gif - --- - -*`http.response.status_code`*:: -+ --- -HTTP response status code. - -type: long - -example: 404 - -format: string - --- - -*`http.version`*:: -+ --- -HTTP version. - -type: keyword - -example: 1.1 - --- - -[float] -=== interface - -The interface fields are used to record ingress and egress interface information when reported by an observer (e.g. firewall, router, load balancer) in the context of the observer handling a network connection. In the case of a single observer interface (e.g. network sensor on a span port) only the observer.ingress information should be populated. - - -*`interface.alias`*:: -+ --- -Interface alias as reported by the system, typically used in firewall implementations for e.g. inside, outside, or dmz logical interface naming. - -type: keyword - -example: outside - --- - -*`interface.id`*:: -+ --- -Interface ID as reported by an observer (typically SNMP interface ID). - -type: keyword - -example: 10 - --- - -*`interface.name`*:: -+ --- -Interface name as reported by the system. - -type: keyword - -example: eth0 - --- - -[float] -=== log - -Details about the event's logging mechanism or logging transport. -The log.* fields are typically populated with details about the logging mechanism used to create and/or transport the event. For example, syslog details belong under `log.syslog.*`. -The details specific to your event source are typically not logged under `log.*`, but rather in `event.*` or in other ECS fields. - - -*`log.file.path`*:: -+ --- -Full path to the log file this event came from, including the file name. It should include the drive letter, when appropriate. -If the event wasn't read from a log file, do not populate this field. - -type: keyword - -example: /var/log/fun-times.log - --- - -*`log.level`*:: -+ --- -Original log level of the log event. -If the source of the event provides a log level or textual severity, this is the one that goes in `log.level`. If your source doesn't specify one, you may put your event transport's severity here (e.g. Syslog severity). -Some examples are `warn`, `err`, `i`, `informational`. - -type: keyword - -example: error - --- - -*`log.logger`*:: -+ --- -The name of the logger inside an application. This is usually the name of the class which initialized the logger, or can be a custom name. - -type: keyword - -example: org.elasticsearch.bootstrap.Bootstrap - --- - -*`log.origin.file.line`*:: -+ --- -The line number of the file containing the source code which originated the log event. - -type: long - -example: 42 - --- - -*`log.origin.file.name`*:: -+ --- -The name of the file containing the source code which originated the log event. -Note that this field is not meant to capture the log file. The correct field to capture the log file is `log.file.path`. - -type: keyword - -example: Bootstrap.java - --- - -*`log.origin.function`*:: -+ --- -The name of the function or method which originated the log event. - -type: keyword - -example: init - --- - -*`log.syslog`*:: -+ --- -The Syslog metadata of the event, if the event was transmitted via Syslog. Please see RFCs 5424 or 3164. - -type: object - --- - -*`log.syslog.facility.code`*:: -+ --- -The Syslog numeric facility of the log event, if available. -According to RFCs 5424 and 3164, this value should be an integer between 0 and 23. - -type: long - -example: 23 - -format: string - --- - -*`log.syslog.facility.name`*:: -+ --- -The Syslog text-based facility of the log event, if available. - -type: keyword - -example: local7 - --- - -*`log.syslog.priority`*:: -+ --- -Syslog numeric priority of the event, if available. -According to RFCs 5424 and 3164, the priority is 8 * facility + severity. This number is therefore expected to contain a value between 0 and 191. - -type: long - -example: 135 - -format: string - --- - -*`log.syslog.severity.code`*:: -+ --- -The Syslog numeric severity of the log event, if available. -If the event source publishing via Syslog provides a different numeric severity value (e.g. firewall, IDS), your source's numeric severity should go to `event.severity`. If the event source does not specify a distinct severity, you can optionally copy the Syslog severity to `event.severity`. - -type: long - -example: 3 - --- - -*`log.syslog.severity.name`*:: -+ --- -The Syslog numeric severity of the log event, if available. -If the event source publishing via Syslog provides a different severity value (e.g. firewall, IDS), your source's text severity should go to `log.level`. If the event source does not specify a distinct severity, you can optionally copy the Syslog severity to `log.level`. - -type: keyword - -example: Error - --- - -[float] -=== network - -The network is defined as the communication path over which a host or network event happens. -The network.* fields should be populated with details about the network activity associated with an event. - - -*`network.application`*:: -+ --- -When a specific application or service is identified from network connection details (source/dest IPs, ports, certificates, or wire format), this field captures the application's or service's name. -For example, the original event identifies the network connection being from a specific web service in a `https` network connection, like `facebook` or `twitter`. -The field value must be normalized to lowercase for querying. - -type: keyword - -example: aim - --- - -*`network.bytes`*:: -+ --- -Total bytes transferred in both directions. -If `source.bytes` and `destination.bytes` are known, `network.bytes` is their sum. - -type: long - -example: 368 - -format: bytes - --- - -*`network.community_id`*:: -+ --- -A hash of source and destination IPs and ports, as well as the protocol used in a communication. This is a tool-agnostic standard to identify flows. -Learn more at https://github.com/corelight/community-id-spec. - -type: keyword - -example: 1:hO+sN4H+MG5MY/8hIrXPqc4ZQz0= - --- - -*`network.direction`*:: -+ --- -Direction of the network traffic. -Recommended values are: - * ingress - * egress - * inbound - * outbound - * internal - * external - * unknown - -When mapping events from a host-based monitoring context, populate this field from the host's point of view, using the values "ingress" or "egress". -When mapping events from a network or perimeter-based monitoring context, populate this field from the point of view of the network perimeter, using the values "inbound", "outbound", "internal" or "external". -Note that "internal" is not crossing perimeter boundaries, and is meant to describe communication between two hosts within the perimeter. Note also that "external" is meant to describe traffic between two hosts that are external to the perimeter. This could for example be useful for ISPs or VPN service providers. - -type: keyword - -example: inbound - --- - -*`network.forwarded_ip`*:: -+ --- -Host IP address when the source IP address is the proxy. - -type: ip - -example: 192.1.1.2 - --- - -*`network.iana_number`*:: -+ --- -IANA Protocol Number (https://www.iana.org/assignments/protocol-numbers/protocol-numbers.xhtml). Standardized list of protocols. This aligns well with NetFlow and sFlow related logs which use the IANA Protocol Number. - -type: keyword - -example: 6 - --- - -*`network.inner`*:: -+ --- -Network.inner fields are added in addition to network.vlan fields to describe the innermost VLAN when q-in-q VLAN tagging is present. Allowed fields include vlan.id and vlan.name. Inner vlan fields are typically used when sending traffic with multiple 802.1q encapsulations to a network sensor (e.g. Zeek, Wireshark.) - -type: object - --- - -*`network.inner.vlan.id`*:: -+ --- -VLAN ID as reported by the observer. - -type: keyword - -example: 10 - --- - -*`network.inner.vlan.name`*:: -+ --- -Optional VLAN name as reported by the observer. - -type: keyword - -example: outside - --- - -*`network.name`*:: -+ --- -Name given by operators to sections of their network. - -type: keyword - -example: Guest Wifi - --- - -*`network.packets`*:: -+ --- -Total packets transferred in both directions. -If `source.packets` and `destination.packets` are known, `network.packets` is their sum. - -type: long - -example: 24 - --- - -*`network.protocol`*:: -+ --- -In the OSI Model this would be the Application Layer protocol. For example, `http`, `dns`, or `ssh`. -The field value must be normalized to lowercase for querying. - -type: keyword - -example: http - --- - -*`network.transport`*:: -+ --- -Same as network.iana_number, but instead using the Keyword name of the transport layer (udp, tcp, ipv6-icmp, etc.) -The field value must be normalized to lowercase for querying. - -type: keyword - -example: tcp - --- - -*`network.type`*:: -+ --- -In the OSI Model this would be the Network Layer. ipv4, ipv6, ipsec, pim, etc -The field value must be normalized to lowercase for querying. - -type: keyword - -example: ipv4 - --- - -*`network.vlan.id`*:: -+ --- -VLAN ID as reported by the observer. - -type: keyword - -example: 10 - --- - -*`network.vlan.name`*:: -+ --- -Optional VLAN name as reported by the observer. - -type: keyword - -example: outside - --- - -[float] -=== observer - -An observer is defined as a special network, security, or application device used to detect, observe, or create network, security, or application-related events and metrics. -This could be a custom hardware appliance or a server that has been configured to run special network, security, or application software. Examples include firewalls, web proxies, intrusion detection/prevention systems, network monitoring sensors, web application firewalls, data loss prevention systems, and APM servers. The observer.* fields shall be populated with details of the system, if any, that detects, observes and/or creates a network, security, or application event or metric. Message queues and ETL components used in processing events or metrics are not considered observers in ECS. - - -*`observer.egress`*:: -+ --- -Observer.egress holds information like interface number and name, vlan, and zone information to classify egress traffic. Single armed monitoring such as a network sensor on a span port should only use observer.ingress to categorize traffic. - -type: object - --- - -*`observer.egress.interface.alias`*:: -+ --- -Interface alias as reported by the system, typically used in firewall implementations for e.g. inside, outside, or dmz logical interface naming. - -type: keyword - -example: outside - --- - -*`observer.egress.interface.id`*:: -+ --- -Interface ID as reported by an observer (typically SNMP interface ID). - -type: keyword - -example: 10 - --- - -*`observer.egress.interface.name`*:: -+ --- -Interface name as reported by the system. - -type: keyword - -example: eth0 - --- - -*`observer.egress.vlan.id`*:: -+ --- -VLAN ID as reported by the observer. - -type: keyword - -example: 10 - --- - -*`observer.egress.vlan.name`*:: -+ --- -Optional VLAN name as reported by the observer. - -type: keyword - -example: outside - --- - -*`observer.egress.zone`*:: -+ --- -Network zone of outbound traffic as reported by the observer to categorize the destination area of egress traffic, e.g. Internal, External, DMZ, HR, Legal, etc. - -type: keyword - -example: Public_Internet - --- - -*`observer.geo.city_name`*:: -+ --- -City name. - -type: keyword - -example: Montreal - --- - -*`observer.geo.continent_code`*:: -+ --- -Two-letter code representing continent's name. - -type: keyword - -example: NA - --- - -*`observer.geo.continent_name`*:: -+ --- -Name of the continent. - -type: keyword - -example: North America - --- - -*`observer.geo.country_iso_code`*:: -+ --- -Country ISO code. - -type: keyword - -example: CA - --- - -*`observer.geo.country_name`*:: -+ --- -Country name. - -type: keyword - -example: Canada - --- - -*`observer.geo.location`*:: -+ --- -Longitude and latitude. - -type: geo_point - -example: { "lon": -73.614830, "lat": 45.505918 } - --- - -*`observer.geo.name`*:: -+ --- -User-defined description of a location, at the level of granularity they care about. -Could be the name of their data centers, the floor number, if this describes a local physical entity, city names. -Not typically used in automated geolocation. - -type: keyword - -example: boston-dc - --- - -*`observer.geo.postal_code`*:: -+ --- -Postal code associated with the location. -Values appropriate for this field may also be known as a postcode or ZIP code and will vary widely from country to country. - -type: keyword - -example: 94040 - --- - -*`observer.geo.region_iso_code`*:: -+ --- -Region ISO code. - -type: keyword - -example: CA-QC - --- - -*`observer.geo.region_name`*:: -+ --- -Region name. - -type: keyword - -example: Quebec - --- - -*`observer.geo.timezone`*:: -+ --- -The time zone of the location, such as IANA time zone name. - -type: keyword - -example: America/Argentina/Buenos_Aires - --- - -*`observer.hostname`*:: -+ --- -Hostname of the observer. - -type: keyword - --- - -*`observer.ingress`*:: -+ --- -Observer.ingress holds information like interface number and name, vlan, and zone information to classify ingress traffic. Single armed monitoring such as a network sensor on a span port should only use observer.ingress to categorize traffic. - -type: object - --- - -*`observer.ingress.interface.alias`*:: -+ --- -Interface alias as reported by the system, typically used in firewall implementations for e.g. inside, outside, or dmz logical interface naming. - -type: keyword - -example: outside - --- - -*`observer.ingress.interface.id`*:: -+ --- -Interface ID as reported by an observer (typically SNMP interface ID). - -type: keyword - -example: 10 - --- - -*`observer.ingress.interface.name`*:: -+ --- -Interface name as reported by the system. - -type: keyword - -example: eth0 - --- - -*`observer.ingress.vlan.id`*:: -+ --- -VLAN ID as reported by the observer. - -type: keyword - -example: 10 - --- - -*`observer.ingress.vlan.name`*:: -+ --- -Optional VLAN name as reported by the observer. - -type: keyword - -example: outside - --- - -*`observer.ingress.zone`*:: -+ --- -Network zone of incoming traffic as reported by the observer to categorize the source area of ingress traffic. e.g. internal, External, DMZ, HR, Legal, etc. - -type: keyword - -example: DMZ - --- - -*`observer.ip`*:: -+ --- -IP addresses of the observer. - -type: ip - --- - -*`observer.mac`*:: -+ --- -MAC addresses of the observer. -The notation format from RFC 7042 is suggested: Each octet (that is, 8-bit byte) is represented by two [uppercase] hexadecimal digits giving the value of the octet as an unsigned integer. Successive octets are separated by a hyphen. - -type: keyword - -example: ["00-00-5E-00-53-23", "00-00-5E-00-53-24"] - --- - -*`observer.name`*:: -+ --- -Custom name of the observer. -This is a name that can be given to an observer. This can be helpful for example if multiple firewalls of the same model are used in an organization. -If no custom name is needed, the field can be left empty. - -type: keyword - -example: 1_proxySG - --- - -*`observer.os.family`*:: -+ --- -OS family (such as redhat, debian, freebsd, windows). - -type: keyword - -example: debian - --- - -*`observer.os.full`*:: -+ --- -Operating system name, including the version or code name. - -type: keyword - -example: Mac OS Mojave - --- - -*`observer.os.full.text`*:: -+ --- -type: match_only_text - --- - -*`observer.os.kernel`*:: -+ --- -Operating system kernel version as a raw string. - -type: keyword - -example: 4.4.0-112-generic - --- - -*`observer.os.name`*:: -+ --- -Operating system name, without the version. - -type: keyword - -example: Mac OS X - --- - -*`observer.os.name.text`*:: -+ --- -type: match_only_text - --- - -*`observer.os.platform`*:: -+ --- -Operating system platform (such centos, ubuntu, windows). - -type: keyword - -example: darwin - --- - -*`observer.os.type`*:: -+ --- -Use the `os.type` field to categorize the operating system into one of the broad commercial families. -One of these following values should be used (lowercase): linux, macos, unix, windows. -If the OS you're dealing with is not in the list, the field should not be populated. Please let us know by opening an issue with ECS, to propose its addition. - -type: keyword - -example: macos - --- - -*`observer.os.version`*:: -+ --- -Operating system version as a raw string. - -type: keyword - -example: 10.14.1 - --- - -*`observer.product`*:: -+ --- -The product name of the observer. - -type: keyword - -example: s200 - --- - -*`observer.serial_number`*:: -+ --- -Observer serial number. - -type: keyword - --- - -*`observer.type`*:: -+ --- -The type of the observer the data is coming from. -There is no predefined list of observer types. Some examples are `forwarder`, `firewall`, `ids`, `ips`, `proxy`, `poller`, `sensor`, `APM server`. - -type: keyword - -example: firewall - --- - -*`observer.vendor`*:: -+ --- -Vendor name of the observer. - -type: keyword - -example: Symantec - --- - -*`observer.version`*:: -+ --- -Observer version. - -type: keyword - --- - -[float] -=== orchestrator - -Fields that describe the resources which container orchestrators manage or act upon. - - -*`orchestrator.api_version`*:: -+ --- -API version being used to carry out the action - -type: keyword - -example: v1beta1 - --- - -*`orchestrator.cluster.name`*:: -+ --- -Name of the cluster. - -type: keyword - --- - -*`orchestrator.cluster.url`*:: -+ --- -URL of the API used to manage the cluster. - -type: keyword - --- - -*`orchestrator.cluster.version`*:: -+ --- -The version of the cluster. - -type: keyword - --- - -*`orchestrator.namespace`*:: -+ --- -Namespace in which the action is taking place. - -type: keyword - -example: kube-system - --- - -*`orchestrator.organization`*:: -+ --- -Organization affected by the event (for multi-tenant orchestrator setups). - -type: keyword - -example: elastic - --- - -*`orchestrator.resource.name`*:: -+ --- -Name of the resource being acted upon. - -type: keyword - -example: test-pod-cdcws - --- - -*`orchestrator.resource.type`*:: -+ --- -Type of resource being acted upon. - -type: keyword - -example: service - --- - -*`orchestrator.type`*:: -+ --- -Orchestrator cluster type (e.g. kubernetes, nomad or cloudfoundry). - -type: keyword - -example: kubernetes - --- - -[float] -=== organization - -The organization fields enrich data with information about the company or entity the data is associated with. -These fields help you arrange or filter data stored in an index by one or multiple organizations. - - -*`organization.id`*:: -+ --- -Unique identifier for the organization. - -type: keyword - --- - -*`organization.name`*:: -+ --- -Organization name. - -type: keyword - --- - -*`organization.name.text`*:: -+ --- -type: match_only_text - --- - -[float] -=== os - -The OS fields contain information about the operating system. - - -*`os.family`*:: -+ --- -OS family (such as redhat, debian, freebsd, windows). - -type: keyword - -example: debian - --- - -*`os.full`*:: -+ --- -Operating system name, including the version or code name. - -type: keyword - -example: Mac OS Mojave - --- - -*`os.full.text`*:: -+ --- -type: match_only_text - --- - -*`os.kernel`*:: -+ --- -Operating system kernel version as a raw string. - -type: keyword - -example: 4.4.0-112-generic - --- - -*`os.name`*:: -+ --- -Operating system name, without the version. - -type: keyword - -example: Mac OS X - --- - -*`os.name.text`*:: -+ --- -type: match_only_text - --- - -*`os.platform`*:: -+ --- -Operating system platform (such centos, ubuntu, windows). - -type: keyword - -example: darwin - --- - -*`os.type`*:: -+ --- -Use the `os.type` field to categorize the operating system into one of the broad commercial families. -One of these following values should be used (lowercase): linux, macos, unix, windows. -If the OS you're dealing with is not in the list, the field should not be populated. Please let us know by opening an issue with ECS, to propose its addition. - -type: keyword - -example: macos - --- - -*`os.version`*:: -+ --- -Operating system version as a raw string. - -type: keyword - -example: 10.14.1 - --- - -[float] -=== package - -These fields contain information about an installed software package. It contains general information about a package, such as name, version or size. It also contains installation details, such as time or location. - - -*`package.architecture`*:: -+ --- -Package architecture. - -type: keyword - -example: x86_64 - --- - -*`package.build_version`*:: -+ --- -Additional information about the build version of the installed package. -For example use the commit SHA of a non-released package. - -type: keyword - -example: 36f4f7e89dd61b0988b12ee000b98966867710cd - --- - -*`package.checksum`*:: -+ --- -Checksum of the installed package for verification. - -type: keyword - -example: 68b329da9893e34099c7d8ad5cb9c940 - --- - -*`package.description`*:: -+ --- -Description of the package. - -type: keyword - -example: Open source programming language to build simple/reliable/efficient software. - --- - -*`package.install_scope`*:: -+ --- -Indicating how the package was installed, e.g. user-local, global. - -type: keyword - -example: global - --- - -*`package.installed`*:: -+ --- -Time when package was installed. - -type: date - --- - -*`package.license`*:: -+ --- -License under which the package was released. -Use a short name, e.g. the license identifier from SPDX License List where possible (https://spdx.org/licenses/). - -type: keyword - -example: Apache License 2.0 - --- - -*`package.name`*:: -+ --- -Package name - -type: keyword - -example: go - --- - -*`package.path`*:: -+ --- -Path where the package is installed. - -type: keyword - -example: /usr/local/Cellar/go/1.12.9/ - --- - -*`package.reference`*:: -+ --- -Home page or reference URL of the software in this package, if available. - -type: keyword - -example: https://golang.org - --- - -*`package.size`*:: -+ --- -Package size in bytes. - -type: long - -example: 62231 - -format: string - --- - -*`package.type`*:: -+ --- -Type of package. -This should contain the package file type, rather than the package manager name. Examples: rpm, dpkg, brew, npm, gem, nupkg, jar. - -type: keyword - -example: rpm - --- - -*`package.version`*:: -+ --- -Package version - -type: keyword - -example: 1.12.9 - --- - -[float] -=== pe - -These fields contain Windows Portable Executable (PE) metadata. - - -*`pe.architecture`*:: -+ --- -CPU architecture target for the file. - -type: keyword - -example: x64 - --- - -*`pe.company`*:: -+ --- -Internal company name of the file, provided at compile-time. - -type: keyword - -example: Microsoft Corporation - --- - -*`pe.description`*:: -+ --- -Internal description of the file, provided at compile-time. - -type: keyword - -example: Paint - --- - -*`pe.file_version`*:: -+ --- -Internal version of the file, provided at compile-time. - -type: keyword - -example: 6.3.9600.17415 - --- - -*`pe.imphash`*:: -+ --- -A hash of the imports in a PE file. An imphash -- or import hash -- can be used to fingerprint binaries even after recompilation or other code-level transformations have occurred, which would change more traditional hash values. -Learn more at https://www.fireeye.com/blog/threat-research/2014/01/tracking-malware-import-hashing.html. - -type: keyword - -example: 0c6803c4e922103c4dca5963aad36ddf - --- - -*`pe.original_file_name`*:: -+ --- -Internal name of the file, provided at compile-time. - -type: keyword - -example: MSPAINT.EXE - --- - -*`pe.product`*:: -+ --- -Internal product name of the file, provided at compile-time. - -type: keyword - -example: Microsoft® Windows® Operating System - --- - -[float] -=== process - -These fields contain information about a process. -These fields can help you correlate metrics information with a process id/name from a log message. The `process.pid` often stays in the metric itself and is copied to the global field for correlation. - - -*`process.args`*:: -+ --- -Array of process arguments, starting with the absolute path to the executable. -May be filtered to protect sensitive information. - -type: keyword - -example: ["/usr/bin/ssh", "-l", "user", "10.0.0.16"] - --- - -*`process.args_count`*:: -+ --- -Length of the process.args array. -This field can be useful for querying or performing bucket analysis on how many arguments were provided to start a process. More arguments may be an indication of suspicious activity. - -type: long - -example: 4 - --- - -*`process.code_signature.digest_algorithm`*:: -+ --- -The hashing algorithm used to sign the process. -This value can distinguish signatures when a file is signed multiple times by the same signer but with a different digest algorithm. - -type: keyword - -example: sha256 - --- - -*`process.code_signature.exists`*:: -+ --- -Boolean to capture if a signature is present. - -type: boolean - -example: true - --- - -*`process.code_signature.signing_id`*:: -+ --- -The identifier used to sign the process. -This is used to identify the application manufactured by a software vendor. The field is relevant to Apple *OS only. - -type: keyword - -example: com.apple.xpc.proxy - --- - -*`process.code_signature.status`*:: -+ --- -Additional information about the certificate status. -This is useful for logging cryptographic errors with the certificate validity or trust status. Leave unpopulated if the validity or trust of the certificate was unchecked. - -type: keyword - -example: ERROR_UNTRUSTED_ROOT - --- - -*`process.code_signature.subject_name`*:: -+ --- -Subject name of the code signer - -type: keyword - -example: Microsoft Corporation - --- - -*`process.code_signature.team_id`*:: -+ --- -The team identifier used to sign the process. -This is used to identify the team or vendor of a software product. The field is relevant to Apple *OS only. - -type: keyword - -example: EQHXZ8M8AV - --- - -*`process.code_signature.timestamp`*:: -+ --- -Date and time when the code signature was generated and signed. - -type: date - -example: 2021-01-01T12:10:30Z - --- - -*`process.code_signature.trusted`*:: -+ --- -Stores the trust status of the certificate chain. -Validating the trust of the certificate chain may be complicated, and this field should only be populated by tools that actively check the status. - -type: boolean - -example: true - --- - -*`process.code_signature.valid`*:: -+ --- -Boolean to capture if the digital signature is verified against the binary content. -Leave unpopulated if a certificate was unchecked. - -type: boolean - -example: true - --- - -*`process.command_line`*:: -+ --- -Full command line that started the process, including the absolute path to the executable, and all arguments. -Some arguments may be filtered to protect sensitive information. - -type: wildcard - -example: /usr/bin/ssh -l user 10.0.0.16 - --- - -*`process.command_line.text`*:: -+ --- -type: match_only_text - --- - -*`process.elf.architecture`*:: -+ --- -Machine architecture of the ELF file. - -type: keyword - -example: x86-64 - --- - -*`process.elf.byte_order`*:: -+ --- -Byte sequence of ELF file. - -type: keyword - -example: Little Endian - --- - -*`process.elf.cpu_type`*:: -+ --- -CPU type of the ELF file. - -type: keyword - -example: Intel - --- - -*`process.elf.creation_date`*:: -+ --- -Extracted when possible from the file's metadata. Indicates when it was built or compiled. It can also be faked by malware creators. - -type: date - --- - -*`process.elf.exports`*:: -+ --- -List of exported element names and types. - -type: flattened - --- - -*`process.elf.header.abi_version`*:: -+ --- -Version of the ELF Application Binary Interface (ABI). - -type: keyword - --- - -*`process.elf.header.class`*:: -+ --- -Header class of the ELF file. - -type: keyword - --- - -*`process.elf.header.data`*:: -+ --- -Data table of the ELF header. - -type: keyword - --- - -*`process.elf.header.entrypoint`*:: -+ --- -Header entrypoint of the ELF file. - -type: long - -format: string - --- - -*`process.elf.header.object_version`*:: -+ --- -"0x1" for original ELF files. - -type: keyword - --- - -*`process.elf.header.os_abi`*:: -+ --- -Application Binary Interface (ABI) of the Linux OS. - -type: keyword - --- - -*`process.elf.header.type`*:: -+ --- -Header type of the ELF file. - -type: keyword - --- - -*`process.elf.header.version`*:: -+ --- -Version of the ELF header. - -type: keyword - --- - -*`process.elf.imports`*:: -+ --- -List of imported element names and types. - -type: flattened - --- - -*`process.elf.sections`*:: -+ --- -An array containing an object for each section of the ELF file. -The keys that should be present in these objects are defined by sub-fields underneath `elf.sections.*`. - -type: nested - --- - -*`process.elf.sections.chi2`*:: -+ --- -Chi-square probability distribution of the section. - -type: long - -format: number - --- - -*`process.elf.sections.entropy`*:: -+ --- -Shannon entropy calculation from the section. - -type: long - -format: number - --- - -*`process.elf.sections.flags`*:: -+ --- -ELF Section List flags. - -type: keyword - --- - -*`process.elf.sections.name`*:: -+ --- -ELF Section List name. - -type: keyword - --- - -*`process.elf.sections.physical_offset`*:: -+ --- -ELF Section List offset. - -type: keyword - --- - -*`process.elf.sections.physical_size`*:: -+ --- -ELF Section List physical size. - -type: long - -format: bytes - --- - -*`process.elf.sections.type`*:: -+ --- -ELF Section List type. - -type: keyword - --- - -*`process.elf.sections.virtual_address`*:: -+ --- -ELF Section List virtual address. - -type: long - -format: string - --- - -*`process.elf.sections.virtual_size`*:: -+ --- -ELF Section List virtual size. - -type: long - -format: string - --- - -*`process.elf.segments`*:: -+ --- -An array containing an object for each segment of the ELF file. -The keys that should be present in these objects are defined by sub-fields underneath `elf.segments.*`. - -type: nested - --- - -*`process.elf.segments.sections`*:: -+ --- -ELF object segment sections. - -type: keyword - --- - -*`process.elf.segments.type`*:: -+ --- -ELF object segment type. - -type: keyword - --- - -*`process.elf.shared_libraries`*:: -+ --- -List of shared libraries used by this ELF object. - -type: keyword - --- - -*`process.elf.telfhash`*:: -+ --- -telfhash symbol hash for ELF file. - -type: keyword - --- - -*`process.end`*:: -+ --- -The time the process ended. - -type: date - -example: 2016-05-23T08:05:34.853Z - --- - -*`process.entity_id`*:: -+ --- -Unique identifier for the process. -The implementation of this is specified by the data source, but some examples of what could be used here are a process-generated UUID, Sysmon Process GUIDs, or a hash of some uniquely identifying components of a process. -Constructing a globally unique identifier is a common practice to mitigate PID reuse as well as to identify a specific process over time, across multiple monitored hosts. - -type: keyword - -example: c2c455d9f99375d - --- - -*`process.executable`*:: -+ --- -Absolute path to the process executable. - -type: keyword - -example: /usr/bin/ssh - --- - -*`process.executable.text`*:: -+ --- -type: match_only_text - --- - -*`process.exit_code`*:: -+ --- -The exit code of the process, if this is a termination event. -The field should be absent if there is no exit code for the event (e.g. process start). - -type: long - -example: 137 - --- - -*`process.hash.md5`*:: -+ --- -MD5 hash. - -type: keyword - --- - -*`process.hash.sha1`*:: -+ --- -SHA1 hash. - -type: keyword - --- - -*`process.hash.sha256`*:: -+ --- -SHA256 hash. - -type: keyword - --- - -*`process.hash.sha512`*:: -+ --- -SHA512 hash. - -type: keyword - --- - -*`process.hash.ssdeep`*:: -+ --- -SSDEEP hash. - -type: keyword - --- - -*`process.name`*:: -+ --- -Process name. -Sometimes called program name or similar. - -type: keyword - -example: ssh - --- - -*`process.name.text`*:: -+ --- -type: match_only_text - --- - -*`process.parent.args`*:: -+ --- -Array of process arguments, starting with the absolute path to the executable. -May be filtered to protect sensitive information. - -type: keyword - -example: ["/usr/bin/ssh", "-l", "user", "10.0.0.16"] - --- - -*`process.parent.args_count`*:: -+ --- -Length of the process.args array. -This field can be useful for querying or performing bucket analysis on how many arguments were provided to start a process. More arguments may be an indication of suspicious activity. - -type: long - -example: 4 - --- - -*`process.parent.code_signature.digest_algorithm`*:: -+ --- -The hashing algorithm used to sign the process. -This value can distinguish signatures when a file is signed multiple times by the same signer but with a different digest algorithm. - -type: keyword - -example: sha256 - --- - -*`process.parent.code_signature.exists`*:: -+ --- -Boolean to capture if a signature is present. - -type: boolean - -example: true - --- - -*`process.parent.code_signature.signing_id`*:: -+ --- -The identifier used to sign the process. -This is used to identify the application manufactured by a software vendor. The field is relevant to Apple *OS only. - -type: keyword - -example: com.apple.xpc.proxy - --- - -*`process.parent.code_signature.status`*:: -+ --- -Additional information about the certificate status. -This is useful for logging cryptographic errors with the certificate validity or trust status. Leave unpopulated if the validity or trust of the certificate was unchecked. - -type: keyword - -example: ERROR_UNTRUSTED_ROOT - --- - -*`process.parent.code_signature.subject_name`*:: -+ --- -Subject name of the code signer - -type: keyword - -example: Microsoft Corporation - --- - -*`process.parent.code_signature.team_id`*:: -+ --- -The team identifier used to sign the process. -This is used to identify the team or vendor of a software product. The field is relevant to Apple *OS only. - -type: keyword - -example: EQHXZ8M8AV - --- - -*`process.parent.code_signature.timestamp`*:: -+ --- -Date and time when the code signature was generated and signed. - -type: date - -example: 2021-01-01T12:10:30Z - --- - -*`process.parent.code_signature.trusted`*:: -+ --- -Stores the trust status of the certificate chain. -Validating the trust of the certificate chain may be complicated, and this field should only be populated by tools that actively check the status. - -type: boolean - -example: true - --- - -*`process.parent.code_signature.valid`*:: -+ --- -Boolean to capture if the digital signature is verified against the binary content. -Leave unpopulated if a certificate was unchecked. - -type: boolean - -example: true - --- - -*`process.parent.command_line`*:: -+ --- -Full command line that started the process, including the absolute path to the executable, and all arguments. -Some arguments may be filtered to protect sensitive information. - -type: wildcard - -example: /usr/bin/ssh -l user 10.0.0.16 - --- - -*`process.parent.command_line.text`*:: -+ --- -type: match_only_text - --- - -*`process.parent.elf.architecture`*:: -+ --- -Machine architecture of the ELF file. - -type: keyword - -example: x86-64 - --- - -*`process.parent.elf.byte_order`*:: -+ --- -Byte sequence of ELF file. - -type: keyword - -example: Little Endian - --- - -*`process.parent.elf.cpu_type`*:: -+ --- -CPU type of the ELF file. - -type: keyword - -example: Intel - --- - -*`process.parent.elf.creation_date`*:: -+ --- -Extracted when possible from the file's metadata. Indicates when it was built or compiled. It can also be faked by malware creators. - -type: date - --- - -*`process.parent.elf.exports`*:: -+ --- -List of exported element names and types. - -type: flattened - --- - -*`process.parent.elf.header.abi_version`*:: -+ --- -Version of the ELF Application Binary Interface (ABI). - -type: keyword - --- - -*`process.parent.elf.header.class`*:: -+ --- -Header class of the ELF file. - -type: keyword - --- - -*`process.parent.elf.header.data`*:: -+ --- -Data table of the ELF header. - -type: keyword - --- - -*`process.parent.elf.header.entrypoint`*:: -+ --- -Header entrypoint of the ELF file. - -type: long - -format: string - --- - -*`process.parent.elf.header.object_version`*:: -+ --- -"0x1" for original ELF files. - -type: keyword - --- - -*`process.parent.elf.header.os_abi`*:: -+ --- -Application Binary Interface (ABI) of the Linux OS. - -type: keyword - --- - -*`process.parent.elf.header.type`*:: -+ --- -Header type of the ELF file. - -type: keyword - --- - -*`process.parent.elf.header.version`*:: -+ --- -Version of the ELF header. - -type: keyword - --- - -*`process.parent.elf.imports`*:: -+ --- -List of imported element names and types. - -type: flattened - --- - -*`process.parent.elf.sections`*:: -+ --- -An array containing an object for each section of the ELF file. -The keys that should be present in these objects are defined by sub-fields underneath `elf.sections.*`. - -type: nested - --- - -*`process.parent.elf.sections.chi2`*:: -+ --- -Chi-square probability distribution of the section. - -type: long - -format: number - --- - -*`process.parent.elf.sections.entropy`*:: -+ --- -Shannon entropy calculation from the section. - -type: long - -format: number - --- - -*`process.parent.elf.sections.flags`*:: -+ --- -ELF Section List flags. - -type: keyword - --- - -*`process.parent.elf.sections.name`*:: -+ --- -ELF Section List name. - -type: keyword - --- - -*`process.parent.elf.sections.physical_offset`*:: -+ --- -ELF Section List offset. - -type: keyword - --- - -*`process.parent.elf.sections.physical_size`*:: -+ --- -ELF Section List physical size. - -type: long - -format: bytes - --- - -*`process.parent.elf.sections.type`*:: -+ --- -ELF Section List type. - -type: keyword - --- - -*`process.parent.elf.sections.virtual_address`*:: -+ --- -ELF Section List virtual address. - -type: long - -format: string - --- - -*`process.parent.elf.sections.virtual_size`*:: -+ --- -ELF Section List virtual size. - -type: long - -format: string - --- - -*`process.parent.elf.segments`*:: -+ --- -An array containing an object for each segment of the ELF file. -The keys that should be present in these objects are defined by sub-fields underneath `elf.segments.*`. - -type: nested - --- - -*`process.parent.elf.segments.sections`*:: -+ --- -ELF object segment sections. - -type: keyword - --- - -*`process.parent.elf.segments.type`*:: -+ --- -ELF object segment type. - -type: keyword - --- - -*`process.parent.elf.shared_libraries`*:: -+ --- -List of shared libraries used by this ELF object. - -type: keyword - --- - -*`process.parent.elf.telfhash`*:: -+ --- -telfhash symbol hash for ELF file. - -type: keyword - --- - -*`process.parent.end`*:: -+ --- -The time the process ended. - -type: date - -example: 2016-05-23T08:05:34.853Z - --- - -*`process.parent.entity_id`*:: -+ --- -Unique identifier for the process. -The implementation of this is specified by the data source, but some examples of what could be used here are a process-generated UUID, Sysmon Process GUIDs, or a hash of some uniquely identifying components of a process. -Constructing a globally unique identifier is a common practice to mitigate PID reuse as well as to identify a specific process over time, across multiple monitored hosts. - -type: keyword - -example: c2c455d9f99375d - --- - -*`process.parent.executable`*:: -+ --- -Absolute path to the process executable. - -type: keyword - -example: /usr/bin/ssh - --- - -*`process.parent.executable.text`*:: -+ --- -type: match_only_text - --- - -*`process.parent.exit_code`*:: -+ --- -The exit code of the process, if this is a termination event. -The field should be absent if there is no exit code for the event (e.g. process start). - -type: long - -example: 137 - --- - -*`process.parent.hash.md5`*:: -+ --- -MD5 hash. - -type: keyword - --- - -*`process.parent.hash.sha1`*:: -+ --- -SHA1 hash. - -type: keyword - --- - -*`process.parent.hash.sha256`*:: -+ --- -SHA256 hash. - -type: keyword - --- - -*`process.parent.hash.sha512`*:: -+ --- -SHA512 hash. - -type: keyword - --- - -*`process.parent.hash.ssdeep`*:: -+ --- -SSDEEP hash. - -type: keyword - --- - -*`process.parent.name`*:: -+ --- -Process name. -Sometimes called program name or similar. - -type: keyword - -example: ssh - --- - -*`process.parent.name.text`*:: -+ --- -type: match_only_text - --- - -*`process.parent.pe.architecture`*:: -+ --- -CPU architecture target for the file. - -type: keyword - -example: x64 - --- - -*`process.parent.pe.company`*:: -+ --- -Internal company name of the file, provided at compile-time. - -type: keyword - -example: Microsoft Corporation - --- - -*`process.parent.pe.description`*:: -+ --- -Internal description of the file, provided at compile-time. - -type: keyword - -example: Paint - --- - -*`process.parent.pe.file_version`*:: -+ --- -Internal version of the file, provided at compile-time. - -type: keyword - -example: 6.3.9600.17415 - --- - -*`process.parent.pe.imphash`*:: -+ --- -A hash of the imports in a PE file. An imphash -- or import hash -- can be used to fingerprint binaries even after recompilation or other code-level transformations have occurred, which would change more traditional hash values. -Learn more at https://www.fireeye.com/blog/threat-research/2014/01/tracking-malware-import-hashing.html. - -type: keyword - -example: 0c6803c4e922103c4dca5963aad36ddf - --- - -*`process.parent.pe.original_file_name`*:: -+ --- -Internal name of the file, provided at compile-time. - -type: keyword - -example: MSPAINT.EXE - --- - -*`process.parent.pe.product`*:: -+ --- -Internal product name of the file, provided at compile-time. - -type: keyword - -example: Microsoft® Windows® Operating System - --- - -*`process.parent.pgid`*:: -+ --- -Identifier of the group of processes the process belongs to. - -type: long - -format: string - --- - -*`process.parent.pid`*:: -+ --- -Process id. - -type: long - -example: 4242 - -format: string - --- - -*`process.parent.start`*:: -+ --- -The time the process started. - -type: date - -example: 2016-05-23T08:05:34.853Z - --- - -*`process.parent.thread.id`*:: -+ --- -Thread ID. - -type: long - -example: 4242 - -format: string - --- - -*`process.parent.thread.name`*:: -+ --- -Thread name. - -type: keyword - -example: thread-0 - --- - -*`process.parent.title`*:: -+ --- -Process title. -The proctitle, some times the same as process name. Can also be different: for example a browser setting its title to the web page currently opened. - -type: keyword - --- - -*`process.parent.title.text`*:: -+ --- -type: match_only_text - --- - -*`process.parent.uptime`*:: -+ --- -Seconds the process has been up. - -type: long - -example: 1325 - --- - -*`process.parent.working_directory`*:: -+ --- -The working directory of the process. - -type: keyword - -example: /home/alice - --- - -*`process.parent.working_directory.text`*:: -+ --- -type: match_only_text - --- - -*`process.pe.architecture`*:: -+ --- -CPU architecture target for the file. - -type: keyword - -example: x64 - --- - -*`process.pe.company`*:: -+ --- -Internal company name of the file, provided at compile-time. - -type: keyword - -example: Microsoft Corporation - --- - -*`process.pe.description`*:: -+ --- -Internal description of the file, provided at compile-time. - -type: keyword - -example: Paint - --- - -*`process.pe.file_version`*:: -+ --- -Internal version of the file, provided at compile-time. - -type: keyword - -example: 6.3.9600.17415 - --- - -*`process.pe.imphash`*:: -+ --- -A hash of the imports in a PE file. An imphash -- or import hash -- can be used to fingerprint binaries even after recompilation or other code-level transformations have occurred, which would change more traditional hash values. -Learn more at https://www.fireeye.com/blog/threat-research/2014/01/tracking-malware-import-hashing.html. - -type: keyword - -example: 0c6803c4e922103c4dca5963aad36ddf - --- - -*`process.pe.original_file_name`*:: -+ --- -Internal name of the file, provided at compile-time. - -type: keyword - -example: MSPAINT.EXE - --- - -*`process.pe.product`*:: -+ --- -Internal product name of the file, provided at compile-time. - -type: keyword - -example: Microsoft® Windows® Operating System - --- - -*`process.pgid`*:: -+ --- -Identifier of the group of processes the process belongs to. - -type: long - -format: string - --- - -*`process.pid`*:: -+ --- -Process id. - -type: long - -example: 4242 - -format: string - --- - -*`process.start`*:: -+ --- -The time the process started. - -type: date - -example: 2016-05-23T08:05:34.853Z - --- - -*`process.thread.id`*:: -+ --- -Thread ID. - -type: long - -example: 4242 - -format: string - --- - -*`process.thread.name`*:: -+ --- -Thread name. - -type: keyword - -example: thread-0 - --- - -*`process.title`*:: -+ --- -Process title. -The proctitle, some times the same as process name. Can also be different: for example a browser setting its title to the web page currently opened. - -type: keyword - --- - -*`process.title.text`*:: -+ --- -type: match_only_text - --- - -*`process.uptime`*:: -+ --- -Seconds the process has been up. - -type: long - -example: 1325 - --- - -*`process.working_directory`*:: -+ --- -The working directory of the process. - -type: keyword - -example: /home/alice - --- - -*`process.working_directory.text`*:: -+ --- -type: match_only_text - --- - -[float] -=== registry - -Fields related to Windows Registry operations. - - -*`registry.data.bytes`*:: -+ --- -Original bytes written with base64 encoding. -For Windows registry operations, such as SetValueEx and RegQueryValueEx, this corresponds to the data pointed by `lp_data`. This is optional but provides better recoverability and should be populated for REG_BINARY encoded values. - -type: keyword - -example: ZQBuAC0AVQBTAAAAZQBuAAAAAAA= - --- - -*`registry.data.strings`*:: -+ --- -Content when writing string types. -Populated as an array when writing string data to the registry. For single string registry types (REG_SZ, REG_EXPAND_SZ), this should be an array with one string. For sequences of string with REG_MULTI_SZ, this array will be variable length. For numeric data, such as REG_DWORD and REG_QWORD, this should be populated with the decimal representation (e.g `"1"`). - -type: wildcard - -example: ["C:\rta\red_ttp\bin\myapp.exe"] - --- - -*`registry.data.type`*:: -+ --- -Standard registry type for encoding contents - -type: keyword - -example: REG_SZ - --- - -*`registry.hive`*:: -+ --- -Abbreviated name for the hive. - -type: keyword - -example: HKLM - --- - -*`registry.key`*:: -+ --- -Hive-relative path of keys. - -type: keyword - -example: SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\winword.exe - --- - -*`registry.path`*:: -+ --- -Full path, including hive, key and value - -type: keyword - -example: HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\winword.exe\Debugger - --- - -*`registry.value`*:: -+ --- -Name of the value written. - -type: keyword - -example: Debugger - --- - -[float] -=== related - -This field set is meant to facilitate pivoting around a piece of data. -Some pieces of information can be seen in many places in an ECS event. To facilitate searching for them, store an array of all seen values to their corresponding field in `related.`. -A concrete example is IP addresses, which can be under host, observer, source, destination, client, server, and network.forwarded_ip. If you append all IPs to `related.ip`, you can then search for a given IP trivially, no matter where it appeared, by querying `related.ip:192.0.2.15`. - - -*`related.hash`*:: -+ --- -All the hashes seen on your event. Populating this field, then using it to search for hashes can help in situations where you're unsure what the hash algorithm is (and therefore which key name to search). - -type: keyword - --- - -*`related.hosts`*:: -+ --- -All hostnames or other host identifiers seen on your event. Example identifiers include FQDNs, domain names, workstation names, or aliases. - -type: keyword - --- - -*`related.ip`*:: -+ --- -All of the IPs seen on your event. - -type: ip - --- - -*`related.user`*:: -+ --- -All the user names or other user identifiers seen on the event. - -type: keyword - --- - -[float] -=== rule - -Rule fields are used to capture the specifics of any observer or agent rules that generate alerts or other notable events. -Examples of data sources that would populate the rule fields include: network admission control platforms, network or host IDS/IPS, network firewalls, web application firewalls, url filters, endpoint detection and response (EDR) systems, etc. - - -*`rule.author`*:: -+ --- -Name, organization, or pseudonym of the author or authors who created the rule used to generate this event. - -type: keyword - -example: ["Star-Lord"] - --- - -*`rule.category`*:: -+ --- -A categorization value keyword used by the entity using the rule for detection of this event. - -type: keyword - -example: Attempted Information Leak - --- - -*`rule.description`*:: -+ --- -The description of the rule generating the event. - -type: keyword - -example: Block requests to public DNS over HTTPS / TLS protocols - --- - -*`rule.id`*:: -+ --- -A rule ID that is unique within the scope of an agent, observer, or other entity using the rule for detection of this event. - -type: keyword - -example: 101 - --- - -*`rule.license`*:: -+ --- -Name of the license under which the rule used to generate this event is made available. - -type: keyword - -example: Apache 2.0 - --- - -*`rule.name`*:: -+ --- -The name of the rule or signature generating the event. - -type: keyword - -example: BLOCK_DNS_over_TLS - --- - -*`rule.reference`*:: -+ --- -Reference URL to additional information about the rule used to generate this event. -The URL can point to the vendor's documentation about the rule. If that's not available, it can also be a link to a more general page describing this type of alert. - -type: keyword - -example: https://en.wikipedia.org/wiki/DNS_over_TLS - --- - -*`rule.ruleset`*:: -+ --- -Name of the ruleset, policy, group, or parent category in which the rule used to generate this event is a member. - -type: keyword - -example: Standard_Protocol_Filters - --- - -*`rule.uuid`*:: -+ --- -A rule ID that is unique within the scope of a set or group of agents, observers, or other entities using the rule for detection of this event. - -type: keyword - -example: 1100110011 - --- - -*`rule.version`*:: -+ --- -The version / revision of the rule being used for analysis. - -type: keyword - -example: 1.1 - --- - -[float] -=== server - -A Server is defined as the responder in a network connection for events regarding sessions, connections, or bidirectional flow records. -For TCP events, the server is the receiver of the initial SYN packet(s) of the TCP connection. For other protocols, the server is generally the responder in the network transaction. Some systems actually use the term "responder" to refer the server in TCP connections. The server fields describe details about the system acting as the server in the network event. Server fields are usually populated in conjunction with client fields. Server fields are generally not populated for packet-level events. -Client / server representations can add semantic context to an exchange, which is helpful to visualize the data in certain situations. If your context falls in that category, you should still ensure that source and destination are filled appropriately. - - -*`server.address`*:: -+ --- -Some event server addresses are defined ambiguously. The event will sometimes list an IP, a domain or a unix socket. You should always store the raw address in the `.address` field. -Then it should be duplicated to `.ip` or `.domain`, depending on which one it is. - -type: keyword - --- - -*`server.as.number`*:: -+ --- -Unique number allocated to the autonomous system. The autonomous system number (ASN) uniquely identifies each network on the Internet. - -type: long - -example: 15169 - --- - -*`server.as.organization.name`*:: -+ --- -Organization name. - -type: keyword - -example: Google LLC - --- - -*`server.as.organization.name.text`*:: -+ --- -type: match_only_text - --- - -*`server.bytes`*:: -+ --- -Bytes sent from the server to the client. - -type: long - -example: 184 - -format: bytes - --- - -*`server.domain`*:: -+ --- -Server domain. - -type: keyword - --- - -*`server.geo.city_name`*:: -+ --- -City name. - -type: keyword - -example: Montreal - --- - -*`server.geo.continent_code`*:: -+ --- -Two-letter code representing continent's name. - -type: keyword - -example: NA - --- - -*`server.geo.continent_name`*:: -+ --- -Name of the continent. - -type: keyword - -example: North America - --- - -*`server.geo.country_iso_code`*:: -+ --- -Country ISO code. - -type: keyword - -example: CA - --- - -*`server.geo.country_name`*:: -+ --- -Country name. - -type: keyword - -example: Canada - --- - -*`server.geo.location`*:: -+ --- -Longitude and latitude. - -type: geo_point - -example: { "lon": -73.614830, "lat": 45.505918 } - --- - -*`server.geo.name`*:: -+ --- -User-defined description of a location, at the level of granularity they care about. -Could be the name of their data centers, the floor number, if this describes a local physical entity, city names. -Not typically used in automated geolocation. - -type: keyword - -example: boston-dc - --- - -*`server.geo.postal_code`*:: -+ --- -Postal code associated with the location. -Values appropriate for this field may also be known as a postcode or ZIP code and will vary widely from country to country. - -type: keyword - -example: 94040 - --- - -*`server.geo.region_iso_code`*:: -+ --- -Region ISO code. - -type: keyword - -example: CA-QC - --- - -*`server.geo.region_name`*:: -+ --- -Region name. - -type: keyword - -example: Quebec - --- - -*`server.geo.timezone`*:: -+ --- -The time zone of the location, such as IANA time zone name. - -type: keyword - -example: America/Argentina/Buenos_Aires - --- - -*`server.ip`*:: -+ --- -IP address of the server (IPv4 or IPv6). - -type: ip - --- - -*`server.mac`*:: -+ --- -MAC address of the server. -The notation format from RFC 7042 is suggested: Each octet (that is, 8-bit byte) is represented by two [uppercase] hexadecimal digits giving the value of the octet as an unsigned integer. Successive octets are separated by a hyphen. - -type: keyword - -example: 00-00-5E-00-53-23 - --- - -*`server.nat.ip`*:: -+ --- -Translated ip of destination based NAT sessions (e.g. internet to private DMZ) -Typically used with load balancers, firewalls, or routers. - -type: ip - --- - -*`server.nat.port`*:: -+ --- -Translated port of destination based NAT sessions (e.g. internet to private DMZ) -Typically used with load balancers, firewalls, or routers. - -type: long - -format: string - --- - -*`server.packets`*:: -+ --- -Packets sent from the server to the client. - -type: long - -example: 12 - --- - -*`server.port`*:: -+ --- -Port of the server. - -type: long - -format: string - --- - -*`server.registered_domain`*:: -+ --- -The highest registered server domain, stripped of the subdomain. -For example, the registered domain for "foo.example.com" is "example.com". -This value can be determined precisely with a list like the public suffix list (http://publicsuffix.org). Trying to approximate this by simply taking the last two labels will not work well for TLDs such as "co.uk". - -type: keyword - -example: example.com - --- - -*`server.subdomain`*:: -+ --- -The subdomain portion of a fully qualified domain name includes all of the names except the host name under the registered_domain. In a partially qualified domain, or if the the qualification level of the full name cannot be determined, subdomain contains all of the names below the registered domain. -For example the subdomain portion of "www.east.mydomain.co.uk" is "east". If the domain has multiple levels of subdomain, such as "sub2.sub1.example.com", the subdomain field should contain "sub2.sub1", with no trailing period. - -type: keyword - -example: east - --- - -*`server.top_level_domain`*:: -+ --- -The effective top level domain (eTLD), also known as the domain suffix, is the last part of the domain name. For example, the top level domain for example.com is "com". -This value can be determined precisely with a list like the public suffix list (http://publicsuffix.org). Trying to approximate this by simply taking the last label will not work well for effective TLDs such as "co.uk". - -type: keyword - -example: co.uk - --- - -*`server.user.domain`*:: -+ --- -Name of the directory the user is a member of. -For example, an LDAP or Active Directory domain name. - -type: keyword - --- - -*`server.user.email`*:: -+ --- -User email address. - -type: keyword - --- - -*`server.user.full_name`*:: -+ --- -User's full name, if available. - -type: keyword - -example: Albert Einstein - --- - -*`server.user.full_name.text`*:: -+ --- -type: match_only_text - --- - -*`server.user.group.domain`*:: -+ --- -Name of the directory the group is a member of. -For example, an LDAP or Active Directory domain name. - -type: keyword - --- - -*`server.user.group.id`*:: -+ --- -Unique identifier for the group on the system/platform. - -type: keyword - --- - -*`server.user.group.name`*:: -+ --- -Name of the group. - -type: keyword - --- - -*`server.user.hash`*:: -+ --- -Unique user hash to correlate information for a user in anonymized form. -Useful if `user.id` or `user.name` contain confidential information and cannot be used. - -type: keyword - --- - -*`server.user.id`*:: -+ --- -Unique identifier of the user. - -type: keyword - -example: S-1-5-21-202424912787-2692429404-2351956786-1000 - --- - -*`server.user.name`*:: -+ --- -Short name or login of the user. - -type: keyword - -example: a.einstein - --- - -*`server.user.name.text`*:: -+ --- -type: match_only_text - --- - -*`server.user.roles`*:: -+ --- -Array of user roles at the time of the event. - -type: keyword - -example: ["kibana_admin", "reporting_user"] - --- - -[float] -=== service - -The service fields describe the service for or from which the data was collected. -These fields help you find and correlate logs for a specific service and version. - - -*`service.address`*:: -+ --- -Address where data about this service was collected from. -This should be a URI, network address (ipv4:port or [ipv6]:port) or a resource path (sockets). - -type: keyword - -example: 172.26.0.2:5432 - --- - -*`service.environment`*:: -+ --- -Identifies the environment where the service is running. -If the same service runs in different environments (production, staging, QA, development, etc.), the environment can identify other instances of the same service. Can also group services and applications from the same environment. - -type: keyword - -example: production - --- - -*`service.ephemeral_id`*:: -+ --- -Ephemeral identifier of this service (if one exists). -This id normally changes across restarts, but `service.id` does not. - -type: keyword - -example: 8a4f500f - --- - -*`service.id`*:: -+ --- -Unique identifier of the running service. If the service is comprised of many nodes, the `service.id` should be the same for all nodes. -This id should uniquely identify the service. This makes it possible to correlate logs and metrics for one specific service, no matter which particular node emitted the event. -Note that if you need to see the events from one specific host of the service, you should filter on that `host.name` or `host.id` instead. - -type: keyword - -example: d37e5ebfe0ae6c4972dbe9f0174a1637bb8247f6 - --- - -*`service.name`*:: -+ --- -Name of the service data is collected from. -The name of the service is normally user given. This allows for distributed services that run on multiple hosts to correlate the related instances based on the name. -In the case of Elasticsearch the `service.name` could contain the cluster name. For Beats the `service.name` is by default a copy of the `service.type` field if no name is specified. - -type: keyword - -example: elasticsearch-metrics - --- - -*`service.node.name`*:: -+ --- -Name of a service node. -This allows for two nodes of the same service running on the same host to be differentiated. Therefore, `service.node.name` should typically be unique across nodes of a given service. -In the case of Elasticsearch, the `service.node.name` could contain the unique node name within the Elasticsearch cluster. In cases where the service doesn't have the concept of a node name, the host name or container name can be used to distinguish running instances that make up this service. If those do not provide uniqueness (e.g. multiple instances of the service running on the same host) - the node name can be manually set. - -type: keyword - -example: instance-0000000016 - --- - -*`service.origin.address`*:: -+ --- -Address where data about this service was collected from. -This should be a URI, network address (ipv4:port or [ipv6]:port) or a resource path (sockets). - -type: keyword - -example: 172.26.0.2:5432 - --- - -*`service.origin.environment`*:: -+ --- -Identifies the environment where the service is running. -If the same service runs in different environments (production, staging, QA, development, etc.), the environment can identify other instances of the same service. Can also group services and applications from the same environment. - -type: keyword - -example: production - --- - -*`service.origin.ephemeral_id`*:: -+ --- -Ephemeral identifier of this service (if one exists). -This id normally changes across restarts, but `service.id` does not. - -type: keyword - -example: 8a4f500f - --- - -*`service.origin.id`*:: -+ --- -Unique identifier of the running service. If the service is comprised of many nodes, the `service.id` should be the same for all nodes. -This id should uniquely identify the service. This makes it possible to correlate logs and metrics for one specific service, no matter which particular node emitted the event. -Note that if you need to see the events from one specific host of the service, you should filter on that `host.name` or `host.id` instead. - -type: keyword - -example: d37e5ebfe0ae6c4972dbe9f0174a1637bb8247f6 - --- - -*`service.origin.name`*:: -+ --- -Name of the service data is collected from. -The name of the service is normally user given. This allows for distributed services that run on multiple hosts to correlate the related instances based on the name. -In the case of Elasticsearch the `service.name` could contain the cluster name. For Beats the `service.name` is by default a copy of the `service.type` field if no name is specified. - -type: keyword - -example: elasticsearch-metrics - --- - -*`service.origin.node.name`*:: -+ --- -Name of a service node. -This allows for two nodes of the same service running on the same host to be differentiated. Therefore, `service.node.name` should typically be unique across nodes of a given service. -In the case of Elasticsearch, the `service.node.name` could contain the unique node name within the Elasticsearch cluster. In cases where the service doesn't have the concept of a node name, the host name or container name can be used to distinguish running instances that make up this service. If those do not provide uniqueness (e.g. multiple instances of the service running on the same host) - the node name can be manually set. - -type: keyword - -example: instance-0000000016 - --- - -*`service.origin.state`*:: -+ --- -Current state of the service. - -type: keyword - --- - -*`service.origin.type`*:: -+ --- -The type of the service data is collected from. -The type can be used to group and correlate logs and metrics from one service type. -Example: If logs or metrics are collected from Elasticsearch, `service.type` would be `elasticsearch`. - -type: keyword - -example: elasticsearch - --- - -*`service.origin.version`*:: -+ --- -Version of the service the data was collected from. -This allows to look at a data set only for a specific version of a service. - -type: keyword - -example: 3.2.4 - --- - -*`service.state`*:: -+ --- -Current state of the service. - -type: keyword - --- - -*`service.target.address`*:: -+ --- -Address where data about this service was collected from. -This should be a URI, network address (ipv4:port or [ipv6]:port) or a resource path (sockets). - -type: keyword - -example: 172.26.0.2:5432 - --- - -*`service.target.environment`*:: -+ --- -Identifies the environment where the service is running. -If the same service runs in different environments (production, staging, QA, development, etc.), the environment can identify other instances of the same service. Can also group services and applications from the same environment. - -type: keyword - -example: production - --- - -*`service.target.ephemeral_id`*:: -+ --- -Ephemeral identifier of this service (if one exists). -This id normally changes across restarts, but `service.id` does not. - -type: keyword - -example: 8a4f500f - --- - -*`service.target.id`*:: -+ --- -Unique identifier of the running service. If the service is comprised of many nodes, the `service.id` should be the same for all nodes. -This id should uniquely identify the service. This makes it possible to correlate logs and metrics for one specific service, no matter which particular node emitted the event. -Note that if you need to see the events from one specific host of the service, you should filter on that `host.name` or `host.id` instead. - -type: keyword - -example: d37e5ebfe0ae6c4972dbe9f0174a1637bb8247f6 - --- - -*`service.target.name`*:: -+ --- -Name of the service data is collected from. -The name of the service is normally user given. This allows for distributed services that run on multiple hosts to correlate the related instances based on the name. -In the case of Elasticsearch the `service.name` could contain the cluster name. For Beats the `service.name` is by default a copy of the `service.type` field if no name is specified. - -type: keyword - -example: elasticsearch-metrics - --- - -*`service.target.node.name`*:: -+ --- -Name of a service node. -This allows for two nodes of the same service running on the same host to be differentiated. Therefore, `service.node.name` should typically be unique across nodes of a given service. -In the case of Elasticsearch, the `service.node.name` could contain the unique node name within the Elasticsearch cluster. In cases where the service doesn't have the concept of a node name, the host name or container name can be used to distinguish running instances that make up this service. If those do not provide uniqueness (e.g. multiple instances of the service running on the same host) - the node name can be manually set. - -type: keyword - -example: instance-0000000016 - --- - -*`service.target.state`*:: -+ --- -Current state of the service. - -type: keyword - --- - -*`service.target.type`*:: -+ --- -The type of the service data is collected from. -The type can be used to group and correlate logs and metrics from one service type. -Example: If logs or metrics are collected from Elasticsearch, `service.type` would be `elasticsearch`. - -type: keyword - -example: elasticsearch - --- - -*`service.target.version`*:: -+ --- -Version of the service the data was collected from. -This allows to look at a data set only for a specific version of a service. - -type: keyword - -example: 3.2.4 - --- - -*`service.type`*:: -+ --- -The type of the service data is collected from. -The type can be used to group and correlate logs and metrics from one service type. -Example: If logs or metrics are collected from Elasticsearch, `service.type` would be `elasticsearch`. - -type: keyword - -example: elasticsearch - --- - -*`service.version`*:: -+ --- -Version of the service the data was collected from. -This allows to look at a data set only for a specific version of a service. - -type: keyword - -example: 3.2.4 - --- - -[float] -=== source - -Source fields capture details about the sender of a network exchange/packet. These fields are populated from a network event, packet, or other event containing details of a network transaction. -Source fields are usually populated in conjunction with destination fields. The source and destination fields are considered the baseline and should always be filled if an event contains source and destination details from a network transaction. If the event also contains identification of the client and server roles, then the client and server fields should also be populated. - - -*`source.address`*:: -+ --- -Some event source addresses are defined ambiguously. The event will sometimes list an IP, a domain or a unix socket. You should always store the raw address in the `.address` field. -Then it should be duplicated to `.ip` or `.domain`, depending on which one it is. - -type: keyword - --- - -*`source.as.number`*:: -+ --- -Unique number allocated to the autonomous system. The autonomous system number (ASN) uniquely identifies each network on the Internet. - -type: long - -example: 15169 - --- - -*`source.as.organization.name`*:: -+ --- -Organization name. - -type: keyword - -example: Google LLC - --- - -*`source.as.organization.name.text`*:: -+ --- -type: match_only_text - --- - -*`source.bytes`*:: -+ --- -Bytes sent from the source to the destination. - -type: long - -example: 184 - -format: bytes - --- - -*`source.domain`*:: -+ --- -Source domain. - -type: keyword - --- - -*`source.geo.city_name`*:: -+ --- -City name. - -type: keyword - -example: Montreal - --- - -*`source.geo.continent_code`*:: -+ --- -Two-letter code representing continent's name. - -type: keyword - -example: NA - --- - -*`source.geo.continent_name`*:: -+ --- -Name of the continent. - -type: keyword - -example: North America - --- - -*`source.geo.country_iso_code`*:: -+ --- -Country ISO code. - -type: keyword - -example: CA - --- - -*`source.geo.country_name`*:: -+ --- -Country name. - -type: keyword - -example: Canada - --- - -*`source.geo.location`*:: -+ --- -Longitude and latitude. - -type: geo_point - -example: { "lon": -73.614830, "lat": 45.505918 } - --- - -*`source.geo.name`*:: -+ --- -User-defined description of a location, at the level of granularity they care about. -Could be the name of their data centers, the floor number, if this describes a local physical entity, city names. -Not typically used in automated geolocation. - -type: keyword - -example: boston-dc - --- - -*`source.geo.postal_code`*:: -+ --- -Postal code associated with the location. -Values appropriate for this field may also be known as a postcode or ZIP code and will vary widely from country to country. - -type: keyword - -example: 94040 - --- - -*`source.geo.region_iso_code`*:: -+ --- -Region ISO code. - -type: keyword - -example: CA-QC - --- - -*`source.geo.region_name`*:: -+ --- -Region name. - -type: keyword - -example: Quebec - --- - -*`source.geo.timezone`*:: -+ --- -The time zone of the location, such as IANA time zone name. - -type: keyword - -example: America/Argentina/Buenos_Aires - --- - -*`source.ip`*:: -+ --- -IP address of the source (IPv4 or IPv6). - -type: ip - --- - -*`source.mac`*:: -+ --- -MAC address of the source. -The notation format from RFC 7042 is suggested: Each octet (that is, 8-bit byte) is represented by two [uppercase] hexadecimal digits giving the value of the octet as an unsigned integer. Successive octets are separated by a hyphen. - -type: keyword - -example: 00-00-5E-00-53-23 - --- - -*`source.nat.ip`*:: -+ --- -Translated ip of source based NAT sessions (e.g. internal client to internet) -Typically connections traversing load balancers, firewalls, or routers. - -type: ip - --- - -*`source.nat.port`*:: -+ --- -Translated port of source based NAT sessions. (e.g. internal client to internet) -Typically used with load balancers, firewalls, or routers. - -type: long - -format: string - --- - -*`source.packets`*:: -+ --- -Packets sent from the source to the destination. - -type: long - -example: 12 - --- - -*`source.port`*:: -+ --- -Port of the source. - -type: long - -format: string - --- - -*`source.registered_domain`*:: -+ --- -The highest registered source domain, stripped of the subdomain. -For example, the registered domain for "foo.example.com" is "example.com". -This value can be determined precisely with a list like the public suffix list (http://publicsuffix.org). Trying to approximate this by simply taking the last two labels will not work well for TLDs such as "co.uk". - -type: keyword - -example: example.com - --- - -*`source.subdomain`*:: -+ --- -The subdomain portion of a fully qualified domain name includes all of the names except the host name under the registered_domain. In a partially qualified domain, or if the the qualification level of the full name cannot be determined, subdomain contains all of the names below the registered domain. -For example the subdomain portion of "www.east.mydomain.co.uk" is "east". If the domain has multiple levels of subdomain, such as "sub2.sub1.example.com", the subdomain field should contain "sub2.sub1", with no trailing period. - -type: keyword - -example: east - --- - -*`source.top_level_domain`*:: -+ --- -The effective top level domain (eTLD), also known as the domain suffix, is the last part of the domain name. For example, the top level domain for example.com is "com". -This value can be determined precisely with a list like the public suffix list (http://publicsuffix.org). Trying to approximate this by simply taking the last label will not work well for effective TLDs such as "co.uk". - -type: keyword - -example: co.uk - --- - -*`source.user.domain`*:: -+ --- -Name of the directory the user is a member of. -For example, an LDAP or Active Directory domain name. - -type: keyword - --- - -*`source.user.email`*:: -+ --- -User email address. - -type: keyword - --- - -*`source.user.full_name`*:: -+ --- -User's full name, if available. - -type: keyword - -example: Albert Einstein - --- - -*`source.user.full_name.text`*:: -+ --- -type: match_only_text - --- - -*`source.user.group.domain`*:: -+ --- -Name of the directory the group is a member of. -For example, an LDAP or Active Directory domain name. - -type: keyword - --- - -*`source.user.group.id`*:: -+ --- -Unique identifier for the group on the system/platform. - -type: keyword - --- - -*`source.user.group.name`*:: -+ --- -Name of the group. - -type: keyword - --- - -*`source.user.hash`*:: -+ --- -Unique user hash to correlate information for a user in anonymized form. -Useful if `user.id` or `user.name` contain confidential information and cannot be used. - -type: keyword - --- - -*`source.user.id`*:: -+ --- -Unique identifier of the user. - -type: keyword - -example: S-1-5-21-202424912787-2692429404-2351956786-1000 - --- - -*`source.user.name`*:: -+ --- -Short name or login of the user. - -type: keyword - -example: a.einstein - --- - -*`source.user.name.text`*:: -+ --- -type: match_only_text - --- - -*`source.user.roles`*:: -+ --- -Array of user roles at the time of the event. - -type: keyword - -example: ["kibana_admin", "reporting_user"] - --- - -[float] -=== threat - -Fields to classify events and alerts according to a threat taxonomy such as the MITRE ATT&CK® framework. -These fields are for users to classify alerts from all of their sources (e.g. IDS, NGFW, etc.) within a common taxonomy. The threat.tactic.* fields are meant to capture the high level category of the threat (e.g. "impact"). The threat.technique.* fields are meant to capture which kind of approach is used by this detected threat, to accomplish the goal (e.g. "endpoint denial of service"). - - -*`threat.enrichments`*:: -+ --- -A list of associated indicators objects enriching the event, and the context of that association/enrichment. - -type: nested - --- - -*`threat.enrichments.indicator`*:: -+ --- -Object containing associated indicators enriching the event. - -type: object - --- - -*`threat.enrichments.indicator.as.number`*:: -+ --- -Unique number allocated to the autonomous system. The autonomous system number (ASN) uniquely identifies each network on the Internet. - -type: long - -example: 15169 - --- - -*`threat.enrichments.indicator.as.organization.name`*:: -+ --- -Organization name. - -type: keyword - -example: Google LLC - --- - -*`threat.enrichments.indicator.as.organization.name.text`*:: -+ --- -type: match_only_text - --- - -*`threat.enrichments.indicator.confidence`*:: -+ --- -Identifies the vendor-neutral confidence rating using the None/Low/Medium/High scale defined in Appendix A of the STIX 2.1 framework. Vendor-specific confidence scales may be added as custom fields. -Expected values are: - * Not Specified - * None - * Low - * Medium - * High - -type: keyword - -example: Medium - --- - -*`threat.enrichments.indicator.description`*:: -+ --- -Describes the type of action conducted by the threat. - -type: keyword - -example: IP x.x.x.x was observed delivering the Angler EK. - --- - -*`threat.enrichments.indicator.email.address`*:: -+ --- -Identifies a threat indicator as an email address (irrespective of direction). - -type: keyword - -example: phish@example.com - --- - -*`threat.enrichments.indicator.file.accessed`*:: -+ --- -Last time the file was accessed. -Note that not all filesystems keep track of access time. - -type: date - --- - -*`threat.enrichments.indicator.file.attributes`*:: -+ --- -Array of file attributes. -Attributes names will vary by platform. Here's a non-exhaustive list of values that are expected in this field: archive, compressed, directory, encrypted, execute, hidden, read, readonly, system, write. - -type: keyword - -example: ["readonly", "system"] - --- - -*`threat.enrichments.indicator.file.code_signature.digest_algorithm`*:: -+ --- -The hashing algorithm used to sign the process. -This value can distinguish signatures when a file is signed multiple times by the same signer but with a different digest algorithm. - -type: keyword - -example: sha256 - --- - -*`threat.enrichments.indicator.file.code_signature.exists`*:: -+ --- -Boolean to capture if a signature is present. - -type: boolean - -example: true - --- - -*`threat.enrichments.indicator.file.code_signature.signing_id`*:: -+ --- -The identifier used to sign the process. -This is used to identify the application manufactured by a software vendor. The field is relevant to Apple *OS only. - -type: keyword - -example: com.apple.xpc.proxy - --- - -*`threat.enrichments.indicator.file.code_signature.status`*:: -+ --- -Additional information about the certificate status. -This is useful for logging cryptographic errors with the certificate validity or trust status. Leave unpopulated if the validity or trust of the certificate was unchecked. - -type: keyword - -example: ERROR_UNTRUSTED_ROOT - --- - -*`threat.enrichments.indicator.file.code_signature.subject_name`*:: -+ --- -Subject name of the code signer - -type: keyword - -example: Microsoft Corporation - --- - -*`threat.enrichments.indicator.file.code_signature.team_id`*:: -+ --- -The team identifier used to sign the process. -This is used to identify the team or vendor of a software product. The field is relevant to Apple *OS only. - -type: keyword - -example: EQHXZ8M8AV - --- - -*`threat.enrichments.indicator.file.code_signature.timestamp`*:: -+ --- -Date and time when the code signature was generated and signed. - -type: date - -example: 2021-01-01T12:10:30Z - --- - -*`threat.enrichments.indicator.file.code_signature.trusted`*:: -+ --- -Stores the trust status of the certificate chain. -Validating the trust of the certificate chain may be complicated, and this field should only be populated by tools that actively check the status. - -type: boolean - -example: true - --- - -*`threat.enrichments.indicator.file.code_signature.valid`*:: -+ --- -Boolean to capture if the digital signature is verified against the binary content. -Leave unpopulated if a certificate was unchecked. - -type: boolean - -example: true - --- - -*`threat.enrichments.indicator.file.created`*:: -+ --- -File creation time. -Note that not all filesystems store the creation time. - -type: date - --- - -*`threat.enrichments.indicator.file.ctime`*:: -+ --- -Last time the file attributes or metadata changed. -Note that changes to the file content will update `mtime`. This implies `ctime` will be adjusted at the same time, since `mtime` is an attribute of the file. - -type: date - --- - -*`threat.enrichments.indicator.file.device`*:: -+ --- -Device that is the source of the file. - -type: keyword - -example: sda - --- - -*`threat.enrichments.indicator.file.directory`*:: -+ --- -Directory where the file is located. It should include the drive letter, when appropriate. - -type: keyword - -example: /home/alice - --- - -*`threat.enrichments.indicator.file.drive_letter`*:: -+ --- -Drive letter where the file is located. This field is only relevant on Windows. -The value should be uppercase, and not include the colon. - -type: keyword - -example: C - --- - -*`threat.enrichments.indicator.file.elf.architecture`*:: -+ --- -Machine architecture of the ELF file. - -type: keyword - -example: x86-64 - --- - -*`threat.enrichments.indicator.file.elf.byte_order`*:: -+ --- -Byte sequence of ELF file. - -type: keyword - -example: Little Endian - --- - -*`threat.enrichments.indicator.file.elf.cpu_type`*:: -+ --- -CPU type of the ELF file. - -type: keyword - -example: Intel - --- - -*`threat.enrichments.indicator.file.elf.creation_date`*:: -+ --- -Extracted when possible from the file's metadata. Indicates when it was built or compiled. It can also be faked by malware creators. - -type: date - --- - -*`threat.enrichments.indicator.file.elf.exports`*:: -+ --- -List of exported element names and types. - -type: flattened - --- - -*`threat.enrichments.indicator.file.elf.header.abi_version`*:: -+ --- -Version of the ELF Application Binary Interface (ABI). - -type: keyword - --- - -*`threat.enrichments.indicator.file.elf.header.class`*:: -+ --- -Header class of the ELF file. - -type: keyword - --- - -*`threat.enrichments.indicator.file.elf.header.data`*:: -+ --- -Data table of the ELF header. - -type: keyword - --- - -*`threat.enrichments.indicator.file.elf.header.entrypoint`*:: -+ --- -Header entrypoint of the ELF file. - -type: long - -format: string - --- - -*`threat.enrichments.indicator.file.elf.header.object_version`*:: -+ --- -"0x1" for original ELF files. - -type: keyword - --- - -*`threat.enrichments.indicator.file.elf.header.os_abi`*:: -+ --- -Application Binary Interface (ABI) of the Linux OS. - -type: keyword - --- - -*`threat.enrichments.indicator.file.elf.header.type`*:: -+ --- -Header type of the ELF file. - -type: keyword - --- - -*`threat.enrichments.indicator.file.elf.header.version`*:: -+ --- -Version of the ELF header. - -type: keyword - --- - -*`threat.enrichments.indicator.file.elf.imports`*:: -+ --- -List of imported element names and types. - -type: flattened - --- - -*`threat.enrichments.indicator.file.elf.sections`*:: -+ --- -An array containing an object for each section of the ELF file. -The keys that should be present in these objects are defined by sub-fields underneath `elf.sections.*`. - -type: nested - --- - -*`threat.enrichments.indicator.file.elf.sections.chi2`*:: -+ --- -Chi-square probability distribution of the section. - -type: long - -format: number - --- - -*`threat.enrichments.indicator.file.elf.sections.entropy`*:: -+ --- -Shannon entropy calculation from the section. - -type: long - -format: number - --- - -*`threat.enrichments.indicator.file.elf.sections.flags`*:: -+ --- -ELF Section List flags. - -type: keyword - --- - -*`threat.enrichments.indicator.file.elf.sections.name`*:: -+ --- -ELF Section List name. - -type: keyword - --- - -*`threat.enrichments.indicator.file.elf.sections.physical_offset`*:: -+ --- -ELF Section List offset. - -type: keyword - --- - -*`threat.enrichments.indicator.file.elf.sections.physical_size`*:: -+ --- -ELF Section List physical size. - -type: long - -format: bytes - --- - -*`threat.enrichments.indicator.file.elf.sections.type`*:: -+ --- -ELF Section List type. - -type: keyword - --- - -*`threat.enrichments.indicator.file.elf.sections.virtual_address`*:: -+ --- -ELF Section List virtual address. - -type: long - -format: string - --- - -*`threat.enrichments.indicator.file.elf.sections.virtual_size`*:: -+ --- -ELF Section List virtual size. - -type: long - -format: string - --- - -*`threat.enrichments.indicator.file.elf.segments`*:: -+ --- -An array containing an object for each segment of the ELF file. -The keys that should be present in these objects are defined by sub-fields underneath `elf.segments.*`. - -type: nested - --- - -*`threat.enrichments.indicator.file.elf.segments.sections`*:: -+ --- -ELF object segment sections. - -type: keyword - --- - -*`threat.enrichments.indicator.file.elf.segments.type`*:: -+ --- -ELF object segment type. - -type: keyword - --- - -*`threat.enrichments.indicator.file.elf.shared_libraries`*:: -+ --- -List of shared libraries used by this ELF object. - -type: keyword - --- - -*`threat.enrichments.indicator.file.elf.telfhash`*:: -+ --- -telfhash symbol hash for ELF file. - -type: keyword - --- - -*`threat.enrichments.indicator.file.extension`*:: -+ --- -File extension, excluding the leading dot. -Note that when the file name has multiple extensions (example.tar.gz), only the last one should be captured ("gz", not "tar.gz"). - -type: keyword - -example: png - --- - -*`threat.enrichments.indicator.file.fork_name`*:: -+ --- -A fork is additional data associated with a filesystem object. -On Linux, a resource fork is used to store additional data with a filesystem object. A file always has at least one fork for the data portion, and additional forks may exist. -On NTFS, this is analogous to an Alternate Data Stream (ADS), and the default data stream for a file is just called $DATA. Zone.Identifier is commonly used by Windows to track contents downloaded from the Internet. An ADS is typically of the form: `C:\path\to\filename.extension:some_fork_name`, and `some_fork_name` is the value that should populate `fork_name`. `filename.extension` should populate `file.name`, and `extension` should populate `file.extension`. The full path, `file.path`, will include the fork name. - -type: keyword - -example: Zone.Identifer - --- - -*`threat.enrichments.indicator.file.gid`*:: -+ --- -Primary group ID (GID) of the file. - -type: keyword - -example: 1001 - --- - -*`threat.enrichments.indicator.file.group`*:: -+ --- -Primary group name of the file. - -type: keyword - -example: alice - --- - -*`threat.enrichments.indicator.file.hash.md5`*:: -+ --- -MD5 hash. - -type: keyword - --- - -*`threat.enrichments.indicator.file.hash.sha1`*:: -+ --- -SHA1 hash. - -type: keyword - --- - -*`threat.enrichments.indicator.file.hash.sha256`*:: -+ --- -SHA256 hash. - -type: keyword - --- - -*`threat.enrichments.indicator.file.hash.sha512`*:: -+ --- -SHA512 hash. - -type: keyword - --- - -*`threat.enrichments.indicator.file.hash.ssdeep`*:: -+ --- -SSDEEP hash. - -type: keyword - --- - -*`threat.enrichments.indicator.file.inode`*:: -+ --- -Inode representing the file in the filesystem. - -type: keyword - -example: 256383 - --- - -*`threat.enrichments.indicator.file.mime_type`*:: -+ --- -MIME type should identify the format of the file or stream of bytes using https://www.iana.org/assignments/media-types/media-types.xhtml[IANA official types], where possible. When more than one type is applicable, the most specific type should be used. - -type: keyword - --- - -*`threat.enrichments.indicator.file.mode`*:: -+ --- -Mode of the file in octal representation. - -type: keyword - -example: 0640 - --- - -*`threat.enrichments.indicator.file.mtime`*:: -+ --- -Last time the file content was modified. - -type: date - --- - -*`threat.enrichments.indicator.file.name`*:: -+ --- -Name of the file including the extension, without the directory. - -type: keyword - -example: example.png - --- - -*`threat.enrichments.indicator.file.owner`*:: -+ --- -File owner's username. - -type: keyword - -example: alice - --- - -*`threat.enrichments.indicator.file.path`*:: -+ --- -Full path to the file, including the file name. It should include the drive letter, when appropriate. - -type: keyword - -example: /home/alice/example.png - --- - -*`threat.enrichments.indicator.file.path.text`*:: -+ --- -type: match_only_text - --- - -*`threat.enrichments.indicator.file.pe.architecture`*:: -+ --- -CPU architecture target for the file. - -type: keyword - -example: x64 - --- - -*`threat.enrichments.indicator.file.pe.company`*:: -+ --- -Internal company name of the file, provided at compile-time. - -type: keyword - -example: Microsoft Corporation - --- - -*`threat.enrichments.indicator.file.pe.description`*:: -+ --- -Internal description of the file, provided at compile-time. - -type: keyword - -example: Paint - --- - -*`threat.enrichments.indicator.file.pe.file_version`*:: -+ --- -Internal version of the file, provided at compile-time. - -type: keyword - -example: 6.3.9600.17415 - --- - -*`threat.enrichments.indicator.file.pe.imphash`*:: -+ --- -A hash of the imports in a PE file. An imphash -- or import hash -- can be used to fingerprint binaries even after recompilation or other code-level transformations have occurred, which would change more traditional hash values. -Learn more at https://www.fireeye.com/blog/threat-research/2014/01/tracking-malware-import-hashing.html. - -type: keyword - -example: 0c6803c4e922103c4dca5963aad36ddf - --- - -*`threat.enrichments.indicator.file.pe.original_file_name`*:: -+ --- -Internal name of the file, provided at compile-time. - -type: keyword - -example: MSPAINT.EXE - --- - -*`threat.enrichments.indicator.file.pe.product`*:: -+ --- -Internal product name of the file, provided at compile-time. - -type: keyword - -example: Microsoft® Windows® Operating System - --- - -*`threat.enrichments.indicator.file.size`*:: -+ --- -File size in bytes. -Only relevant when `file.type` is "file". - -type: long - -example: 16384 - --- - -*`threat.enrichments.indicator.file.target_path`*:: -+ --- -Target path for symlinks. - -type: keyword - --- - -*`threat.enrichments.indicator.file.target_path.text`*:: -+ --- -type: match_only_text - --- - -*`threat.enrichments.indicator.file.type`*:: -+ --- -File type (file, dir, or symlink). - -type: keyword - -example: file - --- - -*`threat.enrichments.indicator.file.uid`*:: -+ --- -The user ID (UID) or security identifier (SID) of the file owner. - -type: keyword - -example: 1001 - --- - -*`threat.enrichments.indicator.file.x509.alternative_names`*:: -+ --- -List of subject alternative names (SAN). Name types vary by certificate authority and certificate type but commonly contain IP addresses, DNS names (and wildcards), and email addresses. - -type: keyword - -example: *.elastic.co - --- - -*`threat.enrichments.indicator.file.x509.issuer.common_name`*:: -+ --- -List of common name (CN) of issuing certificate authority. - -type: keyword - -example: Example SHA2 High Assurance Server CA - --- - -*`threat.enrichments.indicator.file.x509.issuer.country`*:: -+ --- -List of country (C) codes - -type: keyword - -example: US - --- - -*`threat.enrichments.indicator.file.x509.issuer.distinguished_name`*:: -+ --- -Distinguished name (DN) of issuing certificate authority. - -type: keyword - -example: C=US, O=Example Inc, OU=www.example.com, CN=Example SHA2 High Assurance Server CA - --- - -*`threat.enrichments.indicator.file.x509.issuer.locality`*:: -+ --- -List of locality names (L) - -type: keyword - -example: Mountain View - --- - -*`threat.enrichments.indicator.file.x509.issuer.organization`*:: -+ --- -List of organizations (O) of issuing certificate authority. - -type: keyword - -example: Example Inc - --- - -*`threat.enrichments.indicator.file.x509.issuer.organizational_unit`*:: -+ --- -List of organizational units (OU) of issuing certificate authority. - -type: keyword - -example: www.example.com - --- - -*`threat.enrichments.indicator.file.x509.issuer.state_or_province`*:: -+ --- -List of state or province names (ST, S, or P) - -type: keyword - -example: California - --- - -*`threat.enrichments.indicator.file.x509.not_after`*:: -+ --- -Time at which the certificate is no longer considered valid. - -type: date - -example: 2020-07-16 03:15:39+00:00 - --- - -*`threat.enrichments.indicator.file.x509.not_before`*:: -+ --- -Time at which the certificate is first considered valid. - -type: date - -example: 2019-08-16 01:40:25+00:00 - --- - -*`threat.enrichments.indicator.file.x509.public_key_algorithm`*:: -+ --- -Algorithm used to generate the public key. - -type: keyword - -example: RSA - --- - -*`threat.enrichments.indicator.file.x509.public_key_curve`*:: -+ --- -The curve used by the elliptic curve public key algorithm. This is algorithm specific. - -type: keyword - -example: nistp521 - --- - -*`threat.enrichments.indicator.file.x509.public_key_exponent`*:: -+ --- -Exponent used to derive the public key. This is algorithm specific. - -type: long - -example: 65537 - -Field is not indexed. - --- - -*`threat.enrichments.indicator.file.x509.public_key_size`*:: -+ --- -The size of the public key space in bits. - -type: long - -example: 2048 - --- - -*`threat.enrichments.indicator.file.x509.serial_number`*:: -+ --- -Unique serial number issued by the certificate authority. For consistency, if this value is alphanumeric, it should be formatted without colons and uppercase characters. - -type: keyword - -example: 55FBB9C7DEBF09809D12CCAA - --- - -*`threat.enrichments.indicator.file.x509.signature_algorithm`*:: -+ --- -Identifier for certificate signature algorithm. We recommend using names found in Go Lang Crypto library. See https://github.com/golang/go/blob/go1.14/src/crypto/x509/x509.go#L337-L353. - -type: keyword - -example: SHA256-RSA - --- - -*`threat.enrichments.indicator.file.x509.subject.common_name`*:: -+ --- -List of common names (CN) of subject. - -type: keyword - -example: shared.global.example.net - --- - -*`threat.enrichments.indicator.file.x509.subject.country`*:: -+ --- -List of country (C) code - -type: keyword - -example: US - --- - -*`threat.enrichments.indicator.file.x509.subject.distinguished_name`*:: -+ --- -Distinguished name (DN) of the certificate subject entity. - -type: keyword - -example: C=US, ST=California, L=San Francisco, O=Example, Inc., CN=shared.global.example.net - --- - -*`threat.enrichments.indicator.file.x509.subject.locality`*:: -+ --- -List of locality names (L) - -type: keyword - -example: San Francisco - --- - -*`threat.enrichments.indicator.file.x509.subject.organization`*:: -+ --- -List of organizations (O) of subject. - -type: keyword - -example: Example, Inc. - --- - -*`threat.enrichments.indicator.file.x509.subject.organizational_unit`*:: -+ --- -List of organizational units (OU) of subject. - -type: keyword - --- - -*`threat.enrichments.indicator.file.x509.subject.state_or_province`*:: -+ --- -List of state or province names (ST, S, or P) - -type: keyword - -example: California - --- - -*`threat.enrichments.indicator.file.x509.version_number`*:: -+ --- -Version of x509 format. - -type: keyword - -example: 3 - --- - -*`threat.enrichments.indicator.first_seen`*:: -+ --- -The date and time when intelligence source first reported sighting this indicator. - -type: date - -example: 2020-11-05T17:25:47.000Z - --- - -*`threat.enrichments.indicator.geo.city_name`*:: -+ --- -City name. - -type: keyword - -example: Montreal - --- - -*`threat.enrichments.indicator.geo.continent_code`*:: -+ --- -Two-letter code representing continent's name. - -type: keyword - -example: NA - --- - -*`threat.enrichments.indicator.geo.continent_name`*:: -+ --- -Name of the continent. - -type: keyword - -example: North America - --- - -*`threat.enrichments.indicator.geo.country_iso_code`*:: -+ --- -Country ISO code. - -type: keyword - -example: CA - --- - -*`threat.enrichments.indicator.geo.country_name`*:: -+ --- -Country name. - -type: keyword - -example: Canada - --- - -*`threat.enrichments.indicator.geo.location`*:: -+ --- -Longitude and latitude. - -type: geo_point - -example: { "lon": -73.614830, "lat": 45.505918 } - --- - -*`threat.enrichments.indicator.geo.name`*:: -+ --- -User-defined description of a location, at the level of granularity they care about. -Could be the name of their data centers, the floor number, if this describes a local physical entity, city names. -Not typically used in automated geolocation. - -type: keyword - -example: boston-dc - --- - -*`threat.enrichments.indicator.geo.postal_code`*:: -+ --- -Postal code associated with the location. -Values appropriate for this field may also be known as a postcode or ZIP code and will vary widely from country to country. - -type: keyword - -example: 94040 - --- - -*`threat.enrichments.indicator.geo.region_iso_code`*:: -+ --- -Region ISO code. - -type: keyword - -example: CA-QC - --- - -*`threat.enrichments.indicator.geo.region_name`*:: -+ --- -Region name. - -type: keyword - -example: Quebec - --- - -*`threat.enrichments.indicator.geo.timezone`*:: -+ --- -The time zone of the location, such as IANA time zone name. - -type: keyword - -example: America/Argentina/Buenos_Aires - --- - -*`threat.enrichments.indicator.ip`*:: -+ --- -Identifies a threat indicator as an IP address (irrespective of direction). - -type: ip - -example: 1.2.3.4 - --- - -*`threat.enrichments.indicator.last_seen`*:: -+ --- -The date and time when intelligence source last reported sighting this indicator. - -type: date - -example: 2020-11-05T17:25:47.000Z - --- - -*`threat.enrichments.indicator.marking.tlp`*:: -+ --- -Traffic Light Protocol sharing markings. Recommended values are: - * WHITE - * GREEN - * AMBER - * RED - -type: keyword - -example: White - --- - -*`threat.enrichments.indicator.modified_at`*:: -+ --- -The date and time when intelligence source last modified information for this indicator. - -type: date - -example: 2020-11-05T17:25:47.000Z - --- - -*`threat.enrichments.indicator.port`*:: -+ --- -Identifies a threat indicator as a port number (irrespective of direction). - -type: long - -example: 443 - --- - -*`threat.enrichments.indicator.provider`*:: -+ --- -The name of the indicator's provider. - -type: keyword - -example: lrz_urlhaus - --- - -*`threat.enrichments.indicator.reference`*:: -+ --- -Reference URL linking to additional information about this indicator. - -type: keyword - -example: https://system.example.com/indicator/0001234 - --- - -*`threat.enrichments.indicator.registry.data.bytes`*:: -+ --- -Original bytes written with base64 encoding. -For Windows registry operations, such as SetValueEx and RegQueryValueEx, this corresponds to the data pointed by `lp_data`. This is optional but provides better recoverability and should be populated for REG_BINARY encoded values. - -type: keyword - -example: ZQBuAC0AVQBTAAAAZQBuAAAAAAA= - --- - -*`threat.enrichments.indicator.registry.data.strings`*:: -+ --- -Content when writing string types. -Populated as an array when writing string data to the registry. For single string registry types (REG_SZ, REG_EXPAND_SZ), this should be an array with one string. For sequences of string with REG_MULTI_SZ, this array will be variable length. For numeric data, such as REG_DWORD and REG_QWORD, this should be populated with the decimal representation (e.g `"1"`). - -type: wildcard - -example: ["C:\rta\red_ttp\bin\myapp.exe"] - --- - -*`threat.enrichments.indicator.registry.data.type`*:: -+ --- -Standard registry type for encoding contents - -type: keyword - -example: REG_SZ - --- - -*`threat.enrichments.indicator.registry.hive`*:: -+ --- -Abbreviated name for the hive. - -type: keyword - -example: HKLM - --- - -*`threat.enrichments.indicator.registry.key`*:: -+ --- -Hive-relative path of keys. - -type: keyword - -example: SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\winword.exe - --- - -*`threat.enrichments.indicator.registry.path`*:: -+ --- -Full path, including hive, key and value - -type: keyword - -example: HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\winword.exe\Debugger - --- - -*`threat.enrichments.indicator.registry.value`*:: -+ --- -Name of the value written. - -type: keyword - -example: Debugger - --- - -*`threat.enrichments.indicator.scanner_stats`*:: -+ --- -Count of AV/EDR vendors that successfully detected malicious file or URL. - -type: long - -example: 4 - --- - -*`threat.enrichments.indicator.sightings`*:: -+ --- -Number of times this indicator was observed conducting threat activity. - -type: long - -example: 20 - --- - -*`threat.enrichments.indicator.type`*:: -+ --- -Type of indicator as represented by Cyber Observable in STIX 2.0. Recommended values: - * autonomous-system - * artifact - * directory - * domain-name - * email-addr - * file - * ipv4-addr - * ipv6-addr - * mac-addr - * mutex - * port - * process - * software - * url - * user-account - * windows-registry-key - * x509-certificate - -type: keyword - -example: ipv4-addr - --- - -*`threat.enrichments.indicator.url.domain`*:: -+ --- -Domain of the url, such as "www.elastic.co". -In some cases a URL may refer to an IP and/or port directly, without a domain name. In this case, the IP address would go to the `domain` field. -If the URL contains a literal IPv6 address enclosed by `[` and `]` (IETF RFC 2732), the `[` and `]` characters should also be captured in the `domain` field. - -type: keyword - -example: www.elastic.co - --- - -*`threat.enrichments.indicator.url.extension`*:: -+ --- -The field contains the file extension from the original request url, excluding the leading dot. -The file extension is only set if it exists, as not every url has a file extension. -The leading period must not be included. For example, the value must be "png", not ".png". -Note that when the file name has multiple extensions (example.tar.gz), only the last one should be captured ("gz", not "tar.gz"). - -type: keyword - -example: png - --- - -*`threat.enrichments.indicator.url.fragment`*:: -+ --- -Portion of the url after the `#`, such as "top". -The `#` is not part of the fragment. - -type: keyword - --- - -*`threat.enrichments.indicator.url.full`*:: -+ --- -If full URLs are important to your use case, they should be stored in `url.full`, whether this field is reconstructed or present in the event source. - -type: wildcard - -example: https://www.elastic.co:443/search?q=elasticsearch#top - --- - -*`threat.enrichments.indicator.url.full.text`*:: -+ --- -type: match_only_text - --- - -*`threat.enrichments.indicator.url.original`*:: -+ --- -Unmodified original url as seen in the event source. -Note that in network monitoring, the observed URL may be a full URL, whereas in access logs, the URL is often just represented as a path. -This field is meant to represent the URL as it was observed, complete or not. - -type: wildcard - -example: https://www.elastic.co:443/search?q=elasticsearch#top or /search?q=elasticsearch - --- - -*`threat.enrichments.indicator.url.original.text`*:: -+ --- -type: match_only_text - --- - -*`threat.enrichments.indicator.url.password`*:: -+ --- -Password of the request. - -type: keyword - --- - -*`threat.enrichments.indicator.url.path`*:: -+ --- -Path of the request, such as "/search". - -type: wildcard - --- - -*`threat.enrichments.indicator.url.port`*:: -+ --- -Port of the request, such as 443. - -type: long - -example: 443 - -format: string - --- - -*`threat.enrichments.indicator.url.query`*:: -+ --- -The query field describes the query string of the request, such as "q=elasticsearch". -The `?` is excluded from the query string. If a URL contains no `?`, there is no query field. If there is a `?` but no query, the query field exists with an empty string. The `exists` query can be used to differentiate between the two cases. - -type: keyword - --- - -*`threat.enrichments.indicator.url.registered_domain`*:: -+ --- -The highest registered url domain, stripped of the subdomain. -For example, the registered domain for "foo.example.com" is "example.com". -This value can be determined precisely with a list like the public suffix list (http://publicsuffix.org). Trying to approximate this by simply taking the last two labels will not work well for TLDs such as "co.uk". - -type: keyword - -example: example.com - --- - -*`threat.enrichments.indicator.url.scheme`*:: -+ --- -Scheme of the request, such as "https". -Note: The `:` is not part of the scheme. - -type: keyword - -example: https - --- - -*`threat.enrichments.indicator.url.subdomain`*:: -+ --- -The subdomain portion of a fully qualified domain name includes all of the names except the host name under the registered_domain. In a partially qualified domain, or if the the qualification level of the full name cannot be determined, subdomain contains all of the names below the registered domain. -For example the subdomain portion of "www.east.mydomain.co.uk" is "east". If the domain has multiple levels of subdomain, such as "sub2.sub1.example.com", the subdomain field should contain "sub2.sub1", with no trailing period. - -type: keyword - -example: east - --- - -*`threat.enrichments.indicator.url.top_level_domain`*:: -+ --- -The effective top level domain (eTLD), also known as the domain suffix, is the last part of the domain name. For example, the top level domain for example.com is "com". -This value can be determined precisely with a list like the public suffix list (http://publicsuffix.org). Trying to approximate this by simply taking the last label will not work well for effective TLDs such as "co.uk". - -type: keyword - -example: co.uk - --- - -*`threat.enrichments.indicator.url.username`*:: -+ --- -Username of the request. - -type: keyword - --- - -*`threat.enrichments.indicator.x509.alternative_names`*:: -+ --- -List of subject alternative names (SAN). Name types vary by certificate authority and certificate type but commonly contain IP addresses, DNS names (and wildcards), and email addresses. - -type: keyword - -example: *.elastic.co - --- - -*`threat.enrichments.indicator.x509.issuer.common_name`*:: -+ --- -List of common name (CN) of issuing certificate authority. - -type: keyword - -example: Example SHA2 High Assurance Server CA - --- - -*`threat.enrichments.indicator.x509.issuer.country`*:: -+ --- -List of country (C) codes - -type: keyword - -example: US - --- - -*`threat.enrichments.indicator.x509.issuer.distinguished_name`*:: -+ --- -Distinguished name (DN) of issuing certificate authority. - -type: keyword - -example: C=US, O=Example Inc, OU=www.example.com, CN=Example SHA2 High Assurance Server CA - --- - -*`threat.enrichments.indicator.x509.issuer.locality`*:: -+ --- -List of locality names (L) - -type: keyword - -example: Mountain View - --- - -*`threat.enrichments.indicator.x509.issuer.organization`*:: -+ --- -List of organizations (O) of issuing certificate authority. - -type: keyword - -example: Example Inc - --- - -*`threat.enrichments.indicator.x509.issuer.organizational_unit`*:: -+ --- -List of organizational units (OU) of issuing certificate authority. - -type: keyword - -example: www.example.com - --- - -*`threat.enrichments.indicator.x509.issuer.state_or_province`*:: -+ --- -List of state or province names (ST, S, or P) - -type: keyword - -example: California - --- - -*`threat.enrichments.indicator.x509.not_after`*:: -+ --- -Time at which the certificate is no longer considered valid. - -type: date - -example: 2020-07-16 03:15:39+00:00 - --- - -*`threat.enrichments.indicator.x509.not_before`*:: -+ --- -Time at which the certificate is first considered valid. - -type: date - -example: 2019-08-16 01:40:25+00:00 - --- - -*`threat.enrichments.indicator.x509.public_key_algorithm`*:: -+ --- -Algorithm used to generate the public key. - -type: keyword - -example: RSA - --- - -*`threat.enrichments.indicator.x509.public_key_curve`*:: -+ --- -The curve used by the elliptic curve public key algorithm. This is algorithm specific. - -type: keyword - -example: nistp521 - --- - -*`threat.enrichments.indicator.x509.public_key_exponent`*:: -+ --- -Exponent used to derive the public key. This is algorithm specific. - -type: long - -example: 65537 - -Field is not indexed. - --- - -*`threat.enrichments.indicator.x509.public_key_size`*:: -+ --- -The size of the public key space in bits. - -type: long - -example: 2048 - --- - -*`threat.enrichments.indicator.x509.serial_number`*:: -+ --- -Unique serial number issued by the certificate authority. For consistency, if this value is alphanumeric, it should be formatted without colons and uppercase characters. - -type: keyword - -example: 55FBB9C7DEBF09809D12CCAA - --- - -*`threat.enrichments.indicator.x509.signature_algorithm`*:: -+ --- -Identifier for certificate signature algorithm. We recommend using names found in Go Lang Crypto library. See https://github.com/golang/go/blob/go1.14/src/crypto/x509/x509.go#L337-L353. - -type: keyword - -example: SHA256-RSA - --- - -*`threat.enrichments.indicator.x509.subject.common_name`*:: -+ --- -List of common names (CN) of subject. - -type: keyword - -example: shared.global.example.net - --- - -*`threat.enrichments.indicator.x509.subject.country`*:: -+ --- -List of country (C) code - -type: keyword - -example: US - --- - -*`threat.enrichments.indicator.x509.subject.distinguished_name`*:: -+ --- -Distinguished name (DN) of the certificate subject entity. - -type: keyword - -example: C=US, ST=California, L=San Francisco, O=Example, Inc., CN=shared.global.example.net - --- - -*`threat.enrichments.indicator.x509.subject.locality`*:: -+ --- -List of locality names (L) - -type: keyword - -example: San Francisco - --- - -*`threat.enrichments.indicator.x509.subject.organization`*:: -+ --- -List of organizations (O) of subject. - -type: keyword - -example: Example, Inc. - --- - -*`threat.enrichments.indicator.x509.subject.organizational_unit`*:: -+ --- -List of organizational units (OU) of subject. - -type: keyword - --- - -*`threat.enrichments.indicator.x509.subject.state_or_province`*:: -+ --- -List of state or province names (ST, S, or P) - -type: keyword - -example: California - --- - -*`threat.enrichments.indicator.x509.version_number`*:: -+ --- -Version of x509 format. - -type: keyword - -example: 3 - --- - -*`threat.enrichments.matched.atomic`*:: -+ --- -Identifies the atomic indicator value that matched a local environment endpoint or network event. - -type: keyword - -example: bad-domain.com - --- - -*`threat.enrichments.matched.field`*:: -+ --- -Identifies the field of the atomic indicator that matched a local environment endpoint or network event. - -type: keyword - -example: file.hash.sha256 - --- - -*`threat.enrichments.matched.id`*:: -+ --- -Identifies the _id of the indicator document enriching the event. - -type: keyword - -example: ff93aee5-86a1-4a61-b0e6-0cdc313d01b5 - --- - -*`threat.enrichments.matched.index`*:: -+ --- -Identifies the _index of the indicator document enriching the event. - -type: keyword - -example: filebeat-8.0.0-2021.05.23-000011 - --- - -*`threat.enrichments.matched.type`*:: -+ --- -Identifies the type of match that caused the event to be enriched with the given indicator - -type: keyword - -example: indicator_match_rule - --- - -*`threat.framework`*:: -+ --- -Name of the threat framework used to further categorize and classify the tactic and technique of the reported threat. Framework classification can be provided by detecting systems, evaluated at ingest time, or retrospectively tagged to events. - -type: keyword - -example: MITRE ATT&CK - --- - -*`threat.group.alias`*:: -+ --- -The alias(es) of the group for a set of related intrusion activity that are tracked by a common name in the security community. -While not required, you can use a MITRE ATT&CK® group alias(es). - -type: keyword - -example: [ "Magecart Group 6" ] - --- - -*`threat.group.id`*:: -+ --- -The id of the group for a set of related intrusion activity that are tracked by a common name in the security community. -While not required, you can use a MITRE ATT&CK® group id. - -type: keyword - -example: G0037 - --- - -*`threat.group.name`*:: -+ --- -The name of the group for a set of related intrusion activity that are tracked by a common name in the security community. -While not required, you can use a MITRE ATT&CK® group name. - -type: keyword - -example: FIN6 - --- - -*`threat.group.reference`*:: -+ --- -The reference URL of the group for a set of related intrusion activity that are tracked by a common name in the security community. -While not required, you can use a MITRE ATT&CK® group reference URL. - -type: keyword - -example: https://attack.mitre.org/groups/G0037/ - --- - -*`threat.indicator.as.number`*:: -+ --- -Unique number allocated to the autonomous system. The autonomous system number (ASN) uniquely identifies each network on the Internet. - -type: long - -example: 15169 - --- - -*`threat.indicator.as.organization.name`*:: -+ --- -Organization name. - -type: keyword - -example: Google LLC - --- - -*`threat.indicator.as.organization.name.text`*:: -+ --- -type: match_only_text - --- - -*`threat.indicator.confidence`*:: -+ --- -Identifies the vendor-neutral confidence rating using the None/Low/Medium/High scale defined in Appendix A of the STIX 2.1 framework. Vendor-specific confidence scales may be added as custom fields. -Expected values are: - * Not Specified - * None - * Low - * Medium - * High - -type: keyword - -example: Medium - --- - -*`threat.indicator.description`*:: -+ --- -Describes the type of action conducted by the threat. - -type: keyword - -example: IP x.x.x.x was observed delivering the Angler EK. - --- - -*`threat.indicator.email.address`*:: -+ --- -Identifies a threat indicator as an email address (irrespective of direction). - -type: keyword - -example: phish@example.com - --- - -*`threat.indicator.file.accessed`*:: -+ --- -Last time the file was accessed. -Note that not all filesystems keep track of access time. - -type: date - --- - -*`threat.indicator.file.attributes`*:: -+ --- -Array of file attributes. -Attributes names will vary by platform. Here's a non-exhaustive list of values that are expected in this field: archive, compressed, directory, encrypted, execute, hidden, read, readonly, system, write. - -type: keyword - -example: ["readonly", "system"] - --- - -*`threat.indicator.file.code_signature.digest_algorithm`*:: -+ --- -The hashing algorithm used to sign the process. -This value can distinguish signatures when a file is signed multiple times by the same signer but with a different digest algorithm. - -type: keyword - -example: sha256 - --- - -*`threat.indicator.file.code_signature.exists`*:: -+ --- -Boolean to capture if a signature is present. - -type: boolean - -example: true - --- - -*`threat.indicator.file.code_signature.signing_id`*:: -+ --- -The identifier used to sign the process. -This is used to identify the application manufactured by a software vendor. The field is relevant to Apple *OS only. - -type: keyword - -example: com.apple.xpc.proxy - --- - -*`threat.indicator.file.code_signature.status`*:: -+ --- -Additional information about the certificate status. -This is useful for logging cryptographic errors with the certificate validity or trust status. Leave unpopulated if the validity or trust of the certificate was unchecked. - -type: keyword - -example: ERROR_UNTRUSTED_ROOT - --- - -*`threat.indicator.file.code_signature.subject_name`*:: -+ --- -Subject name of the code signer - -type: keyword - -example: Microsoft Corporation - --- - -*`threat.indicator.file.code_signature.team_id`*:: -+ --- -The team identifier used to sign the process. -This is used to identify the team or vendor of a software product. The field is relevant to Apple *OS only. - -type: keyword - -example: EQHXZ8M8AV - --- - -*`threat.indicator.file.code_signature.timestamp`*:: -+ --- -Date and time when the code signature was generated and signed. - -type: date - -example: 2021-01-01T12:10:30Z - --- - -*`threat.indicator.file.code_signature.trusted`*:: -+ --- -Stores the trust status of the certificate chain. -Validating the trust of the certificate chain may be complicated, and this field should only be populated by tools that actively check the status. - -type: boolean - -example: true - --- - -*`threat.indicator.file.code_signature.valid`*:: -+ --- -Boolean to capture if the digital signature is verified against the binary content. -Leave unpopulated if a certificate was unchecked. - -type: boolean - -example: true - --- - -*`threat.indicator.file.created`*:: -+ --- -File creation time. -Note that not all filesystems store the creation time. - -type: date - --- - -*`threat.indicator.file.ctime`*:: -+ --- -Last time the file attributes or metadata changed. -Note that changes to the file content will update `mtime`. This implies `ctime` will be adjusted at the same time, since `mtime` is an attribute of the file. - -type: date - --- - -*`threat.indicator.file.device`*:: -+ --- -Device that is the source of the file. - -type: keyword - -example: sda - --- - -*`threat.indicator.file.directory`*:: -+ --- -Directory where the file is located. It should include the drive letter, when appropriate. - -type: keyword - -example: /home/alice - --- - -*`threat.indicator.file.drive_letter`*:: -+ --- -Drive letter where the file is located. This field is only relevant on Windows. -The value should be uppercase, and not include the colon. - -type: keyword - -example: C - --- - -*`threat.indicator.file.elf.architecture`*:: -+ --- -Machine architecture of the ELF file. - -type: keyword - -example: x86-64 - --- - -*`threat.indicator.file.elf.byte_order`*:: -+ --- -Byte sequence of ELF file. - -type: keyword - -example: Little Endian - --- - -*`threat.indicator.file.elf.cpu_type`*:: -+ --- -CPU type of the ELF file. - -type: keyword - -example: Intel - --- - -*`threat.indicator.file.elf.creation_date`*:: -+ --- -Extracted when possible from the file's metadata. Indicates when it was built or compiled. It can also be faked by malware creators. - -type: date - --- - -*`threat.indicator.file.elf.exports`*:: -+ --- -List of exported element names and types. - -type: flattened - --- - -*`threat.indicator.file.elf.header.abi_version`*:: -+ --- -Version of the ELF Application Binary Interface (ABI). - -type: keyword - --- - -*`threat.indicator.file.elf.header.class`*:: -+ --- -Header class of the ELF file. - -type: keyword - --- - -*`threat.indicator.file.elf.header.data`*:: -+ --- -Data table of the ELF header. - -type: keyword - --- - -*`threat.indicator.file.elf.header.entrypoint`*:: -+ --- -Header entrypoint of the ELF file. - -type: long - -format: string - --- - -*`threat.indicator.file.elf.header.object_version`*:: -+ --- -"0x1" for original ELF files. - -type: keyword - --- - -*`threat.indicator.file.elf.header.os_abi`*:: -+ --- -Application Binary Interface (ABI) of the Linux OS. - -type: keyword - --- - -*`threat.indicator.file.elf.header.type`*:: -+ --- -Header type of the ELF file. - -type: keyword - --- - -*`threat.indicator.file.elf.header.version`*:: -+ --- -Version of the ELF header. - -type: keyword - --- - -*`threat.indicator.file.elf.imports`*:: -+ --- -List of imported element names and types. - -type: flattened - --- - -*`threat.indicator.file.elf.sections`*:: -+ --- -An array containing an object for each section of the ELF file. -The keys that should be present in these objects are defined by sub-fields underneath `elf.sections.*`. - -type: nested - --- - -*`threat.indicator.file.elf.sections.chi2`*:: -+ --- -Chi-square probability distribution of the section. - -type: long - -format: number - --- - -*`threat.indicator.file.elf.sections.entropy`*:: -+ --- -Shannon entropy calculation from the section. - -type: long - -format: number - --- - -*`threat.indicator.file.elf.sections.flags`*:: -+ --- -ELF Section List flags. - -type: keyword - --- - -*`threat.indicator.file.elf.sections.name`*:: -+ --- -ELF Section List name. - -type: keyword - --- - -*`threat.indicator.file.elf.sections.physical_offset`*:: -+ --- -ELF Section List offset. - -type: keyword - --- - -*`threat.indicator.file.elf.sections.physical_size`*:: -+ --- -ELF Section List physical size. - -type: long - -format: bytes - --- - -*`threat.indicator.file.elf.sections.type`*:: -+ --- -ELF Section List type. - -type: keyword - --- - -*`threat.indicator.file.elf.sections.virtual_address`*:: -+ --- -ELF Section List virtual address. - -type: long - -format: string - --- - -*`threat.indicator.file.elf.sections.virtual_size`*:: -+ --- -ELF Section List virtual size. - -type: long - -format: string - --- - -*`threat.indicator.file.elf.segments`*:: -+ --- -An array containing an object for each segment of the ELF file. -The keys that should be present in these objects are defined by sub-fields underneath `elf.segments.*`. - -type: nested - --- - -*`threat.indicator.file.elf.segments.sections`*:: -+ --- -ELF object segment sections. - -type: keyword - --- - -*`threat.indicator.file.elf.segments.type`*:: -+ --- -ELF object segment type. - -type: keyword - --- - -*`threat.indicator.file.elf.shared_libraries`*:: -+ --- -List of shared libraries used by this ELF object. - -type: keyword - --- - -*`threat.indicator.file.elf.telfhash`*:: -+ --- -telfhash symbol hash for ELF file. - -type: keyword - --- - -*`threat.indicator.file.extension`*:: -+ --- -File extension, excluding the leading dot. -Note that when the file name has multiple extensions (example.tar.gz), only the last one should be captured ("gz", not "tar.gz"). - -type: keyword - -example: png - --- - -*`threat.indicator.file.fork_name`*:: -+ --- -A fork is additional data associated with a filesystem object. -On Linux, a resource fork is used to store additional data with a filesystem object. A file always has at least one fork for the data portion, and additional forks may exist. -On NTFS, this is analogous to an Alternate Data Stream (ADS), and the default data stream for a file is just called $DATA. Zone.Identifier is commonly used by Windows to track contents downloaded from the Internet. An ADS is typically of the form: `C:\path\to\filename.extension:some_fork_name`, and `some_fork_name` is the value that should populate `fork_name`. `filename.extension` should populate `file.name`, and `extension` should populate `file.extension`. The full path, `file.path`, will include the fork name. - -type: keyword - -example: Zone.Identifer - --- - -*`threat.indicator.file.gid`*:: -+ --- -Primary group ID (GID) of the file. - -type: keyword - -example: 1001 - --- - -*`threat.indicator.file.group`*:: -+ --- -Primary group name of the file. - -type: keyword - -example: alice - --- - -*`threat.indicator.file.hash.md5`*:: -+ --- -MD5 hash. - -type: keyword - --- - -*`threat.indicator.file.hash.sha1`*:: -+ --- -SHA1 hash. - -type: keyword - --- - -*`threat.indicator.file.hash.sha256`*:: -+ --- -SHA256 hash. - -type: keyword - --- - -*`threat.indicator.file.hash.sha512`*:: -+ --- -SHA512 hash. - -type: keyword - --- - -*`threat.indicator.file.hash.ssdeep`*:: -+ --- -SSDEEP hash. - -type: keyword - --- - -*`threat.indicator.file.inode`*:: -+ --- -Inode representing the file in the filesystem. - -type: keyword - -example: 256383 - --- - -*`threat.indicator.file.mime_type`*:: -+ --- -MIME type should identify the format of the file or stream of bytes using https://www.iana.org/assignments/media-types/media-types.xhtml[IANA official types], where possible. When more than one type is applicable, the most specific type should be used. - -type: keyword - --- - -*`threat.indicator.file.mode`*:: -+ --- -Mode of the file in octal representation. - -type: keyword - -example: 0640 - --- - -*`threat.indicator.file.mtime`*:: -+ --- -Last time the file content was modified. - -type: date - --- - -*`threat.indicator.file.name`*:: -+ --- -Name of the file including the extension, without the directory. - -type: keyword - -example: example.png - --- - -*`threat.indicator.file.owner`*:: -+ --- -File owner's username. - -type: keyword - -example: alice - --- - -*`threat.indicator.file.path`*:: -+ --- -Full path to the file, including the file name. It should include the drive letter, when appropriate. - -type: keyword - -example: /home/alice/example.png - --- - -*`threat.indicator.file.path.text`*:: -+ --- -type: match_only_text - --- - -*`threat.indicator.file.pe.architecture`*:: -+ --- -CPU architecture target for the file. - -type: keyword - -example: x64 - --- - -*`threat.indicator.file.pe.company`*:: -+ --- -Internal company name of the file, provided at compile-time. - -type: keyword - -example: Microsoft Corporation - --- - -*`threat.indicator.file.pe.description`*:: -+ --- -Internal description of the file, provided at compile-time. - -type: keyword - -example: Paint - --- - -*`threat.indicator.file.pe.file_version`*:: -+ --- -Internal version of the file, provided at compile-time. - -type: keyword - -example: 6.3.9600.17415 - --- - -*`threat.indicator.file.pe.imphash`*:: -+ --- -A hash of the imports in a PE file. An imphash -- or import hash -- can be used to fingerprint binaries even after recompilation or other code-level transformations have occurred, which would change more traditional hash values. -Learn more at https://www.fireeye.com/blog/threat-research/2014/01/tracking-malware-import-hashing.html. - -type: keyword - -example: 0c6803c4e922103c4dca5963aad36ddf - --- - -*`threat.indicator.file.pe.original_file_name`*:: -+ --- -Internal name of the file, provided at compile-time. - -type: keyword - -example: MSPAINT.EXE - --- - -*`threat.indicator.file.pe.product`*:: -+ --- -Internal product name of the file, provided at compile-time. - -type: keyword - -example: Microsoft® Windows® Operating System - --- - -*`threat.indicator.file.size`*:: -+ --- -File size in bytes. -Only relevant when `file.type` is "file". - -type: long - -example: 16384 - --- - -*`threat.indicator.file.target_path`*:: -+ --- -Target path for symlinks. - -type: keyword - --- - -*`threat.indicator.file.target_path.text`*:: -+ --- -type: match_only_text - --- - -*`threat.indicator.file.type`*:: -+ --- -File type (file, dir, or symlink). - -type: keyword - -example: file - --- - -*`threat.indicator.file.uid`*:: -+ --- -The user ID (UID) or security identifier (SID) of the file owner. - -type: keyword - -example: 1001 - --- - -*`threat.indicator.file.x509.alternative_names`*:: -+ --- -List of subject alternative names (SAN). Name types vary by certificate authority and certificate type but commonly contain IP addresses, DNS names (and wildcards), and email addresses. - -type: keyword - -example: *.elastic.co - --- - -*`threat.indicator.file.x509.issuer.common_name`*:: -+ --- -List of common name (CN) of issuing certificate authority. - -type: keyword - -example: Example SHA2 High Assurance Server CA - --- - -*`threat.indicator.file.x509.issuer.country`*:: -+ --- -List of country (C) codes - -type: keyword - -example: US - --- - -*`threat.indicator.file.x509.issuer.distinguished_name`*:: -+ --- -Distinguished name (DN) of issuing certificate authority. - -type: keyword - -example: C=US, O=Example Inc, OU=www.example.com, CN=Example SHA2 High Assurance Server CA - --- - -*`threat.indicator.file.x509.issuer.locality`*:: -+ --- -List of locality names (L) - -type: keyword - -example: Mountain View - --- - -*`threat.indicator.file.x509.issuer.organization`*:: -+ --- -List of organizations (O) of issuing certificate authority. - -type: keyword - -example: Example Inc - --- - -*`threat.indicator.file.x509.issuer.organizational_unit`*:: -+ --- -List of organizational units (OU) of issuing certificate authority. - -type: keyword - -example: www.example.com - --- - -*`threat.indicator.file.x509.issuer.state_or_province`*:: -+ --- -List of state or province names (ST, S, or P) - -type: keyword - -example: California - --- - -*`threat.indicator.file.x509.not_after`*:: -+ --- -Time at which the certificate is no longer considered valid. - -type: date - -example: 2020-07-16 03:15:39+00:00 - --- - -*`threat.indicator.file.x509.not_before`*:: -+ --- -Time at which the certificate is first considered valid. - -type: date - -example: 2019-08-16 01:40:25+00:00 - --- - -*`threat.indicator.file.x509.public_key_algorithm`*:: -+ --- -Algorithm used to generate the public key. - -type: keyword - -example: RSA - --- - -*`threat.indicator.file.x509.public_key_curve`*:: -+ --- -The curve used by the elliptic curve public key algorithm. This is algorithm specific. - -type: keyword - -example: nistp521 - --- - -*`threat.indicator.file.x509.public_key_exponent`*:: -+ --- -Exponent used to derive the public key. This is algorithm specific. - -type: long - -example: 65537 - -Field is not indexed. - --- - -*`threat.indicator.file.x509.public_key_size`*:: -+ --- -The size of the public key space in bits. - -type: long - -example: 2048 - --- - -*`threat.indicator.file.x509.serial_number`*:: -+ --- -Unique serial number issued by the certificate authority. For consistency, if this value is alphanumeric, it should be formatted without colons and uppercase characters. - -type: keyword - -example: 55FBB9C7DEBF09809D12CCAA - --- - -*`threat.indicator.file.x509.signature_algorithm`*:: -+ --- -Identifier for certificate signature algorithm. We recommend using names found in Go Lang Crypto library. See https://github.com/golang/go/blob/go1.14/src/crypto/x509/x509.go#L337-L353. - -type: keyword - -example: SHA256-RSA - --- - -*`threat.indicator.file.x509.subject.common_name`*:: -+ --- -List of common names (CN) of subject. - -type: keyword - -example: shared.global.example.net - --- - -*`threat.indicator.file.x509.subject.country`*:: -+ --- -List of country (C) code - -type: keyword - -example: US - --- - -*`threat.indicator.file.x509.subject.distinguished_name`*:: -+ --- -Distinguished name (DN) of the certificate subject entity. - -type: keyword - -example: C=US, ST=California, L=San Francisco, O=Example, Inc., CN=shared.global.example.net - --- - -*`threat.indicator.file.x509.subject.locality`*:: -+ --- -List of locality names (L) - -type: keyword - -example: San Francisco - --- - -*`threat.indicator.file.x509.subject.organization`*:: -+ --- -List of organizations (O) of subject. - -type: keyword - -example: Example, Inc. - --- - -*`threat.indicator.file.x509.subject.organizational_unit`*:: -+ --- -List of organizational units (OU) of subject. - -type: keyword - --- - -*`threat.indicator.file.x509.subject.state_or_province`*:: -+ --- -List of state or province names (ST, S, or P) - -type: keyword - -example: California - --- - -*`threat.indicator.file.x509.version_number`*:: -+ --- -Version of x509 format. - -type: keyword - -example: 3 - --- - -*`threat.indicator.first_seen`*:: -+ --- -The date and time when intelligence source first reported sighting this indicator. - -type: date - -example: 2020-11-05T17:25:47.000Z - --- - -*`threat.indicator.geo.city_name`*:: -+ --- -City name. - -type: keyword - -example: Montreal - --- - -*`threat.indicator.geo.continent_code`*:: -+ --- -Two-letter code representing continent's name. - -type: keyword - -example: NA - --- - -*`threat.indicator.geo.continent_name`*:: -+ --- -Name of the continent. - -type: keyword - -example: North America - --- - -*`threat.indicator.geo.country_iso_code`*:: -+ --- -Country ISO code. - -type: keyword - -example: CA - --- - -*`threat.indicator.geo.country_name`*:: -+ --- -Country name. - -type: keyword - -example: Canada - --- - -*`threat.indicator.geo.location`*:: -+ --- -Longitude and latitude. - -type: geo_point - -example: { "lon": -73.614830, "lat": 45.505918 } - --- - -*`threat.indicator.geo.name`*:: -+ --- -User-defined description of a location, at the level of granularity they care about. -Could be the name of their data centers, the floor number, if this describes a local physical entity, city names. -Not typically used in automated geolocation. - -type: keyword - -example: boston-dc - --- - -*`threat.indicator.geo.postal_code`*:: -+ --- -Postal code associated with the location. -Values appropriate for this field may also be known as a postcode or ZIP code and will vary widely from country to country. - -type: keyword - -example: 94040 - --- - -*`threat.indicator.geo.region_iso_code`*:: -+ --- -Region ISO code. - -type: keyword - -example: CA-QC - --- - -*`threat.indicator.geo.region_name`*:: -+ --- -Region name. - -type: keyword - -example: Quebec - --- - -*`threat.indicator.geo.timezone`*:: -+ --- -The time zone of the location, such as IANA time zone name. - -type: keyword - -example: America/Argentina/Buenos_Aires - --- - -*`threat.indicator.ip`*:: -+ --- -Identifies a threat indicator as an IP address (irrespective of direction). - -type: ip - -example: 1.2.3.4 - --- - -*`threat.indicator.last_seen`*:: -+ --- -The date and time when intelligence source last reported sighting this indicator. - -type: date - -example: 2020-11-05T17:25:47.000Z - --- - -*`threat.indicator.marking.tlp`*:: -+ --- -Traffic Light Protocol sharing markings. -Recommended values are: - * WHITE - * GREEN - * AMBER - * RED - -type: keyword - -example: WHITE - --- - -*`threat.indicator.modified_at`*:: -+ --- -The date and time when intelligence source last modified information for this indicator. - -type: date - -example: 2020-11-05T17:25:47.000Z - --- - -*`threat.indicator.port`*:: -+ --- -Identifies a threat indicator as a port number (irrespective of direction). - -type: long - -example: 443 - --- - -*`threat.indicator.provider`*:: -+ --- -The name of the indicator's provider. - -type: keyword - -example: lrz_urlhaus - --- - -*`threat.indicator.reference`*:: -+ --- -Reference URL linking to additional information about this indicator. - -type: keyword - -example: https://system.example.com/indicator/0001234 - --- - -*`threat.indicator.registry.data.bytes`*:: -+ --- -Original bytes written with base64 encoding. -For Windows registry operations, such as SetValueEx and RegQueryValueEx, this corresponds to the data pointed by `lp_data`. This is optional but provides better recoverability and should be populated for REG_BINARY encoded values. - -type: keyword - -example: ZQBuAC0AVQBTAAAAZQBuAAAAAAA= - --- - -*`threat.indicator.registry.data.strings`*:: -+ --- -Content when writing string types. -Populated as an array when writing string data to the registry. For single string registry types (REG_SZ, REG_EXPAND_SZ), this should be an array with one string. For sequences of string with REG_MULTI_SZ, this array will be variable length. For numeric data, such as REG_DWORD and REG_QWORD, this should be populated with the decimal representation (e.g `"1"`). - -type: wildcard - -example: ["C:\rta\red_ttp\bin\myapp.exe"] - --- - -*`threat.indicator.registry.data.type`*:: -+ --- -Standard registry type for encoding contents - -type: keyword - -example: REG_SZ - --- - -*`threat.indicator.registry.hive`*:: -+ --- -Abbreviated name for the hive. - -type: keyword - -example: HKLM - --- - -*`threat.indicator.registry.key`*:: -+ --- -Hive-relative path of keys. - -type: keyword - -example: SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\winword.exe - --- - -*`threat.indicator.registry.path`*:: -+ --- -Full path, including hive, key and value - -type: keyword - -example: HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\winword.exe\Debugger - --- - -*`threat.indicator.registry.value`*:: -+ --- -Name of the value written. - -type: keyword - -example: Debugger - --- - -*`threat.indicator.scanner_stats`*:: -+ --- -Count of AV/EDR vendors that successfully detected malicious file or URL. - -type: long - -example: 4 - --- - -*`threat.indicator.sightings`*:: -+ --- -Number of times this indicator was observed conducting threat activity. - -type: long - -example: 20 - --- - -*`threat.indicator.type`*:: -+ --- -Type of indicator as represented by Cyber Observable in STIX 2.0. -Recommended values: - * autonomous-system - * artifact - * directory - * domain-name - * email-addr - * file - * ipv4-addr - * ipv6-addr - * mac-addr - * mutex - * port - * process - * software - * url - * user-account - * windows-registry-key - * x509-certificate - -type: keyword - -example: ipv4-addr - --- - -*`threat.indicator.url.domain`*:: -+ --- -Domain of the url, such as "www.elastic.co". -In some cases a URL may refer to an IP and/or port directly, without a domain name. In this case, the IP address would go to the `domain` field. -If the URL contains a literal IPv6 address enclosed by `[` and `]` (IETF RFC 2732), the `[` and `]` characters should also be captured in the `domain` field. - -type: keyword - -example: www.elastic.co - --- - -*`threat.indicator.url.extension`*:: -+ --- -The field contains the file extension from the original request url, excluding the leading dot. -The file extension is only set if it exists, as not every url has a file extension. -The leading period must not be included. For example, the value must be "png", not ".png". -Note that when the file name has multiple extensions (example.tar.gz), only the last one should be captured ("gz", not "tar.gz"). - -type: keyword - -example: png - --- - -*`threat.indicator.url.fragment`*:: -+ --- -Portion of the url after the `#`, such as "top". -The `#` is not part of the fragment. - -type: keyword - --- - -*`threat.indicator.url.full`*:: -+ --- -If full URLs are important to your use case, they should be stored in `url.full`, whether this field is reconstructed or present in the event source. - -type: wildcard - -example: https://www.elastic.co:443/search?q=elasticsearch#top - --- - -*`threat.indicator.url.full.text`*:: -+ --- -type: match_only_text - --- - -*`threat.indicator.url.original`*:: -+ --- -Unmodified original url as seen in the event source. -Note that in network monitoring, the observed URL may be a full URL, whereas in access logs, the URL is often just represented as a path. -This field is meant to represent the URL as it was observed, complete or not. - -type: wildcard - -example: https://www.elastic.co:443/search?q=elasticsearch#top or /search?q=elasticsearch - --- - -*`threat.indicator.url.original.text`*:: -+ --- -type: match_only_text - --- - -*`threat.indicator.url.password`*:: -+ --- -Password of the request. - -type: keyword - --- - -*`threat.indicator.url.path`*:: -+ --- -Path of the request, such as "/search". - -type: wildcard - --- - -*`threat.indicator.url.port`*:: -+ --- -Port of the request, such as 443. - -type: long - -example: 443 - -format: string - --- - -*`threat.indicator.url.query`*:: -+ --- -The query field describes the query string of the request, such as "q=elasticsearch". -The `?` is excluded from the query string. If a URL contains no `?`, there is no query field. If there is a `?` but no query, the query field exists with an empty string. The `exists` query can be used to differentiate between the two cases. - -type: keyword - --- - -*`threat.indicator.url.registered_domain`*:: -+ --- -The highest registered url domain, stripped of the subdomain. -For example, the registered domain for "foo.example.com" is "example.com". -This value can be determined precisely with a list like the public suffix list (http://publicsuffix.org). Trying to approximate this by simply taking the last two labels will not work well for TLDs such as "co.uk". - -type: keyword - -example: example.com - --- - -*`threat.indicator.url.scheme`*:: -+ --- -Scheme of the request, such as "https". -Note: The `:` is not part of the scheme. - -type: keyword - -example: https - --- - -*`threat.indicator.url.subdomain`*:: -+ --- -The subdomain portion of a fully qualified domain name includes all of the names except the host name under the registered_domain. In a partially qualified domain, or if the the qualification level of the full name cannot be determined, subdomain contains all of the names below the registered domain. -For example the subdomain portion of "www.east.mydomain.co.uk" is "east". If the domain has multiple levels of subdomain, such as "sub2.sub1.example.com", the subdomain field should contain "sub2.sub1", with no trailing period. - -type: keyword - -example: east - --- - -*`threat.indicator.url.top_level_domain`*:: -+ --- -The effective top level domain (eTLD), also known as the domain suffix, is the last part of the domain name. For example, the top level domain for example.com is "com". -This value can be determined precisely with a list like the public suffix list (http://publicsuffix.org). Trying to approximate this by simply taking the last label will not work well for effective TLDs such as "co.uk". - -type: keyword - -example: co.uk - --- - -*`threat.indicator.url.username`*:: -+ --- -Username of the request. - -type: keyword - --- - -*`threat.indicator.x509.alternative_names`*:: -+ --- -List of subject alternative names (SAN). Name types vary by certificate authority and certificate type but commonly contain IP addresses, DNS names (and wildcards), and email addresses. - -type: keyword - -example: *.elastic.co - --- - -*`threat.indicator.x509.issuer.common_name`*:: -+ --- -List of common name (CN) of issuing certificate authority. - -type: keyword - -example: Example SHA2 High Assurance Server CA - --- - -*`threat.indicator.x509.issuer.country`*:: -+ --- -List of country (C) codes - -type: keyword - -example: US - --- - -*`threat.indicator.x509.issuer.distinguished_name`*:: -+ --- -Distinguished name (DN) of issuing certificate authority. - -type: keyword - -example: C=US, O=Example Inc, OU=www.example.com, CN=Example SHA2 High Assurance Server CA - --- - -*`threat.indicator.x509.issuer.locality`*:: -+ --- -List of locality names (L) - -type: keyword - -example: Mountain View - --- - -*`threat.indicator.x509.issuer.organization`*:: -+ --- -List of organizations (O) of issuing certificate authority. - -type: keyword - -example: Example Inc - --- - -*`threat.indicator.x509.issuer.organizational_unit`*:: -+ --- -List of organizational units (OU) of issuing certificate authority. - -type: keyword - -example: www.example.com - --- - -*`threat.indicator.x509.issuer.state_or_province`*:: -+ --- -List of state or province names (ST, S, or P) - -type: keyword - -example: California - --- - -*`threat.indicator.x509.not_after`*:: -+ --- -Time at which the certificate is no longer considered valid. - -type: date - -example: 2020-07-16 03:15:39+00:00 - --- - -*`threat.indicator.x509.not_before`*:: -+ --- -Time at which the certificate is first considered valid. - -type: date - -example: 2019-08-16 01:40:25+00:00 - --- - -*`threat.indicator.x509.public_key_algorithm`*:: -+ --- -Algorithm used to generate the public key. - -type: keyword - -example: RSA - --- - -*`threat.indicator.x509.public_key_curve`*:: -+ --- -The curve used by the elliptic curve public key algorithm. This is algorithm specific. - -type: keyword - -example: nistp521 - --- - -*`threat.indicator.x509.public_key_exponent`*:: -+ --- -Exponent used to derive the public key. This is algorithm specific. - -type: long - -example: 65537 - -Field is not indexed. - --- - -*`threat.indicator.x509.public_key_size`*:: -+ --- -The size of the public key space in bits. - -type: long - -example: 2048 - --- - -*`threat.indicator.x509.serial_number`*:: -+ --- -Unique serial number issued by the certificate authority. For consistency, if this value is alphanumeric, it should be formatted without colons and uppercase characters. - -type: keyword - -example: 55FBB9C7DEBF09809D12CCAA - --- - -*`threat.indicator.x509.signature_algorithm`*:: -+ --- -Identifier for certificate signature algorithm. We recommend using names found in Go Lang Crypto library. See https://github.com/golang/go/blob/go1.14/src/crypto/x509/x509.go#L337-L353. - -type: keyword - -example: SHA256-RSA - --- - -*`threat.indicator.x509.subject.common_name`*:: -+ --- -List of common names (CN) of subject. - -type: keyword - -example: shared.global.example.net - --- - -*`threat.indicator.x509.subject.country`*:: -+ --- -List of country (C) code - -type: keyword - -example: US - --- - -*`threat.indicator.x509.subject.distinguished_name`*:: -+ --- -Distinguished name (DN) of the certificate subject entity. - -type: keyword - -example: C=US, ST=California, L=San Francisco, O=Example, Inc., CN=shared.global.example.net - --- - -*`threat.indicator.x509.subject.locality`*:: -+ --- -List of locality names (L) - -type: keyword - -example: San Francisco - --- - -*`threat.indicator.x509.subject.organization`*:: -+ --- -List of organizations (O) of subject. - -type: keyword - -example: Example, Inc. - --- - -*`threat.indicator.x509.subject.organizational_unit`*:: -+ --- -List of organizational units (OU) of subject. - -type: keyword - --- - -*`threat.indicator.x509.subject.state_or_province`*:: -+ --- -List of state or province names (ST, S, or P) - -type: keyword - -example: California - --- - -*`threat.indicator.x509.version_number`*:: -+ --- -Version of x509 format. - -type: keyword - -example: 3 - --- - -*`threat.software.alias`*:: -+ --- -The alias(es) of the software for a set of related intrusion activity that are tracked by a common name in the security community. -While not required, you can use a MITRE ATT&CK® associated software description. - -type: keyword - -example: [ "X-Agent" ] - --- - -*`threat.software.id`*:: -+ --- -The id of the software used by this threat to conduct behavior commonly modeled using MITRE ATT&CK®. -While not required, you can use a MITRE ATT&CK® software id. - -type: keyword - -example: S0552 - --- - -*`threat.software.name`*:: -+ --- -The name of the software used by this threat to conduct behavior commonly modeled using MITRE ATT&CK®. -While not required, you can use a MITRE ATT&CK® software name. - -type: keyword - -example: AdFind - --- - -*`threat.software.platforms`*:: -+ --- -The platforms of the software used by this threat to conduct behavior commonly modeled using MITRE ATT&CK®. -Recommended Values: - * AWS - * Azure - * Azure AD - * GCP - * Linux - * macOS - * Network - * Office 365 - * SaaS - * Windows - -While not required, you can use a MITRE ATT&CK® software platforms. - -type: keyword - -example: [ "Windows" ] - --- - -*`threat.software.reference`*:: -+ --- -The reference URL of the software used by this threat to conduct behavior commonly modeled using MITRE ATT&CK®. -While not required, you can use a MITRE ATT&CK® software reference URL. - -type: keyword - -example: https://attack.mitre.org/software/S0552/ - --- - -*`threat.software.type`*:: -+ --- -The type of software used by this threat to conduct behavior commonly modeled using MITRE ATT&CK®. -Recommended values - * Malware - * Tool - - While not required, you can use a MITRE ATT&CK® software type. - -type: keyword - -example: Tool - --- - -*`threat.tactic.id`*:: -+ --- -The id of tactic used by this threat. You can use a MITRE ATT&CK® tactic, for example. (ex. https://attack.mitre.org/tactics/TA0002/ ) - -type: keyword - -example: TA0002 - --- - -*`threat.tactic.name`*:: -+ --- -Name of the type of tactic used by this threat. You can use a MITRE ATT&CK® tactic, for example. (ex. https://attack.mitre.org/tactics/TA0002/) - -type: keyword - -example: Execution - --- - -*`threat.tactic.reference`*:: -+ --- -The reference url of tactic used by this threat. You can use a MITRE ATT&CK® tactic, for example. (ex. https://attack.mitre.org/tactics/TA0002/ ) - -type: keyword - -example: https://attack.mitre.org/tactics/TA0002/ - --- - -*`threat.technique.id`*:: -+ --- -The id of technique used by this threat. You can use a MITRE ATT&CK® technique, for example. (ex. https://attack.mitre.org/techniques/T1059/) - -type: keyword - -example: T1059 - --- - -*`threat.technique.name`*:: -+ --- -The name of technique used by this threat. You can use a MITRE ATT&CK® technique, for example. (ex. https://attack.mitre.org/techniques/T1059/) - -type: keyword - -example: Command and Scripting Interpreter - --- - -*`threat.technique.name.text`*:: -+ --- -type: match_only_text - --- - -*`threat.technique.reference`*:: -+ --- -The reference url of technique used by this threat. You can use a MITRE ATT&CK® technique, for example. (ex. https://attack.mitre.org/techniques/T1059/) - -type: keyword - -example: https://attack.mitre.org/techniques/T1059/ - --- - -*`threat.technique.subtechnique.id`*:: -+ --- -The full id of subtechnique used by this threat. You can use a MITRE ATT&CK® subtechnique, for example. (ex. https://attack.mitre.org/techniques/T1059/001/) - -type: keyword - -example: T1059.001 - --- - -*`threat.technique.subtechnique.name`*:: -+ --- -The name of subtechnique used by this threat. You can use a MITRE ATT&CK® subtechnique, for example. (ex. https://attack.mitre.org/techniques/T1059/001/) - -type: keyword - -example: PowerShell - --- - -*`threat.technique.subtechnique.name.text`*:: -+ --- -type: match_only_text - --- - -*`threat.technique.subtechnique.reference`*:: -+ --- -The reference url of subtechnique used by this threat. You can use a MITRE ATT&CK® subtechnique, for example. (ex. https://attack.mitre.org/techniques/T1059/001/) - -type: keyword - -example: https://attack.mitre.org/techniques/T1059/001/ - --- - -[float] -=== tls - -Fields related to a TLS connection. These fields focus on the TLS protocol itself and intentionally avoids in-depth analysis of the related x.509 certificate files. - - -*`tls.cipher`*:: -+ --- -String indicating the cipher used during the current connection. - -type: keyword - -example: TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 - --- - -*`tls.client.certificate`*:: -+ --- -PEM-encoded stand-alone certificate offered by the client. This is usually mutually-exclusive of `client.certificate_chain` since this value also exists in that list. - -type: keyword - -example: MII... - --- - -*`tls.client.certificate_chain`*:: -+ --- -Array of PEM-encoded certificates that make up the certificate chain offered by the client. This is usually mutually-exclusive of `client.certificate` since that value should be the first certificate in the chain. - -type: keyword - -example: ["MII...", "MII..."] - --- - -*`tls.client.hash.md5`*:: -+ --- -Certificate fingerprint using the MD5 digest of DER-encoded version of certificate offered by the client. For consistency with other hash values, this value should be formatted as an uppercase hash. - -type: keyword - -example: 0F76C7F2C55BFD7D8E8B8F4BFBF0C9EC - --- - -*`tls.client.hash.sha1`*:: -+ --- -Certificate fingerprint using the SHA1 digest of DER-encoded version of certificate offered by the client. For consistency with other hash values, this value should be formatted as an uppercase hash. - -type: keyword - -example: 9E393D93138888D288266C2D915214D1D1CCEB2A - --- - -*`tls.client.hash.sha256`*:: -+ --- -Certificate fingerprint using the SHA256 digest of DER-encoded version of certificate offered by the client. For consistency with other hash values, this value should be formatted as an uppercase hash. - -type: keyword - -example: 0687F666A054EF17A08E2F2162EAB4CBC0D265E1D7875BE74BF3C712CA92DAF0 - --- - -*`tls.client.issuer`*:: -+ --- -Distinguished name of subject of the issuer of the x.509 certificate presented by the client. - -type: keyword - -example: CN=Example Root CA, OU=Infrastructure Team, DC=example, DC=com - --- - -*`tls.client.ja3`*:: -+ --- -A hash that identifies clients based on how they perform an SSL/TLS handshake. - -type: keyword - -example: d4e5b18d6b55c71272893221c96ba240 - --- - -*`tls.client.not_after`*:: -+ --- -Date/Time indicating when client certificate is no longer considered valid. - -type: date - -example: 2021-01-01T00:00:00.000Z - --- - -*`tls.client.not_before`*:: -+ --- -Date/Time indicating when client certificate is first considered valid. - -type: date - -example: 1970-01-01T00:00:00.000Z - --- - -*`tls.client.server_name`*:: -+ --- -Also called an SNI, this tells the server which hostname to which the client is attempting to connect to. When this value is available, it should get copied to `destination.domain`. - -type: keyword - -example: www.elastic.co - --- - -*`tls.client.subject`*:: -+ --- -Distinguished name of subject of the x.509 certificate presented by the client. - -type: keyword - -example: CN=myclient, OU=Documentation Team, DC=example, DC=com - --- - -*`tls.client.supported_ciphers`*:: -+ --- -Array of ciphers offered by the client during the client hello. - -type: keyword - -example: ["TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384", "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384", "..."] - --- - -*`tls.client.x509.alternative_names`*:: -+ --- -List of subject alternative names (SAN). Name types vary by certificate authority and certificate type but commonly contain IP addresses, DNS names (and wildcards), and email addresses. - -type: keyword - -example: *.elastic.co - --- - -*`tls.client.x509.issuer.common_name`*:: -+ --- -List of common name (CN) of issuing certificate authority. - -type: keyword - -example: Example SHA2 High Assurance Server CA - --- - -*`tls.client.x509.issuer.country`*:: -+ --- -List of country (C) codes - -type: keyword - -example: US - --- - -*`tls.client.x509.issuer.distinguished_name`*:: -+ --- -Distinguished name (DN) of issuing certificate authority. - -type: keyword - -example: C=US, O=Example Inc, OU=www.example.com, CN=Example SHA2 High Assurance Server CA - --- - -*`tls.client.x509.issuer.locality`*:: -+ --- -List of locality names (L) - -type: keyword - -example: Mountain View - --- - -*`tls.client.x509.issuer.organization`*:: -+ --- -List of organizations (O) of issuing certificate authority. - -type: keyword - -example: Example Inc - --- - -*`tls.client.x509.issuer.organizational_unit`*:: -+ --- -List of organizational units (OU) of issuing certificate authority. - -type: keyword - -example: www.example.com - --- - -*`tls.client.x509.issuer.state_or_province`*:: -+ --- -List of state or province names (ST, S, or P) - -type: keyword - -example: California - --- - -*`tls.client.x509.not_after`*:: -+ --- -Time at which the certificate is no longer considered valid. - -type: date - -example: 2020-07-16 03:15:39+00:00 - --- - -*`tls.client.x509.not_before`*:: -+ --- -Time at which the certificate is first considered valid. - -type: date - -example: 2019-08-16 01:40:25+00:00 - --- - -*`tls.client.x509.public_key_algorithm`*:: -+ --- -Algorithm used to generate the public key. - -type: keyword - -example: RSA - --- - -*`tls.client.x509.public_key_curve`*:: -+ --- -The curve used by the elliptic curve public key algorithm. This is algorithm specific. - -type: keyword - -example: nistp521 - --- - -*`tls.client.x509.public_key_exponent`*:: -+ --- -Exponent used to derive the public key. This is algorithm specific. - -type: long - -example: 65537 - -Field is not indexed. - --- - -*`tls.client.x509.public_key_size`*:: -+ --- -The size of the public key space in bits. - -type: long - -example: 2048 - --- - -*`tls.client.x509.serial_number`*:: -+ --- -Unique serial number issued by the certificate authority. For consistency, if this value is alphanumeric, it should be formatted without colons and uppercase characters. - -type: keyword - -example: 55FBB9C7DEBF09809D12CCAA - --- - -*`tls.client.x509.signature_algorithm`*:: -+ --- -Identifier for certificate signature algorithm. We recommend using names found in Go Lang Crypto library. See https://github.com/golang/go/blob/go1.14/src/crypto/x509/x509.go#L337-L353. - -type: keyword - -example: SHA256-RSA - --- - -*`tls.client.x509.subject.common_name`*:: -+ --- -List of common names (CN) of subject. - -type: keyword - -example: shared.global.example.net - --- - -*`tls.client.x509.subject.country`*:: -+ --- -List of country (C) code - -type: keyword - -example: US - --- - -*`tls.client.x509.subject.distinguished_name`*:: -+ --- -Distinguished name (DN) of the certificate subject entity. - -type: keyword - -example: C=US, ST=California, L=San Francisco, O=Example, Inc., CN=shared.global.example.net - --- - -*`tls.client.x509.subject.locality`*:: -+ --- -List of locality names (L) - -type: keyword - -example: San Francisco - --- - -*`tls.client.x509.subject.organization`*:: -+ --- -List of organizations (O) of subject. - -type: keyword - -example: Example, Inc. - --- - -*`tls.client.x509.subject.organizational_unit`*:: -+ --- -List of organizational units (OU) of subject. - -type: keyword - --- - -*`tls.client.x509.subject.state_or_province`*:: -+ --- -List of state or province names (ST, S, or P) - -type: keyword - -example: California - --- - -*`tls.client.x509.version_number`*:: -+ --- -Version of x509 format. - -type: keyword - -example: 3 - --- - -*`tls.curve`*:: -+ --- -String indicating the curve used for the given cipher, when applicable. - -type: keyword - -example: secp256r1 - --- - -*`tls.established`*:: -+ --- -Boolean flag indicating if the TLS negotiation was successful and transitioned to an encrypted tunnel. - -type: boolean - --- - -*`tls.next_protocol`*:: -+ --- -String indicating the protocol being tunneled. Per the values in the IANA registry (https://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml#alpn-protocol-ids), this string should be lower case. - -type: keyword - -example: http/1.1 - --- - -*`tls.resumed`*:: -+ --- -Boolean flag indicating if this TLS connection was resumed from an existing TLS negotiation. - -type: boolean - --- - -*`tls.server.certificate`*:: -+ --- -PEM-encoded stand-alone certificate offered by the server. This is usually mutually-exclusive of `server.certificate_chain` since this value also exists in that list. - -type: keyword - -example: MII... - --- - -*`tls.server.certificate_chain`*:: -+ --- -Array of PEM-encoded certificates that make up the certificate chain offered by the server. This is usually mutually-exclusive of `server.certificate` since that value should be the first certificate in the chain. - -type: keyword - -example: ["MII...", "MII..."] - --- - -*`tls.server.hash.md5`*:: -+ --- -Certificate fingerprint using the MD5 digest of DER-encoded version of certificate offered by the server. For consistency with other hash values, this value should be formatted as an uppercase hash. - -type: keyword - -example: 0F76C7F2C55BFD7D8E8B8F4BFBF0C9EC - --- - -*`tls.server.hash.sha1`*:: -+ --- -Certificate fingerprint using the SHA1 digest of DER-encoded version of certificate offered by the server. For consistency with other hash values, this value should be formatted as an uppercase hash. - -type: keyword - -example: 9E393D93138888D288266C2D915214D1D1CCEB2A - --- - -*`tls.server.hash.sha256`*:: -+ --- -Certificate fingerprint using the SHA256 digest of DER-encoded version of certificate offered by the server. For consistency with other hash values, this value should be formatted as an uppercase hash. - -type: keyword - -example: 0687F666A054EF17A08E2F2162EAB4CBC0D265E1D7875BE74BF3C712CA92DAF0 - --- - -*`tls.server.issuer`*:: -+ --- -Subject of the issuer of the x.509 certificate presented by the server. - -type: keyword - -example: CN=Example Root CA, OU=Infrastructure Team, DC=example, DC=com - --- - -*`tls.server.ja3s`*:: -+ --- -A hash that identifies servers based on how they perform an SSL/TLS handshake. - -type: keyword - -example: 394441ab65754e2207b1e1b457b3641d - --- - -*`tls.server.not_after`*:: -+ --- -Timestamp indicating when server certificate is no longer considered valid. - -type: date - -example: 2021-01-01T00:00:00.000Z - --- - -*`tls.server.not_before`*:: -+ --- -Timestamp indicating when server certificate is first considered valid. - -type: date - -example: 1970-01-01T00:00:00.000Z - --- - -*`tls.server.subject`*:: -+ --- -Subject of the x.509 certificate presented by the server. - -type: keyword - -example: CN=www.example.com, OU=Infrastructure Team, DC=example, DC=com - --- - -*`tls.server.x509.alternative_names`*:: -+ --- -List of subject alternative names (SAN). Name types vary by certificate authority and certificate type but commonly contain IP addresses, DNS names (and wildcards), and email addresses. - -type: keyword - -example: *.elastic.co - --- - -*`tls.server.x509.issuer.common_name`*:: -+ --- -List of common name (CN) of issuing certificate authority. - -type: keyword - -example: Example SHA2 High Assurance Server CA - --- - -*`tls.server.x509.issuer.country`*:: -+ --- -List of country (C) codes - -type: keyword - -example: US - --- - -*`tls.server.x509.issuer.distinguished_name`*:: -+ --- -Distinguished name (DN) of issuing certificate authority. - -type: keyword - -example: C=US, O=Example Inc, OU=www.example.com, CN=Example SHA2 High Assurance Server CA - --- - -*`tls.server.x509.issuer.locality`*:: -+ --- -List of locality names (L) - -type: keyword - -example: Mountain View - --- - -*`tls.server.x509.issuer.organization`*:: -+ --- -List of organizations (O) of issuing certificate authority. - -type: keyword - -example: Example Inc - --- - -*`tls.server.x509.issuer.organizational_unit`*:: -+ --- -List of organizational units (OU) of issuing certificate authority. - -type: keyword - -example: www.example.com - --- - -*`tls.server.x509.issuer.state_or_province`*:: -+ --- -List of state or province names (ST, S, or P) - -type: keyword - -example: California - --- - -*`tls.server.x509.not_after`*:: -+ --- -Time at which the certificate is no longer considered valid. - -type: date - -example: 2020-07-16 03:15:39+00:00 - --- - -*`tls.server.x509.not_before`*:: -+ --- -Time at which the certificate is first considered valid. - -type: date - -example: 2019-08-16 01:40:25+00:00 - --- - -*`tls.server.x509.public_key_algorithm`*:: -+ --- -Algorithm used to generate the public key. - -type: keyword - -example: RSA - --- - -*`tls.server.x509.public_key_curve`*:: -+ --- -The curve used by the elliptic curve public key algorithm. This is algorithm specific. - -type: keyword - -example: nistp521 - --- - -*`tls.server.x509.public_key_exponent`*:: -+ --- -Exponent used to derive the public key. This is algorithm specific. - -type: long - -example: 65537 - -Field is not indexed. - --- - -*`tls.server.x509.public_key_size`*:: -+ --- -The size of the public key space in bits. - -type: long - -example: 2048 - --- - -*`tls.server.x509.serial_number`*:: -+ --- -Unique serial number issued by the certificate authority. For consistency, if this value is alphanumeric, it should be formatted without colons and uppercase characters. - -type: keyword - -example: 55FBB9C7DEBF09809D12CCAA - --- - -*`tls.server.x509.signature_algorithm`*:: -+ --- -Identifier for certificate signature algorithm. We recommend using names found in Go Lang Crypto library. See https://github.com/golang/go/blob/go1.14/src/crypto/x509/x509.go#L337-L353. - -type: keyword - -example: SHA256-RSA - --- - -*`tls.server.x509.subject.common_name`*:: -+ --- -List of common names (CN) of subject. - -type: keyword - -example: shared.global.example.net - --- - -*`tls.server.x509.subject.country`*:: -+ --- -List of country (C) code - -type: keyword - -example: US - --- - -*`tls.server.x509.subject.distinguished_name`*:: -+ --- -Distinguished name (DN) of the certificate subject entity. - -type: keyword - -example: C=US, ST=California, L=San Francisco, O=Example, Inc., CN=shared.global.example.net - --- - -*`tls.server.x509.subject.locality`*:: -+ --- -List of locality names (L) - -type: keyword - -example: San Francisco - --- - -*`tls.server.x509.subject.organization`*:: -+ --- -List of organizations (O) of subject. - -type: keyword - -example: Example, Inc. - --- - -*`tls.server.x509.subject.organizational_unit`*:: -+ --- -List of organizational units (OU) of subject. - -type: keyword - --- - -*`tls.server.x509.subject.state_or_province`*:: -+ --- -List of state or province names (ST, S, or P) - -type: keyword - -example: California - --- - -*`tls.server.x509.version_number`*:: -+ --- -Version of x509 format. - -type: keyword - -example: 3 - --- - -*`tls.version`*:: -+ --- -Numeric part of the version parsed from the original string. - -type: keyword - -example: 1.2 - --- - -*`tls.version_protocol`*:: -+ --- -Normalized lowercase protocol name parsed from original string. - -type: keyword - -example: tls - --- - -*`span.id`*:: -+ --- -Unique identifier of the span within the scope of its trace. -A span represents an operation within a transaction, such as a request to another service, or a database query. - -type: keyword - -example: 3ff9a8981b7ccd5a - --- - -*`trace.id`*:: -+ --- -Unique identifier of the trace. -A trace groups multiple events like transactions that belong together. For example, a user request handled by multiple inter-connected services. - -type: keyword - -example: 4bf92f3577b34da6a3ce929d0e0e4736 - --- - -*`transaction.id`*:: -+ --- -Unique identifier of the transaction within the scope of its trace. -A transaction is the highest level of work measured within a service, such as a request to a server. - -type: keyword - -example: 00f067aa0ba902b7 - --- - -[float] -=== url - -URL fields provide support for complete or partial URLs, and supports the breaking down into scheme, domain, path, and so on. - - -*`url.domain`*:: -+ --- -Domain of the url, such as "www.elastic.co". -In some cases a URL may refer to an IP and/or port directly, without a domain name. In this case, the IP address would go to the `domain` field. -If the URL contains a literal IPv6 address enclosed by `[` and `]` (IETF RFC 2732), the `[` and `]` characters should also be captured in the `domain` field. - -type: keyword - -example: www.elastic.co - --- - -*`url.extension`*:: -+ --- -The field contains the file extension from the original request url, excluding the leading dot. -The file extension is only set if it exists, as not every url has a file extension. -The leading period must not be included. For example, the value must be "png", not ".png". -Note that when the file name has multiple extensions (example.tar.gz), only the last one should be captured ("gz", not "tar.gz"). - -type: keyword - -example: png - --- - -*`url.fragment`*:: -+ --- -Portion of the url after the `#`, such as "top". -The `#` is not part of the fragment. - -type: keyword - --- - -*`url.full`*:: -+ --- -If full URLs are important to your use case, they should be stored in `url.full`, whether this field is reconstructed or present in the event source. - -type: wildcard - -example: https://www.elastic.co:443/search?q=elasticsearch#top - --- - -*`url.full.text`*:: -+ --- -type: match_only_text - --- - -*`url.original`*:: -+ --- -Unmodified original url as seen in the event source. -Note that in network monitoring, the observed URL may be a full URL, whereas in access logs, the URL is often just represented as a path. -This field is meant to represent the URL as it was observed, complete or not. - -type: wildcard - -example: https://www.elastic.co:443/search?q=elasticsearch#top or /search?q=elasticsearch - --- - -*`url.original.text`*:: -+ --- -type: match_only_text - --- - -*`url.password`*:: -+ --- -Password of the request. - -type: keyword - --- - -*`url.path`*:: -+ --- -Path of the request, such as "/search". - -type: wildcard - --- - -*`url.port`*:: -+ --- -Port of the request, such as 443. - -type: long - -example: 443 - -format: string - --- - -*`url.query`*:: -+ --- -The query field describes the query string of the request, such as "q=elasticsearch". -The `?` is excluded from the query string. If a URL contains no `?`, there is no query field. If there is a `?` but no query, the query field exists with an empty string. The `exists` query can be used to differentiate between the two cases. - -type: keyword - --- - -*`url.registered_domain`*:: -+ --- -The highest registered url domain, stripped of the subdomain. -For example, the registered domain for "foo.example.com" is "example.com". -This value can be determined precisely with a list like the public suffix list (http://publicsuffix.org). Trying to approximate this by simply taking the last two labels will not work well for TLDs such as "co.uk". - -type: keyword - -example: example.com - --- - -*`url.scheme`*:: -+ --- -Scheme of the request, such as "https". -Note: The `:` is not part of the scheme. - -type: keyword - -example: https - --- - -*`url.subdomain`*:: -+ --- -The subdomain portion of a fully qualified domain name includes all of the names except the host name under the registered_domain. In a partially qualified domain, or if the the qualification level of the full name cannot be determined, subdomain contains all of the names below the registered domain. -For example the subdomain portion of "www.east.mydomain.co.uk" is "east". If the domain has multiple levels of subdomain, such as "sub2.sub1.example.com", the subdomain field should contain "sub2.sub1", with no trailing period. - -type: keyword - -example: east - --- - -*`url.top_level_domain`*:: -+ --- -The effective top level domain (eTLD), also known as the domain suffix, is the last part of the domain name. For example, the top level domain for example.com is "com". -This value can be determined precisely with a list like the public suffix list (http://publicsuffix.org). Trying to approximate this by simply taking the last label will not work well for effective TLDs such as "co.uk". - -type: keyword - -example: co.uk - --- - -*`url.username`*:: -+ --- -Username of the request. - -type: keyword - --- - -[float] -=== user - -The user fields describe information about the user that is relevant to the event. -Fields can have one entry or multiple entries. If a user has more than one id, provide an array that includes all of them. - - -*`user.changes.domain`*:: -+ --- -Name of the directory the user is a member of. -For example, an LDAP or Active Directory domain name. - -type: keyword - --- - -*`user.changes.email`*:: -+ --- -User email address. - -type: keyword - --- - -*`user.changes.full_name`*:: -+ --- -User's full name, if available. - -type: keyword - -example: Albert Einstein - --- - -*`user.changes.full_name.text`*:: -+ --- -type: match_only_text - --- - -*`user.changes.group.domain`*:: -+ --- -Name of the directory the group is a member of. -For example, an LDAP or Active Directory domain name. - -type: keyword - --- - -*`user.changes.group.id`*:: -+ --- -Unique identifier for the group on the system/platform. - -type: keyword - --- - -*`user.changes.group.name`*:: -+ --- -Name of the group. - -type: keyword - --- - -*`user.changes.hash`*:: -+ --- -Unique user hash to correlate information for a user in anonymized form. -Useful if `user.id` or `user.name` contain confidential information and cannot be used. - -type: keyword - --- - -*`user.changes.id`*:: -+ --- -Unique identifier of the user. - -type: keyword - -example: S-1-5-21-202424912787-2692429404-2351956786-1000 - --- - -*`user.changes.name`*:: -+ --- -Short name or login of the user. - -type: keyword - -example: a.einstein - --- - -*`user.changes.name.text`*:: -+ --- -type: match_only_text - --- - -*`user.changes.roles`*:: -+ --- -Array of user roles at the time of the event. - -type: keyword - -example: ["kibana_admin", "reporting_user"] - --- - -*`user.domain`*:: -+ --- -Name of the directory the user is a member of. -For example, an LDAP or Active Directory domain name. - -type: keyword - --- - -*`user.effective.domain`*:: -+ --- -Name of the directory the user is a member of. -For example, an LDAP or Active Directory domain name. - -type: keyword - --- - -*`user.effective.email`*:: -+ --- -User email address. - -type: keyword - --- - -*`user.effective.full_name`*:: -+ --- -User's full name, if available. - -type: keyword - -example: Albert Einstein - --- - -*`user.effective.full_name.text`*:: -+ --- -type: match_only_text - --- - -*`user.effective.group.domain`*:: -+ --- -Name of the directory the group is a member of. -For example, an LDAP or Active Directory domain name. - -type: keyword - --- - -*`user.effective.group.id`*:: -+ --- -Unique identifier for the group on the system/platform. - -type: keyword - --- - -*`user.effective.group.name`*:: -+ --- -Name of the group. - -type: keyword - --- - -*`user.effective.hash`*:: -+ --- -Unique user hash to correlate information for a user in anonymized form. -Useful if `user.id` or `user.name` contain confidential information and cannot be used. - -type: keyword - --- - -*`user.effective.id`*:: -+ --- -Unique identifier of the user. - -type: keyword - -example: S-1-5-21-202424912787-2692429404-2351956786-1000 - --- - -*`user.effective.name`*:: -+ --- -Short name or login of the user. - -type: keyword - -example: a.einstein - --- - -*`user.effective.name.text`*:: -+ --- -type: match_only_text - --- - -*`user.effective.roles`*:: -+ --- -Array of user roles at the time of the event. - -type: keyword - -example: ["kibana_admin", "reporting_user"] - --- - -*`user.email`*:: -+ --- -User email address. - -type: keyword - --- - -*`user.full_name`*:: -+ --- -User's full name, if available. - -type: keyword - -example: Albert Einstein - --- - -*`user.full_name.text`*:: -+ --- -type: match_only_text - --- - -*`user.group.domain`*:: -+ --- -Name of the directory the group is a member of. -For example, an LDAP or Active Directory domain name. - -type: keyword - --- - -*`user.group.id`*:: -+ --- -Unique identifier for the group on the system/platform. - -type: keyword - --- - -*`user.group.name`*:: -+ --- -Name of the group. - -type: keyword - --- - -*`user.hash`*:: -+ --- -Unique user hash to correlate information for a user in anonymized form. -Useful if `user.id` or `user.name` contain confidential information and cannot be used. - -type: keyword - --- - -*`user.id`*:: -+ --- -Unique identifier of the user. - -type: keyword - -example: S-1-5-21-202424912787-2692429404-2351956786-1000 - --- - -*`user.name`*:: -+ --- -Short name or login of the user. - -type: keyword - -example: a.einstein - --- - -*`user.name.text`*:: -+ --- -type: match_only_text - --- - -*`user.roles`*:: -+ --- -Array of user roles at the time of the event. - -type: keyword - -example: ["kibana_admin", "reporting_user"] - --- - -*`user.target.domain`*:: -+ --- -Name of the directory the user is a member of. -For example, an LDAP or Active Directory domain name. - -type: keyword - --- - -*`user.target.email`*:: -+ --- -User email address. - -type: keyword - --- - -*`user.target.full_name`*:: -+ --- -User's full name, if available. - -type: keyword - -example: Albert Einstein - --- - -*`user.target.full_name.text`*:: -+ --- -type: match_only_text - --- - -*`user.target.group.domain`*:: -+ --- -Name of the directory the group is a member of. -For example, an LDAP or Active Directory domain name. - -type: keyword - --- - -*`user.target.group.id`*:: -+ --- -Unique identifier for the group on the system/platform. - -type: keyword - --- - -*`user.target.group.name`*:: -+ --- -Name of the group. - -type: keyword - --- - -*`user.target.hash`*:: -+ --- -Unique user hash to correlate information for a user in anonymized form. -Useful if `user.id` or `user.name` contain confidential information and cannot be used. - -type: keyword - --- - -*`user.target.id`*:: -+ --- -Unique identifier of the user. - -type: keyword - -example: S-1-5-21-202424912787-2692429404-2351956786-1000 - --- - -*`user.target.name`*:: -+ --- -Short name or login of the user. - -type: keyword - -example: a.einstein - --- - -*`user.target.name.text`*:: -+ --- -type: match_only_text - --- - -*`user.target.roles`*:: -+ --- -Array of user roles at the time of the event. - -type: keyword - -example: ["kibana_admin", "reporting_user"] - --- - -[float] -=== user_agent - -The user_agent fields normally come from a browser request. -They often show up in web service logs coming from the parsed user agent string. - - -*`user_agent.device.name`*:: -+ --- -Name of the device. - -type: keyword - -example: iPhone - --- - -*`user_agent.name`*:: -+ --- -Name of the user agent. - -type: keyword - -example: Safari - --- - -*`user_agent.original`*:: -+ --- -Unparsed user_agent string. - -type: keyword - -example: Mozilla/5.0 (iPhone; CPU iPhone OS 12_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/12.0 Mobile/15E148 Safari/604.1 - --- - -*`user_agent.original.text`*:: -+ --- -type: match_only_text - --- - -*`user_agent.os.family`*:: -+ --- -OS family (such as redhat, debian, freebsd, windows). - -type: keyword - -example: debian - --- - -*`user_agent.os.full`*:: -+ --- -Operating system name, including the version or code name. - -type: keyword - -example: Mac OS Mojave - --- - -*`user_agent.os.full.text`*:: -+ --- -type: match_only_text - --- - -*`user_agent.os.kernel`*:: -+ --- -Operating system kernel version as a raw string. - -type: keyword - -example: 4.4.0-112-generic - --- - -*`user_agent.os.name`*:: -+ --- -Operating system name, without the version. - -type: keyword - -example: Mac OS X - --- - -*`user_agent.os.name.text`*:: -+ --- -type: match_only_text - --- - -*`user_agent.os.platform`*:: -+ --- -Operating system platform (such centos, ubuntu, windows). - -type: keyword - -example: darwin - --- - -*`user_agent.os.type`*:: -+ --- -Use the `os.type` field to categorize the operating system into one of the broad commercial families. -One of these following values should be used (lowercase): linux, macos, unix, windows. -If the OS you're dealing with is not in the list, the field should not be populated. Please let us know by opening an issue with ECS, to propose its addition. - -type: keyword - -example: macos - --- - -*`user_agent.os.version`*:: -+ --- -Operating system version as a raw string. - -type: keyword - -example: 10.14.1 - --- - -*`user_agent.version`*:: -+ --- -Version of the user agent. - -type: keyword - -example: 12.0 - --- - -[float] -=== vlan - -The VLAN fields are used to identify 802.1q tag(s) of a packet, as well as ingress and egress VLAN associations of an observer in relation to a specific packet or connection. -Network.vlan fields are used to record a single VLAN tag, or the outer tag in the case of q-in-q encapsulations, for a packet or connection as observed, typically provided by a network sensor (e.g. Zeek, Wireshark) passively reporting on traffic. -Network.inner VLAN fields are used to report inner q-in-q 802.1q tags (multiple 802.1q encapsulations) as observed, typically provided by a network sensor (e.g. Zeek, Wireshark) passively reporting on traffic. Network.inner VLAN fields should only be used in addition to network.vlan fields to indicate q-in-q tagging. -Observer.ingress and observer.egress VLAN values are used to record observer specific information when observer events contain discrete ingress and egress VLAN information, typically provided by firewalls, routers, or load balancers. - - -*`vlan.id`*:: -+ --- -VLAN ID as reported by the observer. - -type: keyword - -example: 10 - --- - -*`vlan.name`*:: -+ --- -Optional VLAN name as reported by the observer. - -type: keyword - -example: outside - --- - -[float] -=== vulnerability - -The vulnerability fields describe information about a vulnerability that is relevant to an event. - - -*`vulnerability.category`*:: -+ --- -The type of system or architecture that the vulnerability affects. These may be platform-specific (for example, Debian or SUSE) or general (for example, Database or Firewall). For example (https://qualysguard.qualys.com/qwebhelp/fo_portal/knowledgebase/vulnerability_categories.htm[Qualys vulnerability categories]) -This field must be an array. - -type: keyword - -example: ["Firewall"] - --- - -*`vulnerability.classification`*:: -+ --- -The classification of the vulnerability scoring system. For example (https://www.first.org/cvss/) - -type: keyword - -example: CVSS - --- - -*`vulnerability.description`*:: -+ --- -The description of the vulnerability that provides additional context of the vulnerability. For example (https://cve.mitre.org/about/faqs.html#cve_entry_descriptions_created[Common Vulnerabilities and Exposure CVE description]) - -type: keyword - -example: In macOS before 2.12.6, there is a vulnerability in the RPC... - --- - -*`vulnerability.description.text`*:: -+ --- -type: match_only_text - --- - -*`vulnerability.enumeration`*:: -+ --- -The type of identifier used for this vulnerability. For example (https://cve.mitre.org/about/) - -type: keyword - -example: CVE - --- - -*`vulnerability.id`*:: -+ --- -The identification (ID) is the number portion of a vulnerability entry. It includes a unique identification number for the vulnerability. For example (https://cve.mitre.org/about/faqs.html#what_is_cve_id)[Common Vulnerabilities and Exposure CVE ID] - -type: keyword - -example: CVE-2019-00001 - --- - -*`vulnerability.reference`*:: -+ --- -A resource that provides additional information, context, and mitigations for the identified vulnerability. - -type: keyword - -example: https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-6111 - --- - -*`vulnerability.report_id`*:: -+ --- -The report or scan identification number. - -type: keyword - -example: 20191018.0001 - --- - -*`vulnerability.scanner.vendor`*:: -+ --- -The name of the vulnerability scanner vendor. - -type: keyword - -example: Tenable - --- - -*`vulnerability.score.base`*:: -+ --- -Scores can range from 0.0 to 10.0, with 10.0 being the most severe. -Base scores cover an assessment for exploitability metrics (attack vector, complexity, privileges, and user interaction), impact metrics (confidentiality, integrity, and availability), and scope. For example (https://www.first.org/cvss/specification-document) - -type: float - -example: 5.5 - --- - -*`vulnerability.score.environmental`*:: -+ --- -Scores can range from 0.0 to 10.0, with 10.0 being the most severe. -Environmental scores cover an assessment for any modified Base metrics, confidentiality, integrity, and availability requirements. For example (https://www.first.org/cvss/specification-document) - -type: float - -example: 5.5 - --- - -*`vulnerability.score.temporal`*:: -+ --- -Scores can range from 0.0 to 10.0, with 10.0 being the most severe. -Temporal scores cover an assessment for code maturity, remediation level, and confidence. For example (https://www.first.org/cvss/specification-document) - -type: float - --- - -*`vulnerability.score.version`*:: -+ --- -The National Vulnerability Database (NVD) provides qualitative severity rankings of "Low", "Medium", and "High" for CVSS v2.0 base score ranges in addition to the severity ratings for CVSS v3.0 as they are defined in the CVSS v3.0 specification. -CVSS is owned and managed by FIRST.Org, Inc. (FIRST), a US-based non-profit organization, whose mission is to help computer security incident response teams across the world. For example (https://nvd.nist.gov/vuln-metrics/cvss) - -type: keyword - -example: 2.0 - --- - -*`vulnerability.severity`*:: -+ --- -The severity of the vulnerability can help with metrics and internal prioritization regarding remediation. For example (https://nvd.nist.gov/vuln-metrics/cvss) - -type: keyword - -example: Critical - --- - -[float] -=== x509 - -This implements the common core fields for x509 certificates. This information is likely logged with TLS sessions, digital signatures found in executable binaries, S/MIME information in email bodies, or analysis of files on disk. -When the certificate relates to a file, use the fields at `file.x509`. When hashes of the DER-encoded certificate are available, the `hash` data set should be populated as well (e.g. `file.hash.sha256`). -Events that contain certificate information about network connections, should use the x509 fields under the relevant TLS fields: `tls.server.x509` and/or `tls.client.x509`. - - -*`x509.alternative_names`*:: -+ --- -List of subject alternative names (SAN). Name types vary by certificate authority and certificate type but commonly contain IP addresses, DNS names (and wildcards), and email addresses. - -type: keyword - -example: *.elastic.co - --- - -*`x509.issuer.common_name`*:: -+ --- -List of common name (CN) of issuing certificate authority. - -type: keyword - -example: Example SHA2 High Assurance Server CA - --- - -*`x509.issuer.country`*:: -+ --- -List of country (C) codes - -type: keyword - -example: US - --- - -*`x509.issuer.distinguished_name`*:: -+ --- -Distinguished name (DN) of issuing certificate authority. - -type: keyword - -example: C=US, O=Example Inc, OU=www.example.com, CN=Example SHA2 High Assurance Server CA - --- - -*`x509.issuer.locality`*:: -+ --- -List of locality names (L) - -type: keyword - -example: Mountain View - --- - -*`x509.issuer.organization`*:: -+ --- -List of organizations (O) of issuing certificate authority. - -type: keyword - -example: Example Inc - --- - -*`x509.issuer.organizational_unit`*:: -+ --- -List of organizational units (OU) of issuing certificate authority. - -type: keyword - -example: www.example.com - --- - -*`x509.issuer.state_or_province`*:: -+ --- -List of state or province names (ST, S, or P) - -type: keyword - -example: California - --- - -*`x509.not_after`*:: -+ --- -Time at which the certificate is no longer considered valid. - -type: date - -example: 2020-07-16 03:15:39+00:00 - --- - -*`x509.not_before`*:: -+ --- -Time at which the certificate is first considered valid. - -type: date - -example: 2019-08-16 01:40:25+00:00 - --- - -*`x509.public_key_algorithm`*:: -+ --- -Algorithm used to generate the public key. - -type: keyword - -example: RSA - --- - -*`x509.public_key_curve`*:: -+ --- -The curve used by the elliptic curve public key algorithm. This is algorithm specific. - -type: keyword - -example: nistp521 - --- - -*`x509.public_key_exponent`*:: -+ --- -Exponent used to derive the public key. This is algorithm specific. - -type: long - -example: 65537 - -Field is not indexed. - --- - -*`x509.public_key_size`*:: -+ --- -The size of the public key space in bits. - -type: long - -example: 2048 - --- - -*`x509.serial_number`*:: -+ --- -Unique serial number issued by the certificate authority. For consistency, if this value is alphanumeric, it should be formatted without colons and uppercase characters. - -type: keyword - -example: 55FBB9C7DEBF09809D12CCAA - --- - -*`x509.signature_algorithm`*:: -+ --- -Identifier for certificate signature algorithm. We recommend using names found in Go Lang Crypto library. See https://github.com/golang/go/blob/go1.14/src/crypto/x509/x509.go#L337-L353. - -type: keyword - -example: SHA256-RSA - --- - -*`x509.subject.common_name`*:: -+ --- -List of common names (CN) of subject. - -type: keyword - -example: shared.global.example.net - --- - -*`x509.subject.country`*:: -+ --- -List of country (C) code - -type: keyword - -example: US - --- - -*`x509.subject.distinguished_name`*:: -+ --- -Distinguished name (DN) of the certificate subject entity. - -type: keyword - -example: C=US, ST=California, L=San Francisco, O=Example, Inc., CN=shared.global.example.net - --- - -*`x509.subject.locality`*:: -+ --- -List of locality names (L) - -type: keyword - -example: San Francisco - --- - -*`x509.subject.organization`*:: -+ --- -List of organizations (O) of subject. - -type: keyword - -example: Example, Inc. - --- - -*`x509.subject.organizational_unit`*:: -+ --- -List of organizational units (OU) of subject. - -type: keyword - --- - -*`x509.subject.state_or_province`*:: -+ --- -List of state or province names (ST, S, or P) - -type: keyword - -example: California - --- - -*`x509.version_number`*:: -+ --- -Version of x509 format. - -type: keyword - -example: 3 - --- - -[[exported-fields-host-processor]] -== Host fields - -Info collected for the host machine. - - - - -*`host.containerized`*:: -+ --- -If the host is a container. - - -type: boolean - --- - -*`host.os.build`*:: -+ --- -OS build information. - - -type: keyword - -example: 18D109 - --- - -*`host.os.codename`*:: -+ --- -OS codename, if any. - - -type: keyword - -example: stretch - --- - -[[exported-fields-jolokia-autodiscover]] -== Jolokia Discovery autodiscover provider fields - -Metadata from Jolokia Discovery added by the jolokia provider. - - - -*`jolokia.agent.version`*:: -+ --- -Version number of jolokia agent. - - -type: keyword - --- - -*`jolokia.agent.id`*:: -+ --- -Each agent has a unique id which can be either provided during startup of the agent in form of a configuration parameter or being autodetected. If autodected, the id has several parts: The IP, the process id, hashcode of the agent and its type. - - -type: keyword - --- - -*`jolokia.server.product`*:: -+ --- -The container product if detected. - - -type: keyword - --- - -*`jolokia.server.version`*:: -+ --- -The container's version (if detected). - - -type: keyword - --- - -*`jolokia.server.vendor`*:: -+ --- -The vendor of the container the agent is running in. - - -type: keyword - --- - -*`jolokia.url`*:: -+ --- -The URL how this agent can be contacted. - - -type: keyword - --- - -*`jolokia.secured`*:: -+ --- -Whether the agent was configured for authentication or not. - - -type: boolean - --- - -[[exported-fields-kubernetes-processor]] -== Kubernetes fields - -Kubernetes metadata added by the kubernetes processor - - - - -*`kubernetes.pod.name`*:: -+ --- -Kubernetes pod name - - -type: keyword - --- - -*`kubernetes.pod.uid`*:: -+ --- -Kubernetes Pod UID - - -type: keyword - --- - -*`kubernetes.pod.ip`*:: -+ --- -Kubernetes Pod IP - - -type: ip - --- - - -*`kubernetes.namespace.name`*:: -+ --- -Kubernetes namespace name - - -type: keyword - --- - -*`kubernetes.namespace.uuid`*:: -+ --- -Kubernetes namespace uuid - - -type: keyword - --- - -*`kubernetes.namespace.labels.*`*:: -+ --- -Kubernetes namespace labels map - - -type: object - --- - -*`kubernetes.namespace.annotations.*`*:: -+ --- -Kubernetes namespace annotations map - - -type: object - --- - -*`kubernetes.node.name`*:: -+ --- -Kubernetes node name - - -type: keyword - --- - -*`kubernetes.node.hostname`*:: -+ --- -Kubernetes hostname as reported by the node’s kernel - - -type: keyword - --- - -*`kubernetes.labels.*`*:: -+ --- -Kubernetes labels map - - -type: object - --- - -*`kubernetes.annotations.*`*:: -+ --- -Kubernetes annotations map - - -type: object - --- - -*`kubernetes.selectors.*`*:: -+ --- -Kubernetes selectors map - - -type: object - --- - -*`kubernetes.replicaset.name`*:: -+ --- -Kubernetes replicaset name - - -type: keyword - --- - -*`kubernetes.deployment.name`*:: -+ --- -Kubernetes deployment name - - -type: keyword - --- - -*`kubernetes.statefulset.name`*:: -+ --- -Kubernetes statefulset name - - -type: keyword - --- - -*`kubernetes.container.name`*:: -+ --- -Kubernetes container name (different than the name from the runtime) - - -type: keyword - --- - -[[exported-fields-process]] -== Process fields - -Process metadata fields - - - - -*`process.exe`*:: -+ --- -type: alias - -alias to: process.executable - --- - -[float] -=== owner - -Process owner information. - - -*`process.owner.id`*:: -+ --- -Unique identifier of the user. - -type: keyword - --- - -*`process.owner.name`*:: -+ --- -Short name or login of the user. - -type: keyword - -example: albert - --- - -*`process.owner.name.text`*:: -+ --- -type: text - --- - diff --git a/journalbeat/docs/filtering.asciidoc b/journalbeat/docs/filtering.asciidoc deleted file mode 100644 index 5bfcdd53254..00000000000 --- a/journalbeat/docs/filtering.asciidoc +++ /dev/null @@ -1,36 +0,0 @@ -[[filtering-and-enhancing-data]] -== Filter and enhance data with processors - -++++ -Processors -++++ - -Your use case might require only a subset of the data exported by {beatname_uc}, -or you might need to enhance the exported data (for example, by adding -metadata). {beatname_uc} provides a couple of options for filtering and -enhancing exported data. - -You can configure {beatname_uc} to include events that match specific filtering -criteria. To do this, use the <> -option. The advantage of this approach is that you can reduce the number of -fields that {beatname_uc} needs to process. - -Another approach (the one described here) is to define processors to configure -global processing across all data exported by {beatname_uc}. - - -[float] -[[using-processors]] -=== Processors - -include::{libbeat-dir}/processors.asciidoc[] - -// You must set the processor-scope attribute to resolve the attribute reference -// defined in processors-using.asciidoc. The attribute is used to indicate where -// processors are valid. If processors are valid in more than two locations -// (root and :processor-scope:), you need to add a conditionally coded section -// to processors-using.asciidoc. - -:processor-scope: input -include::{libbeat-dir}/processors-using.asciidoc[] -:processor-scope!: diff --git a/journalbeat/docs/general-options.asciidoc b/journalbeat/docs/general-options.asciidoc deleted file mode 100644 index 32c39676bfe..00000000000 --- a/journalbeat/docs/general-options.asciidoc +++ /dev/null @@ -1,64 +0,0 @@ -[[configuration-general-options]] -== Configure general settings - -++++ -General settings -++++ - -You can specify settings in the +{beatname_lc}.yml+ config file to control the -general behavior of {beatname_uc}. This includes: - -* <> that control things like -publisher behavior and the location of some files. - -* <> that are supported by all Elastic -Beats. - -[float] -[[configuration-global-options]] -=== Global {beatname_uc} configuration options - -These options are in the +{beatname_lc}+ namespace. - -[float] -[id="{beatname_lc}-registry-file"] -==== `registry_file` - -The name of the registry file. If a relative path is used, it is considered relative to the -data path. See the <> section for details. The default is `${path.data}/registry`. - -["source","sh",subs="attributes"] ----- -{beatname_lc}.registry_file: registry ----- - -[float] -==== `backoff` deprecated:[5.6.1,Use the option under `paths` instead.] - -This option is valid as a global setting under the +{beatname_lc}+ namespace -or under `paths`. For a description of this option, see -<<{beatname_lc}-backoff,`backoff`>>. - -[float] -==== `max_backoff` deprecated:[5.6.1,Use the option under `paths` instead.] - -This option is valid as a global setting under the +{beatname_lc}+ namespace -or under `paths`. For a description of this option, see -<<{beatname_lc}-max-backoff,`max_backoff`>>. - -[float] -==== `seek` deprecated:[5.6.1,Use the option under `paths` instead.] - -This option is valid as a global setting under the +{beatname_lc}+ namespace -or under `paths`. For a description of this option, see -<>. - -[float] -==== `include_matches` deprecated:[5.6.1,Use the option under `paths` instead.] - -This option is valid as a global setting under the +{beatname_lc}+ namespace -or under `paths`. For a description of this option, see -<>. - -include::{libbeat-dir}/generalconfig.asciidoc[] - diff --git a/journalbeat/docs/getting-started.asciidoc b/journalbeat/docs/getting-started.asciidoc deleted file mode 100644 index 75da26ee141..00000000000 --- a/journalbeat/docs/getting-started.asciidoc +++ /dev/null @@ -1,175 +0,0 @@ -[id="{beatname_lc}-installation-configuration"] -== {beatname_uc} quick start: installation and configuration - -++++ -Quick start: installation and configuration -++++ - -This guide describes how to get started quickly with log data collection from -systemd journals. You'll learn how to: - -* install {beatname_uc} on each system you want to monitor -* specify the location of your log files -* parse log data into fields and send it to {es} -* visualize the log data in {kib} - -[float] -=== Before you begin - -You need {es} for storing and searching your data, and {kib} for visualizing and -managing it. - -include::{libbeat-dir}/tab-widgets/spinup-stack-widget.asciidoc[] - -[float] -[[install]] -=== Step 1: Install {beatname_uc} - -Install {beatname_uc} on all the servers you want to monitor. - -To download and install {beatname_uc}, use the commands that work with your -system: - -include::{libbeat-dir}/tab-widgets/install-deb-rpm-linux-widget.asciidoc[] - -[float] -[[other-installation-options]] -==== Other installation options - -* <> -* https://www.elastic.co/downloads/beats/{beatname_lc}[Download page] -* <> - -[float] -[[set-connection]] -=== Step 2: Connect to the {stack} - -include::{libbeat-dir}/shared/connecting-to-es.asciidoc[] - - -[float] -[[configuration]] -=== Step 3: Configure {beatname_uc} - -Before running {beatname_uc}, specify the location of the systemd journal files -and configure how you want the files to be read. If you accept the default -configuration, {beatname_uc} reads from the local journal. - -. In +{beatname_lc}.yml+, specify a list of paths to your systemd journal files. -Each path can be a directory path (to collect events from all journals in a -directory), or a file path. For example: -+ -["source","sh",subs="attributes"] ----- -{beatname_lc}.inputs: -- paths: - - "/dev/log" - - "/var/log/messages/my-journal-file.journal" - seek: head ----- -+ -If no paths are specified, {beatname_uc} reads from the default journal. - -. Set the <> option to control the position where -{beatname_uc} starts reading the journal. The available options are `head`, -`tail`, and `cursor`. The default is `cursor`, which means that on first read, -{beatname_uc} starts reading at the beginning of the file, but continues reading -at the last known position after a reload or restart. For more detail about -the settings, see the reference docs for the -<>. - -. (Optional) Set the <> option -to filter entries in journald before collecting any log events. This reduces the -number of events that {beatname_uc} needs to process. For example, to fetch only -Redis events from a Docker container tagged as `redis`, use: -+ -["source","sh",subs="attributes"] ----- -{beatname_lc}.inputs: -- paths: [] - include_matches: - - "CONTAINER_TAG=redis" - - "_COMM=redis" ----- - -include::{libbeat-dir}/shared/config-check.asciidoc[] - -[float] -[[setup-assets]] -=== Step 4: Set up assets - -{beatname_uc} comes with predefined assets for parsing, indexing, and -visualizing your data. To load these assets: - -. Make sure the user specified in +{beatname_lc}.yml+ is -<>. - -. From the installation directory, run: -+ --- -include::{libbeat-dir}/tab-widgets/setup-deb-rpm-linux-widget.asciidoc[] --- -+ -`-e` is optional and sends output to standard error instead of the configured log output. - -This step loads the recommended {ref}/index-templates.html[index template] for writing to {es}. - -[TIP] -===== -A connection to {es} (or {ess}) is required to set up the initial -environment. If you're using a different output, such as {ls}, see -<>. -===== - -[float] -[[start]] -=== Step 5: Start {beatname_uc} - -Before starting {beatname_uc}, modify the user credentials in -+{beatname_lc}.yml+ and specify a user who is -<>. - -To start {beatname_uc}, run: - -// tag::start-step[] -include::{libbeat-dir}/tab-widgets/start-deb-rpm-linux-widget.asciidoc[] -// end::start-step[] - -{beatname_uc} is now ready to send journal events to the {es}. - -[float] -[[view-data]] -=== Step 6: View your data in {kib} - -There is currently no dashboard available for {beatname_uc}. To start exploring -your data, go to the Discover app in {kib}. From there, you can submit search -queries, filter the search results, and view document data. - -To learn how to build visualizations and dashboards to view your data, see the -_{kibana-ref}/index.html[{kib} User Guide]_. - - -[float] -=== What's next? - -Now that you have your logs streaming into {es}, learn how to unify your logs, -metrics, uptime, and application performance data. - -include::{libbeat-dir}/shared/obs-apps.asciidoc[] - -[TIP] -==== -The {logs-app} shows logs from `filebeat-*` indices by default. To show -{beatname_uc} indices, configure the source to include `journalbeat-*`. You can -do this in the {logs-app} when you configure the source, or you can modify the {kib} -configuration. For -example: - -[source,yaml] ----- -xpack.infra: - sources: - default: - logAlias: "filebeat-*,journalbeat-*" ----- -==== diff --git a/journalbeat/docs/howto/howto.asciidoc b/journalbeat/docs/howto/howto.asciidoc deleted file mode 100644 index 14a26a59c1a..00000000000 --- a/journalbeat/docs/howto/howto.asciidoc +++ /dev/null @@ -1,35 +0,0 @@ -[[howto-guides]] -= How to guides - -[partintro] --- -Learn how to perform common {beatname_uc} configuration tasks. - -* <<{beatname_lc}-template>> -* <> -* <<{beatname_lc}-geoip>> -* <> -* <> -* <> - - --- - -include::{libbeat-dir}/howto/load-index-templates.asciidoc[] - -include::{libbeat-dir}/howto/change-index-name.asciidoc[] - -include::{libbeat-dir}/shared-geoip.asciidoc[] - -:standalone: -include::{libbeat-dir}/shared-env-vars.asciidoc[] -:standalone!: - -include::{libbeat-dir}/shared-config-ingest.asciidoc[] - -:standalone: -include::{libbeat-dir}/yaml.asciidoc[] -:standalone!: - - - diff --git a/journalbeat/docs/images/coordinate-map.png b/journalbeat/docs/images/coordinate-map.png deleted file mode 100644 index 8ac69fe747c..00000000000 Binary files a/journalbeat/docs/images/coordinate-map.png and /dev/null differ diff --git a/journalbeat/docs/images/journald-log-data.png b/journalbeat/docs/images/journald-log-data.png deleted file mode 100644 index 9a746e96837..00000000000 Binary files a/journalbeat/docs/images/journald-log-data.png and /dev/null differ diff --git a/journalbeat/docs/index.asciidoc b/journalbeat/docs/index.asciidoc deleted file mode 100644 index 4ace63c41fc..00000000000 --- a/journalbeat/docs/index.asciidoc +++ /dev/null @@ -1,47 +0,0 @@ -= Journalbeat Reference - -:libbeat-dir: {docdir}/../../libbeat/docs - -include::{libbeat-dir}/version.asciidoc[] - -include::{asciidoc-dir}/../../shared/versions/stack/{source_branch}.asciidoc[] - -include::{asciidoc-dir}/../../shared/attributes.asciidoc[] - -:beatname_lc: journalbeat -:beatname_uc: Journalbeat -:beatname_pkg: {beatname_lc} -:github_repo_name: beats -:discuss_forum: beats/{beatname_lc} -:beat_default_index_prefix: {beatname_lc} -:beat_kib_app: {kib} Logs -:deb_os: -:rpm_os: -:linux_os: -:docker_platform: -:no_dashboards: -:no_decode_cef_processor: - -include::{libbeat-dir}/shared-beats-attributes.asciidoc[] - -include::./overview.asciidoc[] - -include::./getting-started.asciidoc[] - -include::./setting-up-running.asciidoc[] - -include::./configuring-howto.asciidoc[] - -include::{docdir}/howto/howto.asciidoc[] - -include::./fields.asciidoc[] - -include::{libbeat-dir}/monitoring/monitoring-beats.asciidoc[] - -include::{libbeat-dir}/shared-securing-beat.asciidoc[] - -include::./troubleshooting.asciidoc[] - -include::./faq.asciidoc[] - - diff --git a/journalbeat/docs/overview.asciidoc b/journalbeat/docs/overview.asciidoc deleted file mode 100644 index 645aa87ca48..00000000000 --- a/journalbeat/docs/overview.asciidoc +++ /dev/null @@ -1,11 +0,0 @@ -[id="{beatname_lc}-overview"] -== {beatname_uc} overview - -{beatname_uc} is a lightweight shipper for forwarding and centralizing log data -from https://www.freedesktop.org/software/systemd/man/systemd-journald.service.html[systemd journals]. -Installed as an agent on your servers, {beatname_uc} monitors the journal -locations that you specify, collects log events, and forwards them to either to -https://www.elastic.co/products/elasticsearch[Elasticsearch] or -https://www.elastic.co/products/logstash[Logstash]. - -include::{libbeat-dir}/shared-libbeat-description.asciidoc[] diff --git a/journalbeat/docs/page_header.html b/journalbeat/docs/page_header.html deleted file mode 100644 index 0f01f3bfad5..00000000000 --- a/journalbeat/docs/page_header.html +++ /dev/null @@ -1,4 +0,0 @@ -This functionality is experimental and may be changed or removed completely in a -future release. Elastic will take a best effort approach to fix any issues, but -experimental features are not subject to the support SLA of official GA -features. \ No newline at end of file diff --git a/journalbeat/docs/running-on-docker.asciidoc b/journalbeat/docs/running-on-docker.asciidoc deleted file mode 100644 index dbfcce5b489..00000000000 --- a/journalbeat/docs/running-on-docker.asciidoc +++ /dev/null @@ -1 +0,0 @@ -include::{libbeat-dir}/shared-docker.asciidoc[] diff --git a/journalbeat/docs/setting-up-running.asciidoc b/journalbeat/docs/setting-up-running.asciidoc deleted file mode 100644 index ef95d59b8ff..00000000000 --- a/journalbeat/docs/setting-up-running.asciidoc +++ /dev/null @@ -1,47 +0,0 @@ -///// -// NOTE: -// Each beat has its own setup overview to allow for the addition of content -// that is unique to each beat. -///// - -[[setting-up-and-running]] -== Set up and run {beatname_uc} - -++++ -Set up and run -++++ - -Before reading this section, see -<<{beatname_lc}-installation-configuration>> for basic -installation instructions to get you started. - -This section includes additional information on how to install, set up, and run -{beatname_uc}, including: - -* <> -* <> -* <> -* <> -* <> -* <> -* <<{beatname_lc}-starting>> -* <> - - -//MAINTAINERS: If you add a new file to this section, make sure you update the bulleted list ^^ too. - -include::{libbeat-dir}/shared-directory-layout.asciidoc[] - -include::{libbeat-dir}/keystore.asciidoc[] - -include::{libbeat-dir}/command-reference.asciidoc[] - -include::{libbeat-dir}/repositories.asciidoc[] - -include::./running-on-docker.asciidoc[] - -include::{libbeat-dir}/shared-systemd.asciidoc[] - -include::{libbeat-dir}/shared/start-beat.asciidoc[] - -include::{libbeat-dir}/shared/shutdown.asciidoc[] diff --git a/journalbeat/docs/troubleshooting.asciidoc b/journalbeat/docs/troubleshooting.asciidoc deleted file mode 100644 index b32d1b5fca2..00000000000 --- a/journalbeat/docs/troubleshooting.asciidoc +++ /dev/null @@ -1,31 +0,0 @@ -[[troubleshooting]] -= Troubleshoot - -[partintro] --- - -If you have issues installing or running {beatname_uc}, read the -following tips: - -* <> -* <> -* <> - -//sets block macro for getting-help.asciidoc included in next section - --- - -[[getting-help]] -== Get help - -include::{libbeat-dir}/getting-help.asciidoc[] - -//sets block macro for debugging.asciidoc included in next section - -[id="enable-{beatname_lc}-debugging"] -== Debug - -include::{libbeat-dir}/debugging.asciidoc[] - - - diff --git a/journalbeat/include/fields.go b/journalbeat/include/fields.go deleted file mode 100644 index 244c702bf9e..00000000000 --- a/journalbeat/include/fields.go +++ /dev/null @@ -1,36 +0,0 @@ -// Licensed to Elasticsearch B.V. under one or more contributor -// license agreements. See the NOTICE file distributed with -// this work for additional information regarding copyright -// ownership. Elasticsearch B.V. licenses this file to you 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. - -// Code generated by beats/dev-tools/cmd/asset/asset.go - DO NOT EDIT. - -package include - -import ( - "github.com/elastic/beats/v7/libbeat/asset" -) - -func init() { - if err := asset.SetFields("journalbeat", "fields.yml", asset.BeatFieldsPri, AssetFieldsYml); err != nil { - panic(err) - } -} - -// AssetFieldsYml returns asset data. -// This is the base64 encoded zlib format compressed contents of fields.yml. -func AssetFieldsYml() string { - return "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" -} diff --git a/journalbeat/input/config.go b/journalbeat/input/config.go deleted file mode 100644 index 6c202030b35..00000000000 --- a/journalbeat/input/config.go +++ /dev/null @@ -1,67 +0,0 @@ -// Licensed to Elasticsearch B.V. under one or more contributor -// license agreements. See the NOTICE file distributed with -// this work for additional information regarding copyright -// ownership. Elasticsearch B.V. licenses this file to you 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 input - -import ( - "time" - - "github.com/elastic/beats/v7/journalbeat/pkg/journalfield" - "github.com/elastic/beats/v7/journalbeat/pkg/journalread" - "github.com/elastic/beats/v7/libbeat/common" - "github.com/elastic/beats/v7/libbeat/common/fmtstr" - "github.com/elastic/beats/v7/libbeat/processors" -) - -// Config stores the options of an input. -type Config struct { - // Unique ID of the input for state persistence purposes. - ID string `config:"id"` - // Paths stores the paths to the journal files to be read. - Paths []string `config:"paths"` - // Backoff is the current interval to wait before - // attemting to read again from the journal. - Backoff time.Duration `config:"backoff" validate:"min=0,nonzero"` - // MaxBackoff is the limit of the backoff time. - MaxBackoff time.Duration `config:"max_backoff" validate:"min=0,nonzero"` - // Seek is the method to read from journals. - Seek journalread.SeekMode `config:"seek"` - // CursorSeekFallback sets where to seek if registry file is not available. - CursorSeekFallback journalread.SeekMode `config:"cursor_seek_fallback"` - // Matches store the key value pairs to match entries. - Matches []journalfield.Matcher `config:"include_matches"` - // SaveRemoteHostname defines if the original source of the entry needs to be saved. - SaveRemoteHostname bool `config:"save_remote_hostname"` - - // Fields and tags to add to events. - common.EventMetadata `config:",inline"` - // Processors to run on events. - Processors processors.PluginConfig `config:"processors"` - // ES output index pattern - Index fmtstr.EventFormatString `config:"index"` -} - -var ( - // DefaultConfig is the defaults for an inputs - DefaultConfig = Config{ - Backoff: 1 * time.Second, - MaxBackoff: 20 * time.Second, - Seek: journalread.SeekCursor, - CursorSeekFallback: journalread.SeekHead, - SaveRemoteHostname: false, - } -) diff --git a/journalbeat/input/input.go b/journalbeat/input/input.go deleted file mode 100644 index f1238d61c81..00000000000 --- a/journalbeat/input/input.go +++ /dev/null @@ -1,274 +0,0 @@ -// Licensed to Elasticsearch B.V. under one or more contributor -// license agreements. See the NOTICE file distributed with -// this work for additional information regarding copyright -// ownership. Elasticsearch B.V. licenses this file to you 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 input - -import ( - "context" - "fmt" - "strings" - "sync" - "syscall" - "time" - - "github.com/elastic/beats/v7/libbeat/processors/add_formatted_index" - "github.com/elastic/go-concert/timed" - - "github.com/elastic/beats/v7/libbeat/common/acker" - "github.com/elastic/beats/v7/libbeat/common/atomic" - "github.com/elastic/beats/v7/libbeat/common/fmtstr" - - "github.com/elastic/beats/v7/journalbeat/checkpoint" - "github.com/elastic/beats/v7/journalbeat/reader" - "github.com/elastic/beats/v7/libbeat/beat" - "github.com/elastic/beats/v7/libbeat/common" - "github.com/elastic/beats/v7/libbeat/logp" - "github.com/elastic/beats/v7/libbeat/processors" -) - -// Input manages readers and forwards entries from journals. -type Input struct { - readers []*reader.Reader - done chan struct{} - config Config - client beat.Client - states map[string]checkpoint.JournalState - logger *logp.Logger - eventMeta common.EventMetadata - processors beat.ProcessorList -} - -// New returns a new Inout -func New( - c *common.Config, - info beat.Info, - done chan struct{}, - states map[string]checkpoint.JournalState, -) (*Input, error) { - config := DefaultConfig - if err := c.Unpack(&config); err != nil { - return nil, err - } - - logger := logp.NewLogger("input") - if config.ID != "" { - logger = logger.With("id", config.ID) - } - - var readers []*reader.Reader - if len(config.Paths) == 0 { - cfg := reader.Config{ - Path: reader.LocalSystemJournalID, // used to identify the state in the registry - Backoff: config.Backoff, - MaxBackoff: config.MaxBackoff, - Seek: config.Seek, - CursorSeekFallback: config.CursorSeekFallback, - Matches: config.Matches, - SaveRemoteHostname: config.SaveRemoteHostname, - CheckpointID: checkpointID(config.ID, reader.LocalSystemJournalID), - } - - state := states[cfg.CheckpointID] - r, err := reader.NewLocal(cfg, done, state, logger) - if err != nil { - return nil, fmt.Errorf("error creating reader for local journal: %+v", err) - } - readers = append(readers, r) - } - - for _, p := range config.Paths { - cfg := reader.Config{ - Path: p, - Backoff: config.Backoff, - MaxBackoff: config.MaxBackoff, - Seek: config.Seek, - CursorSeekFallback: config.CursorSeekFallback, - Matches: config.Matches, - SaveRemoteHostname: config.SaveRemoteHostname, - CheckpointID: checkpointID(config.ID, p), - } - - state := states[cfg.CheckpointID] - r, err := reader.New(cfg, done, state, logger) - if err != nil { - return nil, fmt.Errorf("error creating reader for journal: %+v", err) - } - readers = append(readers, r) - } - - inputProcessors, err := processorsForInput(info, config) - if err != nil { - return nil, err - } - - logger.Debugf("New input is created for paths %v", config.Paths) - - return &Input{ - readers: readers, - done: done, - config: config, - states: states, - logger: logger, - eventMeta: config.EventMetadata, - processors: inputProcessors, - }, nil -} - -// Run connects to the output, collects entries from the readers -// and then publishes the events. -func (i *Input) Run(pipeline beat.Pipeline) { - var err error - i.client, err = pipeline.ConnectWith(beat.ClientConfig{ - PublishMode: beat.GuaranteedSend, - Processing: beat.ProcessingConfig{ - EventMetadata: i.eventMeta, - Meta: nil, - Processor: i.processors, - }, - ACKHandler: acker.Counting(func(n int) { - i.logger.Debugw("journalbeat successfully published events", "event.count", n) - }), - }) - if err != nil { - i.logger.Error("Error connecting to output: %v", err) - return - } - - i.publishAll() -} - -// publishAll reads events from all readers and publishes them. -func (i *Input) publishAll() { - out := make(chan *beat.Event) - defer close(out) - - var wg sync.WaitGroup - defer wg.Wait() - for _, r := range i.readers { - wg.Add(1) - r := r - go func() { - defer wg.Done() - - suppressed := atomic.NewBool(false) - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() - - for { - select { - case <-i.done: - return - default: - } - - event, err := r.Next() - if event == nil { - if err != nil { - if i.isErrSuppressed(ctx, err, suppressed) { - i.logger.Debugf("Error message suppressed: EBADMSG") - continue - } - i.logger.Errorf("Error while reading event: %v", err) - } - continue - } - - select { - case <-i.done: - case out <- event: - } - } - }() - } - - for { - select { - case <-i.done: - return - case e := <-out: - i.client.Publish(*e) - } - } -} - -// isErrSuppressed checks if the error is due to a corrupt journal. If yes, only the first error message -// is displayed and then it is suppressed for 5 seconds. -func (i *Input) isErrSuppressed(ctx context.Context, err error, suppressed *atomic.Bool) bool { - if strings.Contains(err.Error(), syscall.EBADMSG.Error()) { - if suppressed.Load() { - return true - } - - suppressed.Store(true) - go func(ctx context.Context, suppressed *atomic.Bool) { - if err := timed.Wait(ctx, 5*time.Second); err == nil { - suppressed.Store(false) - } - - }(ctx, suppressed) - } - - return false -} - -// Stop stops all readers of the input. -func (i *Input) Stop() { - for _, r := range i.readers { - r.Close() - } - i.client.Close() -} - -// Wait waits until all readers are done. -func (i *Input) Wait() { - i.Stop() -} - -func processorsForInput(beatInfo beat.Info, config Config) (*processors.Processors, error) { - procs := processors.NewList(nil) - - // Processor ordering is important: - // 1. Index configuration - if !config.Index.IsEmpty() { - staticFields := fmtstr.FieldsForBeat(beatInfo.Beat, beatInfo.Version) - timestampFormat, err := - fmtstr.NewTimestampFormatString(&config.Index, staticFields) - if err != nil { - return nil, err - } - indexProcessor := add_formatted_index.New(timestampFormat) - procs.AddProcessor(indexProcessor) - } - - // 2. User processors - userProcessors, err := processors.New(config.Processors) - if err != nil { - return nil, err - } - procs.AddProcessors(*userProcessors) - - return procs, nil -} - -// checkpointID returns the identifier used to track persistent state for the -// input. -func checkpointID(id, path string) string { - if id == "" { - return path - } - return "journald::" + path + "::" + id -} diff --git a/journalbeat/input/input_test.go b/journalbeat/input/input_test.go deleted file mode 100644 index eb925f1ef0b..00000000000 --- a/journalbeat/input/input_test.go +++ /dev/null @@ -1,167 +0,0 @@ -// Licensed to Elasticsearch B.V. under one or more contributor -// license agreements. See the NOTICE file distributed with -// this work for additional information regarding copyright -// ownership. Elasticsearch B.V. licenses this file to you 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 input - -import ( - "fmt" - "testing" - "time" - - "github.com/stretchr/testify/assert" - - "github.com/elastic/beats/v7/libbeat/beat" - "github.com/elastic/beats/v7/libbeat/beat/events" - "github.com/elastic/beats/v7/libbeat/common" - "github.com/elastic/beats/v7/libbeat/processors" - _ "github.com/elastic/beats/v7/libbeat/processors/actions" -) - -func TestProcessorsForInput(t *testing.T) { - testCases := map[string]struct { - beatInfo beat.Info - configStr string - event beat.Event - expectedFields map[string]string - }{ - "Simple static index": { - configStr: "index: 'test'", - expectedFields: map[string]string{ - "@metadata.raw_index": "test", - }, - }, - "Index with agent info + timestamp": { - beatInfo: beat.Info{Beat: "TestBeat", Version: "3.9.27"}, - configStr: "index: 'beat-%{[agent.name]}-%{[agent.version]}-%{+yyyy.MM.dd}'", - event: beat.Event{Timestamp: time.Date(1999, time.December, 31, 23, 0, 0, 0, time.UTC)}, - expectedFields: map[string]string{ - "@metadata.raw_index": "beat-TestBeat-3.9.27-1999.12.31", - }, - }, - "Set field in input config": { - configStr: `processors: [add_fields: {fields: {testField: inputConfig}}]`, - expectedFields: map[string]string{ - "fields.testField": "inputConfig", - }, - }, - } - for description, test := range testCases { - t.Run(description, func(t *testing.T) { - if test.event.Fields == nil { - test.event.Fields = common.MapStr{} - } - config, err := inputConfigFromString(test.configStr) - if err != nil { - t.Errorf("[%s] %v", description, err) - return - } - processors, err := processorsForInput(test.beatInfo, config) - if err != nil { - t.Errorf("[%s] %v", description, err) - return - } - processedEvent, err := processors.Run(&test.event) - // We don't check if err != nil, because we are testing the final outcome - // of running the processors, including when some of them fail. - if processedEvent == nil { - t.Errorf("[%s] Unexpected fatal error running processors: %v\n", - description, err) - } - for key, value := range test.expectedFields { - field, err := processedEvent.GetValue(key) - if err != nil { - t.Errorf("[%s] Couldn't get field %s from event: %v", description, key, err) - return - } - assert.Equal(t, field, value) - fieldStr, ok := field.(string) - if !ok { - // Note that requiring a string here is just to simplify the test setup, - // not a requirement of the underlying api. - t.Errorf("[%s] Field [%s] should be a string", description, key) - return - } - if fieldStr != value { - t.Errorf("[%s] Event field [%s]: expected [%s], got [%s]", description, key, value, fieldStr) - } - } - }) - } -} - -func TestProcessorsForInputIsFlat(t *testing.T) { - // This test is regrettable, and exists because of inconsistencies in - // processor handling between processors.Processors and processing.group - // (which implements beat.ProcessorList) -- see processorsForConfig for - // details. The upshot is that, for now, if the input configuration specifies - // processors, they must be returned as direct children of the resulting - // processors.Processors (rather than being collected in additional tree - // structure). - // This test should be removed once we have a more consistent mechanism for - // collecting and running processors. - configStr := `processors: -- add_fields: {fields: {testField: value}} -- add_fields: {fields: {testField2: stuff}}` - config, err := inputConfigFromString(configStr) - if err != nil { - t.Fatal(err) - } - processors, err := processorsForInput( - beat.Info{}, config) - if err != nil { - t.Fatal(err) - } - assert.Equal(t, 2, len(processors.List)) -} - -// setRawIndex is a bare-bones processor to set the raw_index field to a -// constant string in the event metadata. It is used to test order of operations -// for processorsForConfig. -type setRawIndex struct { - indexStr string -} - -func (p *setRawIndex) Run(event *beat.Event) (*beat.Event, error) { - if event.Meta == nil { - event.Meta = common.MapStr{} - } - event.Meta[events.FieldMetaRawIndex] = p.indexStr - return event, nil -} - -func (p *setRawIndex) String() string { - return fmt.Sprintf("set_raw_index=%v", p.indexStr) -} - -// Helper function to convert from YML input string to an unpacked -// Config -func inputConfigFromString(s string) (Config, error) { - config := DefaultConfig - cfg, err := common.NewConfigFrom(s) - if err != nil { - return config, err - } - err = cfg.Unpack(&config) - return config, err -} - -// makeProcessors wraps one or more bare Processor objects in Processors. -func makeProcessors(procs ...processors.Processor) *processors.Processors { - procList := processors.NewList(nil) - procList.List = procs - return procList -} diff --git a/journalbeat/journalbeat.docker.yml b/journalbeat/journalbeat.docker.yml deleted file mode 100644 index 643eea808b8..00000000000 --- a/journalbeat/journalbeat.docker.yml +++ /dev/null @@ -1,12 +0,0 @@ -journalbeat.inputs: -- paths: [] - seek: cursor - -processors: - - add_cloud_metadata: ~ - - add_docker_metadata: ~ - -output.elasticsearch: - hosts: '${ELASTICSEARCH_HOSTS:elasticsearch:9200}' - username: '${ELASTICSEARCH_USERNAME:}' - password: '${ELASTICSEARCH_PASSWORD:}' diff --git a/journalbeat/journalbeat.reference.yml b/journalbeat/journalbeat.reference.yml deleted file mode 100644 index 5058ed19cce..00000000000 --- a/journalbeat/journalbeat.reference.yml +++ /dev/null @@ -1,1626 +0,0 @@ -###################### Journalbeat Configuration Example ######################### - -# This file is an example configuration file highlighting only the most common -# options. The journalbeat.reference.yml file from the same directory contains all the -# supported options with more comments. You can use it as a reference. -# -# You can find the full configuration reference here: -# https://www.elastic.co/guide/en/beats/journalbeat/index.html - -# For more available modules and options, please see the journalbeat.reference.yml sample -# configuration file. - -# ============================= Journalbeat inputs ============================= - -journalbeat.inputs: - # Paths that should be crawled and fetched. Possible values files and directories. - # When setting a directory, all journals under it are merged. - # When empty starts to read from local journal. -- paths: [] - - # An optional unique identifier for the input. By providing a unique `id` you - # can operate multiple inputs on the same journal. This allows each input's - # cursor to be persisted independently in the registry file. - #id: "" - - # The number of seconds to wait before trying to read again from journals. - #backoff: 1s - # The maximum number of seconds to wait before attempting to read again from journals. - #max_backoff: 20s - - # Position to start reading from journal. Valid values: head, tail, cursor - seek: cursor - # Fallback position if no cursor data is available. - #cursor_seek_fallback: head - - # Exact matching for field values of events. - # Matching for nginx entries: "systemd.unit=nginx" - #include_matches: [] - - # Set the option to preserve the remote hostname in entries from a remote journal. - # It is only needed when used with add_host_metadata, so the original host name - # does not get overwritten by the processor. - #save_remote_hostname: false - - # Optional fields that you can specify to add additional information to the - # output. Fields can be scalar values, arrays, dictionaries, or any nested - # combination of these. - #fields: - # env: staging - - -# ========================= Journalbeat global options ========================= -#journalbeat: - # Name of the registry file. If a relative path is used, it is considered relative to the - # data path. - #registry_file: registry - -# ======================= Elasticsearch template setting ======================= -setup.template.settings: - index.number_of_shards: 1 - #index.codec: best_compression - #_source.enabled: false - -# ================================== General =================================== - -# The name of the shipper that publishes the network data. It can be used to group -# all the transactions sent by a single shipper in the web interface. -# If this options is not defined, the hostname is used. -#name: - -# The tags of the shipper are included in their own field with each -# transaction published. Tags make it easy to group servers by different -# logical properties. -#tags: ["service-X", "web-tier"] - -# Optional fields that you can specify to add additional information to the -# output. Fields can be scalar values, arrays, dictionaries, or any nested -# combination of these. -#fields: -# env: staging - -# If this option is set to true, the custom fields are stored as top-level -# fields in the output document instead of being grouped under a fields -# sub-dictionary. Default is false. -#fields_under_root: false - -# Internal queue configuration for buffering events to be published. -#queue: - # Queue type by name (default 'mem') - # The memory queue will present all available events (up to the outputs - # bulk_max_size) to the output, the moment the output is ready to server - # another batch of events. - #mem: - # Max number of events the queue can buffer. - #events: 4096 - - # Hints the minimum number of events stored in the queue, - # before providing a batch of events to the outputs. - # The default value is set to 2048. - # A value of 0 ensures events are immediately available - # to be sent to the outputs. - #flush.min_events: 2048 - - # Maximum duration after which events are available to the outputs, - # if the number of events stored in the queue is < `flush.min_events`. - #flush.timeout: 1s - - # The disk queue stores incoming events on disk until the output is - # ready for them. This allows a higher event limit than the memory-only - # queue and lets pending events persist through a restart. - #disk: - # The directory path to store the queue's data. - #path: "${path.data}/diskqueue" - - # The maximum space the queue should occupy on disk. Depending on - # input settings, events that exceed this limit are delayed or discarded. - #max_size: 10GB - - # The maximum size of a single queue data file. Data in the queue is - # stored in smaller segments that are deleted after all their events - # have been processed. - #segment_size: 1GB - - # The number of events to read from disk to memory while waiting for - # the output to request them. - #read_ahead: 512 - - # The number of events to accept from inputs while waiting for them - # to be written to disk. If event data arrives faster than it - # can be written to disk, this setting prevents it from overflowing - # main memory. - #write_ahead: 2048 - - # The duration to wait before retrying when the queue encounters a disk - # write error. - #retry_interval: 1s - - # The maximum length of time to wait before retrying on a disk write - # error. If the queue encounters repeated errors, it will double the - # length of its retry interval each time, up to this maximum. - #max_retry_interval: 30s - - # The spool queue will store events in a local spool file, before - # forwarding the events to the outputs. - # Note: the spool queue is deprecated and will be removed in the future. - # Use the disk queue instead. - # - # The spool file is a circular buffer, which blocks once the file/buffer is full. - # Events are put into a write buffer and flushed once the write buffer - # is full or the flush_timeout is triggered. - # Once ACKed by the output, events are removed immediately from the queue, - # making space for new events to be persisted. - #spool: - # The file namespace configures the file path and the file creation settings. - # Once the file exists, the `size`, `page_size` and `prealloc` settings - # will have no more effect. - #file: - # Location of spool file. The default value is ${path.data}/spool.dat. - #path: "${path.data}/spool.dat" - - # Configure file permissions if file is created. The default value is 0600. - #permissions: 0600 - - # File size hint. The spool blocks, once this limit is reached. The default value is 100 MiB. - #size: 100MiB - - # The files page size. A file is split into multiple pages of the same size. The default value is 4KiB. - #page_size: 4KiB - - # If prealloc is set, the required space for the file is reserved using - # truncate. The default value is true. - #prealloc: true - - # Spool writer settings - # Events are serialized into a write buffer. The write buffer is flushed if: - # - The buffer limit has been reached. - # - The configured limit of buffered events is reached. - # - The flush timeout is triggered. - #write: - # Sets the write buffer size. - #buffer_size: 1MiB - - # Maximum duration after which events are flushed if the write buffer - # is not full yet. The default value is 1s. - #flush.timeout: 1s - - # Number of maximum buffered events. The write buffer is flushed once the - # limit is reached. - #flush.events: 16384 - - # Configure the on-disk event encoding. The encoding can be changed - # between restarts. - # Valid encodings are: json, ubjson, and cbor. - #codec: cbor - #read: - # Reader flush timeout, waiting for more events to become available, so - # to fill a complete batch as required by the outputs. - # If flush_timeout is 0, all available events are forwarded to the - # outputs immediately. - # The default value is 0s. - #flush.timeout: 0s - -# Sets the maximum number of CPUs that can be executing simultaneously. The -# default is the number of logical CPUs available in the system. -#max_procs: - -# ================================= Processors ================================= - -# Processors are used to reduce the number of fields in the exported event or to -# enhance the event with external metadata. This section defines a list of -# processors that are applied one by one and the first one receives the initial -# event: -# -# event -> filter1 -> event1 -> filter2 ->event2 ... -# -# The supported processors are drop_fields, drop_event, include_fields, -# decode_json_fields, and add_cloud_metadata. -# -# For example, you can use the following processors to keep the fields that -# contain CPU load percentages, but remove the fields that contain CPU ticks -# values: -# -#processors: -# - include_fields: -# fields: ["cpu"] -# - drop_fields: -# fields: ["cpu.user", "cpu.system"] -# -# The following example drops the events that have the HTTP response code 200: -# -#processors: -# - drop_event: -# when: -# equals: -# http.code: 200 -# -# The following example renames the field a to b: -# -#processors: -# - rename: -# fields: -# - from: "a" -# to: "b" -# -# The following example tokenizes the string into fields: -# -#processors: -# - dissect: -# tokenizer: "%{key1} - %{key2}" -# field: "message" -# target_prefix: "dissect" -# -# The following example enriches each event with metadata from the cloud -# provider about the host machine. It works on EC2, GCE, DigitalOcean, -# Tencent Cloud, and Alibaba Cloud. -# -#processors: -# - add_cloud_metadata: ~ -# -# The following example enriches each event with the machine's local time zone -# offset from UTC. -# -#processors: -# - add_locale: -# format: offset -# -# The following example enriches each event with docker metadata, it matches -# given fields to an existing container id and adds info from that container: -# -#processors: -# - add_docker_metadata: -# host: "unix:///var/run/docker.sock" -# match_fields: ["system.process.cgroup.id"] -# match_pids: ["process.pid", "process.parent.pid"] -# match_source: true -# match_source_index: 4 -# match_short_id: false -# cleanup_timeout: 60 -# labels.dedot: false -# # To connect to Docker over TLS you must specify a client and CA certificate. -# #ssl: -# # certificate_authority: "/etc/pki/root/ca.pem" -# # certificate: "/etc/pki/client/cert.pem" -# # key: "/etc/pki/client/cert.key" -# -# The following example enriches each event with docker metadata, it matches -# container id from log path available in `source` field (by default it expects -# it to be /var/lib/docker/containers/*/*.log). -# -#processors: -# - add_docker_metadata: ~ -# -# The following example enriches each event with host metadata. -# -#processors: -# - add_host_metadata: ~ -# -# The following example enriches each event with process metadata using -# process IDs included in the event. -# -#processors: -# - add_process_metadata: -# match_pids: ["system.process.ppid"] -# target: system.process.parent -# -# The following example decodes fields containing JSON strings -# and replaces the strings with valid JSON objects. -# -#processors: -# - decode_json_fields: -# fields: ["field1", "field2", ...] -# process_array: false -# max_depth: 1 -# target: "" -# overwrite_keys: false -# -#processors: -# - decompress_gzip_field: -# from: "field1" -# to: "field2" -# ignore_missing: false -# fail_on_error: true -# -# The following example copies the value of message to message_copied -# -#processors: -# - copy_fields: -# fields: -# - from: message -# to: message_copied -# fail_on_error: true -# ignore_missing: false -# -# The following example truncates the value of message to 1024 bytes -# -#processors: -# - truncate_fields: -# fields: -# - message -# max_bytes: 1024 -# fail_on_error: false -# ignore_missing: true -# -# The following example preserves the raw message under event.original -# -#processors: -# - copy_fields: -# fields: -# - from: message -# to: event.original -# fail_on_error: false -# ignore_missing: true -# - truncate_fields: -# fields: -# - event.original -# max_bytes: 1024 -# fail_on_error: false -# ignore_missing: true -# -# The following example URL-decodes the value of field1 to field2 -# -#processors: -# - urldecode: -# fields: -# - from: "field1" -# to: "field2" -# ignore_missing: false -# fail_on_error: true - -# =============================== Elastic Cloud ================================ - -# These settings simplify using Journalbeat with the Elastic Cloud (https://cloud.elastic.co/). - -# The cloud.id setting overwrites the `output.elasticsearch.hosts` and -# `setup.kibana.host` options. -# You can find the `cloud.id` in the Elastic Cloud web UI. -#cloud.id: - -# The cloud.auth setting overwrites the `output.elasticsearch.username` and -# `output.elasticsearch.password` settings. The format is `:`. -#cloud.auth: - -# ================================== Outputs =================================== - -# Configure what output to use when sending the data collected by the beat. - -# ---------------------------- Elasticsearch Output ---------------------------- -output.elasticsearch: - # Boolean flag to enable or disable the output module. - #enabled: true - - # Array of hosts to connect to. - # Scheme and port can be left out and will be set to the default (http and 9200) - # In case you specify and additional path, the scheme is required: http://localhost:9200/path - # IPv6 addresses should always be defined as: https://[2001:db8::1]:9200 - hosts: ["localhost:9200"] - - # Set gzip compression level. - #compression_level: 0 - - # Configure escaping HTML symbols in strings. - #escape_html: false - - # Protocol - either `http` (default) or `https`. - #protocol: "https" - - # Authentication credentials - either API key or username/password. - #api_key: "id:api_key" - #username: "elastic" - #password: "changeme" - - # Dictionary of HTTP parameters to pass within the URL with index operations. - #parameters: - #param1: value1 - #param2: value2 - - # Number of workers per Elasticsearch host. - #worker: 1 - - # Optional index name. The default is "journalbeat" plus date - # and generates [journalbeat-]YYYY.MM.DD keys. - # In case you modify this pattern you must update setup.template.name and setup.template.pattern accordingly. - #index: "journalbeat-%{[agent.version]}-%{+yyyy.MM.dd}" - - # Optional ingest pipeline. By default no pipeline will be used. - #pipeline: "" - - # Optional HTTP path - #path: "/elasticsearch" - - # Custom HTTP headers to add to each request - #headers: - # X-My-Header: Contents of the header - - # Proxy server URL - #proxy_url: http://proxy:3128 - - # Whether to disable proxy settings for outgoing connections. If true, this - # takes precedence over both the proxy_url field and any environment settings - # (HTTP_PROXY, HTTPS_PROXY). The default is false. - #proxy_disable: false - - # The number of times a particular Elasticsearch index operation is attempted. If - # the indexing operation doesn't succeed after this many retries, the events are - # dropped. The default is 3. - #max_retries: 3 - - # The maximum number of events to bulk in a single Elasticsearch bulk API index request. - # The default is 50. - #bulk_max_size: 50 - - # The number of seconds to wait before trying to reconnect to Elasticsearch - # after a network error. After waiting backoff.init seconds, the Beat - # tries to reconnect. If the attempt fails, the backoff timer is increased - # exponentially up to backoff.max. After a successful connection, the backoff - # timer is reset. The default is 1s. - #backoff.init: 1s - - # The maximum number of seconds to wait before attempting to connect to - # Elasticsearch after a network error. The default is 60s. - #backoff.max: 60s - - # Configure HTTP request timeout before failing a request to Elasticsearch. - #timeout: 90 - - # Use SSL settings for HTTPS. - #ssl.enabled: true - - # Controls the verification of certificates. Valid values are: - # * full, which verifies that the provided certificate is signed by a trusted - # authority (CA) and also verifies that the server's hostname (or IP address) - # matches the names identified within the certificate. - # * strict, which verifies that the provided certificate is signed by a trusted - # authority (CA) and also verifies that the server's hostname (or IP address) - # matches the names identified within the certificate. If the Subject Alternative - # Name is empty, it returns an error. - # * certificate, which verifies that the provided certificate is signed by a - # trusted authority (CA), but does not perform any hostname verification. - # * none, which performs no verification of the server's certificate. This - # mode disables many of the security benefits of SSL/TLS and should only be used - # after very careful consideration. It is primarily intended as a temporary - # diagnostic mechanism when attempting to resolve TLS errors; its use in - # production environments is strongly discouraged. - # The default value is full. - #ssl.verification_mode: full - - # List of supported/valid TLS versions. By default all TLS versions from 1.1 - # up to 1.3 are enabled. - #ssl.supported_protocols: [TLSv1.1, TLSv1.2, TLSv1.3] - - # List of root certificates for HTTPS server verifications - #ssl.certificate_authorities: ["/etc/pki/root/ca.pem"] - - # Certificate for SSL client authentication - #ssl.certificate: "/etc/pki/client/cert.pem" - - # Client certificate key - #ssl.key: "/etc/pki/client/cert.key" - - # Optional passphrase for decrypting the certificate key. - #ssl.key_passphrase: '' - - # Configure cipher suites to be used for SSL connections - #ssl.cipher_suites: [] - - # Configure curve types for ECDHE-based cipher suites - #ssl.curve_types: [] - - # Configure what types of renegotiation are supported. Valid options are - # never, once, and freely. Default is never. - #ssl.renegotiation: never - - # Configure a pin that can be used to do extra validation of the verified certificate chain, - # this allow you to ensure that a specific certificate is used to validate the chain of trust. - # - # The pin is a base64 encoded string of the SHA-256 fingerprint. - #ssl.ca_sha256: "" - - # Enable Kerberos support. Kerberos is automatically enabled if any Kerberos setting is set. - #kerberos.enabled: true - - # Authentication type to use with Kerberos. Available options: keytab, password. - #kerberos.auth_type: password - - # Path to the keytab file. It is used when auth_type is set to keytab. - #kerberos.keytab: /etc/elastic.keytab - - # Path to the Kerberos configuration. - #kerberos.config_path: /etc/krb5.conf - - # Name of the Kerberos user. - #kerberos.username: elastic - - # Password of the Kerberos user. It is used when auth_type is set to password. - #kerberos.password: changeme - - # Kerberos realm. - #kerberos.realm: ELASTIC - - -# ------------------------------ Logstash Output ------------------------------- -#output.logstash: - # Boolean flag to enable or disable the output module. - #enabled: true - - # The Logstash hosts - #hosts: ["localhost:5044"] - - # Number of workers per Logstash host. - #worker: 1 - - # Set gzip compression level. - #compression_level: 3 - - # Configure escaping HTML symbols in strings. - #escape_html: false - - # Optional maximum time to live for a connection to Logstash, after which the - # connection will be re-established. A value of `0s` (the default) will - # disable this feature. - # - # Not yet supported for async connections (i.e. with the "pipelining" option set) - #ttl: 30s - - # Optionally load-balance events between Logstash hosts. Default is false. - #loadbalance: false - - # Number of batches to be sent asynchronously to Logstash while processing - # new batches. - #pipelining: 2 - - # If enabled only a subset of events in a batch of events is transferred per - # transaction. The number of events to be sent increases up to `bulk_max_size` - # if no error is encountered. - #slow_start: false - - # The number of seconds to wait before trying to reconnect to Logstash - # after a network error. After waiting backoff.init seconds, the Beat - # tries to reconnect. If the attempt fails, the backoff timer is increased - # exponentially up to backoff.max. After a successful connection, the backoff - # timer is reset. The default is 1s. - #backoff.init: 1s - - # The maximum number of seconds to wait before attempting to connect to - # Logstash after a network error. The default is 60s. - #backoff.max: 60s - - # Optional index name. The default index name is set to journalbeat - # in all lowercase. - #index: 'journalbeat' - - # SOCKS5 proxy server URL - #proxy_url: socks5://user:password@socks5-server:2233 - - # Resolve names locally when using a proxy server. Defaults to false. - #proxy_use_local_resolver: false - - # Use SSL settings for HTTPS. - #ssl.enabled: true - - # Controls the verification of certificates. Valid values are: - # * full, which verifies that the provided certificate is signed by a trusted - # authority (CA) and also verifies that the server's hostname (or IP address) - # matches the names identified within the certificate. - # * strict, which verifies that the provided certificate is signed by a trusted - # authority (CA) and also verifies that the server's hostname (or IP address) - # matches the names identified within the certificate. If the Subject Alternative - # Name is empty, it returns an error. - # * certificate, which verifies that the provided certificate is signed by a - # trusted authority (CA), but does not perform any hostname verification. - # * none, which performs no verification of the server's certificate. This - # mode disables many of the security benefits of SSL/TLS and should only be used - # after very careful consideration. It is primarily intended as a temporary - # diagnostic mechanism when attempting to resolve TLS errors; its use in - # production environments is strongly discouraged. - # The default value is full. - #ssl.verification_mode: full - - # List of supported/valid TLS versions. By default all TLS versions from 1.1 - # up to 1.3 are enabled. - #ssl.supported_protocols: [TLSv1.1, TLSv1.2, TLSv1.3] - - # List of root certificates for HTTPS server verifications - #ssl.certificate_authorities: ["/etc/pki/root/ca.pem"] - - # Certificate for SSL client authentication - #ssl.certificate: "/etc/pki/client/cert.pem" - - # Client certificate key - #ssl.key: "/etc/pki/client/cert.key" - - # Optional passphrase for decrypting the certificate key. - #ssl.key_passphrase: '' - - # Configure cipher suites to be used for SSL connections - #ssl.cipher_suites: [] - - # Configure curve types for ECDHE-based cipher suites - #ssl.curve_types: [] - - # Configure what types of renegotiation are supported. Valid options are - # never, once, and freely. Default is never. - #ssl.renegotiation: never - - # Configure a pin that can be used to do extra validation of the verified certificate chain, - # this allow you to ensure that a specific certificate is used to validate the chain of trust. - # - # The pin is a base64 encoded string of the SHA-256 fingerprint. - #ssl.ca_sha256: "" - - # The number of times to retry publishing an event after a publishing failure. - # After the specified number of retries, the events are typically dropped. - # Some Beats, such as Filebeat and Winlogbeat, ignore the max_retries setting - # and retry until all events are published. Set max_retries to a value less - # than 0 to retry until all events are published. The default is 3. - #max_retries: 3 - - # The maximum number of events to bulk in a single Logstash request. The - # default is 2048. - #bulk_max_size: 2048 - - # The number of seconds to wait for responses from the Logstash server before - # timing out. The default is 30s. - #timeout: 30s - -# -------------------------------- Kafka Output -------------------------------- -#output.kafka: - # Boolean flag to enable or disable the output module. - #enabled: true - - # The list of Kafka broker addresses from which to fetch the cluster metadata. - # The cluster metadata contain the actual Kafka brokers events are published - # to. - #hosts: ["localhost:9092"] - - # The Kafka topic used for produced events. The setting can be a format string - # using any event field. To set the topic from document type use `%{[type]}`. - #topic: beats - - # The Kafka event key setting. Use format string to create a unique event key. - # By default no event key will be generated. - #key: '' - - # The Kafka event partitioning strategy. Default hashing strategy is `hash` - # using the `output.kafka.key` setting or randomly distributes events if - # `output.kafka.key` is not configured. - #partition.hash: - # If enabled, events will only be published to partitions with reachable - # leaders. Default is false. - #reachable_only: false - - # Configure alternative event field names used to compute the hash value. - # If empty `output.kafka.key` setting will be used. - # Default value is empty list. - #hash: [] - - # Authentication details. Password is required if username is set. - #username: '' - #password: '' - - # SASL authentication mechanism used. Can be one of PLAIN, SCRAM-SHA-256 or SCRAM-SHA-512. - # Defaults to PLAIN when `username` and `password` are configured. - #sasl.mechanism: '' - - # Kafka version Journalbeat is assumed to run against. Defaults to the "1.0.0". - #version: '1.0.0' - - # Configure JSON encoding - #codec.json: - # Pretty-print JSON event - #pretty: false - - # Configure escaping HTML symbols in strings. - #escape_html: false - - # Metadata update configuration. Metadata contains leader information - # used to decide which broker to use when publishing. - #metadata: - # Max metadata request retry attempts when cluster is in middle of leader - # election. Defaults to 3 retries. - #retry.max: 3 - - # Wait time between retries during leader elections. Default is 250ms. - #retry.backoff: 250ms - - # Refresh metadata interval. Defaults to every 10 minutes. - #refresh_frequency: 10m - - # Strategy for fetching the topics metadata from the broker. Default is false. - #full: false - - # The number of concurrent load-balanced Kafka output workers. - #worker: 1 - - # The number of times to retry publishing an event after a publishing failure. - # After the specified number of retries, events are typically dropped. - # Some Beats, such as Filebeat, ignore the max_retries setting and retry until - # all events are published. Set max_retries to a value less than 0 to retry - # until all events are published. The default is 3. - #max_retries: 3 - - # The number of seconds to wait before trying to republish to Kafka - # after a network error. After waiting backoff.init seconds, the Beat - # tries to republish. If the attempt fails, the backoff timer is increased - # exponentially up to backoff.max. After a successful publish, the backoff - # timer is reset. The default is 1s. - #backoff.init: 1s - - # The maximum number of seconds to wait before attempting to republish to - # Kafka after a network error. The default is 60s. - #backoff.max: 60s - - # The maximum number of events to bulk in a single Kafka request. The default - # is 2048. - #bulk_max_size: 2048 - - # Duration to wait before sending bulk Kafka request. 0 is no delay. The default - # is 0. - #bulk_flush_frequency: 0s - - # The number of seconds to wait for responses from the Kafka brokers before - # timing out. The default is 30s. - #timeout: 30s - - # The maximum duration a broker will wait for number of required ACKs. The - # default is 10s. - #broker_timeout: 10s - - # The number of messages buffered for each Kafka broker. The default is 256. - #channel_buffer_size: 256 - - # The keep-alive period for an active network connection. If 0s, keep-alives - # are disabled. The default is 0 seconds. - #keep_alive: 0 - - # Sets the output compression codec. Must be one of none, snappy and gzip. The - # default is gzip. - #compression: gzip - - # Set the compression level. Currently only gzip provides a compression level - # between 0 and 9. The default value is chosen by the compression algorithm. - #compression_level: 4 - - # The maximum permitted size of JSON-encoded messages. Bigger messages will be - # dropped. The default value is 1000000 (bytes). This value should be equal to - # or less than the broker's message.max.bytes. - #max_message_bytes: 1000000 - - # The ACK reliability level required from broker. 0=no response, 1=wait for - # local commit, -1=wait for all replicas to commit. The default is 1. Note: - # If set to 0, no ACKs are returned by Kafka. Messages might be lost silently - # on error. - #required_acks: 1 - - # The configurable ClientID used for logging, debugging, and auditing - # purposes. The default is "beats". - #client_id: beats - - # Use SSL settings for HTTPS. - #ssl.enabled: true - - # Controls the verification of certificates. Valid values are: - # * full, which verifies that the provided certificate is signed by a trusted - # authority (CA) and also verifies that the server's hostname (or IP address) - # matches the names identified within the certificate. - # * strict, which verifies that the provided certificate is signed by a trusted - # authority (CA) and also verifies that the server's hostname (or IP address) - # matches the names identified within the certificate. If the Subject Alternative - # Name is empty, it returns an error. - # * certificate, which verifies that the provided certificate is signed by a - # trusted authority (CA), but does not perform any hostname verification. - # * none, which performs no verification of the server's certificate. This - # mode disables many of the security benefits of SSL/TLS and should only be used - # after very careful consideration. It is primarily intended as a temporary - # diagnostic mechanism when attempting to resolve TLS errors; its use in - # production environments is strongly discouraged. - # The default value is full. - #ssl.verification_mode: full - - # List of supported/valid TLS versions. By default all TLS versions from 1.1 - # up to 1.3 are enabled. - #ssl.supported_protocols: [TLSv1.1, TLSv1.2, TLSv1.3] - - # List of root certificates for HTTPS server verifications - #ssl.certificate_authorities: ["/etc/pki/root/ca.pem"] - - # Certificate for SSL client authentication - #ssl.certificate: "/etc/pki/client/cert.pem" - - # Client certificate key - #ssl.key: "/etc/pki/client/cert.key" - - # Optional passphrase for decrypting the certificate key. - #ssl.key_passphrase: '' - - # Configure cipher suites to be used for SSL connections - #ssl.cipher_suites: [] - - # Configure curve types for ECDHE-based cipher suites - #ssl.curve_types: [] - - # Configure what types of renegotiation are supported. Valid options are - # never, once, and freely. Default is never. - #ssl.renegotiation: never - - # Configure a pin that can be used to do extra validation of the verified certificate chain, - # this allow you to ensure that a specific certificate is used to validate the chain of trust. - # - # The pin is a base64 encoded string of the SHA-256 fingerprint. - #ssl.ca_sha256: "" - - # Enable Kerberos support. Kerberos is automatically enabled if any Kerberos setting is set. - #kerberos.enabled: true - - # Authentication type to use with Kerberos. Available options: keytab, password. - #kerberos.auth_type: password - - # Path to the keytab file. It is used when auth_type is set to keytab. - #kerberos.keytab: /etc/security/keytabs/kafka.keytab - - # Path to the Kerberos configuration. - #kerberos.config_path: /etc/krb5.conf - - # The service name. Service principal name is contructed from - # service_name/hostname@realm. - #kerberos.service_name: kafka - - # Name of the Kerberos user. - #kerberos.username: elastic - - # Password of the Kerberos user. It is used when auth_type is set to password. - #kerberos.password: changeme - - # Kerberos realm. - #kerberos.realm: ELASTIC - - # Enables Kerberos FAST authentication. This may - # conflict with certain Active Directory configurations. - #kerberos.enable_krb5_fast: false - -# -------------------------------- Redis Output -------------------------------- -#output.redis: - # Boolean flag to enable or disable the output module. - #enabled: true - - # Configure JSON encoding - #codec.json: - # Pretty print json event - #pretty: false - - # Configure escaping HTML symbols in strings. - #escape_html: false - - # The list of Redis servers to connect to. If load-balancing is enabled, the - # events are distributed to the servers in the list. If one server becomes - # unreachable, the events are distributed to the reachable servers only. - # The hosts setting supports redis and rediss urls with custom password like - # redis://:password@localhost:6379. - #hosts: ["localhost:6379"] - - # The name of the Redis list or channel the events are published to. The - # default is journalbeat. - #key: journalbeat - - # The password to authenticate to Redis with. The default is no authentication. - #password: - - # The Redis database number where the events are published. The default is 0. - #db: 0 - - # The Redis data type to use for publishing events. If the data type is list, - # the Redis RPUSH command is used. If the data type is channel, the Redis - # PUBLISH command is used. The default value is list. - #datatype: list - - # The number of workers to use for each host configured to publish events to - # Redis. Use this setting along with the loadbalance option. For example, if - # you have 2 hosts and 3 workers, in total 6 workers are started (3 for each - # host). - #worker: 1 - - # If set to true and multiple hosts or workers are configured, the output - # plugin load balances published events onto all Redis hosts. If set to false, - # the output plugin sends all events to only one host (determined at random) - # and will switch to another host if the currently selected one becomes - # unreachable. The default value is true. - #loadbalance: true - - # The Redis connection timeout in seconds. The default is 5 seconds. - #timeout: 5s - - # The number of times to retry publishing an event after a publishing failure. - # After the specified number of retries, the events are typically dropped. - # Some Beats, such as Filebeat, ignore the max_retries setting and retry until - # all events are published. Set max_retries to a value less than 0 to retry - # until all events are published. The default is 3. - #max_retries: 3 - - # The number of seconds to wait before trying to reconnect to Redis - # after a network error. After waiting backoff.init seconds, the Beat - # tries to reconnect. If the attempt fails, the backoff timer is increased - # exponentially up to backoff.max. After a successful connection, the backoff - # timer is reset. The default is 1s. - #backoff.init: 1s - - # The maximum number of seconds to wait before attempting to connect to - # Redis after a network error. The default is 60s. - #backoff.max: 60s - - # The maximum number of events to bulk in a single Redis request or pipeline. - # The default is 2048. - #bulk_max_size: 2048 - - # The URL of the SOCKS5 proxy to use when connecting to the Redis servers. The - # value must be a URL with a scheme of socks5://. - #proxy_url: - - # This option determines whether Redis hostnames are resolved locally when - # using a proxy. The default value is false, which means that name resolution - # occurs on the proxy server. - #proxy_use_local_resolver: false - - # Use SSL settings for HTTPS. - #ssl.enabled: true - - # Controls the verification of certificates. Valid values are: - # * full, which verifies that the provided certificate is signed by a trusted - # authority (CA) and also verifies that the server's hostname (or IP address) - # matches the names identified within the certificate. - # * strict, which verifies that the provided certificate is signed by a trusted - # authority (CA) and also verifies that the server's hostname (or IP address) - # matches the names identified within the certificate. If the Subject Alternative - # Name is empty, it returns an error. - # * certificate, which verifies that the provided certificate is signed by a - # trusted authority (CA), but does not perform any hostname verification. - # * none, which performs no verification of the server's certificate. This - # mode disables many of the security benefits of SSL/TLS and should only be used - # after very careful consideration. It is primarily intended as a temporary - # diagnostic mechanism when attempting to resolve TLS errors; its use in - # production environments is strongly discouraged. - # The default value is full. - #ssl.verification_mode: full - - # List of supported/valid TLS versions. By default all TLS versions from 1.1 - # up to 1.3 are enabled. - #ssl.supported_protocols: [TLSv1.1, TLSv1.2, TLSv1.3] - - # List of root certificates for HTTPS server verifications - #ssl.certificate_authorities: ["/etc/pki/root/ca.pem"] - - # Certificate for SSL client authentication - #ssl.certificate: "/etc/pki/client/cert.pem" - - # Client certificate key - #ssl.key: "/etc/pki/client/cert.key" - - # Optional passphrase for decrypting the certificate key. - #ssl.key_passphrase: '' - - # Configure cipher suites to be used for SSL connections - #ssl.cipher_suites: [] - - # Configure curve types for ECDHE-based cipher suites - #ssl.curve_types: [] - - # Configure what types of renegotiation are supported. Valid options are - # never, once, and freely. Default is never. - #ssl.renegotiation: never - - # Configure a pin that can be used to do extra validation of the verified certificate chain, - # this allow you to ensure that a specific certificate is used to validate the chain of trust. - # - # The pin is a base64 encoded string of the SHA-256 fingerprint. - #ssl.ca_sha256: "" - - -# -------------------------------- File Output --------------------------------- -#output.file: - # Boolean flag to enable or disable the output module. - #enabled: true - - # Configure JSON encoding - #codec.json: - # Pretty-print JSON event - #pretty: false - - # Configure escaping HTML symbols in strings. - #escape_html: false - - # Path to the directory where to save the generated files. The option is - # mandatory. - #path: "/tmp/journalbeat" - - # Name of the generated files. The default is `journalbeat` and it generates - # files: `journalbeat`, `journalbeat.1`, `journalbeat.2`, etc. - #filename: journalbeat - - # Maximum size in kilobytes of each file. When this size is reached, and on - # every Journalbeat restart, the files are rotated. The default value is 10240 - # kB. - #rotate_every_kb: 10000 - - # Maximum number of files under path. When this number of files is reached, - # the oldest file is deleted and the rest are shifted from last to first. The - # default is 7 files. - #number_of_files: 7 - - # Permissions to use for file creation. The default is 0600. - #permissions: 0600 - - # Configure automatic file rotation on every startup. The default is true. - #rotate_on_startup: true -# ------------------------------- Console Output ------------------------------- -#output.console: - # Boolean flag to enable or disable the output module. - #enabled: true - - # Configure JSON encoding - #codec.json: - # Pretty-print JSON event - #pretty: false - - # Configure escaping HTML symbols in strings. - #escape_html: false - -# =================================== Paths ==================================== - -# The home path for the Journalbeat installation. This is the default base path -# for all other path settings and for miscellaneous files that come with the -# distribution (for example, the sample dashboards). -# If not set by a CLI flag or in the configuration file, the default for the -# home path is the location of the binary. -#path.home: - -# The configuration path for the Journalbeat installation. This is the default -# base path for configuration files, including the main YAML configuration file -# and the Elasticsearch template file. If not set by a CLI flag or in the -# configuration file, the default for the configuration path is the home path. -#path.config: ${path.home} - -# The data path for the Journalbeat installation. This is the default base path -# for all the files in which Journalbeat needs to store its data. If not set by a -# CLI flag or in the configuration file, the default for the data path is a data -# subdirectory inside the home path. -#path.data: ${path.home}/data - -# The logs path for a Journalbeat installation. This is the default location for -# the Beat's log files. If not set by a CLI flag or in the configuration file, -# the default for the logs path is a logs subdirectory inside the home path. -#path.logs: ${path.home}/logs - -# ================================== Keystore ================================== - -# Location of the Keystore containing the keys and their sensitive values. -#keystore.path: "${path.config}/beats.keystore" - -# ================================= Dashboards ================================= - -# These settings control loading the sample dashboards to the Kibana index. Loading -# the dashboards are disabled by default and can be enabled either by setting the -# options here, or by using the `-setup` CLI flag or the `setup` command. -#setup.dashboards.enabled: false - -# The directory from where to read the dashboards. The default is the `kibana` -# folder in the home path. -#setup.dashboards.directory: ${path.home}/kibana - -# The URL from where to download the dashboards archive. It is used instead of -# the directory if it has a value. -#setup.dashboards.url: - -# The file archive (zip file) from where to read the dashboards. It is used instead -# of the directory when it has a value. -#setup.dashboards.file: - -# In case the archive contains the dashboards from multiple Beats, this lets you -# select which one to load. You can load all the dashboards in the archive by -# setting this to the empty string. -#setup.dashboards.beat: journalbeat - -# The name of the Kibana index to use for setting the configuration. Default is ".kibana" -#setup.dashboards.kibana_index: .kibana - -# The Elasticsearch index name. This overwrites the index name defined in the -# dashboards and index pattern. Example: testbeat-* -#setup.dashboards.index: - -# Always use the Kibana API for loading the dashboards instead of autodetecting -# how to install the dashboards by first querying Elasticsearch. -#setup.dashboards.always_kibana: false - -# If true and Kibana is not reachable at the time when dashboards are loaded, -# it will retry to reconnect to Kibana instead of exiting with an error. -#setup.dashboards.retry.enabled: false - -# Duration interval between Kibana connection retries. -#setup.dashboards.retry.interval: 1s - -# Maximum number of retries before exiting with an error, 0 for unlimited retrying. -#setup.dashboards.retry.maximum: 0 - -# ================================== Template ================================== - -# A template is used to set the mapping in Elasticsearch -# By default template loading is enabled and the template is loaded. -# These settings can be adjusted to load your own template or overwrite existing ones. - -# Set to false to disable template loading. -#setup.template.enabled: true - -# Select the kind of index template. From Elasticsearch 7.8, it is possible to -# use component templates. Available options: legacy, component, index. -# By default journalbeat uses the legacy index templates. -#setup.template.type: legacy - -# Template name. By default the template name is "journalbeat-%{[agent.version]}" -# The template name and pattern has to be set in case the Elasticsearch index pattern is modified. -#setup.template.name: "journalbeat-%{[agent.version]}" - -# Template pattern. By default the template pattern is "-%{[agent.version]}-*" to apply to the default index settings. -# The first part is the version of the beat and then -* is used to match all daily indices. -# The template name and pattern has to be set in case the Elasticsearch index pattern is modified. -#setup.template.pattern: "journalbeat-%{[agent.version]}-*" - -# Path to fields.yml file to generate the template -#setup.template.fields: "${path.config}/fields.yml" - -# A list of fields to be added to the template and Kibana index pattern. Also -# specify setup.template.overwrite: true to overwrite the existing template. -#setup.template.append_fields: -#- name: field_name -# type: field_type - -# Enable JSON template loading. If this is enabled, the fields.yml is ignored. -#setup.template.json.enabled: false - -# Path to the JSON template file -#setup.template.json.path: "${path.config}/template.json" - -# Name under which the template is stored in Elasticsearch -#setup.template.json.name: "" - -# Overwrite existing template -# Do not enable this option for more than one instance of journalbeat as it might -# overload your Elasticsearch with too many update requests. -#setup.template.overwrite: false - -# Elasticsearch template settings -setup.template.settings: - - # A dictionary of settings to place into the settings.index dictionary - # of the Elasticsearch template. For more details, please check - # https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping.html - #index: - #number_of_shards: 1 - #codec: best_compression - - # A dictionary of settings for the _source field. For more details, please check - # https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping-source-field.html - #_source: - #enabled: false - -# ====================== Index Lifecycle Management (ILM) ====================== - -# Configure index lifecycle management (ILM). These settings create a write -# alias and add additional settings to the index template. When ILM is enabled, -# output.elasticsearch.index is ignored, and the write alias is used to set the -# index name. - -# Enable ILM support. Valid values are true, false, and auto. When set to auto -# (the default), the Beat uses index lifecycle management when it connects to a -# cluster that supports ILM; otherwise, it creates daily indices. -#setup.ilm.enabled: auto - -# Set the prefix used in the index lifecycle write alias name. The default alias -# name is 'journalbeat-%{[agent.version]}'. -#setup.ilm.rollover_alias: 'journalbeat' - -# Set the rollover index pattern. The default is "%{now/d}-000001". -#setup.ilm.pattern: "{now/d}-000001" - -# Set the lifecycle policy name. The default policy name is -# 'beatname'. -#setup.ilm.policy_name: "mypolicy" - -# The path to a JSON file that contains a lifecycle policy configuration. Used -# to load your own lifecycle policy. -#setup.ilm.policy_file: - -# Disable the check for an existing lifecycle policy. The default is true. If -# you disable this check, set setup.ilm.overwrite: true so the lifecycle policy -# can be installed. -#setup.ilm.check_exists: true - -# Overwrite the lifecycle policy at startup. The default is false. -#setup.ilm.overwrite: false - -# =================================== Kibana =================================== - -# Starting with Beats version 6.0.0, the dashboards are loaded via the Kibana API. -# This requires a Kibana endpoint configuration. -setup.kibana: - - # Kibana Host - # Scheme and port can be left out and will be set to the default (http and 5601) - # In case you specify and additional path, the scheme is required: http://localhost:5601/path - # IPv6 addresses should always be defined as: https://[2001:db8::1]:5601 - #host: "localhost:5601" - - # Optional protocol and basic auth credentials. - #protocol: "https" - #username: "elastic" - #password: "changeme" - - # Optional HTTP path - #path: "" - - # Optional Kibana space ID. - #space.id: "" - - # Custom HTTP headers to add to each request - #headers: - # X-My-Header: Contents of the header - - # Use SSL settings for HTTPS. - #ssl.enabled: true - - # Controls the verification of certificates. Valid values are: - # * full, which verifies that the provided certificate is signed by a trusted - # authority (CA) and also verifies that the server's hostname (or IP address) - # matches the names identified within the certificate. - # * strict, which verifies that the provided certificate is signed by a trusted - # authority (CA) and also verifies that the server's hostname (or IP address) - # matches the names identified within the certificate. If the Subject Alternative - # Name is empty, it returns an error. - # * certificate, which verifies that the provided certificate is signed by a - # trusted authority (CA), but does not perform any hostname verification. - # * none, which performs no verification of the server's certificate. This - # mode disables many of the security benefits of SSL/TLS and should only be used - # after very careful consideration. It is primarily intended as a temporary - # diagnostic mechanism when attempting to resolve TLS errors; its use in - # production environments is strongly discouraged. - # The default value is full. - #ssl.verification_mode: full - - # List of supported/valid TLS versions. By default all TLS versions from 1.1 - # up to 1.3 are enabled. - #ssl.supported_protocols: [TLSv1.1, TLSv1.2, TLSv1.3] - - # List of root certificates for HTTPS server verifications - #ssl.certificate_authorities: ["/etc/pki/root/ca.pem"] - - # Certificate for SSL client authentication - #ssl.certificate: "/etc/pki/client/cert.pem" - - # Client certificate key - #ssl.key: "/etc/pki/client/cert.key" - - # Optional passphrase for decrypting the certificate key. - #ssl.key_passphrase: '' - - # Configure cipher suites to be used for SSL connections - #ssl.cipher_suites: [] - - # Configure curve types for ECDHE-based cipher suites - #ssl.curve_types: [] - - # Configure what types of renegotiation are supported. Valid options are - # never, once, and freely. Default is never. - #ssl.renegotiation: never - - # Configure a pin that can be used to do extra validation of the verified certificate chain, - # this allow you to ensure that a specific certificate is used to validate the chain of trust. - # - # The pin is a base64 encoded string of the SHA-256 fingerprint. - #ssl.ca_sha256: "" - - -# ================================== Logging =================================== - -# There are four options for the log output: file, stderr, syslog, eventlog -# The file output is the default. - -# Sets log level. The default log level is info. -# Available log levels are: error, warning, info, debug -#logging.level: info - -# Enable debug output for selected components. To enable all selectors use ["*"] -# Other available selectors are "beat", "publisher", "service" -# Multiple selectors can be chained. -#logging.selectors: [ ] - -# Send all logging output to stderr. The default is false. -#logging.to_stderr: false - -# Send all logging output to syslog. The default is false. -#logging.to_syslog: false - -# Send all logging output to Windows Event Logs. The default is false. -#logging.to_eventlog: false - -# If enabled, Journalbeat periodically logs its internal metrics that have changed -# in the last period. For each metric that changed, the delta from the value at -# the beginning of the period is logged. Also, the total values for -# all non-zero internal metrics are logged on shutdown. The default is true. -#logging.metrics.enabled: true - -# The period after which to log the internal metrics. The default is 30s. -#logging.metrics.period: 30s - -# A list of metrics namespaces to report in the logs. Defaults to [stats]. -# `stats` contains general Beat metrics. `dataset` may be present in some -# Beats and contains module or input metrics. -#logging.metrics.namespaces: [stats] - -# Logging to rotating files. Set logging.to_files to false to disable logging to -# files. -logging.to_files: true -logging.files: - # Configure the path where the logs are written. The default is the logs directory - # under the home path (the binary location). - #path: /var/log/journalbeat - - # The name of the files where the logs are written to. - #name: journalbeat - - # Configure log file size limit. If limit is reached, log file will be - # automatically rotated - #rotateeverybytes: 10485760 # = 10MB - - # Number of rotated log files to keep. Oldest files will be deleted first. - #keepfiles: 7 - - # The permissions mask to apply when rotating log files. The default value is 0600. - # Must be a valid Unix-style file permissions mask expressed in octal notation. - #permissions: 0600 - - # Enable log file rotation on time intervals in addition to size-based rotation. - # Intervals must be at least 1s. Values of 1m, 1h, 24h, 7*24h, 30*24h, and 365*24h - # are boundary-aligned with minutes, hours, days, weeks, months, and years as - # reported by the local system clock. All other intervals are calculated from the - # Unix epoch. Defaults to disabled. - #interval: 0 - - # Rotate existing logs on startup rather than appending to the existing - # file. Defaults to true. - # rotateonstartup: true - - # Rotated files are either suffixed with a number e.g. journalbeat.1 when - # renamed during rotation. Or when set to date, the date is added to - # the end of the file. On rotation a new file is created, older files are untouched. - #suffix: count - -# ============================= X-Pack Monitoring ============================== -# Journalbeat can export internal metrics to a central Elasticsearch monitoring -# cluster. This requires xpack monitoring to be enabled in Elasticsearch. The -# reporting is disabled by default. - -# Set to true to enable the monitoring reporter. -#monitoring.enabled: false - -# Sets the UUID of the Elasticsearch cluster under which monitoring data for this -# Journalbeat instance will appear in the Stack Monitoring UI. If output.elasticsearch -# is enabled, the UUID is derived from the Elasticsearch cluster referenced by output.elasticsearch. -#monitoring.cluster_uuid: - -# Uncomment to send the metrics to Elasticsearch. Most settings from the -# Elasticsearch output are accepted here as well. -# Note that the settings should point to your Elasticsearch *monitoring* cluster. -# Any setting that is not set is automatically inherited from the Elasticsearch -# output configuration, so if you have the Elasticsearch output configured such -# that it is pointing to your Elasticsearch monitoring cluster, you can simply -# uncomment the following line. -#monitoring.elasticsearch: - - # Array of hosts to connect to. - # Scheme and port can be left out and will be set to the default (http and 9200) - # In case you specify and additional path, the scheme is required: http://localhost:9200/path - # IPv6 addresses should always be defined as: https://[2001:db8::1]:9200 - #hosts: ["localhost:9200"] - - # Set gzip compression level. - #compression_level: 0 - - # Protocol - either `http` (default) or `https`. - #protocol: "https" - - # Authentication credentials - either API key or username/password. - #api_key: "id:api_key" - #username: "beats_system" - #password: "changeme" - - # Dictionary of HTTP parameters to pass within the URL with index operations. - #parameters: - #param1: value1 - #param2: value2 - - # Custom HTTP headers to add to each request - #headers: - # X-My-Header: Contents of the header - - # Proxy server url - #proxy_url: http://proxy:3128 - - # The number of times a particular Elasticsearch index operation is attempted. If - # the indexing operation doesn't succeed after this many retries, the events are - # dropped. The default is 3. - #max_retries: 3 - - # The maximum number of events to bulk in a single Elasticsearch bulk API index request. - # The default is 50. - #bulk_max_size: 50 - - # The number of seconds to wait before trying to reconnect to Elasticsearch - # after a network error. After waiting backoff.init seconds, the Beat - # tries to reconnect. If the attempt fails, the backoff timer is increased - # exponentially up to backoff.max. After a successful connection, the backoff - # timer is reset. The default is 1s. - #backoff.init: 1s - - # The maximum number of seconds to wait before attempting to connect to - # Elasticsearch after a network error. The default is 60s. - #backoff.max: 60s - - # Configure HTTP request timeout before failing an request to Elasticsearch. - #timeout: 90 - - # Use SSL settings for HTTPS. - #ssl.enabled: true - - # Controls the verification of certificates. Valid values are: - # * full, which verifies that the provided certificate is signed by a trusted - # authority (CA) and also verifies that the server's hostname (or IP address) - # matches the names identified within the certificate. - # * strict, which verifies that the provided certificate is signed by a trusted - # authority (CA) and also verifies that the server's hostname (or IP address) - # matches the names identified within the certificate. If the Subject Alternative - # Name is empty, it returns an error. - # * certificate, which verifies that the provided certificate is signed by a - # trusted authority (CA), but does not perform any hostname verification. - # * none, which performs no verification of the server's certificate. This - # mode disables many of the security benefits of SSL/TLS and should only be used - # after very careful consideration. It is primarily intended as a temporary - # diagnostic mechanism when attempting to resolve TLS errors; its use in - # production environments is strongly discouraged. - # The default value is full. - #ssl.verification_mode: full - - # List of supported/valid TLS versions. By default all TLS versions from 1.1 - # up to 1.3 are enabled. - #ssl.supported_protocols: [TLSv1.1, TLSv1.2, TLSv1.3] - - # List of root certificates for HTTPS server verifications - #ssl.certificate_authorities: ["/etc/pki/root/ca.pem"] - - # Certificate for SSL client authentication - #ssl.certificate: "/etc/pki/client/cert.pem" - - # Client certificate key - #ssl.key: "/etc/pki/client/cert.key" - - # Optional passphrase for decrypting the certificate key. - #ssl.key_passphrase: '' - - # Configure cipher suites to be used for SSL connections - #ssl.cipher_suites: [] - - # Configure curve types for ECDHE-based cipher suites - #ssl.curve_types: [] - - # Configure what types of renegotiation are supported. Valid options are - # never, once, and freely. Default is never. - #ssl.renegotiation: never - - # Configure a pin that can be used to do extra validation of the verified certificate chain, - # this allow you to ensure that a specific certificate is used to validate the chain of trust. - # - # The pin is a base64 encoded string of the SHA-256 fingerprint. - #ssl.ca_sha256: "" - - # Enable Kerberos support. Kerberos is automatically enabled if any Kerberos setting is set. - #kerberos.enabled: true - - # Authentication type to use with Kerberos. Available options: keytab, password. - #kerberos.auth_type: password - - # Path to the keytab file. It is used when auth_type is set to keytab. - #kerberos.keytab: /etc/elastic.keytab - - # Path to the Kerberos configuration. - #kerberos.config_path: /etc/krb5.conf - - # Name of the Kerberos user. - #kerberos.username: elastic - - # Password of the Kerberos user. It is used when auth_type is set to password. - #kerberos.password: changeme - - # Kerberos realm. - #kerberos.realm: ELASTIC - - #metrics.period: 10s - #state.period: 1m - -# The `monitoring.cloud.id` setting overwrites the `monitoring.elasticsearch.hosts` -# setting. You can find the value for this setting in the Elastic Cloud web UI. -#monitoring.cloud.id: - -# The `monitoring.cloud.auth` setting overwrites the `monitoring.elasticsearch.username` -# and `monitoring.elasticsearch.password` settings. The format is `:`. -#monitoring.cloud.auth: - -# =============================== HTTP Endpoint ================================ - -# Each beat can expose internal metrics through a HTTP endpoint. For security -# reasons the endpoint is disabled by default. This feature is currently experimental. -# Stats can be access through http://localhost:5066/stats . For pretty JSON output -# append ?pretty to the URL. - -# Defines if the HTTP endpoint is enabled. -#http.enabled: false - -# The HTTP endpoint will bind to this hostname, IP address, unix socket or named pipe. -# When using IP addresses, it is recommended to only use localhost. -#http.host: localhost - -# Port on which the HTTP endpoint will bind. Default is 5066. -#http.port: 5066 - -# Define which user should be owning the named pipe. -#http.named_pipe.user: - -# Define which the permissions that should be applied to the named pipe, use the Security -# Descriptor Definition Language (SDDL) to define the permission. This option cannot be used with -# `http.user`. -#http.named_pipe.security_descriptor: - -# Defines if the HTTP pprof endpoints are enabled. -# It is recommended that this is only enabled on localhost as these endpoints may leak data. -#http.pprof.enabled: false - -# ============================== Process Security ============================== - -# Enable or disable seccomp system call filtering on Linux. Default is enabled. -#seccomp.enabled: true - -# ============================== Instrumentation =============================== - -# Instrumentation support for the journalbeat. -#instrumentation: - # Set to true to enable instrumentation of journalbeat. - #enabled: false - - # Environment in which journalbeat is running on (eg: staging, production, etc.) - #environment: "" - - # APM Server hosts to report instrumentation results to. - #hosts: - # - http://localhost:8200 - - # API Key for the APM Server(s). - # If api_key is set then secret_token will be ignored. - #api_key: - - # Secret token for the APM Server(s). - #secret_token: - - # Enable profiling of the server, recording profile samples as events. - # - # This feature is experimental. - #profiling: - #cpu: - # Set to true to enable CPU profiling. - #enabled: false - #interval: 60s - #duration: 10s - #heap: - # Set to true to enable heap profiling. - #enabled: false - #interval: 60s - -# ================================= Migration ================================== - -# This allows to enable 6.7 migration aliases -#migration.6_to_7.enabled: false - diff --git a/journalbeat/journalbeat.yml b/journalbeat/journalbeat.yml deleted file mode 100644 index e049dbc908e..00000000000 --- a/journalbeat/journalbeat.yml +++ /dev/null @@ -1,217 +0,0 @@ -###################### Journalbeat Configuration Example ######################### - -# This file is an example configuration file highlighting only the most common -# options. The journalbeat.reference.yml file from the same directory contains all the -# supported options with more comments. You can use it as a reference. -# -# You can find the full configuration reference here: -# https://www.elastic.co/guide/en/beats/journalbeat/index.html - -# For more available modules and options, please see the journalbeat.reference.yml sample -# configuration file. - -# ============================= Journalbeat inputs ============================= - -journalbeat.inputs: - # Paths that should be crawled and fetched. Possible values files and directories. - # When setting a directory, all journals under it are merged. - # When empty starts to read from local journal. -- paths: [] - - # An optional unique identifier for the input. By providing a unique `id` you - # can operate multiple inputs on the same journal. This allows each input's - # cursor to be persisted independently in the registry file. - #id: "" - - # The number of seconds to wait before trying to read again from journals. - #backoff: 1s - # The maximum number of seconds to wait before attempting to read again from journals. - #max_backoff: 20s - - # Position to start reading from journal. Valid values: head, tail, cursor - seek: cursor - # Fallback position if no cursor data is available. - #cursor_seek_fallback: head - - # Exact matching for field values of events. - # Matching for nginx entries: "systemd.unit=nginx" - #include_matches: [] - - # Optional fields that you can specify to add additional information to the - # output. Fields can be scalar values, arrays, dictionaries, or any nested - # combination of these. - #fields: - # env: staging - - -# ========================= Journalbeat global options ========================= -#journalbeat: - # Name of the registry file. If a relative path is used, it is considered relative to the - # data path. - #registry_file: registry - -# ======================= Elasticsearch template setting ======================= -setup.template.settings: - index.number_of_shards: 1 - #index.codec: best_compression - #_source.enabled: false - -# ================================== General =================================== - -# The name of the shipper that publishes the network data. It can be used to group -# all the transactions sent by a single shipper in the web interface. -#name: - -# The tags of the shipper are included in their own field with each -# transaction published. -#tags: ["service-X", "web-tier"] - -# Optional fields that you can specify to add additional information to the -# output. -#fields: -# env: staging - -# ================================= Dashboards ================================= -# These settings control loading the sample dashboards to the Kibana index. Loading -# the dashboards is disabled by default and can be enabled either by setting the -# options here or by using the `setup` command. -#setup.dashboards.enabled: false - -# The URL from where to download the dashboards archive. By default this URL -# has a value which is computed based on the Beat name and version. For released -# versions, this URL points to the dashboard archive on the artifacts.elastic.co -# website. -#setup.dashboards.url: - -# =================================== Kibana =================================== - -# Starting with Beats version 6.0.0, the dashboards are loaded via the Kibana API. -# This requires a Kibana endpoint configuration. -setup.kibana: - - # Kibana Host - # Scheme and port can be left out and will be set to the default (http and 5601) - # In case you specify and additional path, the scheme is required: http://localhost:5601/path - # IPv6 addresses should always be defined as: https://[2001:db8::1]:5601 - #host: "localhost:5601" - - # Kibana Space ID - # ID of the Kibana Space into which the dashboards should be loaded. By default, - # the Default Space will be used. - #space.id: - -# =============================== Elastic Cloud ================================ - -# These settings simplify using Journalbeat with the Elastic Cloud (https://cloud.elastic.co/). - -# The cloud.id setting overwrites the `output.elasticsearch.hosts` and -# `setup.kibana.host` options. -# You can find the `cloud.id` in the Elastic Cloud web UI. -#cloud.id: - -# The cloud.auth setting overwrites the `output.elasticsearch.username` and -# `output.elasticsearch.password` settings. The format is `:`. -#cloud.auth: - -# ================================== Outputs =================================== - -# Configure what output to use when sending the data collected by the beat. - -# ---------------------------- Elasticsearch Output ---------------------------- -output.elasticsearch: - # Array of hosts to connect to. - hosts: ["localhost:9200"] - - # Protocol - either `http` (default) or `https`. - #protocol: "https" - - # Authentication credentials - either API key or username/password. - #api_key: "id:api_key" - #username: "elastic" - #password: "changeme" - -# ------------------------------ Logstash Output ------------------------------- -#output.logstash: - # The Logstash hosts - #hosts: ["localhost:5044"] - - # Optional SSL. By default is off. - # List of root certificates for HTTPS server verifications - #ssl.certificate_authorities: ["/etc/pki/root/ca.pem"] - - # Certificate for SSL client authentication - #ssl.certificate: "/etc/pki/client/cert.pem" - - # Client Certificate Key - #ssl.key: "/etc/pki/client/cert.key" - -# ================================= Processors ================================= - -# Configure processors to enhance or manipulate events generated by the beat. - -processors: - - add_host_metadata: ~ - - add_cloud_metadata: ~ - - add_docker_metadata: ~ - - -# ================================== Logging =================================== - -# Sets log level. The default log level is info. -# Available log levels are: error, warning, info, debug -#logging.level: debug - -# At debug level, you can selectively enable logging only for some components. -# To enable all selectors use ["*"]. Examples of other selectors are "beat", -# "publisher", "service". -#logging.selectors: ["*"] - -# ============================= X-Pack Monitoring ============================== -# Journalbeat can export internal metrics to a central Elasticsearch monitoring -# cluster. This requires xpack monitoring to be enabled in Elasticsearch. The -# reporting is disabled by default. - -# Set to true to enable the monitoring reporter. -#monitoring.enabled: false - -# Sets the UUID of the Elasticsearch cluster under which monitoring data for this -# Journalbeat instance will appear in the Stack Monitoring UI. If output.elasticsearch -# is enabled, the UUID is derived from the Elasticsearch cluster referenced by output.elasticsearch. -#monitoring.cluster_uuid: - -# Uncomment to send the metrics to Elasticsearch. Most settings from the -# Elasticsearch output are accepted here as well. -# Note that the settings should point to your Elasticsearch *monitoring* cluster. -# Any setting that is not set is automatically inherited from the Elasticsearch -# output configuration, so if you have the Elasticsearch output configured such -# that it is pointing to your Elasticsearch monitoring cluster, you can simply -# uncomment the following line. -#monitoring.elasticsearch: - -# ============================== Instrumentation =============================== - -# Instrumentation support for the journalbeat. -#instrumentation: - # Set to true to enable instrumentation of journalbeat. - #enabled: false - - # Environment in which journalbeat is running on (eg: staging, production, etc.) - #environment: "" - - # APM Server hosts to report instrumentation results to. - #hosts: - # - http://localhost:8200 - - # API Key for the APM Server(s). - # If api_key is set then secret_token will be ignored. - #api_key: - - # Secret token for the APM Server(s). - #secret_token: - - -# ================================= Migration ================================== - -# This allows to enable 6.7 migration aliases -#migration.6_to_7.enabled: true - diff --git a/journalbeat/magefile.go b/journalbeat/magefile.go deleted file mode 100644 index 0ba6de46d4b..00000000000 --- a/journalbeat/magefile.go +++ /dev/null @@ -1,171 +0,0 @@ -// Licensed to Elasticsearch B.V. under one or more contributor -// license agreements. See the NOTICE file distributed with -// this work for additional information regarding copyright -// ownership. Elasticsearch B.V. licenses this file to you 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. - -//go:build mage -// +build mage - -package main - -import ( - "fmt" - "runtime" - "strings" - "time" - - "github.com/magefile/mage/mg" - "github.com/magefile/mage/sh" - - devtools "github.com/elastic/beats/v7/dev-tools/mage" - - // mage:import - "github.com/elastic/beats/v7/dev-tools/mage/target/common" - // mage:import - _ "github.com/elastic/beats/v7/dev-tools/mage/target/integtest/notests" - // mage:import - _ "github.com/elastic/beats/v7/dev-tools/mage/target/unittest" - // mage:import - _ "github.com/elastic/beats/v7/dev-tools/mage/target/test" -) - -func init() { - common.RegisterCheckDeps(Update) - - devtools.BeatDescription = "Journalbeat ships systemd journal entries to Elasticsearch or Logstash." - - devtools.Platforms = devtools.Platforms.Filter("linux !linux/ppc64 !linux/mips64") -} - -const ( - libsystemdDevPkgName = "libsystemd-dev" - libsystemdPkgName = "libsystemd0" - libgcryptPkgName = "libgcrypt20" -) - -// Build builds the Beat binary. -func Build() error { - return devtools.Build(devtools.DefaultBuildArgs()) -} - -// GolangCrossBuild build the Beat binary inside of the golang-builder. -// Do not use directly, use crossBuild instead. -func GolangCrossBuild() error { - mg.Deps(deps.Installer(devtools.Platform.Name)) - return devtools.GolangCrossBuild(devtools.DefaultGolangCrossBuildArgs()) -} - -// BuildGoDaemon builds the go-daemon binary (use crossBuildGoDaemon). -func BuildGoDaemon() error { - return devtools.BuildGoDaemon() -} - -// CrossBuild cross-builds the beat for all target platforms. -func CrossBuild() error { - return devtools.CrossBuild(devtools.ImageSelector(selectImage)) -} - -// CrossBuildXPack cross-builds the beat with XPack for all target platforms. -func CrossBuildXPack() error { - return devtools.CrossBuildXPack(devtools.ImageSelector(selectImage)) -} - -// CrossBuildGoDaemon cross-builds the go-daemon binary using Docker. -func CrossBuildGoDaemon() error { - return devtools.CrossBuildGoDaemon(devtools.ImageSelector(selectImage)) -} - -// Package packages the Beat for distribution. -// Use SNAPSHOT=true to build snapshots. -// Use PLATFORMS to control the target platforms. -func Package() { - start := time.Now() - defer func() { fmt.Println("package ran for", time.Since(start)) }() - - devtools.UseElasticBeatPackaging() - - mg.Deps(Update) - mg.Deps(CrossBuild, CrossBuildXPack, CrossBuildGoDaemon) - mg.SerialDeps(devtools.Package, TestPackages) -} - -// TestPackages tests the generated packages (i.e. file modes, owners, groups). -func TestPackages() error { - return devtools.TestPackages() -} - -// Update updates the generated files (aka make update). -func Update() error { - return sh.Run("make", "update") -} - -// Fields generates a fields.yml for the Beat. -func Fields() error { - return devtools.GenerateFieldsYAML() -} - -// ----------------------------------------------------------------------------- -// Customizations specific to Journalbeat. -// - Install required headers on builders for different architectures. - -var ( - journaldPlatforms = []devtools.PlatformDescription{ - devtools.Linux386, devtools.LinuxAMD64, - devtools.LinuxARM64, devtools.LinuxARM5, devtools.LinuxARM6, devtools.LinuxARM7, - devtools.LinuxMIPS, devtools.LinuxMIPSLE, devtools.LinuxMIPS64LE, - devtools.LinuxPPC64LE, - devtools.LinuxS390x, - } - - deps = devtools.NewPackageInstaller(). - AddEach(journaldPlatforms, libsystemdDevPkgName). - Add(devtools.Linux386, libsystemdPkgName, libgcryptPkgName) -) - -func selectImage(platform string) (string, error) { - tagSuffix := "main" - - switch { - case strings.HasPrefix(platform, "linux/armv7"): - tagSuffix = "armhf" - case strings.HasPrefix(platform, "linux/arm"): - tagSuffix = "arm" - if runtime.GOARCH == "arm64" { - tagSuffix = "base-arm-debian9" - } - case strings.HasPrefix(platform, "linux/mips"): - tagSuffix = "mips" - case strings.HasPrefix(platform, "linux/ppc"): - tagSuffix = "ppc" - case platform == "linux/s390x": - tagSuffix = "s390x" - case strings.HasPrefix(platform, "linux"): - tagSuffix = "main-debian8" - } - - goVersion, err := devtools.GoVersion() - if err != nil { - return "", err - } - - return devtools.BeatsCrossBuildImage + ":" + goVersion + "-" + tagSuffix, nil -} - -// Config generates both the short/reference/docker configs. -func Config() error { - p := devtools.DefaultConfigFileParams() - p.Templates = append(p.Templates, devtools.OSSBeatDir("_meta/config/*.tmpl")) - return devtools.Config(devtools.AllConfigTypes, p, ".") -} diff --git a/journalbeat/main.go b/journalbeat/main.go deleted file mode 100644 index 56c0e645406..00000000000 --- a/journalbeat/main.go +++ /dev/null @@ -1,30 +0,0 @@ -// Licensed to Elasticsearch B.V. under one or more contributor -// license agreements. See the NOTICE file distributed with -// this work for additional information regarding copyright -// ownership. Elasticsearch B.V. licenses this file to you 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 main - -import ( - "os" - - "github.com/elastic/beats/v7/journalbeat/cmd" -) - -func main() { - if err := cmd.RootCmd.Execute(); err != nil { - os.Exit(1) - } -} diff --git a/journalbeat/main_test.go b/journalbeat/main_test.go deleted file mode 100644 index 7881c30d52c..00000000000 --- a/journalbeat/main_test.go +++ /dev/null @@ -1,49 +0,0 @@ -// Licensed to Elasticsearch B.V. under one or more contributor -// license agreements. See the NOTICE file distributed with -// this work for additional information regarding copyright -// ownership. Elasticsearch B.V. licenses this file to you 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 main - -// This file is mandatory as otherwise the journalbeat.test binary is not generated correctly. - -import ( - "flag" - "testing" - - "github.com/elastic/beats/v7/journalbeat/cmd" - "github.com/elastic/beats/v7/libbeat/tests/system/template" -) - -var systemTest *bool - -func init() { - testing.Init() - systemTest = flag.Bool("systemTest", false, "Set to true when running system tests") - - cmd.RootCmd.PersistentFlags().AddGoFlag(flag.CommandLine.Lookup("systemTest")) - cmd.RootCmd.PersistentFlags().AddGoFlag(flag.CommandLine.Lookup("test.coverprofile")) -} - -// Test started when the test binary is started. Only calls main. -func TestSystem(t *testing.T) { - if *systemTest { - main() - } -} - -func TestTemplate(t *testing.T) { - template.TestTemplate(t, cmd.Name, false) -} diff --git a/journalbeat/pkg/journalfield/matcher.go b/journalbeat/pkg/journalfield/matcher.go deleted file mode 100644 index 0227b2aae83..00000000000 --- a/journalbeat/pkg/journalfield/matcher.go +++ /dev/null @@ -1,120 +0,0 @@ -// Licensed to Elasticsearch B.V. under one or more contributor -// license agreements. See the NOTICE file distributed with -// this work for additional information regarding copyright -// ownership. Elasticsearch B.V. licenses this file to you 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 journalfield - -import ( - "fmt" - "strings" -) - -// Matcher is a single field condition for filtering journal entries. -// -// The Matcher type can be used as is with Beats configuration unpacking. The -// internal default conversion table will be used, similar to BuildMatcher. -type Matcher struct { - str string -} - -// MatcherBuilder can be used to create a custom builder for creating matchers -// based on a conversion table. -type MatcherBuilder struct { - Conversions map[string]Conversion -} - -type journal interface { - AddMatch(string) error - AddDisjunction() error -} - -var defaultBuilder = MatcherBuilder{Conversions: journaldEventFields} - -// Build creates a new Matcher using the configured conversion table. -// If no table has been configured the internal default table will be used. -func (b MatcherBuilder) Build(in string) (Matcher, error) { - elems := strings.Split(in, "=") - if len(elems) != 2 { - return Matcher{}, fmt.Errorf("invalid match format: %s", in) - } - - conversions := b.Conversions - if conversions == nil { - conversions = journaldEventFields - } - - for journalKey, eventField := range conversions { - for _, name := range eventField.Names { - if elems[0] == name { - return Matcher{journalKey + "=" + elems[1]}, nil - } - } - } - - // pass custom fields as is - return Matcher{in}, nil -} - -// BuildMatcher creates a Matcher from a field filter string. -func BuildMatcher(in string) (Matcher, error) { - return defaultBuilder.Build(in) -} - -// IsValid returns true if the matcher was initialized correctly. -func (m Matcher) IsValid() bool { return m.str != "" } - -// String returns the string representation of the field match. -func (m Matcher) String() string { return m.str } - -// Apply adds the field match to an open journal for filtering. -func (m Matcher) Apply(j journal) error { - if !m.IsValid() { - return fmt.Errorf("can not apply invalid matcher to a journal") - } - - err := j.AddMatch(m.str) - if err != nil { - return fmt.Errorf("error adding match '%s' to journal: %v", m.str, err) - } - return nil -} - -// Unpack initializes the Matcher from a given string representation. Unpack -// fails if the input string is invalid. -// Unpack can be used with Beats configuration loading. -func (m *Matcher) Unpack(value string) error { - tmp, err := BuildMatcher(value) - if err != nil { - return err - } - *m = tmp - return nil -} - -// ApplyMatchersOr adds a list of matchers to a journal, calling AddDisjunction after each matcher being added. -func ApplyMatchersOr(j journal, matchers []Matcher) error { - for _, m := range matchers { - if err := m.Apply(j); err != nil { - return err - } - - if err := j.AddDisjunction(); err != nil { - return fmt.Errorf("error adding disjunction to journal: %v", err) - } - } - - return nil -} diff --git a/journalbeat/reader/config.go b/journalbeat/reader/config.go deleted file mode 100644 index e559681aea7..00000000000 --- a/journalbeat/reader/config.go +++ /dev/null @@ -1,52 +0,0 @@ -// Licensed to Elasticsearch B.V. under one or more contributor -// license agreements. See the NOTICE file distributed with -// this work for additional information regarding copyright -// ownership. Elasticsearch B.V. licenses this file to you 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 reader - -import ( - "time" - - "github.com/elastic/beats/v7/journalbeat/pkg/journalfield" - "github.com/elastic/beats/v7/journalbeat/pkg/journalread" -) - -// Config stores the options of a reder. -type Config struct { - // Path is the path to the journal file. - Path string - // Seek specifies the seeking stategy. - // Possible values: head, tail, cursor. - Seek journalread.SeekMode - // CursorSeekFallback sets where to seek if registry file is not available. - CursorSeekFallback journalread.SeekMode - // MaxBackoff is the limit of the backoff time. - MaxBackoff time.Duration - // Backoff is the current interval to wait before - // attemting to read again from the journal. - Backoff time.Duration - // Matches store the key value pairs to match entries. - Matches []journalfield.Matcher - // SaveRemoteHostname defines if the original source of the entry needs to be saved. - SaveRemoteHostname bool - // CheckpointID is the identifier to use when persisting state. - CheckpointID string -} - -const ( - // LocalSystemJournalID is the ID of the local system journal. - LocalSystemJournalID = "LOCAL_SYSTEM_JOURNAL" -) diff --git a/journalbeat/reader/fields.go b/journalbeat/reader/fields.go deleted file mode 100644 index 7076a92a19d..00000000000 --- a/journalbeat/reader/fields.go +++ /dev/null @@ -1,21 +0,0 @@ -// Licensed to Elasticsearch B.V. under one or more contributor -// license agreements. See the NOTICE file distributed with -// this work for additional information regarding copyright -// ownership. Elasticsearch B.V. licenses this file to you 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. - -//go:build linux && cgo -// +build linux,cgo - -package reader diff --git a/journalbeat/reader/journal.go b/journalbeat/reader/journal.go deleted file mode 100644 index 93fc3963348..00000000000 --- a/journalbeat/reader/journal.go +++ /dev/null @@ -1,151 +0,0 @@ -// Licensed to Elasticsearch B.V. under one or more contributor -// license agreements. See the NOTICE file distributed with -// this work for additional information regarding copyright -// ownership. Elasticsearch B.V. licenses this file to you 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. - -//go:build linux && cgo -// +build linux,cgo - -package reader - -import ( - "time" - - "github.com/coreos/go-systemd/v22/sdjournal" - - "github.com/elastic/beats/v7/journalbeat/checkpoint" - "github.com/elastic/beats/v7/journalbeat/cmd/instance" - "github.com/elastic/beats/v7/journalbeat/pkg/journalfield" - "github.com/elastic/beats/v7/journalbeat/pkg/journalread" - "github.com/elastic/beats/v7/libbeat/beat" - "github.com/elastic/beats/v7/libbeat/common/backoff" - "github.com/elastic/beats/v7/libbeat/logp" - "github.com/elastic/go-concert/ctxtool" -) - -// Reader reads entries from journal(s). -type Reader struct { - r *journalread.Reader - journal *sdjournal.Journal - config Config - ctx ctxtool.CancelContext - logger *logp.Logger - backoff backoff.Backoff -} - -// New creates a new journal reader and moves the FP to the configured position. -func New(c Config, done <-chan struct{}, state checkpoint.JournalState, logger *logp.Logger) (*Reader, error) { - return newReader(c.Path, c, done, state, logger) -} - -// NewLocal creates a reader to read form the local journal and moves the FP -// to the configured position. -func NewLocal(c Config, done <-chan struct{}, state checkpoint.JournalState, logger *logp.Logger) (*Reader, error) { - return newReader(LocalSystemJournalID, c, done, state, logger) -} - -func newReader(path string, c Config, done <-chan struct{}, state checkpoint.JournalState, logger *logp.Logger) (*Reader, error) { - logger = logger.With("path", path) - backoff := backoff.NewExpBackoff(done, c.Backoff, c.MaxBackoff) - - var journal *sdjournal.Journal - r, err := journalread.Open(logger, c.Path, backoff, func(j *sdjournal.Journal) error { - journal = j - return journalfield.ApplyMatchersOr(j, c.Matches) - }) - if err != nil { - return nil, err - } - - if err := r.Seek(seekBy(logger, c, state)); err != nil { - logger.Error("Continue from current position. Seek failed with: %v", err) - } - - logger.Debug("New journal is opened for reading") - instance.AddJournalToMonitor(c.Path, journal) - - return &Reader{ - r: r, - journal: journal, - config: c, - ctx: ctxtool.WithCancelContext(ctxtool.FromChannel(done)), - logger: logger, - backoff: backoff, - }, nil -} - -func seekBy(log *logp.Logger, c Config, state checkpoint.JournalState) (journalread.SeekMode, string) { - mode := c.Seek - if mode == journalread.SeekCursor && state.Cursor == "" { - mode = c.CursorSeekFallback - if mode != journalread.SeekHead && mode != journalread.SeekTail { - log.Error("Invalid option for cursor_seek_fallback") - mode = journalread.SeekHead - } - } - return mode, state.Cursor -} - -// Close closes the underlying journal reader. -func (r *Reader) Close() { - instance.StopMonitoringJournal(r.config.Path) - r.ctx.Cancel() - r.r.Close() -} - -// Next waits until a new event shows up and returns it. -// It blocks until an event is returned or an error occurs. -func (r *Reader) Next() (*beat.Event, error) { - entry, err := r.r.Next(r.ctx) - if err != nil { - return nil, err - } - - event := toEvent(r.logger, r.config.CheckpointID, entry, r.config.SaveRemoteHostname) - return event, nil -} - -// toEvent creates a beat.Event from journal entries. -func toEvent(logger *logp.Logger, id string, entry *sdjournal.JournalEntry, saveRemoteHostname bool) *beat.Event { - created := time.Now() - fields := journalfield.NewConverter(logger, nil).Convert(entry.Fields) - fields.Put("event.kind", "event") - - // if entry is coming from a remote journal, add_host_metadata overwrites the source hostname, so it - // has to be copied to a different field - if saveRemoteHostname { - remoteHostname, err := fields.GetValue("host.hostname") - if err == nil { - fields.Put("log.source.address", remoteHostname) - } - } - - state := checkpoint.JournalState{ - Path: id, - Cursor: entry.Cursor, - RealtimeTimestamp: entry.RealtimeTimestamp, - MonotonicTimestamp: entry.MonotonicTimestamp, - } - - fields.Put("event.created", created) - receivedByJournal := time.Unix(0, int64(entry.RealtimeTimestamp)*1000) - - event := beat.Event{ - Timestamp: receivedByJournal, - Fields: fields, - Private: state, - } - return &event -} diff --git a/journalbeat/reader/journal_other.go b/journalbeat/reader/journal_other.go deleted file mode 100644 index a44d1a07db0..00000000000 --- a/journalbeat/reader/journal_other.go +++ /dev/null @@ -1,56 +0,0 @@ -// Licensed to Elasticsearch B.V. under one or more contributor -// license agreements. See the NOTICE file distributed with -// this work for additional information regarding copyright -// ownership. Elasticsearch B.V. licenses this file to you 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. - -//go:build !linux || !cgo -// +build !linux !cgo - -package reader - -import ( - "errors" - - "github.com/elastic/beats/v7/journalbeat/checkpoint" - "github.com/elastic/beats/v7/libbeat/beat" - "github.com/elastic/beats/v7/libbeat/logp" -) - -// Reader stub for non linux builds. -type Reader struct{} - -// New creates a new journal reader and moves the FP to the configured position. -// -// Note: New fails if journalbeat is not compiled for linux -func New(c Config, done chan struct{}, state checkpoint.JournalState, logger *logp.Logger) (*Reader, error) { - return nil, errors.New("journald reader only supported on linux") -} - -// NewLocal creates a reader to read form the local journal and moves the FP -// to the configured position. -// -// Note: NewLocal fails if journalbeat is not compiled for linux -func NewLocal(c Config, done chan struct{}, state checkpoint.JournalState, logger *logp.Logger) (*Reader, error) { - return nil, errors.New("journald reader only supported on linux") -} - -// Next waits until a new event shows up and returns it. -// It blocks until an event is returned or an error occurs. -func (r *Reader) Next() (*beat.Event, error) { - return nil, nil -} - -// Close closes the underlying journal reader. -func (r *Reader) Close() {} diff --git a/journalbeat/tests/system/config/journalbeat.yml.j2 b/journalbeat/tests/system/config/journalbeat.yml.j2 deleted file mode 100644 index 858181ca409..00000000000 --- a/journalbeat/tests/system/config/journalbeat.yml.j2 +++ /dev/null @@ -1,13 +0,0 @@ -journalbeat.inputs: -{% for input in inputs %} -- {{ input | tojson }} -{% endfor %} - -{% if registry_file is defined %} -journalbeat.registry_file: {{ registry_file }} -{% endif %} - -output: - file: - path: {{ output_file_path|default(beat.working_dir + "/output") }} - filename: {{ output_file_filename|default("journalbeat") }} diff --git a/journalbeat/tests/system/input/test.registry b/journalbeat/tests/system/input/test.registry deleted file mode 100644 index 9b9dee108b3..00000000000 --- a/journalbeat/tests/system/input/test.registry +++ /dev/null @@ -1,6 +0,0 @@ -update_time: 2018-09-11T10:06:50.895829905Z -journal_entries: -- path: /home/n/go/src/github.com/elastic/beats/journalbeat/tests/system/input/test.journal - cursor: s=018329e08e3a45a0ae03694421c4f553;i=2015d;b=fa3c2e3080dc4cd5be5cb5a43e140d51;m=29102136a4;t=5ab0792b1dc62;x=84a1467480b8f1af - realtime_timestamp: 1595423897803874 - monotonic_timestamp: 176364271268 diff --git a/journalbeat/tests/system/journalbeat.py b/journalbeat/tests/system/journalbeat.py deleted file mode 100644 index 2ad3bd3c37f..00000000000 --- a/journalbeat/tests/system/journalbeat.py +++ /dev/null @@ -1,12 +0,0 @@ -import os -import sys -from beat.beat import TestCase - - -class BaseTest(TestCase): - - @classmethod - def setUpClass(self): - self.beat_name = "journalbeat" - self.beat_path = os.path.abspath(os.path.join(os.path.dirname(__file__), "../../")) - super(BaseTest, self).setUpClass() diff --git a/journalbeat/tests/system/test_base.py b/journalbeat/tests/system/test_base.py deleted file mode 100644 index 2d7269dd5f4..00000000000 --- a/journalbeat/tests/system/test_base.py +++ /dev/null @@ -1,210 +0,0 @@ -from journalbeat import BaseTest - -import os -import sys -import unittest -import time -import yaml -from shutil import copyfile -from beat import common_tests - - -class Test(BaseTest, common_tests.TestExportsMixin): - - @unittest.skipUnless(sys.platform.startswith("linux"), "Journald only on Linux") - def test_start_with_local_journal(self): - """ - Journalbeat is able to start with the local journal. - """ - - self.render_config_template( - inputs=[{ - "paths": [], - }], - ) - journalbeat_proc = self.start_beat() - - self.wait_until(lambda: self.log_contains("journalbeat is running")) - - exit_code = journalbeat_proc.kill_and_wait() - assert exit_code == 0 - - @unittest.skipUnless(sys.platform.startswith("linux"), "Journald only on Linux") - def test_start_with_journal_directory(self): - """ - Journalbeat is able to open a directory of journal files and starts tailing them. - """ - - self.render_config_template( - inputs=[{ - "paths": [ - self.beat_path + "/tests/system/input/", - ], - "seek": "tail", - }], - ) - journalbeat_proc = self.start_beat() - - self.wait_until(lambda: self.log_contains("journalbeat is running")) - - exit_code = journalbeat_proc.kill_and_wait() - assert exit_code == 0 - - # journalbeat is tailing an inactive journal - assert self.output_is_empty() - - @unittest.skipUnless(sys.platform.startswith("linux"), "Journald only on Linux") - def test_start_with_selected_journal_file(self): - """ - Journalbeat is able to open a journal file and start to read it from the begining. - """ - - self.render_config_template( - inputs=[{ - "paths": [ - self.beat_path + "/tests/system/input/test.journal", - ], - "seek": "head", - }], - ) - journalbeat_proc = self.start_beat() - - self.wait_until(lambda: self.output_has(lines=23)) - - exit_code = journalbeat_proc.kill_and_wait() - assert exit_code == 0 - - @unittest.skipUnless(sys.platform.startswith("linux"), "Journald only on Linux") - def test_start_with_selected_journal_file_with_cursor_fallback(self): - """ - Journalbeat is able to open a journal file and start to read it from the position configured by seek and cursor_seek_fallback. - """ - - self.render_config_template( - inputs=[{ - "paths": [ - self.beat_path + "/tests/system/input/test.journal", - ], - "seek": "cursor", - "cursor_seek_fallback": "tail", - }], - ) - journalbeat_proc = self.start_beat() - - self.wait_until(lambda: self.log_contains("journalbeat is running")) - - exit_code = journalbeat_proc.kill_and_wait() - assert exit_code == 0 - - # journalbeat is tailing an inactive journal with no cursor data - assert self.output_is_empty() - - @unittest.skipUnless(sys.platform.startswith("linux"), "Journald only on Linux") - def test_read_events_with_existing_registry(self): - """ - Journalbeat is able to follow reading a from a journal with an existing registry file. - """ - - registry_path = os.path.join(os.path.abspath(self.working_dir), "data", "registry") - os.mkdir(os.path.dirname(registry_path)) - copyfile(self.beat_path + "/tests/system/input/test.registry", - os.path.join(os.path.abspath(self.working_dir), "data/registry")) - input_path = self.beat_path + "/tests/system/input/test.journal" - self._prepare_registry_file(registry_path, input_path) - - self.render_config_template( - inputs=[{ - "paths": [input_path], - "seek": "cursor", - "cursor_seek_fallback": "tail", - }], - ) - journalbeat_proc = self.start_beat() - - self.wait_until(lambda: self.output_has(lines=9)) - - exit_code = journalbeat_proc.kill_and_wait() - assert exit_code == 0 - - @unittest.skipUnless(sys.platform.startswith("linux"), "Journald only on Linux") - def test_read_events_with_include_matches(self): - """ - Journalbeat is able to pass matchers to the journal reader and read filtered messages. - """ - - self.render_config_template( - inputs=[{ - "paths": [ - self.beat_path + "/tests/system/input/test.journal", - ], - "seek": "head", - "include_matches": [ - "syslog.priority=6", - ] - }], - ) - journalbeat_proc = self.start_beat() - - self.wait_until(lambda: self.output_has(lines=6)) - - exit_code = journalbeat_proc.kill_and_wait() - assert exit_code == 0 - - @unittest.skipUnless(sys.platform.startswith("linux"), "Journald only on Linux") - def test_input_id(self): - """ - Journalbeat persists states with IDs. - """ - - self.render_config_template( - inputs=[ - { - "id": "serviceA.unit", - "paths": [ - self.beat_path + "/tests/system/input/test.journal", - ], - }, - { - "id": "serviceB unit", - "paths": [ - self.beat_path + "/tests/system/input/test.journal", - ], - } - ], - ) - - # Run the beat until it publishes events from both inputs. - journalbeat_proc = self.start_beat() - expected_msg = 'successfully published events' - self.wait_until(lambda: self.log_contains(expected_msg)) - self.wait_until(lambda: self.log_contains(expected_msg)) - journalbeat_proc.check_kill_and_wait() - - # Verify that registry paths are prefixed with an ID. - registry_data = self.read_registry() - self.assertIn("journal_entries", registry_data) - journal_entries = registry_data['journal_entries'] - self.assertGreater(len(journal_entries), 0) - for item in journal_entries: - self.assertTrue(item['path'].startswith('journald::'), "starts with journald::") - self.assertTrue(item['path'].find('::service'), "ends with ::") - - def _prepare_registry_file(self, registry_path, journal_path): - lines = [] - with open(registry_path, "r") as registry_file: - lines = registry_file.readlines() - lines[2] = "- path: " + journal_path + "\n" - - with open(registry_path, "w") as registry_file: - for line in lines: - registry_file.write(line) - - def read_registry(self): - registry_path = os.path.join(os.path.abspath(self.working_dir), "data", "registry") - - with open(registry_path, "r") as stream: - return yaml.safe_load(stream) - - -if __name__ == '__main__': - unittest.main() diff --git a/libbeat/Dockerfile b/libbeat/Dockerfile index e02f709d191..97a1b634384 100644 --- a/libbeat/Dockerfile +++ b/libbeat/Dockerfile @@ -1,8 +1,8 @@ -FROM golang:1.17.2 +FROM golang:1.17.5 RUN \ apt-get update \ - && apt-get install -y --no-install-recommends \ + && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \ netcat \ libpcap-dev \ python3 \ diff --git a/libbeat/README.md b/libbeat/README.md index cf99987c5a3..06a22219dfe 100644 --- a/libbeat/README.md +++ b/libbeat/README.md @@ -8,7 +8,7 @@ If you want to create a new project that reads some sort of operational data and ships it to Elasticsearch, we suggest you make use of this library. Please start by reading our [CONTRIBUTING](../CONTRIBUTING.md) file. We also have a [developer -guide](https://www.elastic.co/guide/en/beats/libbeat/current/new-beat.html) to +guide](https://www.elastic.co/guide/en/beats/devguide/master/index.html) to help you with the creation of new Beats. Please also open a topic on the [forums](https://discuss.elastic.co/c/beats/libbeat) and diff --git a/libbeat/_meta/config/general.reference.yml.tmpl b/libbeat/_meta/config/general.reference.yml.tmpl index 58a39af4b34..27118c979c9 100644 --- a/libbeat/_meta/config/general.reference.yml.tmpl +++ b/libbeat/_meta/config/general.reference.yml.tmpl @@ -77,66 +77,6 @@ # length of its retry interval each time, up to this maximum. #max_retry_interval: 30s - # The spool queue will store events in a local spool file, before - # forwarding the events to the outputs. - # Note: the spool queue is deprecated and will be removed in the future. - # Use the disk queue instead. - # - # The spool file is a circular buffer, which blocks once the file/buffer is full. - # Events are put into a write buffer and flushed once the write buffer - # is full or the flush_timeout is triggered. - # Once ACKed by the output, events are removed immediately from the queue, - # making space for new events to be persisted. - #spool: - # The file namespace configures the file path and the file creation settings. - # Once the file exists, the `size`, `page_size` and `prealloc` settings - # will have no more effect. - #file: - # Location of spool file. The default value is ${path.data}/spool.dat. - #path: "${path.data}/spool.dat" - - # Configure file permissions if file is created. The default value is 0600. - #permissions: 0600 - - # File size hint. The spool blocks, once this limit is reached. The default value is 100 MiB. - #size: 100MiB - - # The files page size. A file is split into multiple pages of the same size. The default value is 4KiB. - #page_size: 4KiB - - # If prealloc is set, the required space for the file is reserved using - # truncate. The default value is true. - #prealloc: true - - # Spool writer settings - # Events are serialized into a write buffer. The write buffer is flushed if: - # - The buffer limit has been reached. - # - The configured limit of buffered events is reached. - # - The flush timeout is triggered. - #write: - # Sets the write buffer size. - #buffer_size: 1MiB - - # Maximum duration after which events are flushed if the write buffer - # is not full yet. The default value is 1s. - #flush.timeout: 1s - - # Number of maximum buffered events. The write buffer is flushed once the - # limit is reached. - #flush.events: 16384 - - # Configure the on-disk event encoding. The encoding can be changed - # between restarts. - # Valid encodings are: json, ubjson, and cbor. - #codec: cbor - #read: - # Reader flush timeout, waiting for more events to become available, so - # to fill a complete batch as required by the outputs. - # If flush_timeout is 0, all available events are forwarded to the - # outputs immediately. - # The default value is 0s. - #flush.timeout: 0s - # Sets the maximum number of CPUs that can be executing simultaneously. The # default is the number of logical CPUs available in the system. #max_procs: diff --git a/libbeat/_meta/config/logging.reference.yml.tmpl b/libbeat/_meta/config/logging.reference.yml.tmpl index 9a1e91a0af8..f4ca435be01 100644 --- a/libbeat/_meta/config/logging.reference.yml.tmpl +++ b/libbeat/_meta/config/logging.reference.yml.tmpl @@ -67,8 +67,3 @@ logging.files: # Rotate existing logs on startup rather than appending to the existing # file. Defaults to true. # rotateonstartup: true - - # Rotated files are either suffixed with a number e.g. {{.BeatName}}.1 when - # renamed during rotation. Or when set to date, the date is added to - # the end of the file. On rotation a new file is created, older files are untouched. - #suffix: count diff --git a/libbeat/_meta/config/output-file.reference.yml.tmpl b/libbeat/_meta/config/output-file.reference.yml.tmpl index 7f7ff9998b3..665b8f3a7c1 100644 --- a/libbeat/_meta/config/output-file.reference.yml.tmpl +++ b/libbeat/_meta/config/output-file.reference.yml.tmpl @@ -16,7 +16,7 @@ #path: "/tmp/{{.BeatName}}" # Name of the generated files. The default is `{{.BeatName}}` and it generates - # files: `{{.BeatName}}`, `{{.BeatName}}.1`, `{{.BeatName}}.2`, etc. + # files: `{{.BeatName}}-{datetime}.ndjson`, `{{.BeatName}}-{datetime}-1.ndjson`, etc. #filename: {{.BeatName}} # Maximum size in kilobytes of each file. When this size is reached, and on @@ -33,4 +33,4 @@ #permissions: 0600 # Configure automatic file rotation on every startup. The default is true. - #rotate_on_startup: true \ No newline at end of file + #rotate_on_startup: true diff --git a/libbeat/_meta/config/setup.ilm.reference.yml.tmpl b/libbeat/_meta/config/setup.ilm.reference.yml.tmpl index 1416da0cc8d..5e4a2e642fe 100644 --- a/libbeat/_meta/config/setup.ilm.reference.yml.tmpl +++ b/libbeat/_meta/config/setup.ilm.reference.yml.tmpl @@ -5,17 +5,8 @@ # output.elasticsearch.index is ignored, and the write alias is used to set the # index name. -# Enable ILM support. Valid values are true, false, and auto. When set to auto -# (the default), the Beat uses index lifecycle management when it connects to a -# cluster that supports ILM; otherwise, it creates daily indices. -#setup.ilm.enabled: auto - -# Set the prefix used in the index lifecycle write alias name. The default alias -# name is '{{.BeatName}}-%{[agent.version]}'. -#setup.ilm.rollover_alias: '{{.BeatIndexPrefix}}' - -# Set the rollover index pattern. The default is "%{now/d}-000001". -#setup.ilm.pattern: "{now/d}-000001" +# Enable ILM support. Valid values are true, false. +#setup.ilm.enabled: true # Set the lifecycle policy name. The default policy name is # 'beatname'. diff --git a/libbeat/_meta/config/setup.template.reference.yml.tmpl b/libbeat/_meta/config/setup.template.reference.yml.tmpl index 95d8d4a50c8..d3019c6f2b8 100644 --- a/libbeat/_meta/config/setup.template.reference.yml.tmpl +++ b/libbeat/_meta/config/setup.template.reference.yml.tmpl @@ -7,19 +7,13 @@ # Set to false to disable template loading. #setup.template.enabled: true -# Select the kind of index template. From Elasticsearch 7.8, it is possible to -# use component templates. Available options: legacy, component, index. -# By default {{.BeatName}} uses the legacy index templates. -#setup.template.type: legacy - # Template name. By default the template name is "{{.BeatIndexPrefix}}-%{[agent.version]}" # The template name and pattern has to be set in case the Elasticsearch index pattern is modified. #setup.template.name: "{{.BeatIndexPrefix}}-%{[agent.version]}" -# Template pattern. By default the template pattern is "-%{[agent.version]}-*" to apply to the default index settings. -# The first part is the version of the beat and then -* is used to match all daily indices. +# Template pattern. By default the template pattern is "{{.BeatIndexPrefix}}-%{[agent.version]}" to apply to the default index settings. # The template name and pattern has to be set in case the Elasticsearch index pattern is modified. -#setup.template.pattern: "{{.BeatIndexPrefix}}-%{[agent.version]}-*" +#setup.template.pattern: "{{.BeatIndexPrefix}}-%{[agent.version]}" # Path to fields.yml file to generate the template #setup.template.fields: "${path.config}/fields.yml" diff --git a/libbeat/_meta/config/ssl.reference.yml.tmpl b/libbeat/_meta/config/ssl.reference.yml.tmpl index 65920fb646f..e6928c894fa 100644 --- a/libbeat/_meta/config/ssl.reference.yml.tmpl +++ b/libbeat/_meta/config/ssl.reference.yml.tmpl @@ -50,3 +50,10 @@ # # The pin is a base64 encoded string of the SHA-256 fingerprint. #ssl.ca_sha256: "" + +# A root CA HEX encoded fingerprint. During the SSL handshake if the +# fingerprint matches the root CA certificate, it will be added to +# the provided list of root CAs (`certificate_authorities`), if the +# list is empty or not defined, the matching certificate will be the +# only one in the list. Then the normal SSL validation happens. +#ssl.ca_trusted_fingerprint: "" diff --git a/libbeat/autodiscover/README.md b/libbeat/autodiscover/README.md new file mode 100644 index 00000000000..912d254b6f5 --- /dev/null +++ b/libbeat/autodiscover/README.md @@ -0,0 +1,191 @@ +# Kubernetes autodiscover provider in Beats and Agent + +https://www.elastic.co/guide/en/beats/metricbeat/master/configuration-autodiscover.html +https://www.elastic.co/guide/en/beats/filebeat/current/configuration-autodiscover.html +https://www.elastic.co/guide/en/fleet/7.x/dynamic-input-configuration.html#providers + +When you run applications on containers, they become moving targets to the monitoring system. Autodiscover allows you to track them and adapt settings as changes happen. By defining configuration templates, the autodiscover subsystem can monitor services as they start running. + +You define autodiscover settings in the autodiscover section of the metricbeat.yml/filebeat.yml config file. To enable autodiscover, you specify a list of providers. +For Elastic Agent we will discuss later. + +**Providers** +Autodiscover providers work by watching for events on the system and translating those events into internal autodiscover events with a common format. When you configure the provider, you can optionally use fields from the autodiscover event to set conditions that, when met, launch specific configurations. + +On start Metricbeat/Filebeat/Agent will scan existing containers and launch the proper configs for them. Then it will watch for new start/stop events. This ensures you don’t need to worry about state, but only define your desired configs. + +The Kubernetes autodiscover provider watches for Kubernetes nodes, pods, services and namespaces when they start, update, and stop. + +We will describe the internals of three ways of Kubernetes autodiscover process. +1. Templates Based Autodiscover +2. Hints Based Autodiscover +3. Autodiscover provider in Elastic Agent + +## Templates Based Autodiscover + +As the name suggests, user needs to set a template to indicate to autodiscover provider what to do. +There is one configuration variable that differentiates in a way how the autosicover process is performed. +This variable is `unique` + +### Autodiscover with LeaderElection +When setting `unique: true` the Leader Election mechanism is activated. That way **only** the Beat instance that will gain the leader lease/lock will enable the provided template. +The best appliance of this feature is when collecting cluster wide metrics from `kube-state-metrics` or `apiserver`. +In that case having all instances of metricbeat collecting the same metrics is not desirable. + +Example: +``` +metricbeat.autodiscover: + providers: + - type: kubernetes + scope: cluster + node: ${NODE_NAME} + unique: true + identifier: leader-election-metricbeat + templates: + - config: + - module: kubernetes + hosts: ["kube-state-metrics:8080"] + period: 10s + add_metadata: true + metricsets: + - state_node +``` + +##### How it works + +We will deep dive in the internals of [libbeat kubernetes autodiscover provider](https://github.com/elastic/beats/blob/4b1f69923b3f2abbbf1860295fe5dbff7db3d63c/libbeat/autodiscover/providers/kubernetes). + +We will use metricbeat as an example. + +Step-by-step walkthrough +1. Kubernetes provider `init` function [adds](https://github.com/elastic/beats/blob/4b1f69923b3f2abbbf1860295fe5dbff7db3d63c/libbeat/autodiscover/providers/kubernetes/kubernetes.go#L46) the provider in the autodiscover providers registry at startup. For Kubernetes provider an `AutodiscoverBuilder` func is passed as an argument. +2. Metricbeat calls `NewAutodiscover` [function](https://github.com/elastic/beats/blob/4b1f69923b3f2abbbf1860295fe5dbff7db3d63c/metricbeat/beater/metricbeat.go#L183) which checks in the config for enabled providers and [builds](https://github.com/elastic/beats/blob/4b1f69923b3f2abbbf1860295fe5dbff7db3d63c/libbeat/autodiscover/provider.go#L90) them one by one, calling the `AutodiscoverBuilder` func. +3. Kubernetes `AutodiscoverBuilder` creates and returns a [Kubernetes Provider struct](https://github.com/elastic/beats/blob/4b1f69923b3f2abbbf1860295fe5dbff7db3d63c/libbeat/autodiscover/providers/kubernetes/kubernetes.go#L131) which is then added to an Autodiscover manager struct. +4. When unique is set to true [NewLeaderElectionManager](https://github.com/elastic/beats/blob/4b1f69923b3f2abbbf1860295fe5dbff7db3d63c/libbeat/autodiscover/providers/kubernetes/kubernetes.go#L141) is set as the eventManager of Kubernetes Provider. +5. Metricbeat [starts](https://github.com/elastic/beats/blob/4b1f69923b3f2abbbf1860295fe5dbff7db3d63c/metricbeat/beater/metricbeat.go#L249) the Autodiscover manager which starts for Kubernets provider the [leaderElectionManager](https://github.com/elastic/beats/blob/4b1f69923b3f2abbbf1860295fe5dbff7db3d63c/libbeat/autodiscover/providers/kubernetes/kubernetes.go#L326). Before starting the providers it also starts a worker for listening of events that will be published by the eventers of each provider. +6. `OnStartedLeading` is executed when the specific metricbeat instance gains the leader election lock. [StartLeading](https://github.com/elastic/beats/blob/4b1f69923b3f2abbbf1860295fe5dbff7db3d63c/libbeat/autodiscover/providers/kubernetes/kubernetes.go#L205) creates a bus event with `"start": true,` and publishes it. The template configurations is also added in this event. +7. [Listener](https://github.com/elastic/beats/blob/4b1f69923b3f2abbbf1860295fe5dbff7db3d63c/libbeat/autodiscover/autodiscover.go#L140) of events get the published event and generates [configs](https://github.com/elastic/beats/blob/4b1f69923b3f2abbbf1860295fe5dbff7db3d63c/libbeat/autodiscover/autodiscover.go#L185) for it. Configs include the variables and settings from the template set by the user. +8. For each config the worker checks if it already [exists](https://github.com/elastic/beats/blob/4b1f69923b3f2abbbf1860295fe5dbff7db3d63c/libbeat/autodiscover/autodiscover.go#L221) (It was already handled). If at least one of the events config does not exist, then the config is marked as `updated`. +9. The runners list get [reloaded](https://github.com/elastic/beats/blob/4b1f69923b3f2abbbf1860295fe5dbff7db3d63c/libbeat/cfgfile/list.go#L54). It is checked from the list of current runners if each config is handled by one of them. + If no runner is handling that config a new runner will [start](https://github.com/elastic/beats/blob/4b1f69923b3f2abbbf1860295fe5dbff7db3d63c/libbeat/cfgfile/list.go#L107). If some runners are no longer needed will be removed. +10. Starting of a runner starts under the hood the metricbeat [module](https://github.com/elastic/beats/blob/4b1f69923b3f2abbbf1860295fe5dbff7db3d63c/metricbeat/mb/module/runner.go#L76) with the specific metricsets as they are set in the template. Same also applies for filebeat and heartbeat cases. + +### Autodiscover without LeaderElection + +When setting `unique: false` or not setting it at all the Leader Election mechanism is disabled. That way all Beat instances will enable the provided template. Or at least the ones that match a condition. +A good appliance of this is when user wants to enable a specific module(for example redis) each time a pod with a specific label appears in each kubernetes node. + +Example: +``` +metricbeat.autodiscover: + providers: + - type: kubernetes + templates: + - condition: + contains: + kubernetes.labels.app: "redis" + config: + - module: redis + metricsets: ["info", "keyspace"] + hosts: "${data.host}:6379" + password: "${REDIS_PASSWORD}" +``` + +##### How it works + +We will use metricbeat and redis module as example. +Step-by-step walkthrough + +Steps 1-3 are exactly the same as with Leader Election. +4. In the [Kubernetes Provider struct](https://github.com/elastic/beats/blob/4b1f69923b3f2abbbf1860295fe5dbff7db3d63c/libbeat/autodiscover/providers/kubernetes/kubernetes.go#L131) created by the Kubernetes AutodiscoverBuilder in case there is a [condition](https://github.com/elastic/beats/blob/4b1f69923b3f2abbbf1860295fe5dbff7db3d63c/libbeat/autodiscover/providers/kubernetes/kubernetes.go#L116) a `NewConfigMapper` is created. It contains the condition [map](https://github.com/elastic/beats/blob/4b1f69923b3f2abbbf1860295fe5dbff7db3d63c/libbeat/autodiscover/template/config.go#L64) with all the conditions of a given config. +4. When unique is set to false, the resource is [checked](https://github.com/elastic/beats/blob/4b1f69923b3f2abbbf1860295fe5dbff7db3d63c/libbeat/autodiscover/providers/kubernetes/kubernetes.go#L239) from the configuration template(default is pod) and a new PodEventer/NodeEventer/ServiceEventer is set as the eventManager of Kubernetes Provider. +5. The kubernetes node that the metricbeat instance is running on is [discovered](https://github.com/elastic/beats/blob/4b1f69923b3f2abbbf1860295fe5dbff7db3d63c/libbeat/autodiscover/providers/kubernetes/pod.go#L72). +6. A dedicated watcher to watch [pods](https://github.com/elastic/beats/blob/4b1f69923b3f2abbbf1860295fe5dbff7db3d63c/libbeat/autodiscover/providers/kubernetes/pod.go#L82), nodes and namespaces get started. Also a [metadata generator](https://github.com/elastic/beats/blob/4b1f69923b3f2abbbf1860295fe5dbff7db3d63c/libbeat/autodiscover/providers/kubernetes/pod.go#L113) is started to enrich the events with kubernetes metadata. +7. Each time a new event is about to be published by the watchers(we will have a dedicated section of how events are published), it is checked whether the condition set by the user [matches](https://github.com/elastic/beats/blob/4b1f69923b3f2abbbf1860295fe5dbff7db3d63c/libbeat/autodiscover/providers/kubernetes/kubernetes.go#L182) the event. +8. If it matches, then a config is created with the configuration set by user and it is added in the event. After that the event gets published. +9. The worker listening for events receives the start event and checks if there is any update in the configs of the event. (same process with leader election steps 6-9) +10. If there is an update it starts or stops the runners needed. In our example it starts a new runner that starts the redis module. + +##### How pod eventer works + +The [watcher](https://github.com/elastic/beats/blob/4b1f69923b3f2abbbf1860295fe5dbff7db3d63c/libbeat/common/kubernetes/watcher.go#L124) struct has a kubernetes informer field which depending on the resource type [watches](https://github.com/elastic/beats/blob/4b1f69923b3f2abbbf1860295fe5dbff7db3d63c/libbeat/common/kubernetes/informer.go#L52) and lists the changes in the kubernetes cluster for that specific resource. +When a new pod for example is discovered it is added in the work [queue](https://github.com/elastic/beats/blob/4b1f69923b3f2abbbf1860295fe5dbff7db3d63c/libbeat/common/kubernetes/watcher.go#L137) for processing. +The watcher processes that [queue](https://github.com/elastic/beats/blob/4b1f69923b3f2abbbf1860295fe5dbff7db3d63c/libbeat/common/kubernetes/watcher.go#L218) and depending if there was an addition,deletion or update of a resource it calls the +related [method](https://github.com/elastic/beats/blob/4b1f69923b3f2abbbf1860295fe5dbff7db3d63c/libbeat/common/kubernetes/watcher.go#L250). +* [OnAdd](https://github.com/elastic/beats/blob/4b1f69923b3f2abbbf1860295fe5dbff7db3d63c/libbeat/autodiscover/providers/kubernetes/pod.go#L137) is called when there is a pod addition and it executes [emit](https://github.com/elastic/beats/blob/4b1f69923b3f2abbbf1860295fe5dbff7db3d63c/libbeat/autodiscover/providers/kubernetes/pod.go#L314) with `start` flag. Emit adds the pod to a new event together will all metadata, sets `start: true` and [publishes](https://github.com/elastic/beats/blob/4b1f69923b3f2abbbf1860295fe5dbff7db3d63c/libbeat/autodiscover/providers/kubernetes/pod.go#L343) it. Step 7 follows. +* [OnDelete](https://github.com/elastic/beats/blob/4b1f69923b3f2abbbf1860295fe5dbff7db3d63c/libbeat/autodiscover/providers/kubernetes/pod.go#L160) is called when there is a pod deletion and it ecexutes emit with `stop` flag. Emit adds the pod to a new event with ``stop: true`` and publishes it. Step 7 follows. +* [OnUpdate](https://github.com/elastic/beats/blob/4b1f69923b3f2abbbf1860295fe5dbff7db3d63c/libbeat/autodiscover/providers/kubernetes/pod.go#L146) is called when there is update in the an existing resource and it ecexutes at first emit with `stop` flag to generate a stop event and then with `start` flag to generate a start event. + + +## Hints Based Autodiscover + +https://www.elastic.co/guide/en/beats/metricbeat/master/configuration-autodiscover-hints.html + +Metricbeat, Filebeat and Heartbeat support autodiscover based on hints from the provider. The hints system looks for hints in Kubernetes Pod annotations which have the prefix co.elastic.metrics. As soon as the container starts, Metricbeat/Filebeat will check if it contains any hints and launch the proper config for it. Hints tell Metricbeat/Filebeat how to get metrics for the given container. + +Example metricbeat configuration: +``` +metricbeat.autodiscover: + providers: + - type: kubernetes + node: ${NODE_NAME} + hints.enabled: true +``` + +Example redis pod with right annotations: +``` +apiVersion: v1 +kind: Pod +metadata: + name: redis + annotations: + co.elastic.metrics/module: redis + co.elastic.metrics/metricsets: info + co.elastic.metrics/hosts: '${data.host}:6379' +spec: + containers: + - name: redis + image: redis:5.0.4 + command: + - redis-server + - "/redis-master/redis.conf" + env: + - name: MASTER + value: "true" + ports: + - containerPort: 6379 + resources: + limits: + cpu: "0.1" + volumeMounts: + - mountPath: /redis-master-data + name: data + - mountPath: /redis-master + name: config + volumes: + - name: data + emptyDir: {} + - name: config + configMap: + name: example-redis-config + items: + - key: redis-config + path: redis.conf +``` + +##### How hints work + +Everything works the same as Autodiscover without LeaderElection until step 8. + +8. If there is no conditions in the template set by the user, the configs will be generated from [hints](https://github.com/elastic/beats/blob/4b1f69923b3f2abbbf1860295fe5dbff7db3d63c/libbeat/autodiscover/providers/kubernetes/kubernetes.go#L186). +9. Wether hints are enabled or not is part of the [Kubernetes Provider struct](https://github.com/elastic/beats/blob/4b1f69923b3f2abbbf1860295fe5dbff7db3d63c/libbeat/autodiscover/providers/kubernetes/kubernetes.go#L121) builders field. +10. [GenerateHints](https://github.com/elastic/beats/blob/eff92354db783001880f4bade9f59942fca747ba/libbeat/autodiscover/builder/helper.go#L213) function looks into the event's annotations. A [hints map](https://github.com/elastic/beats/blob/eff92354db783001880f4bade9f59942fca747ba/libbeat/autodiscover/builder/helper.go#L226) is created with all hints and returned. +11. From those hints, configs are [created](https://github.com/elastic/beats/blob/4b1f69923b3f2abbbf1860295fe5dbff7db3d63c/libbeat/autodiscover/builder.go#L97) in the same form as in `Autodiscover without LeaderElection` step 8. + They contain the same information as if they where set explicitly in the metricbeat configureation but actually derive from the pod annotations. +12. Those configs are then [added](https://github.com/elastic/beats/blob/4b1f69923b3f2abbbf1860295fe5dbff7db3d63c/libbeat/autodiscover/providers/kubernetes/kubernetes.go#L197) in the event and gets published. +13. The process after that is same as in `Autodiscover without LeaderElection` step 9 and onward. + + + +## Autodiscover provider in Elastic Agent +Follow the link [here](https://github.com/elastic/beats/blob/aa264bdf008a9bf309e61744e9ec8c5586593f12/x-pack/elastic-agent/pkg/composable/providers/kubernetes/README.md). diff --git a/libbeat/autodiscover/autodiscover.go b/libbeat/autodiscover/autodiscover.go index 8c6977e8362..e1f1d8d2bfc 100644 --- a/libbeat/autodiscover/autodiscover.go +++ b/libbeat/autodiscover/autodiscover.go @@ -64,6 +64,10 @@ type Autodiscover struct { meta *meta.Map listener bus.Listener logger *logp.Logger + + // workDone is a channel used for testing purpouses, to know when the worker has + // done some work. + workDone chan struct{} } // NewAutodiscover instantiates and returns a new Autodiscover manager @@ -165,6 +169,11 @@ func (a *Autodiscover) worker() { // reset updated status updated = false } + + // For testing purpouses. + if a.workDone != nil { + a.workDone <- struct{}{} + } } } @@ -207,26 +216,30 @@ func (a *Autodiscover) handleStart(event bus.Event) bool { continue } - err = a.factory.CheckConfig(config) - if err != nil { - a.logger.Error(errors.Wrap(err, fmt.Sprintf( - "Auto discover config check failed for config '%s', won't start runner", - common.DebugString(config, true)))) - continue - } - // Update meta no matter what dynFields := a.meta.Store(hash, meta) + if _, ok := newCfg[hash]; ok { + a.logger.Debugf("Config %v duplicated in start event", common.DebugString(config, true)) + continue + } + if cfg, ok := a.configs[eventID][hash]; ok { a.logger.Debugf("Config %v is already running", common.DebugString(config, true)) newCfg[hash] = cfg continue - } else { - newCfg[hash] = &reload.ConfigWithMeta{ - Config: config, - Meta: &dynFields, - } + } + + err = a.factory.CheckConfig(config) + if err != nil { + a.logger.Error(errors.Wrap(err, fmt.Sprintf( + "Auto discover config check failed for config '%s', won't start runner", + common.DebugString(config, true)))) + continue + } + newCfg[hash] = &reload.ConfigWithMeta{ + Config: config, + Meta: &dynFields, } updated = true diff --git a/libbeat/autodiscover/autodiscover_test.go b/libbeat/autodiscover/autodiscover_test.go index 4b2ecfef128..2d0ea26b689 100644 --- a/libbeat/autodiscover/autodiscover_test.go +++ b/libbeat/autodiscover/autodiscover_test.go @@ -75,6 +75,8 @@ type mockAdapter struct { mutex sync.Mutex configs []*common.Config runners []*mockRunner + + CheckConfigCallCount int } // CreateConfig generates a valid list of configs from the given event, the received event will have all keys defined by `StartFilter` @@ -87,6 +89,8 @@ func (m *mockAdapter) CreateConfig(event bus.Event) ([]*common.Config, error) { // CheckConfig tests given config to check if it will work or not, returns errors in case it won't work func (m *mockAdapter) CheckConfig(c *common.Config) error { + m.CheckConfigCallCount++ + config := struct { Broken bool `config:"broken"` }{} @@ -324,6 +328,66 @@ func TestAutodiscoverHash(t *testing.T) { assert.False(t, runners[1].stopped) } +func TestAutodiscoverDuplicatedConfigConfigCheckCalledOnce(t *testing.T) { + goroutines := resources.NewGoroutinesChecker() + defer goroutines.Check(t) + + // Register mock autodiscover provider + busChan := make(chan bus.Bus, 1) + + Registry = NewRegistry() + Registry.AddProvider("mock", func(beatName string, b bus.Bus, uuid uuid.UUID, c *common.Config, k keystore.Keystore) (Provider, error) { + // intercept bus to mock events + busChan <- b + + return &mockProvider{}, nil + }) + + // Create a mock adapter that returns a duplicated config + runnerConfig, _ := common.NewConfigFrom(map[string]string{ + "id": "foo", + }) + adapter := mockAdapter{ + configs: []*common.Config{runnerConfig, runnerConfig}, + } + + // and settings: + providerConfig, _ := common.NewConfigFrom(map[string]string{ + "type": "mock", + }) + config := Config{ + Providers: []*common.Config{providerConfig}, + } + k, _ := keystore.NewFileKeystore("test") + // Create autodiscover manager + autodiscover, err := NewAutodiscover("test", nil, &adapter, &adapter, &config, k) + if err != nil { + t.Fatal(err) + } + + autodiscover.workDone = make(chan struct{}) + + // Start it + autodiscover.Start() + defer autodiscover.Stop() + eventBus := <-busChan + + // Publish a couple of events. + for i := 0; i < 2; i++ { + eventBus.Publish(bus.Event{ + "id": "foo", + "provider": "mock", + "start": true, + "meta": common.MapStr{ + "foo": "bar", + }, + }) + <-autodiscover.workDone + assert.Equal(t, 1, len(adapter.Runners()), "Only one runner should be started") + assert.Equal(t, 1, adapter.CheckConfigCallCount, "Check config should have been called only once") + } +} + func TestAutodiscoverWithConfigCheckFailures(t *testing.T) { goroutines := resources.NewGoroutinesChecker() defer goroutines.Check(t) diff --git a/libbeat/autodiscover/providers/kubernetes/config.go b/libbeat/autodiscover/providers/kubernetes/config.go index 173a5208c99..46f73930141 100644 --- a/libbeat/autodiscover/providers/kubernetes/config.go +++ b/libbeat/autodiscover/providers/kubernetes/config.go @@ -66,11 +66,12 @@ var DefaultCleanupTimeout time.Duration = 0 func defaultConfig() *Config { return &Config{ - SyncPeriod: 10 * time.Minute, - Resource: "pod", - CleanupTimeout: DefaultCleanupTimeout, - Prefix: "co.elastic", - Unique: false, + SyncPeriod: 10 * time.Minute, + Resource: "pod", + CleanupTimeout: DefaultCleanupTimeout, + Prefix: "co.elastic", + Unique: false, + AddResourceMetadata: metadata.GetDefaultResourceMetadataConfig(), } } diff --git a/libbeat/autodiscover/providers/kubernetes/pod.go b/libbeat/autodiscover/providers/kubernetes/pod.go index e380712f182..be423080068 100644 --- a/libbeat/autodiscover/providers/kubernetes/pod.go +++ b/libbeat/autodiscover/providers/kubernetes/pod.go @@ -33,7 +33,6 @@ import ( "github.com/elastic/beats/v7/libbeat/common/bus" "github.com/elastic/beats/v7/libbeat/common/kubernetes" "github.com/elastic/beats/v7/libbeat/common/kubernetes/metadata" - "github.com/elastic/beats/v7/libbeat/common/safemapstr" "github.com/elastic/beats/v7/libbeat/logp" ) @@ -100,9 +99,6 @@ func NewPodEventer(uuid uuid.UUID, cfg *common.Config, client k8s.Interface, pub options.Namespace = config.Namespace } metaConf := config.AddResourceMetadata - if metaConf == nil { - metaConf = metadata.GetDefaultResourceMetadataConfig() - } nodeWatcher, err := kubernetes.NewNamedWatcher("node", client, &kubernetes.Node{}, options, nil) if err != nil { logger.Errorf("couldn't create watcher for %T due to error %+v", &kubernetes.Node{}, err) @@ -128,8 +124,13 @@ func NewPodEventer(uuid uuid.UUID, cfg *common.Config, client k8s.Interface, pub watcher.AddEventHandler(p) + if nodeWatcher != nil && (config.Hints.Enabled() || metaConf.Node.Enabled()) { + updater := kubernetes.NewNodePodUpdater(p.unlockedUpdate, watcher.Store(), &p.crossUpdate) + nodeWatcher.AddEventHandler(updater) + } + if namespaceWatcher != nil && (config.Hints.Enabled() || metaConf.Namespace.Enabled()) { - updater := newNamespacePodUpdater(p.unlockedUpdate, watcher.Store(), &p.crossUpdate) + updater := kubernetes.NewNamespacePodUpdater(p.unlockedUpdate, watcher.Store(), &p.crossUpdate) namespaceWatcher.AddEventHandler(updater) } @@ -189,8 +190,7 @@ func (p *pod) GenerateHints(event bus.Event) bus.Event { } // Look at all the namespace level default annotations and do a merge with priority going to the pod annotations. - rawNsAnn, err := kubeMeta.GetValue("namespace.annotations") - if err == nil { + if rawNsAnn, ok := kubeMeta["namespace_annotations"]; ok { namespaceAnnotations, _ := rawNsAnn.(common.MapStr) if len(namespaceAnnotations) != 0 { annotations.DeepUpdateNoOverwrite(namespaceAnnotations) @@ -260,47 +260,6 @@ func (p *pod) Stop() { } } -type containerInPod struct { - id string - runtime string - spec kubernetes.Container - status kubernetes.PodContainerStatus -} - -// getContainersInPod returns all the containers defined in a pod and their statuses. -// It includes init and ephemeral containers. -func getContainersInPod(pod *kubernetes.Pod) []*containerInPod { - var containers []*containerInPod - for _, c := range pod.Spec.Containers { - containers = append(containers, &containerInPod{spec: c}) - } - for _, c := range pod.Spec.InitContainers { - containers = append(containers, &containerInPod{spec: c}) - } - for _, c := range pod.Spec.EphemeralContainers { - c := kubernetes.Container(c.EphemeralContainerCommon) - containers = append(containers, &containerInPod{spec: c}) - } - - statuses := make(map[string]*kubernetes.PodContainerStatus) - mapStatuses := func(s []kubernetes.PodContainerStatus) { - for i := range s { - statuses[s[i].Name] = &s[i] - } - } - mapStatuses(pod.Status.ContainerStatuses) - mapStatuses(pod.Status.InitContainerStatuses) - mapStatuses(pod.Status.EphemeralContainerStatuses) - for _, c := range containers { - if s, ok := statuses[c.spec.Name]; ok { - c.id, c.runtime = kubernetes.ContainerIDWithRuntime(*s) - c.status = *s - } - } - - return containers -} - // emit emits the events for the given pod according to its state and // the given flag. // It emits a pod event if the pod has at least a running container, @@ -316,15 +275,15 @@ func getContainersInPod(pod *kubernetes.Pod) []*containerInPod { // Network information is only included in events for running containers // and for pods with at least one running container. func (p *pod) emit(pod *kubernetes.Pod, flag string) { - annotations := podAnnotations(pod) - namespaceAnnotations := podNamespaceAnnotations(pod, p.namespaceWatcher) + annotations := kubernetes.PodAnnotations(pod) + namespaceAnnotations := kubernetes.PodNamespaceAnnotations(pod, p.namespaceWatcher) eventList := make([][]bus.Event, 0) portsMap := common.MapStr{} - containers := getContainersInPod(pod) + containers := kubernetes.GetContainersInPod(pod) anyContainerRunning := false for _, c := range containers { - if c.status.State.Running != nil { + if c.Status.State.Running != nil { anyContainerRunning = true } @@ -343,7 +302,7 @@ func (p *pod) emit(pod *kubernetes.Pod, flag string) { eventList = append([][]bus.Event{{event}}, eventList...) } - delay := (flag == "stop" && podTerminated(pod, containers)) + delay := (flag == "stop" && kubernetes.PodTerminated(pod, containers)) p.publishAll(eventList, delay) } @@ -354,22 +313,22 @@ func (p *pod) emit(pod *kubernetes.Pod, flag string) { // running. // If the container ID is unknown, only "stop" events are generated. // It also returns a map with the named ports. -func (p *pod) containerPodEvents(flag string, pod *kubernetes.Pod, c *containerInPod, annotations, namespaceAnnotations common.MapStr) ([]bus.Event, common.MapStr) { - if c.id == "" && flag != "stop" { +func (p *pod) containerPodEvents(flag string, pod *kubernetes.Pod, c *kubernetes.ContainerInPod, annotations, namespaceAnnotations common.MapStr) ([]bus.Event, common.MapStr) { + if c.ID == "" && flag != "stop" { return nil, nil } // This must be an id that doesn't depend on the state of the container // so it works also on `stop` if containers have been already deleted. - eventID := fmt.Sprintf("%s.%s", pod.GetObjectMeta().GetUID(), c.spec.Name) + eventID := fmt.Sprintf("%s.%s", pod.GetObjectMeta().GetUID(), c.Spec.Name) - meta := p.metagen.Generate(pod, metadata.WithFields("container.name", c.spec.Name)) + meta := p.metagen.Generate(pod, metadata.WithFields("container.name", c.Spec.Name)) cmeta := common.MapStr{ - "id": c.id, - "runtime": c.runtime, + "id": c.ID, + "runtime": c.Runtime, "image": common.MapStr{ - "name": c.spec.Image, + "name": c.Spec.Image, }, } @@ -379,16 +338,16 @@ func (p *pod) containerPodEvents(flag string, pod *kubernetes.Pod, c *containerI kubemeta = kubemeta.Clone() kubemeta["annotations"] = annotations kubemeta["container"] = common.MapStr{ - "id": c.id, - "name": c.spec.Name, - "image": c.spec.Image, - "runtime": c.runtime, + "id": c.ID, + "name": c.Spec.Name, + "image": c.Spec.Image, + "runtime": c.Runtime, } if len(namespaceAnnotations) != 0 { - kubemeta.Put("namespace.annotations", namespaceAnnotations) + kubemeta["namespace_annotations"] = namespaceAnnotations } - ports := c.spec.Ports + ports := c.Spec.Ports if len(ports) == 0 { // Ensure that at least one event is generated for this container. // Set port to zero to signify that the event is from a container @@ -412,7 +371,7 @@ func (p *pod) containerPodEvents(flag string, pod *kubernetes.Pod, c *containerI } // Include network information only if the container is running, // so templates that need network don't generate a config. - if c.status.State.Running != nil { + if c.Status.State.Running != nil { if port.Name != "" && port.ContainerPort != 0 { portsMap[port.Name] = port.ContainerPort } @@ -437,7 +396,7 @@ func (p *pod) podEvent(flag string, pod *kubernetes.Pod, ports common.MapStr, in kubemeta = kubemeta.Clone() kubemeta["annotations"] = annotations if len(namespaceAnnotations) != 0 { - kubemeta.Put("namespace.annotations", namespaceAnnotations) + kubemeta["namespace_annotations"] = namespaceAnnotations } // Don't set a port on the event @@ -461,71 +420,6 @@ func (p *pod) podEvent(flag string, pod *kubernetes.Pod, ports common.MapStr, in return event } -// podAnnotations returns the annotations in a pod -func podAnnotations(pod *kubernetes.Pod) common.MapStr { - annotations := common.MapStr{} - for k, v := range pod.GetObjectMeta().GetAnnotations() { - safemapstr.Put(annotations, k, v) - } - return annotations -} - -// podNamespaceAnnotations returns the annotations of the namespace of the pod -func podNamespaceAnnotations(pod *kubernetes.Pod, watcher kubernetes.Watcher) common.MapStr { - if watcher == nil { - return nil - } - - rawNs, ok, err := watcher.Store().GetByKey(pod.Namespace) - if !ok || err != nil { - return nil - } - - namespace, ok := rawNs.(*kubernetes.Namespace) - if !ok { - return nil - } - - annotations := common.MapStr{} - for k, v := range namespace.GetAnnotations() { - safemapstr.Put(annotations, k, v) - } - return annotations -} - -// podTerminating returns true if a pod is marked for deletion or is in a phase beyond running. -func podTerminating(pod *kubernetes.Pod) bool { - if pod.GetObjectMeta().GetDeletionTimestamp() != nil { - return true - } - - switch pod.Status.Phase { - case kubernetes.PodRunning, kubernetes.PodPending: - default: - return true - } - - return false -} - -// podTerminated returns true if a pod is terminated, this method considers a -// pod as terminated if none of its containers are running (or going to be running). -func podTerminated(pod *kubernetes.Pod, containers []*containerInPod) bool { - // Pod is not marked for termination, so it is not terminated. - if !podTerminating(pod) { - return false - } - - // If any container is running, the pod is not terminated yet. - for _, container := range containers { - if container.status.State.Running != nil { - return false - } - } - - return true -} - // publishAll publishes all events in the event list in the same order. If delay is true // publishAll schedules the publication of the events after the configured `CleanupPeriod` // and returns inmediatelly. @@ -544,60 +438,3 @@ func (p *pod) publishAll(eventList [][]bus.Event, delay bool) { p.publishFunc(events) } } - -// podUpdaterHandlerFunc is a function that handles pod updater notifications. -type podUpdaterHandlerFunc func(interface{}) - -// podUpdaterStore is the interface that an object needs to implement to be -// used as a pod updater store. -type podUpdaterStore interface { - List() []interface{} -} - -// namespacePodUpdater notifies updates on pods when their namespaces are updated. -type namespacePodUpdater struct { - handler podUpdaterHandlerFunc - store podUpdaterStore - locker sync.Locker -} - -// newNamespacePodUpdater creates a namespacePodUpdater -func newNamespacePodUpdater(handler podUpdaterHandlerFunc, store podUpdaterStore, locker sync.Locker) *namespacePodUpdater { - return &namespacePodUpdater{ - handler: handler, - store: store, - locker: locker, - } -} - -// OnUpdate handles update events on namespaces. -func (n *namespacePodUpdater) OnUpdate(obj interface{}) { - ns, ok := obj.(*kubernetes.Namespace) - if !ok { - return - } - - // n.store.List() returns a snapshot at this point. If a delete is received - // from the main watcher, this loop may generate an update event after the - // delete is processed, leaving configurations that would never be deleted. - // Also this loop can miss updates, what could leave outdated configurations. - // Avoid these issues by locking the processing of events from the main watcher. - if n.locker != nil { - n.locker.Lock() - defer n.locker.Unlock() - } - for _, pod := range n.store.List() { - pod, ok := pod.(*kubernetes.Pod) - if ok && pod.Namespace == ns.Name { - n.handler(pod) - } - } -} - -// OnAdd handles add events on namespaces. Nothing to do, if pods are added to this -// namespace they will generate their own add events. -func (*namespacePodUpdater) OnAdd(interface{}) {} - -// OnDelete handles delete events on namespaces. Nothing to do, if pods are deleted from this -// namespace they will generate their own delete events. -func (*namespacePodUpdater) OnDelete(interface{}) {} diff --git a/libbeat/autodiscover/providers/kubernetes/pod_test.go b/libbeat/autodiscover/providers/kubernetes/pod_test.go index 266a15fb159..adf98a7cdad 100644 --- a/libbeat/autodiscover/providers/kubernetes/pod_test.go +++ b/libbeat/autodiscover/providers/kubernetes/pod_test.go @@ -162,19 +162,17 @@ func TestGenerateHints(t *testing.T) { "co.elastic.logs/json.keys_under_root": "true", "not.to.include": "true", }), + "namespace_annotations": getNestedAnnotations(common.MapStr{ + "co.elastic.metrics/module": "prometheus", + "co.elastic.metrics/period": "10s", + "co.elastic.metrics.foobar/period": "15s", + }), "container": common.MapStr{ "name": "foobar", "id": "abc", "runtime": "docker", }, - "namespace": common.MapStr{ - "name": "ns", - "annotations": getNestedAnnotations(common.MapStr{ - "co.elastic.metrics/module": "prometheus", - "co.elastic.metrics/period": "10s", - "co.elastic.metrics.foobar/period": "15s", - }), - }, + "namespace": "ns", }, }, result: bus.Event{ @@ -184,19 +182,17 @@ func TestGenerateHints(t *testing.T) { "co.elastic.logs/json.keys_under_root": "true", "not.to.include": "true", }), + "namespace_annotations": getNestedAnnotations(common.MapStr{ + "co.elastic.metrics/period": "10s", + "co.elastic.metrics.foobar/period": "15s", + "co.elastic.metrics/module": "prometheus", + }), "container": common.MapStr{ "name": "foobar", "id": "abc", "runtime": "docker", }, - "namespace": common.MapStr{ - "name": "ns", - "annotations": getNestedAnnotations(common.MapStr{ - "co.elastic.metrics/period": "10s", - "co.elastic.metrics.foobar/period": "15s", - "co.elastic.metrics/module": "prometheus", - }), - }, + "namespace": "ns", }, "hints": common.MapStr{ "logs": common.MapStr{ @@ -231,14 +227,12 @@ func TestGenerateHints(t *testing.T) { "co.elastic.metrics.foobar/period": "15s", "not.to.include": "true", }), - "namespace": common.MapStr{ - "name": "ns", - "annotations": getNestedAnnotations(common.MapStr{ - "co.elastic.metrics/module": "dropwizard", - "co.elastic.metrics/period": "60s", - "co.elastic.metrics.foobar/period": "25s", - }), - }, + "namespace_annotations": getNestedAnnotations(common.MapStr{ + "co.elastic.metrics/module": "dropwizard", + "co.elastic.metrics/period": "60s", + "co.elastic.metrics.foobar/period": "25s", + }), + "namespace": "ns", "container": common.MapStr{ "name": "foobar", "id": "abc", @@ -254,19 +248,17 @@ func TestGenerateHints(t *testing.T) { "co.elastic.metrics.foobar/period": "15s", "not.to.include": "true", }), + "namespace_annotations": getNestedAnnotations(common.MapStr{ + "co.elastic.metrics/module": "dropwizard", + "co.elastic.metrics/period": "60s", + "co.elastic.metrics.foobar/period": "25s", + }), "container": common.MapStr{ "name": "foobar", "id": "abc", "runtime": "docker", }, - "namespace": common.MapStr{ - "name": "ns", - "annotations": getNestedAnnotations(common.MapStr{ - "co.elastic.metrics/module": "dropwizard", - "co.elastic.metrics/period": "60s", - "co.elastic.metrics.foobar/period": "25s", - }), - }, + "namespace": "ns", }, "hints": common.MapStr{ "metrics": common.MapStr{ @@ -287,36 +279,32 @@ func TestGenerateHints(t *testing.T) { { event: bus.Event{ "kubernetes": common.MapStr{ + "namespace_annotations": getNestedAnnotations(common.MapStr{ + "co.elastic.metrics/module": "prometheus", + "co.elastic.metrics/period": "10s", + "co.elastic.metrics.foobar/period": "15s", + }), "container": common.MapStr{ "name": "foobar", "id": "abc", "runtime": "docker", }, - "namespace": common.MapStr{ - "name": "ns", - "annotations": getNestedAnnotations(common.MapStr{ - "co.elastic.metrics/module": "prometheus", - "co.elastic.metrics/period": "10s", - "co.elastic.metrics.foobar/period": "15s", - }), - }, + "namespace": "ns", }, }, result: bus.Event{ "kubernetes": common.MapStr{ + "namespace_annotations": getNestedAnnotations(common.MapStr{ + "co.elastic.metrics/module": "prometheus", + "co.elastic.metrics/period": "10s", + "co.elastic.metrics.foobar/period": "15s", + }), "container": common.MapStr{ "name": "foobar", "id": "abc", "runtime": "docker", }, - "namespace": common.MapStr{ - "name": "ns", - "annotations": getNestedAnnotations(common.MapStr{ - "co.elastic.metrics/module": "prometheus", - "co.elastic.metrics/period": "10s", - "co.elastic.metrics.foobar/period": "15s", - }), - }, + "namespace": "ns", }, "hints": common.MapStr{ "metrics": common.MapStr{ @@ -419,16 +407,12 @@ func TestPod_EmitEvent(t *testing.T) { "node": common.MapStr{ "name": "node", }, - "namespace": common.MapStr{ - "name": "default", - }, + "namespace": "default", "annotations": common.MapStr{}, }, "meta": common.MapStr{ "kubernetes": common.MapStr{ - "namespace": common.MapStr{ - "name": "default", - }, + "namespace": "default", "pod": common.MapStr{ "name": "filebeat", "uid": "005f3b90-4b9d-12f8-acf0-31020a840133", @@ -461,16 +445,12 @@ func TestPod_EmitEvent(t *testing.T) { "node": common.MapStr{ "name": "node", }, - "namespace": common.MapStr{ - "name": "default", - }, + "namespace": "default", "annotations": common.MapStr{}, }, "meta": common.MapStr{ "kubernetes": common.MapStr{ - "namespace": common.MapStr{ - "name": "default", - }, + "namespace": "default", "pod": common.MapStr{ "name": "filebeat", "uid": "005f3b90-4b9d-12f8-acf0-31020a840133", @@ -555,16 +535,12 @@ func TestPod_EmitEvent(t *testing.T) { "node": common.MapStr{ "name": "node", }, - "namespace": common.MapStr{ - "name": "default", - }, + "namespace": "default", "annotations": common.MapStr{}, }, "meta": common.MapStr{ "kubernetes": common.MapStr{ - "namespace": common.MapStr{ - "name": "default", - }, + "namespace": "default", "pod": common.MapStr{ "name": "filebeat", "uid": "005f3b90-4b9d-12f8-acf0-31020a840133", @@ -597,16 +573,12 @@ func TestPod_EmitEvent(t *testing.T) { "node": common.MapStr{ "name": "node", }, - "namespace": common.MapStr{ - "name": "default", - }, + "namespace": "default", "annotations": common.MapStr{}, }, "meta": common.MapStr{ "kubernetes": common.MapStr{ - "namespace": common.MapStr{ - "name": "default", - }, + "namespace": "default", "pod": common.MapStr{ "name": "filebeat", "uid": "005f3b90-4b9d-12f8-acf0-31020a840133", @@ -646,16 +618,12 @@ func TestPod_EmitEvent(t *testing.T) { "node": common.MapStr{ "name": "node", }, - "namespace": common.MapStr{ - "name": "default", - }, + "namespace": "default", "annotations": common.MapStr{}, }, "meta": common.MapStr{ "kubernetes": common.MapStr{ - "namespace": common.MapStr{ - "name": "default", - }, + "namespace": "default", "pod": common.MapStr{ "name": "filebeat", "uid": "005f3b90-4b9d-12f8-acf0-31020a840133", @@ -736,16 +704,12 @@ func TestPod_EmitEvent(t *testing.T) { "node": common.MapStr{ "name": "node", }, - "namespace": common.MapStr{ - "name": "default", - }, + "namespace": "default", "annotations": common.MapStr{}, }, "meta": common.MapStr{ "kubernetes": common.MapStr{ - "namespace": common.MapStr{ - "name": "default", - }, + "namespace": "default", "pod": common.MapStr{ "name": "filebeat", "uid": "005f3b90-4b9d-12f8-acf0-31020a840133", @@ -776,16 +740,12 @@ func TestPod_EmitEvent(t *testing.T) { "node": common.MapStr{ "name": "node", }, - "namespace": common.MapStr{ - "name": "default", - }, + "namespace": "default", "annotations": common.MapStr{}, }, "meta": common.MapStr{ "kubernetes": common.MapStr{ - "namespace": common.MapStr{ - "name": "default", - }, + "namespace": "default", "pod": common.MapStr{ "name": "filebeat", "uid": "005f3b90-4b9d-12f8-acf0-31020a840133", @@ -823,16 +783,12 @@ func TestPod_EmitEvent(t *testing.T) { "node": common.MapStr{ "name": "node", }, - "namespace": common.MapStr{ - "name": "default", - }, + "namespace": "default", "annotations": common.MapStr{}, }, "meta": common.MapStr{ "kubernetes": common.MapStr{ - "namespace": common.MapStr{ - "name": "default", - }, + "namespace": "default", "pod": common.MapStr{ "name": "filebeat", "uid": "005f3b90-4b9d-12f8-acf0-31020a840133", @@ -960,16 +916,12 @@ func TestPod_EmitEvent(t *testing.T) { "node": common.MapStr{ "name": "node", }, - "namespace": common.MapStr{ - "name": "default", - }, + "namespace": "default", "annotations": common.MapStr{}, }, "meta": common.MapStr{ "kubernetes": common.MapStr{ - "namespace": common.MapStr{ - "name": "default", - }, + "namespace": "default", "pod": common.MapStr{ "name": "filebeat", "uid": "005f3b90-4b9d-12f8-acf0-31020a840133", @@ -998,16 +950,12 @@ func TestPod_EmitEvent(t *testing.T) { "node": common.MapStr{ "name": "node", }, - "namespace": common.MapStr{ - "name": "default", - }, + "namespace": "default", "annotations": common.MapStr{}, }, "meta": common.MapStr{ "kubernetes": common.MapStr{ - "namespace": common.MapStr{ - "name": "default", - }, + "namespace": "default", "pod": common.MapStr{ "name": "filebeat", "uid": "005f3b90-4b9d-12f8-acf0-31020a840133", @@ -1071,16 +1019,12 @@ func TestPod_EmitEvent(t *testing.T) { "node": common.MapStr{ "name": "node", }, - "namespace": common.MapStr{ - "name": "default", - }, + "namespace": "default", "annotations": common.MapStr{}, }, "meta": common.MapStr{ "kubernetes": common.MapStr{ - "namespace": common.MapStr{ - "name": "default", - }, + "namespace": "default", "pod": common.MapStr{ "name": "filebeat", "uid": "005f3b90-4b9d-12f8-acf0-31020a840133", @@ -1111,16 +1055,12 @@ func TestPod_EmitEvent(t *testing.T) { "node": common.MapStr{ "name": "node", }, - "namespace": common.MapStr{ - "name": "default", - }, + "namespace": "default", "annotations": common.MapStr{}, }, "meta": common.MapStr{ "kubernetes": common.MapStr{ - "namespace": common.MapStr{ - "name": "default", - }, + "namespace": "default", "pod": common.MapStr{ "name": "filebeat", "uid": "005f3b90-4b9d-12f8-acf0-31020a840133", @@ -1201,16 +1141,12 @@ func TestPod_EmitEvent(t *testing.T) { "node": common.MapStr{ "name": "node", }, - "namespace": common.MapStr{ - "name": "default", - }, + "namespace": "default", "annotations": common.MapStr{}, }, "meta": common.MapStr{ "kubernetes": common.MapStr{ - "namespace": common.MapStr{ - "name": "default", - }, + "namespace": "default", "pod": common.MapStr{ "name": "filebeat", "uid": "005f3b90-4b9d-12f8-acf0-31020a840133", @@ -1241,16 +1177,12 @@ func TestPod_EmitEvent(t *testing.T) { "node": common.MapStr{ "name": "node", }, - "namespace": common.MapStr{ - "name": "default", - }, + "namespace": "default", "annotations": common.MapStr{}, }, "meta": common.MapStr{ "kubernetes": common.MapStr{ - "namespace": common.MapStr{ - "name": "default", - }, + "namespace": "default", "pod": common.MapStr{ "name": "filebeat", "uid": "005f3b90-4b9d-12f8-acf0-31020a840133", @@ -1288,16 +1220,12 @@ func TestPod_EmitEvent(t *testing.T) { "node": common.MapStr{ "name": "node", }, - "namespace": common.MapStr{ - "name": "default", - }, + "namespace": "default", "annotations": common.MapStr{}, }, "meta": common.MapStr{ "kubernetes": common.MapStr{ - "namespace": common.MapStr{ - "name": "default", - }, + "namespace": "default", "pod": common.MapStr{ "name": "filebeat", "uid": "005f3b90-4b9d-12f8-acf0-31020a840133", @@ -1392,16 +1320,12 @@ func TestPod_EmitEvent(t *testing.T) { "node": common.MapStr{ "name": "node", }, - "namespace": common.MapStr{ - "name": "default", - }, + "namespace": "default", "annotations": common.MapStr{}, }, "meta": common.MapStr{ "kubernetes": common.MapStr{ - "namespace": common.MapStr{ - "name": "default", - }, + "namespace": "default", "pod": common.MapStr{ "name": "filebeat", "uid": "005f3b90-4b9d-12f8-acf0-31020a840133", @@ -1434,16 +1358,12 @@ func TestPod_EmitEvent(t *testing.T) { "node": common.MapStr{ "name": "node", }, - "namespace": common.MapStr{ - "name": "default", - }, + "namespace": "default", "annotations": common.MapStr{}, }, "meta": common.MapStr{ "kubernetes": common.MapStr{ - "namespace": common.MapStr{ - "name": "default", - }, + "namespace": "default", "pod": common.MapStr{ "name": "filebeat", "uid": "005f3b90-4b9d-12f8-acf0-31020a840133", @@ -1481,16 +1401,12 @@ func TestPod_EmitEvent(t *testing.T) { "node": common.MapStr{ "name": "node", }, - "namespace": common.MapStr{ - "name": "default", - }, + "namespace": "default", "annotations": common.MapStr{}, }, "meta": common.MapStr{ "kubernetes": common.MapStr{ - "namespace": common.MapStr{ - "name": "default", - }, + "namespace": "default", "pod": common.MapStr{ "name": "filebeat", "uid": "005f3b90-4b9d-12f8-acf0-31020a840133", @@ -1561,16 +1477,12 @@ func TestPod_EmitEvent(t *testing.T) { "node": common.MapStr{ "name": "node", }, - "namespace": common.MapStr{ - "name": "default", - }, + "namespace": "default", "annotations": common.MapStr{}, }, "meta": common.MapStr{ "kubernetes": common.MapStr{ - "namespace": common.MapStr{ - "name": "default", - }, + "namespace": "default", "pod": common.MapStr{ "name": "filebeat", "uid": "005f3b90-4b9d-12f8-acf0-31020a840133", @@ -1603,16 +1515,12 @@ func TestPod_EmitEvent(t *testing.T) { "node": common.MapStr{ "name": "node", }, - "namespace": common.MapStr{ - "name": "default", - }, + "namespace": "default", "annotations": common.MapStr{}, }, "meta": common.MapStr{ "kubernetes": common.MapStr{ - "namespace": common.MapStr{ - "name": "default", - }, + "namespace": "default", "pod": common.MapStr{ "name": "filebeat", "uid": "005f3b90-4b9d-12f8-acf0-31020a840133", @@ -1685,16 +1593,12 @@ func TestPod_EmitEvent(t *testing.T) { "node": common.MapStr{ "name": "node", }, - "namespace": common.MapStr{ - "name": "default", - }, + "namespace": "default", "annotations": common.MapStr{}, }, "meta": common.MapStr{ "kubernetes": common.MapStr{ - "namespace": common.MapStr{ - "name": "default", - }, + "namespace": "default", "pod": common.MapStr{ "name": "filebeat", "uid": "005f3b90-4b9d-12f8-acf0-31020a840133", @@ -1727,16 +1631,12 @@ func TestPod_EmitEvent(t *testing.T) { "node": common.MapStr{ "name": "node", }, - "namespace": common.MapStr{ - "name": "default", - }, + "namespace": "default", "annotations": common.MapStr{}, }, "meta": common.MapStr{ "kubernetes": common.MapStr{ - "namespace": common.MapStr{ - "name": "default", - }, + "namespace": "default", "pod": common.MapStr{ "name": "filebeat", "uid": "005f3b90-4b9d-12f8-acf0-31020a840133", @@ -1840,16 +1740,12 @@ func TestPod_EmitEvent(t *testing.T) { "node": common.MapStr{ "name": "node", }, - "namespace": common.MapStr{ - "name": "default", - }, + "namespace": "default", "annotations": common.MapStr{}, }, "meta": common.MapStr{ "kubernetes": common.MapStr{ - "namespace": common.MapStr{ - "name": "default", - }, + "namespace": "default", "pod": common.MapStr{ "name": "filebeat", "uid": "005f3b90-4b9d-12f8-acf0-31020a840133", @@ -1883,16 +1779,12 @@ func TestPod_EmitEvent(t *testing.T) { "node": common.MapStr{ "name": "node", }, - "namespace": common.MapStr{ - "name": "default", - }, + "namespace": "default", "annotations": common.MapStr{}, }, "meta": common.MapStr{ "kubernetes": common.MapStr{ - "namespace": common.MapStr{ - "name": "default", - }, + "namespace": "default", "pod": common.MapStr{ "name": "filebeat", "uid": "005f3b90-4b9d-12f8-acf0-31020a840133", @@ -1933,16 +1825,12 @@ func TestPod_EmitEvent(t *testing.T) { "node": common.MapStr{ "name": "node", }, - "namespace": common.MapStr{ - "name": "default", - }, + "namespace": "default", "annotations": common.MapStr{}, }, "meta": common.MapStr{ "kubernetes": common.MapStr{ - "namespace": common.MapStr{ - "name": "default", - }, + "namespace": "default", "pod": common.MapStr{ "name": "filebeat", "uid": "005f3b90-4b9d-12f8-acf0-31020a840133", @@ -1983,16 +1871,12 @@ func TestPod_EmitEvent(t *testing.T) { "node": common.MapStr{ "name": "node", }, - "namespace": common.MapStr{ - "name": "default", - }, + "namespace": "default", "annotations": common.MapStr{}, }, "meta": common.MapStr{ "kubernetes": common.MapStr{ - "namespace": common.MapStr{ - "name": "default", - }, + "namespace": "default", "pod": common.MapStr{ "name": "filebeat", "uid": "005f3b90-4b9d-12f8-acf0-31020a840133", @@ -2016,6 +1900,7 @@ func TestPod_EmitEvent(t *testing.T) { } client := k8sfake.NewSimpleClientset() + addResourceMetadata := metadata.GetDefaultResourceMetadataConfig() for _, test := range tests { t.Run(test.Message, func(t *testing.T) { mapper, err := template.NewConfigMapper(nil, nil, nil) @@ -2023,7 +1908,7 @@ func TestPod_EmitEvent(t *testing.T) { t.Fatal(err) } - metaGen := metadata.NewPodMetadataGenerator(common.NewConfig(), nil, client, nil, nil, true) + metaGen := metadata.NewPodMetadataGenerator(common.NewConfig(), nil, client, nil, nil, addResourceMetadata) p := &Provider{ config: defaultConfig(), bus: bus.New(logp.NewLogger("bus"), "test"), @@ -2102,7 +1987,7 @@ func TestNamespacePodUpdater(t *testing.T) { t.Run(title, func(t *testing.T) { handler := &mockUpdaterHandler{} store := &mockUpdaterStore{objects: c.pods} - updater := newNamespacePodUpdater(handler.OnUpdate, store, &sync.Mutex{}) + updater := kubernetes.NewNamespacePodUpdater(handler.OnUpdate, store, &sync.Mutex{}) namespace := &kubernetes.Namespace{ ObjectMeta: metav1.ObjectMeta{ @@ -2116,6 +2001,58 @@ func TestNamespacePodUpdater(t *testing.T) { } } +func TestNodePodUpdater(t *testing.T) { + pod := func(name, node string) *kubernetes.Pod { + return &kubernetes.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, + }, + Spec: v1.PodSpec{ + NodeName: node, + }, + } + } + + cases := map[string]struct { + pods []interface{} + expected []interface{} + }{ + "no pods": {}, + "two pods but only one in node": { + pods: []interface{}{ + pod("onepod", "foo"), + pod("onepod", "bar"), + }, + expected: []interface{}{ + pod("onepod", "foo"), + }, + }, + "two pods but none in node": { + pods: []interface{}{ + pod("onepod", "bar"), + pod("otherpod", "bar"), + }, + }, + } + + for title, c := range cases { + t.Run(title, func(t *testing.T) { + handler := &mockUpdaterHandler{} + store := &mockUpdaterStore{objects: c.pods} + updater := kubernetes.NewNodePodUpdater(handler.OnUpdate, store, &sync.Mutex{}) + + node := &kubernetes.Node{ + ObjectMeta: metav1.ObjectMeta{ + Name: "foo", + }, + } + updater.OnUpdate(node) + + assert.EqualValues(t, c.expected, handler.objects) + }) + } +} + type mockUpdaterHandler struct { objects []interface{} } diff --git a/libbeat/autodiscover/providers/kubernetes/service.go b/libbeat/autodiscover/providers/kubernetes/service.go index 80942728fcc..9b3c6a0aa77 100644 --- a/libbeat/autodiscover/providers/kubernetes/service.go +++ b/libbeat/autodiscover/providers/kubernetes/service.go @@ -140,8 +140,7 @@ func (s *service) GenerateHints(event bus.Event) bus.Event { } // Look at all the namespace level default annotations and do a merge with priority going to the pod annotations. - rawNsAnn, err := kubeMeta.GetValue("namespace.annotations") - if err == nil { + if rawNsAnn, ok := kubeMeta["namespace_annotations"]; ok { nsAnn, _ := rawNsAnn.(common.MapStr) if len(nsAnn) != 0 { annotations.DeepUpdateNoOverwrite(nsAnn) @@ -215,7 +214,7 @@ func (s *service) emit(svc *kubernetes.Service, flag string) { for k, v := range namespace.GetAnnotations() { safemapstr.Put(nsAnns, k, v) } - kubemeta.Put("namespace.annotations", nsAnns) + kubemeta["namespace_annotations"] = nsAnns } } } diff --git a/libbeat/autodiscover/providers/kubernetes/service_test.go b/libbeat/autodiscover/providers/kubernetes/service_test.go index 1a8dd4696c6..c9ee7764632 100644 --- a/libbeat/autodiscover/providers/kubernetes/service_test.go +++ b/libbeat/autodiscover/providers/kubernetes/service_test.go @@ -108,15 +108,13 @@ func TestGenerateHints_Service(t *testing.T) { "co.elastic.metrics/module": "prometheus", "not.to.include": "true", }), + "namespace_annotations": getNestedAnnotations(common.MapStr{ + "co.elastic.metrics/period": "10s", + }), "service": common.MapStr{ "name": "foobar", }, - "namespace": common.MapStr{ - "name": "ns", - "annotations": getNestedAnnotations(common.MapStr{ - "co.elastic.metrics/period": "10s", - }), - }, + "namespace": "ns", }, }, result: bus.Event{ @@ -128,12 +126,10 @@ func TestGenerateHints_Service(t *testing.T) { "service": common.MapStr{ "name": "foobar", }, - "namespace": common.MapStr{ - "name": "ns", - "annotations": getNestedAnnotations(common.MapStr{ - "co.elastic.metrics/period": "10s", - }), - }, + "namespace_annotations": getNestedAnnotations(common.MapStr{ + "co.elastic.metrics/period": "10s", + }), + "namespace": "ns", }, "hints": common.MapStr{ "metrics": common.MapStr{ @@ -154,13 +150,11 @@ func TestGenerateHints_Service(t *testing.T) { "co.elastic.metrics/period": "10s", "not.to.include": "true", }), - "namespace": common.MapStr{ - "name": "ns", - "annotations": getNestedAnnotations(common.MapStr{ - "co.elastic.metrics/module": "dropwizard", - "co.elastic.metrics/period": "60s", - }), - }, + "namespace_annotations": getNestedAnnotations(common.MapStr{ + "co.elastic.metrics/module": "dropwizard", + "co.elastic.metrics/period": "60s", + }), + "namespace": "ns", "service": common.MapStr{ "name": "foobar", }, @@ -173,13 +167,11 @@ func TestGenerateHints_Service(t *testing.T) { "co.elastic.metrics/period": "10s", "not.to.include": "true", }), - "namespace": common.MapStr{ - "name": "ns", - "annotations": getNestedAnnotations(common.MapStr{ - "co.elastic.metrics/module": "dropwizard", - "co.elastic.metrics/period": "60s", - }), - }, + "namespace_annotations": getNestedAnnotations(common.MapStr{ + "co.elastic.metrics/module": "dropwizard", + "co.elastic.metrics/period": "60s", + }), + "namespace": "ns", "service": common.MapStr{ "name": "foobar", }, @@ -198,30 +190,26 @@ func TestGenerateHints_Service(t *testing.T) { { event: bus.Event{ "kubernetes": common.MapStr{ + "namespace_annotations": getNestedAnnotations(common.MapStr{ + "co.elastic.metrics/module": "prometheus", + "co.elastic.metrics/period": "10s", + }), "service": common.MapStr{ "name": "foobar", }, - "namespace": common.MapStr{ - "name": "ns", - "annotations": getNestedAnnotations(common.MapStr{ - "co.elastic.metrics/module": "prometheus", - "co.elastic.metrics/period": "10s", - }), - }, + "namespace": "ns", }, }, result: bus.Event{ "kubernetes": common.MapStr{ + "namespace_annotations": getNestedAnnotations(common.MapStr{ + "co.elastic.metrics/module": "prometheus", + "co.elastic.metrics/period": "10s", + }), "service": common.MapStr{ "name": "foobar", }, - "namespace": common.MapStr{ - "name": "ns", - "annotations": getNestedAnnotations(common.MapStr{ - "co.elastic.metrics/module": "prometheus", - "co.elastic.metrics/period": "10s", - }), - }, + "namespace": "ns", }, "hints": common.MapStr{ "metrics": common.MapStr{ @@ -298,16 +286,12 @@ func TestEmitEvent_Service(t *testing.T) { "name": "metricbeat", "uid": "005f3b90-4b9d-12f8-acf0-31020a840133", }, - "namespace": common.MapStr{ - "name": "default", - }, + "namespace": "default", "annotations": common.MapStr{}, }, "meta": common.MapStr{ "kubernetes": common.MapStr{ - "namespace": common.MapStr{ - "name": "default", - }, + "namespace": "default", "service": common.MapStr{ "name": "metricbeat", "uid": "005f3b90-4b9d-12f8-acf0-31020a840133", @@ -389,16 +373,12 @@ func TestEmitEvent_Service(t *testing.T) { "name": "metricbeat", "uid": "005f3b90-4b9d-12f8-acf0-31020a840133", }, - "namespace": common.MapStr{ - "name": "default", - }, + "namespace": "default", "annotations": common.MapStr{}, }, "meta": common.MapStr{ "kubernetes": common.MapStr{ - "namespace": common.MapStr{ - "name": "default", - }, + "namespace": "default", "service": common.MapStr{ "name": "metricbeat", "uid": "005f3b90-4b9d-12f8-acf0-31020a840133", diff --git a/libbeat/beat/events/util.go b/libbeat/beat/events/util.go index 46967c82d71..2c2b9c20187 100644 --- a/libbeat/beat/events/util.go +++ b/libbeat/beat/events/util.go @@ -27,9 +27,8 @@ const ( // precedence over values defined using FieldMetaIndex or FieldMetaRawIndex. FieldMetaAlias = "alias" - // FieldMetaIndex defines the base index name to use for the event. The value is suffixed - // with a Y-m-d value based on the event's timestamp. If set, it takes precedence over the - // value defined using FieldMetaRawIndex. + // FieldMetaIndex defines the data stream name to use for the event. + // If set, it takes precedence over the value defined using FieldMetaRawIndex. FieldMetaIndex = "index" // FieldMetaRawIndex defines the raw index name to use for the event. It is used as-is, without diff --git a/libbeat/cmd/instance/beat.go b/libbeat/cmd/instance/beat.go index 3e1da0f62fb..eb126966094 100644 --- a/libbeat/cmd/instance/beat.go +++ b/libbeat/cmd/instance/beat.go @@ -47,7 +47,6 @@ import ( "github.com/elastic/beats/v7/libbeat/cloudid" "github.com/elastic/beats/v7/libbeat/cmd/instance/metrics" "github.com/elastic/beats/v7/libbeat/common" - "github.com/elastic/beats/v7/libbeat/common/cfgwarn" "github.com/elastic/beats/v7/libbeat/common/file" "github.com/elastic/beats/v7/libbeat/common/reload" "github.com/elastic/beats/v7/libbeat/common/seccomp" @@ -1130,22 +1129,13 @@ func initPaths(cfg *common.Config) error { // the paths field. After we will unpack the complete configuration and keystore reference // will be correctly replaced. partialConfig := struct { - Path paths.Path `config:"path"` - Hostfs string `config:"system.hostfs"` + Path paths.Path `config:"path"` }{} - if paths.IsCLISet() { - cfgwarn.Deprecate("8.0.0", "This flag will be removed in the future and replaced by a config value.") - } - if err := cfg.Unpack(&partialConfig); err != nil { return fmt.Errorf("error extracting default paths: %+v", err) } - // Read the value for hostfs as `system.hostfs` - // In the config, there is no `path.hostfs`, as we're merely using the path struct to carry the hostfs variable. - partialConfig.Path.Hostfs = partialConfig.Hostfs - if err := paths.InitPaths(&partialConfig.Path); err != nil { return fmt.Errorf("error setting default paths: %+v", err) } diff --git a/libbeat/cmd/instance/metrics/metrics.go b/libbeat/cmd/instance/metrics/metrics.go index 0df87a522f3..5542e083bee 100644 --- a/libbeat/cmd/instance/metrics/metrics.go +++ b/libbeat/cmd/instance/metrics/metrics.go @@ -31,8 +31,8 @@ import ( "github.com/elastic/beats/v7/libbeat/metric/system/cpu" "github.com/elastic/beats/v7/libbeat/metric/system/numcpu" "github.com/elastic/beats/v7/libbeat/metric/system/process" + "github.com/elastic/beats/v7/libbeat/metric/system/resolve" "github.com/elastic/beats/v7/libbeat/monitoring" - "github.com/elastic/beats/v7/libbeat/paths" ) var ( @@ -288,7 +288,7 @@ func reportBeatCgroups(_ monitoring.Mode, V monitoring.Visitor) { } cgroups, err := cgroup.NewReaderOptions(cgroup.ReaderOptions{ - RootfsMountpoint: paths.Paths.Hostfs, + RootfsMountpoint: resolve.NewTestResolver("/"), IgnoreRootCgroups: true, CgroupsHierarchyOverride: os.Getenv(libbeatMonitoringCgroupsHierarchyOverride), }) diff --git a/libbeat/cmd/root.go b/libbeat/cmd/root.go index f239cbe0c7e..be2cb9d441a 100644 --- a/libbeat/cmd/root.go +++ b/libbeat/cmd/root.go @@ -105,7 +105,6 @@ func GenRootCmdWithSettings(beatCreator beat.Creator, settings instance.Settings rootCmd.PersistentFlags().AddGoFlag(flag.CommandLine.Lookup("path.data")) rootCmd.PersistentFlags().AddGoFlag(flag.CommandLine.Lookup("path.logs")) rootCmd.PersistentFlags().AddGoFlag(flag.CommandLine.Lookup("path.home")) - rootCmd.PersistentFlags().AddGoFlag(flag.CommandLine.Lookup("system.hostfs")) rootCmd.PersistentFlags().AddGoFlag(flag.CommandLine.Lookup("strict.perms")) if f := flag.CommandLine.Lookup("plugin"); f != nil { rootCmd.PersistentFlags().AddGoFlag(f) diff --git a/libbeat/cmd/setup.go b/libbeat/cmd/setup.go index 711ddfd027c..01c2b110a6b 100644 --- a/libbeat/cmd/setup.go +++ b/libbeat/cmd/setup.go @@ -34,16 +34,6 @@ const ( PipelineKey = "pipelines" //IndexManagementKey used for loading all components related to ES index management in setup cmd IndexManagementKey = "index-management" - - //TemplateKey used for loading template in setup cmd - // - //Deprecated: use IndexManagementKey instead - TemplateKey = "template" - - //ILMPolicyKey used for loading ilm in setup cmd - // - //Deprecated: use IndexManagementKey instead - ILMPolicyKey = "ilm-policy" ) func genSetupCmd(settings instance.Settings, beatCreator beat.Creator) *cobra.Command { @@ -68,8 +58,6 @@ func genSetupCmd(settings instance.Settings, beatCreator beat.Creator) *cobra.Co DashboardKey: false, PipelineKey: false, IndexManagementKey: false, - TemplateKey: false, - ILMPolicyKey: false, } var setupAll = true @@ -100,10 +88,6 @@ func genSetupCmd(settings instance.Settings, beatCreator beat.Creator) *cobra.Co s.Pipeline = true case IndexManagementKey: s.IndexManagement = true - case ILMPolicyKey: - s.ILMPolicy = true - case TemplateKey: - s.Template = true } } } @@ -118,10 +102,6 @@ func genSetupCmd(settings instance.Settings, beatCreator beat.Creator) *cobra.Co setup.Flags().Bool(PipelineKey, false, "Setup Ingest pipelines") setup.Flags().Bool(IndexManagementKey, false, "Setup all components related to Elasticsearch index management, including template, ilm policy and rollover alias") - setup.Flags().Bool(TemplateKey, false, "Setup index template") - setup.Flags().MarkDeprecated(TemplateKey, fmt.Sprintf("please use --%s instead", IndexManagementKey)) - setup.Flags().Bool(ILMPolicyKey, false, "Setup ILM policy") - setup.Flags().MarkDeprecated(ILMPolicyKey, fmt.Sprintf("please use --%s instead", IndexManagementKey)) return &setup } diff --git a/libbeat/common/cfgwarn/cfgwarn.go b/libbeat/common/cfgwarn/cfgwarn.go index e102ed20e4b..0295b0b6d3b 100644 --- a/libbeat/common/cfgwarn/cfgwarn.go +++ b/libbeat/common/cfgwarn/cfgwarn.go @@ -33,9 +33,13 @@ func Beta(format string, v ...interface{}) { } // Deprecate logs a deprecation message. -// The version string contains the version when the future will be removed +// The version string contains the version when the future will be removed. +// If version is empty, the message will not mention the removal of the feature. func Deprecate(version string, format string, v ...interface{}) { - postfix := fmt.Sprintf(" Will be removed in version: %s", version) + var postfix string + if version != "" { + postfix = fmt.Sprintf(" Will be removed in version: %s", version) + } logp.NewLogger(selector, zap.AddCallerSkip(1)).Warnf("DEPRECATED: "+format+postfix, v...) } diff --git a/libbeat/common/config.go b/libbeat/common/config.go index e4155c4f3af..3efff0b702c 100644 --- a/libbeat/common/config.go +++ b/libbeat/common/config.go @@ -259,6 +259,11 @@ func (c *Config) IsArray() bool { return c.access().IsArray() } +// FlattenedKeys return a sorted flattened views of the set keys in the configuration. +func (c *Config) FlattenedKeys() []string { + return c.access().FlattenedKeys(configOpts...) +} + func (c *Config) PrintDebugf(msg string, params ...interface{}) { selector := selectorConfigWithPassword filtered := false diff --git a/libbeat/common/file/interval_rotator.go b/libbeat/common/file/interval_rotator.go deleted file mode 100644 index e5105beb0a7..00000000000 --- a/libbeat/common/file/interval_rotator.go +++ /dev/null @@ -1,192 +0,0 @@ -// Licensed to Elasticsearch B.V. under one or more contributor -// license agreements. See the NOTICE file distributed with -// this work for additional information regarding copyright -// ownership. Elasticsearch B.V. licenses this file to you 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 file - -import ( - "fmt" - "os" - "path/filepath" - "sort" - "strconv" - "time" - - "github.com/pkg/errors" -) - -type intervalRotator struct { - log Logger - interval time.Duration - lastRotate time.Time - filename string - fileFormat string - clock clock - weekly bool - arbitrary bool -} - -func newIntervalRotator(log Logger, interval time.Duration, filename string) rotater { - ir := &intervalRotator{ - filename: filename, - log: log, - interval: (interval / time.Second) * time.Second, // drop fractional seconds - clock: realClock{}, - } - ir.initialize() - return ir -} - -func (r *intervalRotator) initialize() { - switch r.interval { - case time.Second: - r.fileFormat = "2006-01-02-15-04-05" - case time.Minute: - r.fileFormat = "2006-01-02-15-04" - case time.Hour: - r.fileFormat = "2006-01-02-15" - case 24 * time.Hour: // calendar day - r.fileFormat = "2006-01-02" - case 7 * 24 * time.Hour: // calendar week - r.fileFormat = "" - r.weekly = true - case 30 * 24 * time.Hour: // calendar month - r.fileFormat = "2006-01" - case 365 * 24 * time.Hour: // calendar year - r.fileFormat = "2006" - default: - r.arbitrary = true - r.fileFormat = "2006-01-02-15-04-05" - } - - fi, err := os.Stat(r.filename) - if err != nil { - if r.log != nil { - r.log.Debugw("Not attempting to find last rotated time, configured logs dir cannot be opened: %v", err) - } - return - } - r.lastRotate = fi.ModTime() -} - -func (r *intervalRotator) ActiveFile() string { - return r.filename -} - -func (r *intervalRotator) LogPrefix(filename string, modTime time.Time) string { - var t time.Time - if r.lastRotate.IsZero() { - t = modTime - } else { - t = r.lastRotate - } - - if r.weekly { - y, w := t.ISOWeek() - return fmt.Sprintf("%s-%04d-%02d-", filename, y, w) - } - if r.arbitrary { - intervalNumber := t.Unix() / (int64(r.interval) / int64(time.Second)) - intervalStart := time.Unix(0, intervalNumber*int64(r.interval)) - return fmt.Sprintf("%s-%s-", filename, intervalStart.Format(r.fileFormat)) - } - return fmt.Sprintf("%s-%s-", filename, t.Format(r.fileFormat)) -} - -func (r *intervalRotator) RotatedFiles() []string { - files, err := filepath.Glob(r.filename + "*") - if err != nil { - if r.log != nil { - r.log.Debugw("failed to list existing logs: %+v", err) - } - } - r.SortIntervalLogs(files) - return files -} - -func (r *intervalRotator) Rotate(reason rotateReason, t time.Time) error { - fi, err := os.Stat(r.ActiveFile()) - if os.IsNotExist(err) { - return nil - } else if err != nil { - return errors.Wrap(err, "failed to rotate backups") - } - - logPrefix := r.LogPrefix(r.ActiveFile(), fi.ModTime()) - files, err := filepath.Glob(logPrefix + "*") - if err != nil { - return errors.Wrap(err, "failed to list logs during rotation") - } - - var targetFilename string - if len(files) == 0 { - targetFilename = logPrefix + "1" - } else { - r.SortIntervalLogs(files) - lastLogIndex, _, err := IntervalLogIndex(files[len(files)-1]) - if err != nil { - return errors.Wrap(err, "failed to locate last log index during rotation") - } - targetFilename = logPrefix + strconv.Itoa(int(lastLogIndex)+1) - } - - if err := os.Rename(r.ActiveFile(), targetFilename); err != nil { - return errors.Wrap(err, "failed to rotate backups") - } - - if r.log != nil { - r.log.Debugw("Rotating file", "filename", r.ActiveFile(), "reason", reason) - } - - r.lastRotate = t - return nil -} - -func (r *intervalRotator) SortIntervalLogs(strings []string) { - sort.Slice( - strings, - func(i, j int) bool { - return OrderIntervalLogs(strings[i]) < OrderIntervalLogs(strings[j]) - }, - ) -} - -// OrderIntervalLogs, when given a log filename in the form [prefix]-[formattedDate]-n -// returns the filename after zero-padding the trailing n so that foo-[date]-2 sorts -// before foo-[date]-10. -func OrderIntervalLogs(filename string) string { - index, i, err := IntervalLogIndex(filename) - if err == nil { - return filename[:i] + fmt.Sprintf("%020d", index) - } - - return "" -} - -// IntervalLogIndex returns n as int given a log filename in the form [prefix]-[formattedDate]-n -func IntervalLogIndex(filename string) (uint64, int, error) { - i := len(filename) - 1 - for ; i >= 0; i-- { - if '0' > filename[i] || filename[i] > '9' { - break - } - } - i++ - - s64 := filename[i:] - u64, err := strconv.ParseUint(s64, 10, 64) - return u64, i, err -} diff --git a/libbeat/common/file/interval_rotator_test.go b/libbeat/common/file/interval_rotator_test.go deleted file mode 100644 index 729d8c713b7..00000000000 --- a/libbeat/common/file/interval_rotator_test.go +++ /dev/null @@ -1,154 +0,0 @@ -// Licensed to Elasticsearch B.V. under one or more contributor -// license agreements. See the NOTICE file distributed with -// this work for additional information regarding copyright -// ownership. Elasticsearch B.V. licenses this file to you 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 file - -import ( - "testing" - "time" - - "github.com/stretchr/testify/assert" -) - -func TestSecondRotator(t *testing.T) { - a := newMockIntervalRotator(time.Second) - - clock := &testClock{time.Date(2018, 12, 31, 0, 0, 1, 100, time.Local)} - a.clock = clock - a.lastRotate = a.clock.Now() - assert.Equal(t, "foo-2018-12-31-00-00-01-", a.LogPrefix("foo", time.Now())) -} - -func TestMinuteRotator(t *testing.T) { - a := newMockIntervalRotator(time.Minute) - - clock := &testClock{time.Date(2018, 12, 31, 0, 1, 1, 0, time.Local)} - a.clock = clock - a.lastRotate = a.clock.Now() - assert.Equal(t, "foo-2018-12-31-00-01-", a.LogPrefix("foo", time.Now())) -} - -func TestHourlyRotator(t *testing.T) { - a := newMockIntervalRotator(time.Hour) - - clock := &testClock{time.Date(2018, 12, 31, 1, 0, 1, 0, time.Local)} - a.clock = clock - a.lastRotate = a.clock.Now() - assert.Equal(t, "foo-2018-12-31-01-", a.LogPrefix("foo", time.Now())) -} - -func TestDailyRotator(t *testing.T) { - a := newMockIntervalRotator(24 * time.Hour) - - clock := &testClock{time.Date(2018, 12, 31, 0, 0, 0, 0, time.Local)} - a.clock = clock - a.lastRotate = a.clock.Now() - assert.Equal(t, "foo-2018-12-31-", a.LogPrefix("foo", time.Now())) -} - -func TestWeeklyRotator(t *testing.T) { - a := newMockIntervalRotator(7 * 24 * time.Hour) - - // Monday, 2018-Dec-31 - clock := &testClock{time.Date(2018, 12, 31, 0, 0, 0, 0, time.Local)} - a.clock = clock - a.lastRotate = a.clock.Now() - assert.Equal(t, "foo-2019-01-", a.LogPrefix("foo", time.Now())) - - // Monday, 2019-Jan-7 - clock.time = clock.time.Add(7 * 24 * time.Hour) - a.lastRotate = a.clock.Now() - assert.Equal(t, "foo-2019-02-", a.LogPrefix("foo", time.Now())) -} - -func TestMonthlyRotator(t *testing.T) { - a := newMockIntervalRotator(30 * 24 * time.Hour) - - clock := &testClock{time.Date(2018, 12, 1, 0, 0, 0, 0, time.Local)} - a.clock = clock - a.lastRotate = a.clock.Now() - assert.Equal(t, "foo-2018-12-", a.LogPrefix("foo", time.Now())) - - clock.time = clock.time.Add(30 * 24 * time.Hour) - assert.Equal(t, "foo-2018-12-", a.LogPrefix("foo", time.Now())) - - clock.time = clock.time.Add(24 * time.Hour) - a.lastRotate = a.clock.Now() - assert.Equal(t, "foo-2019-01-", a.LogPrefix("foo", time.Now())) -} - -func TestYearlyRotator(t *testing.T) { - a := newMockIntervalRotator(365 * 24 * time.Hour) - - clock := &testClock{time.Date(2018, 12, 31, 0, 0, 0, 0, time.Local)} - a.clock = clock - a.lastRotate = a.clock.Now() - assert.Equal(t, "foo-2018-", a.LogPrefix("foo", time.Now())) - - clock.time = clock.time.Add(23 * time.Hour) - assert.Equal(t, "foo-2018-", a.LogPrefix("foo", time.Now())) - - clock.time = clock.time.Add(time.Hour) - a.lastRotate = a.clock.Now() - assert.Equal(t, "foo-2019-", a.LogPrefix("foo", time.Now())) -} - -func TestArbitraryIntervalRotator(t *testing.T) { - a := newMockIntervalRotator(3 * time.Second) - - // Monday, 2018-Dec-31 - clock := &testClock{time.Date(2018, 12, 31, 0, 0, 1, 0, time.Local)} - a.clock = clock - assert.Equal(t, "foo-2018-12-30-00-00-00-", a.LogPrefix("foo", time.Date(2018, 12, 30, 0, 0, 0, 0, time.Local))) - a.lastRotate = a.clock.Now() - assert.Equal(t, "foo-2018-12-31-00-00-00-", a.LogPrefix("foo", time.Now())) - - clock.time = clock.time.Add(time.Second) - assert.Equal(t, "foo-2018-12-31-00-00-00-", a.LogPrefix("foo", time.Now())) - - clock.time = clock.time.Add(time.Second) - a.lastRotate = a.clock.Now() - assert.Equal(t, "foo-2018-12-31-00-00-03-", a.LogPrefix("foo", time.Now())) - - clock.time = clock.time.Add(time.Second) - assert.Equal(t, "foo-2018-12-31-00-00-03-", a.LogPrefix("foo", time.Now())) - - clock.time = clock.time.Add(time.Second) - assert.Equal(t, "foo-2018-12-31-00-00-03-", a.LogPrefix("foo", time.Now())) - - clock.time = clock.time.Add(time.Second) - a.lastRotate = a.clock.Now() - assert.Equal(t, "foo-2018-12-31-00-00-06-", a.LogPrefix("foo", time.Now())) -} - -func TestIntervalIsTruncatedToSeconds(t *testing.T) { - a := newMockIntervalRotator(2345 * time.Millisecond) - assert.Equal(t, 2*time.Second, a.interval) -} - -type testClock struct { - time time.Time -} - -func (t testClock) Now() time.Time { - return t.time -} - -func newMockIntervalRotator(interval time.Duration) *intervalRotator { - r := newIntervalRotator(nil, interval, "foo").(*intervalRotator) - return r -} diff --git a/libbeat/common/file/rotator.go b/libbeat/common/file/rotator.go index 633f94232ef..e32e317dbfb 100644 --- a/libbeat/common/file/rotator.go +++ b/libbeat/common/file/rotator.go @@ -29,22 +29,13 @@ import ( "github.com/pkg/errors" ) -type SuffixType uint32 - const ( // MaxBackupsLimit is the upper bound on the number of backup files. Any values // greater will result in an error. MaxBackupsLimit = 1024 - - SuffixCount SuffixType = iota + 1 - SuffixDate + DateFormat = "20060102" ) -var suffixes = map[string]SuffixType{ - "count": SuffixCount, - "date": SuffixDate, -} - // rotater is the interface responsible for rotating and finding files. type rotater interface { // ActiveFile returns the path to the file that is actively written. @@ -69,9 +60,9 @@ type Rotator struct { interval time.Duration permissions os.FileMode log Logger // Optional Logger (may be nil). - suffix SuffixType rotateOnStartup bool redirectStderr bool + clock clock file *os.File mutex sync.Mutex @@ -85,14 +76,6 @@ type Logger interface { // RotatorOption is a configuration option for Rotator. type RotatorOption func(r *Rotator) -// Interval sets the time interval for log rotation in addition to log -// rotation by size. The default is 0 for disabled. -func Suffix(s SuffixType) RotatorOption { - return func(r *Rotator) { - r.suffix = s - } -} - // MaxSizeBytes configures the maximum number of bytes that a file should // contain before being rotated. The default is 10 MiB. func MaxSizeBytes(n uint) RotatorOption { @@ -150,6 +133,12 @@ func RedirectStderr(redirect bool) RotatorOption { } } +func WithClock(clock clock) RotatorOption { + return func(r *Rotator) { + r.clock = clock + } +} + // NewFileRotator returns a new Rotator. func NewFileRotator(filename string, options ...RotatorOption) (*Rotator, error) { r := &Rotator{ @@ -158,7 +147,7 @@ func NewFileRotator(filename string, options ...RotatorOption) (*Rotator, error) permissions: 0600, interval: 0, rotateOnStartup: true, - suffix: SuffixCount, + clock: &realClock{}, } for _, opt := range options { @@ -179,14 +168,14 @@ func NewFileRotator(filename string, options ...RotatorOption) (*Rotator, error) return nil, errors.New("the minimum time interval for log rotation is 1 second") } - r.rot = newRotater(r.log, r.suffix, filename, r.maxBackups, r.interval) + r.rot = newDateRotater(r.log, filename, r.clock) shouldRotateOnStart := r.rotateOnStartup if _, err := os.Stat(r.rot.ActiveFile()); os.IsNotExist(err) { shouldRotateOnStart = false } - r.triggers = newTriggers(shouldRotateOnStart, r.interval, r.maxSizeBytes) + r.triggers = newTriggers(shouldRotateOnStart, r.interval, r.maxSizeBytes, r.clock) if r.log != nil { r.log.Debugw("Initialized file rotator", @@ -194,7 +183,6 @@ func NewFileRotator(filename string, options ...RotatorOption) (*Rotator, error) "max_size_bytes", r.maxSizeBytes, "max_backups", r.maxBackups, "permissions", r.permissions, - "suffix", r.suffix, ) } @@ -292,7 +280,7 @@ func (r *Rotator) openFile() error { } func (r *Rotator) rotate(reason rotateReason) error { - return r.rotateWithTime(reason, time.Now()) + return r.rotateWithTime(reason, r.clock.Now()) } // rotateWithTime closes the actively written file, and rotates it along with exising @@ -339,7 +327,7 @@ func (r *Rotator) isRotationTriggered(dataLen uint) (rotateReason, time.Time) { for _, t := range r.triggers { reason := t.TriggerRotation(dataLen) if reason != rotateReasonNoRotate { - return reason, time.Now() + return reason, r.clock.Now() } } return rotateReasonNoRotate, time.Time{} @@ -395,52 +383,37 @@ func (r *Rotator) closeFile() error { return errors.Wrap(err, "failed to close active file") } -type countRotator struct { - log Logger - filename string - intervalRotator *intervalRotator - maxBackups uint -} - type dateRotator struct { log Logger + clock clock format string filenamePrefix string currentFilename string - intervalRotator *intervalRotator -} + extension string -func newRotater(log Logger, s SuffixType, filename string, maxBackups uint, interval time.Duration) rotater { - switch s { - case SuffixCount: - if interval > 0 { - return newIntervalRotator(log, interval, filename) - } - return &countRotator{ - log: log, - filename: filename, - maxBackups: maxBackups, - } - case SuffixDate: - return newDateRotater(log, filename) - default: - return &countRotator{ - log: log, - filename: filename, - maxBackups: maxBackups, - } - } + prefixLen int + filenameLen int + extensionLen int + + // logOrderCache is used to cache log file meta information between rotations + logOrderCache map[string]logOrder } -func newDateRotater(log Logger, filename string) rotater { +func newDateRotater(log Logger, filename string, clock clock) rotater { d := &dateRotator{ log: log, + clock: clock, filenamePrefix: filename + "-", - format: "20060102150405", + extension: ".ndjson", + format: DateFormat, + logOrderCache: make(map[string]logOrder), } + d.prefixLen = len(d.filenamePrefix) + d.filenameLen = d.prefixLen + len(DateFormat) + d.extensionLen = len(d.extension) - d.currentFilename = d.filenamePrefix + time.Now().Format(d.format) - files, err := filepath.Glob(d.filenamePrefix + "*") + d.currentFilename = d.filenamePrefix + d.clock.Now().Format(d.format) + d.extension + files, err := filepath.Glob(d.filenamePrefix + "*" + d.extension) if err != nil { return d } @@ -467,7 +440,24 @@ func (d *dateRotator) Rotate(reason rotateReason, rotateTime time.Time) error { d.log.Debugw("Rotating file", "filename", d.currentFilename, "reason", reason) } - d.currentFilename = d.filenamePrefix + rotateTime.Format(d.format) + d.logOrderCache = make(map[string]logOrder, 0) + + newFileNamePrefix := d.filenamePrefix + rotateTime.Format(d.format) + files, err := filepath.Glob(newFileNamePrefix + "*" + d.extension) + if err != nil { + return fmt.Errorf("failed to get possible files: %+v", err) + } + + if len(files) == 0 { + d.currentFilename = newFileNamePrefix + d.extension + return nil + } + + d.SortModTimeLogs(files) + order := d.OrderLog(files[len(files)-1]) + + d.currentFilename = newFileNamePrefix + "-" + strconv.Itoa(order.index+1) + d.extension + return nil } @@ -479,10 +469,18 @@ func (d *dateRotator) RotatedFiles() []string { } } + for i, name := range files { + if name == d.ActiveFile() { + files = append(files[:i], files[i+1:]...) + break + } + } + d.SortModTimeLogs(files) return files } +// SortModTimeLogs puts newest file to the last func (d *dateRotator) SortModTimeLogs(strings []string) { sort.Slice( strings, @@ -492,88 +490,53 @@ func (d *dateRotator) SortModTimeLogs(strings []string) { ) } -func (d *dateRotator) OrderLog(filename string) time.Time { - ts, err := time.Parse(d.filenamePrefix+d.format, filepath.Base(filename)) - if err != nil { - return time.Time{} - } - return ts -} - -func (c *countRotator) ActiveFile() string { - return c.filename +// logOrder stores information required to sort log files +// parsed out from the following format {filename}-{datetime}-{index}.ndjson +type logOrder struct { + index int + datetime time.Time } -func (c *countRotator) RotatedFiles() []string { - files := make([]string, 0) - for i := c.maxBackups + 1; i >= 1; i-- { - name := c.backupName(i) - if _, err := os.Stat(name); os.IsNotExist(err) { - continue - } else if err != nil { - c.log.Debugw("failed to stat rotated file") - return files - } - files = append(files, name) +func (o logOrder) After(other logOrder) bool { + if o.datetime.Equal(other.datetime) { + return other.index > o.index } - - return files + return !o.datetime.After(other.datetime) } -func (c *countRotator) backupName(n uint) string { - if n == 0 { - return c.ActiveFile() +func (d *dateRotator) OrderLog(filename string) logOrder { + if o, ok := d.logOrderCache[filename]; ok { + return o } - return c.ActiveFile() + "." + strconv.Itoa(int(n)) -} -func (c *countRotator) Rotate(reason rotateReason, _ time.Time) error { - for i := c.maxBackups + 1; i > 0; i-- { - old := c.backupName(i - 1) - older := c.backupName(i) + var o logOrder + var err error - if _, err := os.Stat(old); os.IsNotExist(err) { - continue - } else if err != nil { - return errors.Wrap(err, "failed to rotate backups") - } + o.datetime, err = time.Parse(d.format, filename[d.prefixLen:d.filenameLen]) + if err != nil { + return o + } - if err := os.Remove(older); err != nil && !os.IsNotExist(err) { - return errors.Wrap(err, "failed to rotate backups") - } - if err := os.Rename(old, older); err != nil { - return errors.Wrap(err, "failed to rotate backups") - } else if i == 1 { - // Log when rotation of the main file occurs. - if c.log != nil { - c.log.Debugw("Rotating file", "filename", old, "reason", reason) - } + if d.isFilenameWithIndex(filename) { + o.index, err = d.filenameIndex(filename) + if err != nil { + return o } } - return nil -} -func (s *SuffixType) Unpack(v string) error { - i, err := strconv.Atoi(v) - if err == nil { - t := SuffixType(i) - v = t.String() - } + d.logOrderCache[filename] = o - val, ok := suffixes[v] - if !ok { - return fmt.Errorf("invalid suffix type: %+v", v) - } + return o +} - *s = val - return nil +func (d *dateRotator) isFilenameWithIndex(filename string) bool { + return d.filenameLen+d.extensionLen < len(filename) } -func (s *SuffixType) String() string { - for k, v := range suffixes { - if v == *s { - return k - } +func (d *dateRotator) filenameIndex(filename string) (int, error) { + indexStr := filename[d.filenameLen+1 : len(filename)-d.extensionLen] + if len(indexStr) > 0 { + return strconv.Atoi(indexStr) } - return "" + return 0, nil } diff --git a/libbeat/common/file/rotator_test.go b/libbeat/common/file/rotator_test.go index 585d1690e78..6294b042d13 100644 --- a/libbeat/common/file/rotator_test.go +++ b/libbeat/common/file/rotator_test.go @@ -21,8 +21,6 @@ import ( "fmt" "os" "path/filepath" - "regexp" - "sort" "sync" "testing" "time" @@ -39,43 +37,57 @@ func TestFileRotator(t *testing.T) { logp.TestingSetup() dir := t.TempDir() + logname := "sample" + c := &testClock{time.Date(2021, 11, 11, 0, 0, 0, 0, time.Local)} - filename := filepath.Join(dir, "sample.log") + filename := filepath.Join(dir, logname) r, err := file.NewFileRotator(filename, file.MaxBackups(2), file.WithLogger(logp.NewLogger("rotator").With(logp.Namespace("rotator"))), + file.WithClock(c), ) if err != nil { t.Fatal(err) } defer r.Close() + firstFile := fmt.Sprintf("%s-%s.ndjson", logname, c.Now().Format(file.DateFormat)) + WriteMsg(t, r) - AssertDirContents(t, dir, "sample.log") + AssertDirContents(t, dir, firstFile) + + c.time = time.Date(2021, 11, 12, 0, 0, 0, 0, time.Local) Rotate(t, r) - AssertDirContents(t, dir, "sample.log.1") + AssertDirContents(t, dir, firstFile) WriteMsg(t, r) - AssertDirContents(t, dir, "sample.log", "sample.log.1") + + secondFile := fmt.Sprintf("%s-%s.ndjson", logname, c.Now().Format(file.DateFormat)) + AssertDirContents(t, dir, firstFile, secondFile) + + c.time = time.Date(2021, 11, 13, 0, 0, 0, 0, time.Local) Rotate(t, r) - AssertDirContents(t, dir, "sample.log.1", "sample.log.2") + AssertDirContents(t, dir, firstFile, secondFile) WriteMsg(t, r) - AssertDirContents(t, dir, "sample.log", "sample.log.1", "sample.log.2") + thirdFile := fmt.Sprintf("%s-%s.ndjson", logname, c.Now().Format(file.DateFormat)) + AssertDirContents(t, dir, firstFile, secondFile, thirdFile) + c.time = time.Date(2021, 11, 14, 0, 0, 0, 0, time.Local) Rotate(t, r) - AssertDirContents(t, dir, "sample.log.1", "sample.log.2") + AssertDirContents(t, dir, secondFile, thirdFile) + c.time = time.Date(2021, 11, 15, 0, 0, 0, 0, time.Local) Rotate(t, r) - AssertDirContents(t, dir, "sample.log.2", "sample.log.3") + AssertDirContents(t, dir, secondFile, thirdFile) } func TestFileRotatorConcurrently(t *testing.T) { dir := t.TempDir() - filename := filepath.Join(dir, "sample.log") + filename := filepath.Join(dir, "sample") r, err := file.NewFileRotator(filename, file.MaxBackups(2)) if err != nil { t.Fatal(err) @@ -97,29 +109,27 @@ func TestDailyRotation(t *testing.T) { dir := t.TempDir() logname := "daily" - dateFormat := "2006-01-02" - today := time.Now().Format(dateFormat) - yesterday := time.Now().AddDate(0, 0, -1).Format(dateFormat) - twoDaysAgo := time.Now().AddDate(0, 0, -2).Format(dateFormat) + yesterday := time.Now().AddDate(0, 0, -1).Format(file.DateFormat) + twoDaysAgo := time.Now().AddDate(0, 0, -2).Format(file.DateFormat) // seed directory with existing log files files := []string{ - logname + "-" + yesterday + "-1", - logname + "-" + yesterday + "-2", - logname + "-" + yesterday + "-3", - logname + "-" + yesterday + "-4", - logname + "-" + yesterday + "-5", - logname + "-" + yesterday + "-6", - logname + "-" + yesterday + "-7", - logname + "-" + yesterday + "-8", - logname + "-" + yesterday + "-9", - logname + "-" + yesterday + "-10", - logname + "-" + yesterday + "-11", - logname + "-" + yesterday + "-12", - logname + "-" + yesterday + "-13", - logname + "-" + twoDaysAgo + "-1", - logname + "-" + twoDaysAgo + "-2", - logname + "-" + twoDaysAgo + "-3", + logname + "-" + yesterday + "-1.ndjson", + logname + "-" + yesterday + "-2.ndjson", + logname + "-" + yesterday + "-3.ndjson", + logname + "-" + yesterday + "-4.ndjson", + logname + "-" + yesterday + "-5.ndjson", + logname + "-" + yesterday + "-6.ndjson", + logname + "-" + yesterday + "-7.ndjson", + logname + "-" + yesterday + "-8.ndjson", + logname + "-" + yesterday + "-9.ndjson", + logname + "-" + yesterday + "-10.ndjson", + logname + "-" + yesterday + "-11.ndjson", + logname + "-" + yesterday + "-12.ndjson", + logname + "-" + yesterday + "-13.ndjson", + logname + "-" + twoDaysAgo + "-1.ndjson", + logname + "-" + twoDaysAgo + "-2.ndjson", + logname + "-" + twoDaysAgo + "-3.ndjson", } for _, f := range files { @@ -139,25 +149,26 @@ func TestDailyRotation(t *testing.T) { Rotate(t, r) - AssertDirContents(t, dir, logname+"-"+yesterday+"-12", logname+"-"+yesterday+"-13") + AssertDirContents(t, dir, logname+"-"+yesterday+"-12.ndjson", logname+"-"+yesterday+"-13.ndjson") WriteMsg(t, r) - AssertDirContents(t, dir, logname+"-"+yesterday+"-12", logname+"-"+yesterday+"-13", logname) + today := time.Now().Format(file.DateFormat) + AssertDirContents(t, dir, logname+"-"+yesterday+"-12.ndjson", logname+"-"+yesterday+"-13.ndjson", logname+"-"+today+".ndjson") Rotate(t, r) - AssertDirContents(t, dir, logname+"-"+yesterday+"-13", logname+"-"+today+"-1") + AssertDirContents(t, dir, logname+"-"+yesterday+"-13.ndjson", logname+"-"+today+".ndjson") WriteMsg(t, r) - AssertDirContents(t, dir, logname+"-"+yesterday+"-13", logname+"-"+today+"-1", logname) + AssertDirContents(t, dir, logname+"-"+yesterday+"-13.ndjson", logname+"-"+today+".ndjson", logname+"-"+today+"-1.ndjson") for i := 0; i < (int(maxSizeBytes)/len(logMessage))+1; i++ { WriteMsg(t, r) } - AssertDirContents(t, dir, logname+"-"+today+"-1", logname+"-"+today+"-2", logname) + AssertDirContents(t, dir, logname+"-"+today+"-1.ndjson", logname+"-"+today+"-2.ndjson", logname+"-"+today+"-3.ndjson") } // Tests the FileConfig.RotateOnStartup parameter @@ -165,13 +176,15 @@ func TestRotateOnStartup(t *testing.T) { dir := t.TempDir() logname := "rotate_on_open" - filename := filepath.Join(dir, logname) + c := &testClock{time.Date(2021, 11, 11, 0, 0, 0, 0, time.Local)} + firstFile := fmt.Sprintf("%s-%s.ndjson", logname, c.Now().Format(file.DateFormat)) + filename := filepath.Join(dir, firstFile) // Create an existing log file with this name. CreateFile(t, filename) - AssertDirContents(t, dir, logname) + AssertDirContents(t, dir, firstFile) - r, err := file.NewFileRotator(filename, file.RotateOnStartup(false)) + r, err := file.NewFileRotator(filepath.Join(dir, logname), file.RotateOnStartup(false), file.WithClock(c)) if err != nil { t.Fatal(err) } @@ -179,33 +192,37 @@ func TestRotateOnStartup(t *testing.T) { WriteMsg(t, r) // The line should have been appended to the existing file without rotation. - AssertDirContents(t, dir, logname) + AssertDirContents(t, dir, firstFile) // Close the first rotator early (the deferred close will be a no-op if // we haven't hit an error by now), so it can't interfere with the second one. r.Close() // Create a second rotator with the default setting of rotateOnStartup=true - r, err = file.NewFileRotator(filename) + c = &testClock{time.Date(2021, 11, 12, 0, 0, 0, 0, time.Local)} + r, err = file.NewFileRotator(filepath.Join(dir, logname), file.WithClock(c)) if err != nil { t.Fatal(err) } defer r.Close() // The directory contents shouldn't change until the first Write. - AssertDirContents(t, dir, logname) + AssertDirContents(t, dir, firstFile) + + secondFile := fmt.Sprintf("%s-%s.ndjson", logname, c.Now().Format(file.DateFormat)) WriteMsg(t, r) - AssertDirContents(t, dir, logname, logname+".1") + AssertDirContents(t, dir, firstFile, secondFile) } -func TestRotateDateSuffix(t *testing.T) { +func TestRotate(t *testing.T) { dir := t.TempDir() logname := "beatname" filename := filepath.Join(dir, logname) - r, err := file.NewFileRotator(filename, file.Suffix(file.SuffixDate), file.MaxBackups(1)) + c := &testClock{time.Date(2021, 11, 11, 0, 0, 0, 0, time.Local)} + r, err := file.NewFileRotator(filename, file.MaxBackups(1), file.WithClock(c)) if err != nil { t.Fatal(err) } @@ -213,24 +230,24 @@ func TestRotateDateSuffix(t *testing.T) { WriteMsg(t, r) - firstExpectedPattern := fmt.Sprintf("%s-%s.*", logname, time.Now().Format("20060102150405")) - AssertDirContentsPattern(t, dir, firstExpectedPattern) + firstFile := fmt.Sprintf("%s-%s.ndjson", logname, c.Now().Format(file.DateFormat)) + AssertDirContents(t, dir, firstFile) - time.Sleep(2 * time.Second) - secondExpectedPattern := fmt.Sprintf("%s-%s.*", logname, time.Now().Format("20060102150405")) + c.time = time.Date(2021, 11, 13, 0, 0, 0, 0, time.Local) + secondFile := fmt.Sprintf("%s-%s.ndjson", logname, c.Now().Format(file.DateFormat)) Rotate(t, r) WriteMsg(t, r) - AssertDirContentsPattern(t, dir, firstExpectedPattern, secondExpectedPattern) + AssertDirContents(t, dir, firstFile, secondFile) - time.Sleep(2 * time.Second) - thirdExpectedPattern := fmt.Sprintf("%s-%s.*", logname, time.Now().Format("20060102150405")) + c.time = time.Date(2021, 11, 15, 0, 0, 0, 0, time.Local) + thirdFile := fmt.Sprintf("%s-%s.ndjson", logname, c.Now().Format(file.DateFormat)) Rotate(t, r) WriteMsg(t, r) - AssertDirContentsPattern(t, dir, secondExpectedPattern, thirdExpectedPattern) + AssertDirContents(t, dir, secondFile, thirdFile) } func CreateFile(t *testing.T, filename string) { @@ -258,36 +275,7 @@ func AssertDirContents(t *testing.T, dir string, files ...string) { t.Fatal(err) } - sort.Strings(files) - sort.Strings(names) - assert.EqualValues(t, files, names) -} - -func AssertDirContentsPattern(t *testing.T, dir string, patterns ...string) { - t.Helper() - - f, err := os.Open(dir) - if err != nil { - t.Fatal(err) - } - - names, err := f.Readdirnames(-1) - if err != nil { - t.Fatal(err) - } - if len(patterns) != len(names) { - t.Fatal("unexpected number of files") - } - - sort.Strings(patterns) - sort.Strings(names) - for i := 0; i < len(patterns); i++ { - matches, err := regexp.MatchString(patterns[i], names[i]) - if err != nil { - t.Fatal(err) - } - assert.True(t, matches, "pattern: %s name: %s", patterns[i], names[i]) - } + assert.ElementsMatch(t, files, names) } func WriteMsg(t *testing.T, r *file.Rotator) { @@ -307,3 +295,11 @@ func Rotate(t *testing.T, r *file.Rotator) { t.Fatal(err) } } + +type testClock struct { + time time.Time +} + +func (t testClock) Now() time.Time { + return t.time +} diff --git a/libbeat/common/file/trigger.go b/libbeat/common/file/trigger.go index d96d748f922..22c128a334b 100644 --- a/libbeat/common/file/trigger.go +++ b/libbeat/common/file/trigger.go @@ -52,14 +52,14 @@ type trigger interface { TriggerRotation(dataLen uint) rotateReason } -func newTriggers(rotateOnStartup bool, interval time.Duration, maxSizeBytes uint) []trigger { +func newTriggers(rotateOnStartup bool, interval time.Duration, maxSizeBytes uint, clock clock) []trigger { triggers := make([]trigger, 0) if rotateOnStartup { triggers = append(triggers, &initTrigger{}) } if interval > 0 { - triggers = append(triggers, newIntervalTrigger(interval)) + triggers = append(triggers, newIntervalTrigger(interval, clock)) } if maxSizeBytes > 0 { triggers = append(triggers, &sizeTrigger{maxSizeBytes: maxSizeBytes, size: 0}) @@ -113,8 +113,8 @@ func (realClock) Now() time.Time { return time.Now() } -func newIntervalTrigger(interval time.Duration) trigger { - t := intervalTrigger{interval: interval, clock: realClock{}} +func newIntervalTrigger(interval time.Duration, clock clock) trigger { + t := intervalTrigger{interval: interval, clock: clock} switch interval { case time.Second: diff --git a/libbeat/common/flowhash/communityid_test.go b/libbeat/common/flowhash/communityid_test.go index 7972fd24c27..4398d60d946 100644 --- a/libbeat/common/flowhash/communityid_test.go +++ b/libbeat/common/flowhash/communityid_test.go @@ -31,10 +31,11 @@ import ( "testing" "time" + "github.com/google/gopacket" + "github.com/google/gopacket/layers" + "github.com/google/gopacket/pcap" + "github.com/stretchr/testify/assert" - "github.com/tsg/gopacket" - "github.com/tsg/gopacket/layers" - "github.com/tsg/gopacket/pcap" ) const ( @@ -42,9 +43,7 @@ const ( goldenDir = "testdata/golden" ) -var ( - update = flag.Bool("update", false, "updates the golden files") -) +var update = flag.Bool("update", false, "updates the golden files") func TestPCAPFiles(t *testing.T) { pcaps, err := filepath.Glob(filepath.Join(pcapDir, "*.pcap")) diff --git a/libbeat/common/kubernetes/eventhandler.go b/libbeat/common/kubernetes/eventhandler.go index eebe33d4d76..b499b409fe3 100644 --- a/libbeat/common/kubernetes/eventhandler.go +++ b/libbeat/common/kubernetes/eventhandler.go @@ -17,6 +17,10 @@ package kubernetes +import ( + "sync" +) + // ResourceEventHandler can handle notifications for events that happen to a // resource. The events are informational only, so you can't return an // error. @@ -120,3 +124,108 @@ func (r FilteringResourceEventHandler) OnDelete(obj interface{}) { } r.Handler.OnDelete(obj) } + +// podUpdaterHandlerFunc is a function that handles pod updater notifications. +type podUpdaterHandlerFunc func(interface{}) + +// podUpdaterStore is the interface that an object needs to implement to be +// used as a pod updater store. +type podUpdaterStore interface { + List() []interface{} +} + +// namespacePodUpdater notifies updates on pods when their namespaces are updated. +type namespacePodUpdater struct { + handler podUpdaterHandlerFunc + store podUpdaterStore + locker sync.Locker +} + +// NewNamespacePodUpdater creates a namespacePodUpdater +func NewNamespacePodUpdater(handler podUpdaterHandlerFunc, store podUpdaterStore, locker sync.Locker) *namespacePodUpdater { + return &namespacePodUpdater{ + handler: handler, + store: store, + locker: locker, + } +} + +// OnUpdate handles update events on namespaces. +func (n *namespacePodUpdater) OnUpdate(obj interface{}) { + ns, ok := obj.(*Namespace) + if !ok { + return + } + + // n.store.List() returns a snapshot at this point. If a delete is received + // from the main watcher, this loop may generate an update event after the + // delete is processed, leaving configurations that would never be deleted. + // Also this loop can miss updates, what could leave outdated configurations. + // Avoid these issues by locking the processing of events from the main watcher. + if n.locker != nil { + n.locker.Lock() + defer n.locker.Unlock() + } + for _, pod := range n.store.List() { + pod, ok := pod.(*Pod) + if ok && pod.Namespace == ns.Name { + n.handler(pod) + } + } +} + +// OnAdd handles add events on namespaces. Nothing to do, if pods are added to this +// namespace they will generate their own add events. +func (*namespacePodUpdater) OnAdd(interface{}) {} + +// OnDelete handles delete events on namespaces. Nothing to do, if pods are deleted from this +// namespace they will generate their own delete events. +func (*namespacePodUpdater) OnDelete(interface{}) {} + +// nodePodUpdater notifies updates on pods when their nodes are updated. +type nodePodUpdater struct { + handler podUpdaterHandlerFunc + store podUpdaterStore + locker sync.Locker +} + +// NewNodePodUpdater creates a nodePodUpdater +func NewNodePodUpdater(handler podUpdaterHandlerFunc, store podUpdaterStore, locker sync.Locker) *nodePodUpdater { + return &nodePodUpdater{ + handler: handler, + store: store, + locker: locker, + } +} + +// OnUpdate handles update events on nodes. +func (n *nodePodUpdater) OnUpdate(obj interface{}) { + node, ok := obj.(*Node) + if !ok { + return + } + + // n.store.List() returns a snapshot at this point. If a delete is received + // from the main watcher, this loop may generate an update event after the + // delete is processed, leaving configurations that would never be deleted. + // Also this loop can miss updates, what could leave outdated configurations. + // Avoid these issues by locking the processing of events from the main watcher. + if n.locker != nil { + n.locker.Lock() + defer n.locker.Unlock() + } + for _, pod := range n.store.List() { + pod, ok := pod.(*Pod) + if ok && pod.Spec.NodeName == node.Name { + n.handler(pod) + } + } +} + +// OnAdd handles add events on namespaces. Nothing to do, if pods are added to this +// namespace they will generate their own add events. +func (*nodePodUpdater) OnAdd(interface{}) {} + +// OnDelete handles delete events on namespaces. Nothing to do, if pods are deleted from this +// namespace they will generate their own delete events. +func (*nodePodUpdater) OnDelete(interface{}) {} diff --git a/libbeat/common/kubernetes/informer.go b/libbeat/common/kubernetes/informer.go index cd7fb513cf6..48d98e3e003 100644 --- a/libbeat/common/kubernetes/informer.go +++ b/libbeat/common/kubernetes/informer.go @@ -149,6 +149,18 @@ func NewInformer(client kubernetes.Interface, resource Resource, opts WatchOptio } objType = "service" + case *CronJob: + cronjob := client.BatchV1().CronJobs(opts.Namespace) + listwatch = &cache.ListWatch{ + ListFunc: func(options metav1.ListOptions) (runtime.Object, error) { + return cronjob.List(ctx, options) + }, + WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) { + return cronjob.Watch(ctx, options) + }, + } + + objType = "cronjob" case *Job: job := client.BatchV1().Jobs(opts.Namespace) listwatch = &cache.ListWatch{ diff --git a/libbeat/common/kubernetes/k8skeystore/kubernetes_keystore.go b/libbeat/common/kubernetes/k8skeystore/kubernetes_keystore.go index 3497a0a0361..0279e0a9a4d 100644 --- a/libbeat/common/kubernetes/k8skeystore/kubernetes_keystore.go +++ b/libbeat/common/kubernetes/k8skeystore/kubernetes_keystore.go @@ -62,7 +62,7 @@ func (kr *KubernetesKeystoresRegistry) GetKeystore(event bus.Event) keystore.Key namespace := "" if val, ok := event["kubernetes"]; ok { kubernetesMeta := val.(common.MapStr) - ns, err := kubernetesMeta.GetValue("namespace.name") + ns, err := kubernetesMeta.GetValue("namespace") if err != nil { kr.logger.Debugf("Cannot retrieve kubernetes namespace from event: %s", event) return nil diff --git a/libbeat/common/kubernetes/k8skeystore/kubernetes_keystore_test.go b/libbeat/common/kubernetes/k8skeystore/kubernetes_keystore_test.go index 68656b0b4e7..359479b9eb8 100644 --- a/libbeat/common/kubernetes/k8skeystore/kubernetes_keystore_test.go +++ b/libbeat/common/kubernetes/k8skeystore/kubernetes_keystore_test.go @@ -34,10 +34,10 @@ import ( func TestGetKeystore(t *testing.T) { kRegistry := NewKubernetesKeystoresRegistry(nil, nil) - k1 := kRegistry.GetKeystore(bus.Event{"kubernetes": common.MapStr{"namespace": common.MapStr{"name": "my_namespace"}}}) - k2 := kRegistry.GetKeystore(bus.Event{"kubernetes": common.MapStr{"namespace": common.MapStr{"name": "my_namespace"}}}) + k1 := kRegistry.GetKeystore(bus.Event{"kubernetes": common.MapStr{"namespace": "my_namespace"}}) + k2 := kRegistry.GetKeystore(bus.Event{"kubernetes": common.MapStr{"namespace": "my_namespace"}}) assert.Equal(t, k1, k2) - k3 := kRegistry.GetKeystore(bus.Event{"kubernetes": common.MapStr{"namespace": common.MapStr{"name": "my_namespace_2"}}}) + k3 := kRegistry.GetKeystore(bus.Event{"kubernetes": common.MapStr{"namespace": "my_namespace_2"}}) assert.NotEqual(t, k2, k3) } @@ -64,7 +64,7 @@ func TestGetKeystoreAndRetrieve(t *testing.T) { } kRegistry := NewKubernetesKeystoresRegistry(nil, client) - k1 := kRegistry.GetKeystore(bus.Event{"kubernetes": common.MapStr{"namespace": common.MapStr{"name": ns}}}) + k1 := kRegistry.GetKeystore(bus.Event{"kubernetes": common.MapStr{"namespace": ns}}) key := "kubernetes.test_namespace.testing_secret.secret_value" secure, err := k1.Retrieve(key) if err != nil { @@ -100,7 +100,7 @@ func TestGetKeystoreAndRetrieveWithNonAllowedNamespace(t *testing.T) { } kRegistry := NewKubernetesKeystoresRegistry(logger, client) - k1 := kRegistry.GetKeystore(bus.Event{"kubernetes": common.MapStr{"namespace": common.MapStr{"name": ns}}}) + k1 := kRegistry.GetKeystore(bus.Event{"kubernetes": common.MapStr{"namespace": ns}}) key := "kubernetes.test_namespace_HACK.testing_secret.secret_value" _, err = k1.Retrieve(key) assert.Error(t, err) @@ -130,7 +130,7 @@ func TestGetKeystoreAndRetrieveWithWrongKeyFormat(t *testing.T) { } kRegistry := NewKubernetesKeystoresRegistry(logger, client) - k1 := kRegistry.GetKeystore(bus.Event{"kubernetes": common.MapStr{"namespace": common.MapStr{"name": ns}}}) + k1 := kRegistry.GetKeystore(bus.Event{"kubernetes": common.MapStr{"namespace": ns}}) key := "HACK_test_namespace_HACK.testing_secret.secret_value" _, err = k1.Retrieve(key) assert.Error(t, err) @@ -142,7 +142,7 @@ func TestGetKeystoreAndRetrieveWithNoSecretsExistent(t *testing.T) { ns := "test_namespace" kRegistry := NewKubernetesKeystoresRegistry(logger, client) - k1 := kRegistry.GetKeystore(bus.Event{"kubernetes": common.MapStr{"namespace": common.MapStr{"name": ns}}}) + k1 := kRegistry.GetKeystore(bus.Event{"kubernetes": common.MapStr{"namespace": ns}}) key := "kubernetes.test_namespace.testing_secret.secret_value" _, err := k1.Retrieve(key) assert.Error(t, err) @@ -172,7 +172,7 @@ func TestGetKeystoreAndRetrieveWithWrongSecretName(t *testing.T) { } kRegistry := NewKubernetesKeystoresRegistry(logger, client) - k1 := kRegistry.GetKeystore(bus.Event{"kubernetes": common.MapStr{"namespace": common.MapStr{"name": ns}}}) + k1 := kRegistry.GetKeystore(bus.Event{"kubernetes": common.MapStr{"namespace": ns}}) key := "kubernetes.test_namespace.testing_secret_WRONG.secret_value" _, err = k1.Retrieve(key) assert.Error(t, err) @@ -202,7 +202,7 @@ func TestGetKeystoreAndRetrieveWithWrongSecretValue(t *testing.T) { } kRegistry := NewKubernetesKeystoresRegistry(logger, client) - k1 := kRegistry.GetKeystore(bus.Event{"kubernetes": common.MapStr{"namespace": common.MapStr{"name": ns}}}) + k1 := kRegistry.GetKeystore(bus.Event{"kubernetes": common.MapStr{"namespace": ns}}) key := "kubernetes.test_namespace.testing_secret.secret_value_WRONG" _, err = k1.Retrieve(key) assert.Error(t, err) diff --git a/libbeat/common/kubernetes/metadata/metadata.go b/libbeat/common/kubernetes/metadata/metadata.go index 7195d47ab0c..eb55856081b 100644 --- a/libbeat/common/kubernetes/metadata/metadata.go +++ b/libbeat/common/kubernetes/metadata/metadata.go @@ -96,8 +96,7 @@ func GetPodMetaGen( if namespaceWatcher != nil && metaConf.Namespace.Enabled() { namespaceMetaGen = NewNamespaceMetadataGenerator(metaConf.Namespace, namespaceWatcher.Store(), namespaceWatcher.Client()) } - metaGen := NewPodMetadataGenerator(cfg, podWatcher.Store(), podWatcher.Client(), nodeMetaGen, namespaceMetaGen, metaConf.Deployment) - + metaGen := NewPodMetadataGenerator(cfg, podWatcher.Store(), podWatcher.Client(), nodeMetaGen, namespaceMetaGen, metaConf) return metaGen } diff --git a/libbeat/common/kubernetes/metadata/namespace.go b/libbeat/common/kubernetes/metadata/namespace.go index 424eab15d9a..920a0ecf2a1 100644 --- a/libbeat/common/kubernetes/metadata/namespace.go +++ b/libbeat/common/kubernetes/metadata/namespace.go @@ -70,7 +70,7 @@ func (n *namespace) GenerateK8s(obj kubernetes.Resource, opts ...FieldOptions) c } meta := n.resource.GenerateK8s(resource, obj, opts...) - meta = unifyResourceMetadata(meta) + meta = flattenMetadata(meta) // TODO: Add extra fields in here if need be return meta @@ -94,39 +94,25 @@ func (n *namespace) GenerateFromName(name string, opts ...FieldOptions) common.M return nil } -// unifyResourceMetadata moves all the resource's metadata (labels, annotations) -// under the resource field -// example input: -// "kubernetes": common.MapStr{ -// "labels": common.MapStr{ -// "foo": "bar", -// }, -// "annotations": common.MapStr{ -// "spam": "baz", -// }, -// "namespace": common.MapStr{ -// "name": name, -// "uid": uid, -// }, -// }, -// example output: -// "kubernetes": common.MapStr{ -// "namespace": common.MapStr{ -// "name": name, -// "uid": uid, -// "labels": common.MapStr{ -// "foo": "bar", -// }, -// "annotations": common.MapStr{ -// "spam": "baz", -// }, -// }, -// }, -func unifyResourceMetadata(in common.MapStr) common.MapStr { - resourceValues, ok := in[resource].(common.MapStr) +func flattenMetadata(in common.MapStr) common.MapStr { + out := common.MapStr{} + rawFields, err := in.GetValue(resource) + if err != nil { + return nil + } + + fields, ok := rawFields.(common.MapStr) if !ok { - return in + return nil } + for k, v := range fields { + if k == "name" { + out[resource] = v + } else { + out[resource+"_"+k] = v + } + } + populateFromKeys := []string{"labels", "annotations"} for _, key := range populateFromKeys { rawValues, err := in.GetValue(key) @@ -135,10 +121,9 @@ func unifyResourceMetadata(in common.MapStr) common.MapStr { } values, ok := rawValues.(common.MapStr) if ok { - resourceValues.Put(key, values) - in.Delete(key) + out[resource+"_"+key] = values } } - return in + return out } diff --git a/libbeat/common/kubernetes/metadata/namespace_test.go b/libbeat/common/kubernetes/metadata/namespace_test.go index 12f4f1377d9..88cc7859cdd 100644 --- a/libbeat/common/kubernetes/metadata/namespace_test.go +++ b/libbeat/common/kubernetes/metadata/namespace_test.go @@ -51,9 +51,11 @@ func TestNamespace_Generate(t *testing.T) { UID: types.UID(uid), Labels: map[string]string{ "foo": "bar", + "key": "value", }, Annotations: map[string]string{ "spam": "baz", + "key": "value", }, }, TypeMeta: metav1.TypeMeta{ @@ -61,24 +63,21 @@ func TestNamespace_Generate(t *testing.T) { APIVersion: "v1", }, }, - output: common.MapStr{ - "kubernetes": common.MapStr{ - "namespace": common.MapStr{ - "name": name, - "uid": uid, - "labels": common.MapStr{ - "foo": "bar", - }, - "annotations": common.MapStr{ - "spam": "baz", - }, - }, + output: common.MapStr{"kubernetes": common.MapStr{ + "namespace": name, + "namespace_uid": uid, + "namespace_labels": common.MapStr{ + "foo": "bar", }, - }, + "namespace_annotations": common.MapStr{ + "spam": "baz", + }, + }}, }, } cfg, err := common.NewConfigFrom(Config{ + IncludeLabels: []string{"foo"}, IncludeAnnotations: []string{"spam"}, }) if err != nil { @@ -121,15 +120,13 @@ func TestNamespace_GenerateFromName(t *testing.T) { }, }, output: common.MapStr{ - "namespace": common.MapStr{ - "name": name, - "uid": uid, - "labels": common.MapStr{ - "foo": "bar", - }, - "annotations": common.MapStr{ - "spam": "baz", - }, + "namespace": name, + "namespace_uid": uid, + "namespace_labels": common.MapStr{ + "foo": "bar", + }, + "namespace_annotations": common.MapStr{ + "spam": "baz", }, }, }, diff --git a/libbeat/common/kubernetes/metadata/pod.go b/libbeat/common/kubernetes/metadata/pod.go index 5ec63292b6c..6debd974260 100644 --- a/libbeat/common/kubernetes/metadata/pod.go +++ b/libbeat/common/kubernetes/metadata/pod.go @@ -29,12 +29,12 @@ import ( ) type pod struct { - store cache.Store - client k8s.Interface - node MetaGen - namespace MetaGen - resource *Resource - addDeployment bool + store cache.Store + client k8s.Interface + node MetaGen + namespace MetaGen + resource *Resource + addResourceMetadata *AddResourceMetadataConfig } // NewPodMetadataGenerator creates a metagen for pod resources @@ -44,14 +44,15 @@ func NewPodMetadataGenerator( client k8s.Interface, node MetaGen, namespace MetaGen, - addDeploymentMeta bool) MetaGen { + addResourceMetadata *AddResourceMetadataConfig) MetaGen { + return &pod{ - resource: NewResourceMetadataGenerator(cfg, client), - store: pods, - node: node, - namespace: namespace, - client: client, - addDeployment: addDeploymentMeta, + resource: NewResourceMetadataGenerator(cfg, client), + store: pods, + node: node, + namespace: namespace, + client: client, + addResourceMetadata: addResourceMetadata, } } @@ -87,7 +88,8 @@ func (p *pod) GenerateK8s(obj kubernetes.Resource, opts ...FieldOptions) common. out := p.resource.GenerateK8s("pod", obj, opts...) // check if Pod is handled by a ReplicaSet which is controlled by a Deployment - if p.addDeployment { + // TODO: same happens with CronJob vs Job. The hierarcy there is CronJob->Job->Pod + if p.addResourceMetadata.Deployment { rsName, _ := out.GetValue("replicaset.name") if rsName, ok := rsName.(string); ok { dep := p.getRSDeployment(rsName, po.GetNamespace()) diff --git a/libbeat/common/kubernetes/metadata/pod_test.go b/libbeat/common/kubernetes/metadata/pod_test.go index 0ea6053a1fb..ac810692693 100644 --- a/libbeat/common/kubernetes/metadata/pod_test.go +++ b/libbeat/common/kubernetes/metadata/pod_test.go @@ -36,6 +36,8 @@ import ( "github.com/elastic/beats/v7/libbeat/common/kubernetes" ) +var addResourceMetadata = GetDefaultResourceMetadataConfig() + func TestPod_Generate(t *testing.T) { client := k8sfake.NewSimpleClientset() uid := "005f3b90-4b9d-12f8-acf0-31020a840133" @@ -133,9 +135,7 @@ func TestPod_Generate(t *testing.T) { "annotations": common.MapStr{ "app": "production", }, - "namespace": common.MapStr{ - "name": "default", - }, + "namespace": "default", "node": common.MapStr{ "name": "testnode", }, @@ -181,9 +181,7 @@ func TestPod_Generate(t *testing.T) { "uid": uid, "ip": "127.0.0.5", }, - "namespace": common.MapStr{ - "name": "default", - }, + "namespace": "default", "deployment": common.MapStr{ "name": "owner", }, @@ -238,9 +236,7 @@ func TestPod_Generate(t *testing.T) { "uid": uid, "ip": "127.0.0.5", }, - "namespace": common.MapStr{ - "name": "default", - }, + "namespace": "default", "daemonset": common.MapStr{ "name": "owner", }, @@ -256,6 +252,61 @@ func TestPod_Generate(t *testing.T) { }, }, }, + { + name: "test object with owner reference to Job", + input: &v1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, + UID: types.UID(uid), + Namespace: namespace, + Labels: map[string]string{ + "foo": "bar", + }, + Annotations: map[string]string{ + "app": "production", + }, + OwnerReferences: []metav1.OwnerReference{ + { + APIVersion: "batch/v1", + Kind: "Job", + Name: "owner", + UID: "005f3b90-4b9d-12f8-acf0-31020a840144", + Controller: &boolean, + }, + }, + }, + TypeMeta: metav1.TypeMeta{ + Kind: "Pod", + APIVersion: "v1", + }, + Spec: v1.PodSpec{ + NodeName: "testnode", + }, + Status: v1.PodStatus{PodIP: "127.0.0.5"}, + }, + output: common.MapStr{ + "kubernetes": common.MapStr{ + "pod": common.MapStr{ + "name": "obj", + "uid": uid, + "ip": "127.0.0.5", + }, + "namespace": "default", + "job": common.MapStr{ + "name": "owner", + }, + "node": common.MapStr{ + "name": "testnode", + }, + "labels": common.MapStr{ + "foo": "bar", + }, + "annotations": common.MapStr{ + "app": "production", + }, + }, + }, + }, { name: "test object with owner reference to replicaset", input: &v1.Pod{ @@ -295,9 +346,7 @@ func TestPod_Generate(t *testing.T) { "uid": uid, "ip": "127.0.0.5", }, - "namespace": common.MapStr{ - "name": "default", - }, + "namespace": "default", "deployment": common.MapStr{ "name": "nginx-deployment", }, @@ -355,9 +404,7 @@ func TestPod_Generate(t *testing.T) { "uid": uid, "ip": "127.0.0.5", }, - "namespace": common.MapStr{ - "name": "default", - }, + "namespace": "default", "deployment": common.MapStr{ "name": "nginx-deployment", }, @@ -384,7 +431,7 @@ func TestPod_Generate(t *testing.T) { }) assert.NoError(t, err) - metagen := NewPodMetadataGenerator(config, nil, client, nil, nil, true) + metagen := NewPodMetadataGenerator(config, nil, client, nil, nil, addResourceMetadata) for _, test := range tests { t.Run(test.name, func(t *testing.T) { assert.Equal(t, test.output, metagen.Generate(test.input)) @@ -432,9 +479,7 @@ func TestPod_GenerateFromName(t *testing.T) { "uid": uid, "ip": "127.0.0.5", }, - "namespace": common.MapStr{ - "name": "default", - }, + "namespace": "default", "node": common.MapStr{ "name": "testnode", }, @@ -484,9 +529,7 @@ func TestPod_GenerateFromName(t *testing.T) { "uid": uid, "ip": "127.0.0.5", }, - "namespace": common.MapStr{ - "name": "default", - }, + "namespace": "default", "deployment": common.MapStr{ "name": "owner", }, @@ -510,7 +553,7 @@ func TestPod_GenerateFromName(t *testing.T) { assert.NoError(t, err) pods := cache.NewStore(cache.MetaNamespaceKeyFunc) pods.Add(test.input) - metagen := NewPodMetadataGenerator(config, pods, client, nil, nil, true) + metagen := NewPodMetadataGenerator(config, pods, client, nil, nil, addResourceMetadata) accessor, err := meta.Accessor(test.input) require.NoError(t, err) @@ -593,12 +636,10 @@ func TestPod_GenerateWithNodeNamespace(t *testing.T) { "uid": uid, "ip": "127.0.0.5", }, - "namespace": common.MapStr{ - "name": "default", - "uid": uid, - "labels": common.MapStr{ - "nskey": "nsvalue", - }, + "namespace": "default", + "namespace_uid": uid, + "namespace_labels": common.MapStr{ + "nskey": "nsvalue", }, "node": common.MapStr{ "name": "testnode", @@ -634,7 +675,156 @@ func TestPod_GenerateWithNodeNamespace(t *testing.T) { namespaces.Add(test.namespace) nsMeta := NewNamespaceMetadataGenerator(config, namespaces, client) - metagen := NewPodMetadataGenerator(config, pods, client, nodeMeta, nsMeta, true) + metagen := NewPodMetadataGenerator(config, pods, client, nodeMeta, nsMeta, addResourceMetadata) + t.Run(test.name, func(t *testing.T) { + assert.Equal(t, test.output, metagen.Generate(test.input)) + }) + } +} + +func TestPod_GenerateWithNodeNamespaceWithAddResourceConfig(t *testing.T) { + client := k8sfake.NewSimpleClientset() + uid := "005f3b90-4b9d-12f8-acf0-31020a840133" + namespace := "default" + name := "obj" + boolean := true + + tests := []struct { + input kubernetes.Resource + node kubernetes.Resource + namespace kubernetes.Resource + output common.MapStr + name string + }{ + { + name: "test simple object", + input: &v1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, + UID: types.UID(uid), + Namespace: namespace, + Labels: map[string]string{ + "app.kubernetes.io/component": "exporter", + }, + Annotations: map[string]string{ + "app": "production", + }, + OwnerReferences: []metav1.OwnerReference{ + { + APIVersion: "apps", + Kind: "ReplicaSet", + Name: "nginx-rs", + UID: "005f3b90-4b9d-12f8-acf0-31020a8409087", + Controller: &boolean, + }, + }, + }, + TypeMeta: metav1.TypeMeta{ + Kind: "Pod", + APIVersion: "v1", + }, + + Spec: v1.PodSpec{ + NodeName: "testnode", + }, + Status: v1.PodStatus{PodIP: "127.0.0.5"}, + }, + node: &v1.Node{ + ObjectMeta: metav1.ObjectMeta{ + Name: "testnode", + UID: types.UID(uid), + Labels: map[string]string{ + "nodekey": "nodevalue", + "nodekey2": "nodevalue2", + }, + Annotations: map[string]string{}, + }, + TypeMeta: metav1.TypeMeta{ + Kind: "Node", + APIVersion: "v1", + }, + Status: v1.NodeStatus{ + Addresses: []v1.NodeAddress{{Type: v1.NodeHostName, Address: "node1"}}, + }, + }, + namespace: &v1.Namespace{ + ObjectMeta: metav1.ObjectMeta{ + Name: namespace, + UID: types.UID(uid), + Labels: map[string]string{ + "app.kubernetes.io/name": "kube-state-metrics", + "nskey2": "nsvalue2", + }, + Annotations: map[string]string{}, + }, + TypeMeta: metav1.TypeMeta{ + Kind: "Namespace", + APIVersion: "v1", + }, + }, + output: common.MapStr{"kubernetes": common.MapStr{ + "pod": common.MapStr{ + "name": "obj", + "uid": uid, + "ip": "127.0.0.5", + }, + "namespace": "default", + "namespace_uid": uid, + "namespace_labels": common.MapStr{ + "app_kubernetes_io/name": "kube-state-metrics", + }, + "node": common.MapStr{ + "name": "testnode", + "uid": uid, + "labels": common.MapStr{ + "nodekey2": "nodevalue2", + }, + "hostname": "node1", + }, + "labels": common.MapStr{ + "app_kubernetes_io/component": "exporter", + }, + "annotations": common.MapStr{ + "app": "production", + }, + "replicaset": common.MapStr{ + "name": "nginx-rs", + }, + }}, + }, + } + + for _, test := range tests { + config, err := common.NewConfigFrom(map[string]interface{}{ + "include_annotations": []string{"app"}, + }) + + assert.NoError(t, err) + + namespaceConfig, _ := common.NewConfigFrom(map[string]interface{}{ + "include_labels": []string{"app.kubernetes.io/name"}, + }) + nodeConfig, _ := common.NewConfigFrom(map[string]interface{}{ + "include_labels": []string{"nodekey2"}, + }) + metaConfig := AddResourceMetadataConfig{ + Namespace: namespaceConfig, + Node: nodeConfig, + Deployment: false, + } + + pods := cache.NewStore(cache.MetaNamespaceKeyFunc) + pods.Add(test.input) + + nodes := cache.NewStore(cache.MetaNamespaceKeyFunc) + nodes.Add(test.node) + nodeMeta := NewNodeMetadataGenerator(nodeConfig, nodes, client) + + namespaces := cache.NewStore(cache.MetaNamespaceKeyFunc) + namespaces.Add(test.namespace) + nsMeta := NewNamespaceMetadataGenerator(namespaceConfig, namespaces, client) + + metagen := NewPodMetadataGenerator(config, pods, client, nodeMeta, nsMeta, &metaConfig) t.Run(test.name, func(t *testing.T) { assert.Equal(t, test.output, metagen.Generate(test.input)) }) diff --git a/libbeat/common/kubernetes/metadata/resource.go b/libbeat/common/kubernetes/metadata/resource.go index e9591eebbcf..7bff84e9e40 100644 --- a/libbeat/common/kubernetes/metadata/resource.go +++ b/libbeat/common/kubernetes/metadata/resource.go @@ -85,7 +85,7 @@ func (r *Resource) GenerateK8s(kind string, obj kubernetes.Resource, options ... return nil } - labelMap := common.MapStr{} + var labelMap common.MapStr if len(r.config.IncludeLabels) == 0 { labelMap = GenerateMap(accessor.GetLabels(), r.config.LabelsDedot) } else { @@ -107,7 +107,7 @@ func (r *Resource) GenerateK8s(kind string, obj kubernetes.Resource, options ... } if accessor.GetNamespace() != "" { - safemapstr.Put(meta, "namespace.name", accessor.GetNamespace()) + safemapstr.Put(meta, "namespace", accessor.GetNamespace()) } // Add controller metadata if present @@ -118,7 +118,9 @@ func (r *Resource) GenerateK8s(kind string, obj kubernetes.Resource, options ... case "Deployment", "ReplicaSet", "StatefulSet", - "DaemonSet": + "DaemonSet", + "Job", + "CronJob": safemapstr.Put(meta, strings.ToLower(ref.Kind)+".name", ref.Name) } } diff --git a/libbeat/common/kubernetes/metadata/resource_test.go b/libbeat/common/kubernetes/metadata/resource_test.go index 2cbe6d3a970..5ed6f20fce0 100644 --- a/libbeat/common/kubernetes/metadata/resource_test.go +++ b/libbeat/common/kubernetes/metadata/resource_test.go @@ -67,9 +67,7 @@ func TestResource_Generate(t *testing.T) { "labels": common.MapStr{ "foo": "bar", }, - "namespace": common.MapStr{ - "name": "default", - }, + "namespace": "default", }, }, }, @@ -108,9 +106,7 @@ func TestResource_Generate(t *testing.T) { "labels": common.MapStr{ "foo": "bar", }, - "namespace": common.MapStr{ - "name": "default", - }, + "namespace": "default", "deployment": common.MapStr{ "name": "owner", }, diff --git a/libbeat/common/kubernetes/metadata/service_test.go b/libbeat/common/kubernetes/metadata/service_test.go index 197627aa92c..a4b070b55a2 100644 --- a/libbeat/common/kubernetes/metadata/service_test.go +++ b/libbeat/common/kubernetes/metadata/service_test.go @@ -81,9 +81,7 @@ func TestService_Generate(t *testing.T) { "app": "istiod", "istio": "pilot", }, - "namespace": common.MapStr{ - "name": "default", - }, + "namespace": "default", }, }, }, @@ -132,9 +130,7 @@ func TestService_Generate(t *testing.T) { "app": "istiod", "istio": "pilot", }, - "namespace": common.MapStr{ - "name": "default", - }, + "namespace": "default", "deployment": common.MapStr{ "name": "owner", }, @@ -188,9 +184,7 @@ func TestService_GenerateFromName(t *testing.T) { "labels": common.MapStr{ "foo": "bar", }, - "namespace": common.MapStr{ - "name": "default", - }, + "namespace": "default", }, }, { @@ -227,9 +221,7 @@ func TestService_GenerateFromName(t *testing.T) { "labels": common.MapStr{ "foo": "bar", }, - "namespace": common.MapStr{ - "name": "default", - }, + "namespace": "default", "deployment": common.MapStr{ "name": "owner", }, @@ -303,12 +295,10 @@ func TestService_GenerateWithNamespace(t *testing.T) { "labels": common.MapStr{ "foo": "bar", }, - "namespace": common.MapStr{ - "name": "default", - "uid": uid, - "labels": common.MapStr{ - "nskey": "nsvalue", - }, + "namespace": "default", + "namespace_uid": uid, + "namespace_labels": common.MapStr{ + "nskey": "nsvalue", }, }, }, diff --git a/libbeat/common/kubernetes/types.go b/libbeat/common/kubernetes/types.go index 9f50e99b305..a1800671abf 100644 --- a/libbeat/common/kubernetes/types.go +++ b/libbeat/common/kubernetes/types.go @@ -76,6 +76,9 @@ type Service = v1.Service // Job data type Job = batchv1.Job +// CronJob data +type CronJob = batchv1.CronJob + const ( // PodPending phase PodPending = v1.PodPending @@ -94,6 +97,11 @@ func Time(t *metav1.Time) time.Time { return t.Time } +// MicroTime extracts time from k8s.MicroTime type +func MicroTime(t *metav1.MicroTime) time.Time { + return t.Time +} + // ContainerID parses the container ID to get the actual ID string func ContainerID(s PodContainerStatus) string { cID, _ := ContainerIDWithRuntime(s) diff --git a/libbeat/common/kubernetes/util.go b/libbeat/common/kubernetes/util.go index 3314a0dd9f0..b27f32a041f 100644 --- a/libbeat/common/kubernetes/util.go +++ b/libbeat/common/kubernetes/util.go @@ -24,6 +24,9 @@ import ( "os" "strings" + "github.com/elastic/beats/v7/libbeat/common" + "github.com/elastic/beats/v7/libbeat/common/safemapstr" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/kubernetes" restclient "k8s.io/client-go/rest" @@ -192,7 +195,7 @@ func discoverByMachineId(nd *DiscoverKubernetesNodeParams, ctx context.Context) return } -// GetMachineID returns the machine-id +// GetMachineID returns the machine-idadd_kubernetes_metadata/indexers_test.go // borrowed from machineID of cadvisor. func (hd *DefaultDiscoveryUtils) GetMachineID() string { for _, file := range []string{ @@ -226,3 +229,109 @@ func InClusterNamespace() (string, error) { } return strings.TrimSpace(string(data)), nil } + +type ContainerInPod struct { + ID string + Runtime string + Spec Container + Status PodContainerStatus +} + +// GetContainersInPod returns all the containers defined in a pod and their statuses. +// It includes init and ephemeral containers. +func GetContainersInPod(pod *Pod) []*ContainerInPod { + var containers []*ContainerInPod + for _, c := range pod.Spec.Containers { + containers = append(containers, &ContainerInPod{Spec: c}) + } + for _, c := range pod.Spec.InitContainers { + containers = append(containers, &ContainerInPod{Spec: c}) + } + for _, c := range pod.Spec.EphemeralContainers { + c := Container(c.EphemeralContainerCommon) + containers = append(containers, &ContainerInPod{Spec: c}) + } + + statuses := make(map[string]*PodContainerStatus) + mapStatuses := func(s []PodContainerStatus) { + for i := range s { + statuses[s[i].Name] = &s[i] + } + } + mapStatuses(pod.Status.ContainerStatuses) + mapStatuses(pod.Status.InitContainerStatuses) + mapStatuses(pod.Status.EphemeralContainerStatuses) + for _, c := range containers { + if s, ok := statuses[c.Spec.Name]; ok { + c.ID, c.Runtime = ContainerIDWithRuntime(*s) + c.Status = *s + } + } + + return containers +} + +// PodAnnotations returns the annotations in a pod +func PodAnnotations(pod *Pod) common.MapStr { + annotations := common.MapStr{} + for k, v := range pod.GetObjectMeta().GetAnnotations() { + safemapstr.Put(annotations, k, v) + } + return annotations +} + +// PodNamespaceAnnotations returns the annotations of the namespace of the pod +func PodNamespaceAnnotations(pod *Pod, watcher Watcher) common.MapStr { + if watcher == nil { + return nil + } + + rawNs, ok, err := watcher.Store().GetByKey(pod.Namespace) + if !ok || err != nil { + return nil + } + + namespace, ok := rawNs.(*Namespace) + if !ok { + return nil + } + + annotations := common.MapStr{} + for k, v := range namespace.GetAnnotations() { + safemapstr.Put(annotations, k, v) + } + return annotations +} + +// PodTerminating returns true if a pod is marked for deletion or is in a phase beyond running. +func PodTerminating(pod *Pod) bool { + if pod.GetObjectMeta().GetDeletionTimestamp() != nil { + return true + } + + switch pod.Status.Phase { + case PodRunning, PodPending: + default: + return true + } + + return false +} + +// PodTerminated returns true if a pod is terminated, this method considers a +// pod as terminated if none of its containers are running (or going to be running). +func PodTerminated(pod *Pod, containers []*ContainerInPod) bool { + // Pod is not marked for termination, so it is not terminated. + if !PodTerminating(pod) { + return false + } + + // If any container is running, the pod is not terminated yet. + for _, container := range containers { + if container.Status.State.Running != nil { + return false + } + } + + return true +} diff --git a/libbeat/common/kubernetes/util_test.go b/libbeat/common/kubernetes/util_test.go index 44fc9a04660..2a2ed77b682 100644 --- a/libbeat/common/kubernetes/util_test.go +++ b/libbeat/common/kubernetes/util_test.go @@ -73,7 +73,7 @@ func TestDiscoverKubernetesNode(t *testing.T) { namespace: "", }, { - name: "test value with not incluster, machine id not retrieved, env var not set", + name: "test value with not incluster, machine ID not retrieved, env var not set", host: "", node: "", err: ge, @@ -130,7 +130,7 @@ func TestDiscoverKubernetesNode(t *testing.T) { init: createResources, }, { - name: "test value without inCluster, machine-id empty and env var not set", + name: "test value without inCluster, machine-ID empty and env var not set", host: "", isInCluster: false, node: "", @@ -141,7 +141,7 @@ func TestDiscoverKubernetesNode(t *testing.T) { namespace: "", }, { - name: "test value without inCluster, machine-id set, node not found and env var not set", + name: "test value without inCluster, machine-ID set, node not found and env var not set", host: "", isInCluster: false, node: "", @@ -152,7 +152,7 @@ func TestDiscoverKubernetesNode(t *testing.T) { namespace: "", }, { - name: "test value without inCluster, machine-id set, node found and env var not set", + name: "test value without inCluster, machine-ID set, node found and env var not set", host: "", isInCluster: false, node: "worker-2", @@ -164,7 +164,7 @@ func TestDiscoverKubernetesNode(t *testing.T) { init: createResources, }, { - name: "test value without inCluster, machine-id set, node not found and env var set", + name: "test value without inCluster, machine-ID set, node not found and env var set", host: "", isInCluster: false, node: "worker-2", diff --git a/libbeat/common/kubernetes/watcher.go b/libbeat/common/kubernetes/watcher.go index b96b837e4e3..75f32f66d66 100644 --- a/libbeat/common/kubernetes/watcher.go +++ b/libbeat/common/kubernetes/watcher.go @@ -99,9 +99,9 @@ func NewWatcher(client kubernetes.Interface, resource Resource, opts WatchOption return NewNamedWatcher("", client, resource, opts, indexers) } -// NewNamedWatcher does the same as NewWatcher, but also allows to name the k8s -// client's workqueue that is used by the watcher, unlike NewWatcher which sets -// the workqueue name to "". Workqueue name is important for exposing workqueue +// NewNamedWatcher initializes the watcher client to provide an events handler for +// resource from the cluster (filtered to the given node) and also allows to name the k8s +// client's workqueue that is used by the watcher. Workqueue name is important for exposing workqueue // metrics, if it is empty, its metrics will not be logged by the k8s client. func NewNamedWatcher(name string, client kubernetes.Interface, resource Resource, opts WatchOptions, indexers cache.Indexers) (Watcher, error) { var store cache.Store diff --git a/libbeat/common/seccomp/seccomp-profiler-allow.txt b/libbeat/common/seccomp/seccomp-profiler-allow.txt index a166cf6f7da..e22f3db0eef 100644 --- a/libbeat/common/seccomp/seccomp-profiler-allow.txt +++ b/libbeat/common/seccomp/seccomp-profiler-allow.txt @@ -9,7 +9,7 @@ access open stat -# cgo tsg/gopacket +# cgo google/gopacket poll fcntl64 diff --git a/libbeat/common/transport/tlscommon/config.go b/libbeat/common/transport/tlscommon/config.go index 41d1ad6532c..0bb2e35c20c 100644 --- a/libbeat/common/transport/tlscommon/config.go +++ b/libbeat/common/transport/tlscommon/config.go @@ -30,15 +30,16 @@ var warnOnce sync.Once // Config defines the user configurable options in the yaml file. type Config struct { - Enabled *bool `config:"enabled" yaml:"enabled,omitempty"` - VerificationMode TLSVerificationMode `config:"verification_mode" yaml:"verification_mode"` // one of 'none', 'full' - Versions []TLSVersion `config:"supported_protocols" yaml:"supported_protocols,omitempty"` - CipherSuites []CipherSuite `config:"cipher_suites" yaml:"cipher_suites,omitempty"` - CAs []string `config:"certificate_authorities" yaml:"certificate_authorities,omitempty"` - Certificate CertificateConfig `config:",inline" yaml:",inline"` - CurveTypes []tlsCurveType `config:"curve_types" yaml:"curve_types,omitempty"` - Renegotiation TlsRenegotiationSupport `config:"renegotiation" yaml:"renegotiation"` - CASha256 []string `config:"ca_sha256" yaml:"ca_sha256,omitempty"` + Enabled *bool `config:"enabled" yaml:"enabled,omitempty"` + VerificationMode TLSVerificationMode `config:"verification_mode" yaml:"verification_mode"` // one of 'none', 'full' + Versions []TLSVersion `config:"supported_protocols" yaml:"supported_protocols,omitempty"` + CipherSuites []CipherSuite `config:"cipher_suites" yaml:"cipher_suites,omitempty"` + CAs []string `config:"certificate_authorities" yaml:"certificate_authorities,omitempty"` + Certificate CertificateConfig `config:",inline" yaml:",inline"` + CurveTypes []tlsCurveType `config:"curve_types" yaml:"curve_types,omitempty"` + Renegotiation TlsRenegotiationSupport `config:"renegotiation" yaml:"renegotiation"` + CASha256 []string `config:"ca_sha256" yaml:"ca_sha256,omitempty"` + CATrustedFingerprint string `config:"ca_trusted_fingerprint" yaml:"ca_trusted_fingerprint,omitempty"` } // LoadTLSConfig will load a certificate from config with all TLS based keys @@ -82,14 +83,15 @@ func LoadTLSConfig(config *Config) (*TLSConfig, error) { // return config if no error occurred return &TLSConfig{ - Versions: config.Versions, - Verification: config.VerificationMode, - Certificates: certs, - RootCAs: cas, - CipherSuites: config.CipherSuites, - CurvePreferences: curves, - Renegotiation: tls.RenegotiationSupport(config.Renegotiation), - CASha256: config.CASha256, + Versions: config.Versions, + Verification: config.VerificationMode, + Certificates: certs, + RootCAs: cas, + CipherSuites: config.CipherSuites, + CurvePreferences: curves, + Renegotiation: tls.RenegotiationSupport(config.Renegotiation), + CASha256: config.CASha256, + CATrustedFingerprint: config.CATrustedFingerprint, }, nil } diff --git a/libbeat/common/transport/tlscommon/testdata/es-leaf.crt b/libbeat/common/transport/tlscommon/testdata/es-leaf.crt new file mode 100644 index 00000000000..89d5087eb94 --- /dev/null +++ b/libbeat/common/transport/tlscommon/testdata/es-leaf.crt @@ -0,0 +1,32 @@ +-----BEGIN CERTIFICATE----- +MIIFeDCCA2CgAwIBAgIUV7+XlHjcV++/ezqTkJrXSFc1dpAwDQYJKoZIhvcNAQEL +BQAwPDE6MDgGA1UEAxMxRWxhc3RpY3NlYXJjaCBzZWN1cml0eSBhdXRvLWNvbmZp +Z3VyYXRpb24gSFRUUCBDQTAeFw0yMTExMzAxMDMzNTdaFw0yMzExMzAxMDMzNTda +MBExDzANBgNVBAMTBngtd2luZzCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoC +ggIBALL045X6ywAHg9tWuViNyXu30rHhJa/AI45ZwLWzQMEwnCWnMvV0Cy3FgUd6 +VKw4Rg55/SfBKShhTRjC4PmDIHDIBgpm4NWpREIW2+cZfeEU8B34ucK/ZHycTFQ1 +Guh8HfvFy5J3OYT+8Wfz94ZxvVLMOGROTSiWdL2foVk98tbHgL1K3qyv1v0rgIjt +smZ7G4tbl3sBCuYceUL7X/+0kavJGls2T/rtxxEIfj5dNz4h65KmABrrAJfrEx35 +y2jCdY2XQsBxxMvbHEXXJKhrjQ8pajMcWAlDBKweiNIDdgBDYWpodpr4f3A6ZJkM +Nplw7KyLna4s3BO/g7fd5/FyQGFuLPraFtFnTXGqH+LjX0td74bdSP22/uhU3cKY +3y64I3/HEaEY5JITgUArExcMVpXuKJKqXEb+LtjGmUbAiO8Z7QKL+PqmU+3tJJ0p +kXnS07m3F/MgrDir/VCnYGQcXeteBwEgmcOwPmxz98eOSBhtb0PrimycF2tQuT8b +mCU+evTPC+KQ+8XY5vBwdPGpf6YAaHuVhNtKqBQnYOpsadS7zw5DJ0Y1Kp9z0ZPL +ch4DxE40xqAFmxWnAfpy2scD8LGJ1zDII90tAtYdu+3Wlzj6uMqUdqPuJED7XD41 +mlF2OjB5ipTs/1Jjl3pEnGG94sw5bQmnS1xFQp/DO3mjlgFBAgMBAAGjgZwwgZkw +HQYDVR0OBBYEFJKNxskBHE5xQ9S24puXSKm6/bLKMB8GA1UdIwQYMBaAFHEdsBBS +VCiK0fDIVe2vNN8JvHmcMEwGA1UdEQRFMEOHEP6AAAAAAAAAtw+3JU5DX8mCCWxv +Y2FsaG9zdIcQAAAAAAAAAAAAAAAAAAAAAYcEfwAAAYcEwKgqtoIGeC13aW5nMAkG +A1UdEwQCMAAwDQYJKoZIhvcNAQELBQADggIBAF5JAIQ9cu2xroh2F85fBr/F0s8D +aRV6AJpkjSVKInMm7omn+GLB80TwQZ6NsGuXrbaq0rcM85khsBs4rWn5MqescYG/ +8A7gZ4EtYE3LIyeqiqBByrtIqszZeXm7ITDSF/lwn7X2swe7orkhVD4tVEvKH6L6 +Ql0oNe5UBN1Rm9NskDltMDzE2A25slkm99CAdPERDEjBpvd3eDcfbQdHeuAOPfUV +T8P2DAdW4SC955bxnc0GPTla5TKXWWLde3egow5a4LeJv6KVWPTC9chEXZyQKp4p +jvWZW1fTO/kC3oj97tfqoH/r35/+qyXmg38HNAFbEoVM3bsO0vqrI5CbkWTkB1Xb +7CY6jJxemyEprl2gmkgfA/MXBHFc3RoIL7JcX7Sk8ZWpnEVK3KyoyK1RJ5kY1Cz4 +SRw4KLJA4Cu6DE7vXy9pTlIeeQARgQOUxnrlRGYHpKRIwgjrhwEjVqc0CPwj7rWr +0VY4MW80FPFIePpqy3DjoJmORQU632iu/5zeUS4dZ11Ms7NTakqqnFHi7XczqeZn +4HqPW8ebQTXrqRXMF/X30x6gkK1R1tXHSbve7cTQWJEwJd+MS2aA5Npt7hGznjPn +Y1p4k9jEz5BnbLtZ2RbAj2FuL4Ee6iJoyZpFbi/SW+h+1ZaPCeUTnxUkDLEiXpdk +tN8H6/6dudhy6btm +-----END CERTIFICATE----- diff --git a/libbeat/common/transport/tlscommon/testdata/es-root-ca-cert.crt b/libbeat/common/transport/tlscommon/testdata/es-root-ca-cert.crt new file mode 100644 index 00000000000..6234774adc9 --- /dev/null +++ b/libbeat/common/transport/tlscommon/testdata/es-root-ca-cert.crt @@ -0,0 +1,31 @@ +-----BEGIN CERTIFICATE----- +MIIFWTCCA0GgAwIBAgIUAoPlJ3hVr921EyJfiT+9lVft3fcwDQYJKoZIhvcNAQEL +BQAwPDE6MDgGA1UEAxMxRWxhc3RpY3NlYXJjaCBzZWN1cml0eSBhdXRvLWNvbmZp +Z3VyYXRpb24gSFRUUCBDQTAeFw0yMTExMzAxMDMzNTdaFw0yNDExMjkxMDMzNTda +MDwxOjA4BgNVBAMTMUVsYXN0aWNzZWFyY2ggc2VjdXJpdHkgYXV0by1jb25maWd1 +cmF0aW9uIEhUVFAgQ0EwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC2 +soq+heCJNHsMuyyyLndREhYmxYFav06XOLB5oC1bAt+0WMo3n7rxVB8dAhfvigof +DsTIytnCcK+Th8ll2k4Bs2weF16ZhvvC2FKbSkdUxNXnXfx7gdKDXZLbfref5FiL +ucwxa7CtVL28Lfws9J5dZTTAuxR2XxaX+TJbH6MbQgKUYR+DnK8T3jSfiDTQtiHs ++pd+C8hSdMgzKCynYP36VZbtz1ynWjvQ/0wxARO6q2OLZGBNh2ncoFEmosXgc0ir +Vh9NrVmozSI0H2f6W07imqL3oe1pe3bwW/OdfeahCBY3IvDLDn8q8wDl91gRta3n +EsMsiuBRSRRpT0grgoCFNy+wiIrETVLaI2HJ0UpVIpcoS7K5l2zN/wA+w+hAOdh0 +PoBt8AoC1aCCGM4osCTKqbgbOg957io2twuvWJ6ae3J2k5FFDMvIfMfL+5HhPSRp +nYiRDPOhapDhaXhHa4pEFONpdiJJgmqymLqjW4liZOGft28dSkISK3iiBL74p/gu +X/sBI7PZANycpyVjnLHK+FwPlRZPkrqCw2Gke4Oqm9uydwM08uRVZcNylVS7H0ip +9BEcxKlXJSaULnTqQXkiPGKGkCrrIIsNQTFjoaBIBP2o69NSZ0SozDf4aCnYy10v +U1dwI9yisOmMfDkakNcAPXfRfmuuJlstl1W1RraQswIDAQABo1MwUTAdBgNVHQ4E +FgQUcR2wEFJUKIrR8MhV7a803wm8eZwwHwYDVR0jBBgwFoAUcR2wEFJUKIrR8MhV +7a803wm8eZwwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAgEAiHrC +NxCNsyUYLFVivL9AsJ5Y3IrhAHUzYwofLBJiMYNFsaEi3P1VU3TNlo98kzi2QkdY +NPFtRYoOg6sEI0KPEBw54kLP/Q/FJK7jeJSyhJ9V/Z+NS081YHqrMP4YPK6mM4qa +XuM7hpx37vkLDdfrDPionbcLk7Zz+2t6bIThrwta0idMY6LKeFfW1EWeggK6inNc +Ub3n1qcTyOp1RfcLlHCdb17JhgY5hROmqVfhgLlbT0bx1NZS4pRWhw5CDKsflMUe +SyHbLE1BTH6yE0nNXbR6FgDKjQNUSSZBOBck0hdSaRArALavujjBojHmJYWt1jWO +bcBErzwKKwH/peUh7Wgnq1L/lqym9K9AniWUyhvKn8AbxGLnILDMYOSrvlPF2uU+ +uvp2EzhPUyOgYycC28H4fFUdDeoN5FVP+4sFFK+FIgfqLfVMTgDPmGAbkqA6WKlH +fgQ2fP4oB2ZkN0EPxivXkvZkhDVlIXeoisUkNCgAfVuwCjvOLnqz8u0tTnp/wXxq +XAXUPLcG71YFzABlkwuPdA5GhFAL1Rv8GQJEznhZ8mYz/yTtcg/z3pYEhDcM92Cb +161BormFYVRI1B80rSpzeQwJVfvgCwnWOTat+1joFHCzpl99nHu8tMxi6lkO1G9E +8vdk/J0zMMnhO52V2EMNdH2fTJUMZYixBm4BeEM= +-----END CERTIFICATE----- diff --git a/libbeat/common/transport/tlscommon/tls_config.go b/libbeat/common/transport/tlscommon/tls_config.go index 77c60f951f8..64fcf62e47d 100644 --- a/libbeat/common/transport/tlscommon/tls_config.go +++ b/libbeat/common/transport/tlscommon/tls_config.go @@ -18,8 +18,11 @@ package tlscommon import ( + "bytes" + "crypto/sha256" "crypto/tls" "crypto/x509" + "encoding/hex" "fmt" "net" "time" @@ -74,6 +77,10 @@ type TLSConfig struct { // the server certificate. CASha256 []string + // CATrustedFingerprint is the HEX encoded fingerprint of a CA certificate. If present in the chain + // this certificate will be added to the list of trusted CAs (RootCAs) during the handshake. + CATrustedFingerprint string + // time returns the current time as the number of seconds since the epoch. // If time is nil, TLS uses time.Now. time func() time.Time @@ -151,10 +158,45 @@ func (c *TLSConfig) BuildServerConfig(host string) *tls.Config { return config } +func trustRootCA(cfg *TLSConfig, peerCerts []*x509.Certificate) error { + logger := logp.NewLogger("tls") + logger.Info("'ca_trusted_fingerprint' set, looking for matching fingerprints") + fingerprint, err := hex.DecodeString(cfg.CATrustedFingerprint) + if err != nil { + return fmt.Errorf("decode 'ca_trusted_fingerprint': %w", err) + } + + for _, cert := range peerCerts { + // Compute digest for each certificate. + digest := sha256.Sum256(cert.Raw) + + if bytes.Equal(digest[0:], fingerprint) { + logger.Info("CA certificate matching 'ca_trusted_fingerprint' found, adding it to 'certificate_authorities'") + // Make sure the fingerprint matches a CA certificate + if cert.IsCA { + if cfg.RootCAs == nil { + cfg.RootCAs = x509.NewCertPool() + } + + cfg.RootCAs.AddCert(cert) + return nil + } + } + } + + logger.Warn("no CA certificate matching the fingerprint") + return nil +} + func makeVerifyConnection(cfg *TLSConfig) func(tls.ConnectionState) error { switch cfg.Verification { case VerifyFull: return func(cs tls.ConnectionState) error { + if cfg.CATrustedFingerprint != "" { + if err := trustRootCA(cfg, cs.PeerCertificates); err != nil { + return err + } + } // On the client side, PeerCertificates can't be empty. if len(cs.PeerCertificates) == 0 { return MissingPeerCertificate @@ -172,6 +214,11 @@ func makeVerifyConnection(cfg *TLSConfig) func(tls.ConnectionState) error { } case VerifyCertificate: return func(cs tls.ConnectionState) error { + if cfg.CATrustedFingerprint != "" { + if err := trustRootCA(cfg, cs.PeerCertificates); err != nil { + return err + } + } // On the client side, PeerCertificates can't be empty. if len(cs.PeerCertificates) == 0 { return MissingPeerCertificate @@ -186,6 +233,11 @@ func makeVerifyConnection(cfg *TLSConfig) func(tls.ConnectionState) error { case VerifyStrict: if len(cfg.CASha256) > 0 { return func(cs tls.ConnectionState) error { + if cfg.CATrustedFingerprint != "" { + if err := trustRootCA(cfg, cs.PeerCertificates); err != nil { + return err + } + } return verifyCAPin(cfg.CASha256, cs.VerifiedChains) } } @@ -193,7 +245,6 @@ func makeVerifyConnection(cfg *TLSConfig) func(tls.ConnectionState) error { } return nil - } func makeVerifyServerConnection(cfg *TLSConfig) func(tls.ConnectionState) error { diff --git a/libbeat/common/transport/tlscommon/tls_config_test.go b/libbeat/common/transport/tlscommon/tls_config_test.go index 76dfa61497f..2fd0b76e2a0 100644 --- a/libbeat/common/transport/tlscommon/tls_config_test.go +++ b/libbeat/common/transport/tlscommon/tls_config_test.go @@ -26,13 +26,11 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestMakeVerifyServerConnection(t *testing.T) { - testCerts, err := openTestCerts() - if err != nil { - t.Fatalf("failed to open test certs: %+v", err) - } + testCerts := openTestCerts(t) testCA, errs := LoadCertificateAuthorities([]string{ filepath.Join("testdata", "ca.crt"), @@ -159,7 +157,6 @@ func TestMakeVerifyServerConnection(t *testing.T) { for name, test := range testcases { t.Run(name, func(t *testing.T) { - test := test cfg := &TLSConfig{ Verification: test.verificationMode, ClientAuth: test.clientAuth, @@ -177,16 +174,20 @@ func TestMakeVerifyServerConnection(t *testing.T) { ServerName: test.serverName, }) if test.expectedError == nil { - assert.Nil(t, err) + assert.NoError(t, err) } else { - assert.Error(t, test.expectedError, err) + require.Error(t, err) + // We want to ensure the error type/message are the expected ones + // so we compare the types and the message + assert.IsType(t, test.expectedError, err) + assert.Contains(t, err.Error(), test.expectedError.Error()) } }) } - } -func openTestCerts() (map[string]*x509.Certificate, error) { +func openTestCerts(t testing.TB) map[string]*x509.Certificate { + t.Helper() certs := make(map[string]*x509.Certificate, 0) for testcase, certname := range map[string]string{ @@ -194,19 +195,190 @@ func openTestCerts() (map[string]*x509.Certificate, error) { "unknown authority": "unsigned_tls.crt", "correct": "client1.crt", "wildcard": "server.crt", + "es-leaf": "es-leaf.crt", + "es-root-ca": "es-root-ca-cert.crt", } { certBytes, err := ioutil.ReadFile(filepath.Join("testdata", certname)) if err != nil { - return nil, err + t.Fatalf("reading file %q: %+v", certname, err) } block, _ := pem.Decode(certBytes) testCert, err := x509.ParseCertificate(block.Bytes) if err != nil { - return nil, err + t.Fatalf("parsing certificate %q: %+v", certname, err) } certs[testcase] = testCert } - return certs, nil + return certs +} + +func TestTrustRootCA(t *testing.T) { + certs := openTestCerts(t) + + nonEmptyCertPool := x509.NewCertPool() + nonEmptyCertPool.AddCert(certs["wildcard"]) + nonEmptyCertPool.AddCert(certs["unknown authority"]) + + testCases := []struct { + name string + rootCAs *x509.CertPool + caTrustedFingerprint string + peerCerts []*x509.Certificate + expectingError bool + expectedRootCAsLen int + }{ + { + name: "RootCA cert matches the fingerprint and is added to cfg.RootCAs", + caTrustedFingerprint: "e83171aa133b2b507e057fe091e296a7e58e9653c2b88d203b64a47eef6ec62b", + peerCerts: []*x509.Certificate{certs["es-leaf"], certs["es-root-ca"]}, + expectedRootCAsLen: 1, + }, + { + name: "RootCA cert doesn not matche the fingerprint and is not added to cfg.RootCAs", + caTrustedFingerprint: "e83171aa133b2b507e057fe091e296a7e58e9653c2b88d203b64a47eef6ec62b", + peerCerts: []*x509.Certificate{certs["es-leaf"], certs["es-root-ca"]}, + expectedRootCAsLen: 0, + }, + { + name: "non empty CertPool has the RootCA added", + rootCAs: nonEmptyCertPool, + caTrustedFingerprint: "e83171aa133b2b507e057fe091e296a7e58e9653c2b88d203b64a47eef6ec62b", + peerCerts: []*x509.Certificate{certs["es-leaf"], certs["es-root-ca"]}, + expectedRootCAsLen: 3, + }, + { + name: "invalis HEX encoding", + caTrustedFingerprint: "INVALID ENCODING", + expectedRootCAsLen: 0, + expectingError: true, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + cfg := TLSConfig{ + RootCAs: tc.rootCAs, + CATrustedFingerprint: tc.caTrustedFingerprint, + } + err := trustRootCA(&cfg, tc.peerCerts) + if tc.expectingError && err == nil { + t.Fatal("expecting an error when calling trustRootCA") + } + + if !tc.expectingError && err != nil { + t.Fatalf("did not expect an error calling trustRootCA: %v", err) + } + + if tc.expectedRootCAsLen != 0 { + if cfg.RootCAs == nil { + t.Fatal("cfg.RootCAs cannot be nil") + } + + // we want to know the number of certificates in the CertPool (RootCAs), as it is not + // directly available, we use this workaround of reading the number of subjects in the pool. + if got, expected := len(cfg.RootCAs.Subjects()), tc.expectedRootCAsLen; got != expected { + t.Fatalf("expecting cfg.RootCAs to have %d element, got %d instead", expected, got) + } + } + }) + } +} + +func TestMakeVerifyConnectionUsesCATrustedFingerprint(t *testing.T) { + testCerts := openTestCerts(t) + + testcases := map[string]struct { + verificationMode TLSVerificationMode + peerCerts []*x509.Certificate + serverName string + expectedCallback bool + expectingError bool + CATrustedFingerprint string + CASHA256 []string + }{ + "CATrustedFingerprint and verification mode:VerifyFull": { + verificationMode: VerifyFull, + peerCerts: []*x509.Certificate{testCerts["es-leaf"], testCerts["es-root-ca"]}, + serverName: "localhost", + expectedCallback: true, + CATrustedFingerprint: "e83171aa133b2b507e057fe091e296a7e58e9653c2b88d203b64a47eef6ec62b", + }, + "CATrustedFingerprint and verification mode:VerifyCertificate": { + verificationMode: VerifyCertificate, + peerCerts: []*x509.Certificate{testCerts["es-leaf"], testCerts["es-root-ca"]}, + serverName: "localhost", + expectedCallback: true, + CATrustedFingerprint: "e83171aa133b2b507e057fe091e296a7e58e9653c2b88d203b64a47eef6ec62b", + }, + "CATrustedFingerprint and verification mode:VerifyStrict": { + verificationMode: VerifyStrict, + peerCerts: []*x509.Certificate{testCerts["es-leaf"], testCerts["es-root-ca"]}, + serverName: "localhost", + expectedCallback: true, + CATrustedFingerprint: "e83171aa133b2b507e057fe091e296a7e58e9653c2b88d203b64a47eef6ec62b", + CASHA256: []string{Fingerprint(testCerts["es-leaf"])}, + }, + "CATrustedFingerprint and verification mode:VerifyNone": { + verificationMode: VerifyNone, + peerCerts: []*x509.Certificate{testCerts["es-leaf"], testCerts["es-root-ca"]}, + serverName: "localhost", + expectedCallback: false, + }, + "invalid CATrustedFingerprint and verification mode:VerifyFull returns error": { + verificationMode: VerifyFull, + peerCerts: []*x509.Certificate{testCerts["es-leaf"], testCerts["es-root-ca"]}, + serverName: "localhost", + expectedCallback: true, + CATrustedFingerprint: "INVALID HEX ENCODING", + expectingError: true, + }, + "invalid CATrustedFingerprint and verification mode:VerifyCertificate returns error": { + verificationMode: VerifyCertificate, + peerCerts: []*x509.Certificate{testCerts["es-leaf"], testCerts["es-root-ca"]}, + serverName: "localhost", + expectedCallback: true, + CATrustedFingerprint: "INVALID HEX ENCODING", + expectingError: true, + }, + "invalid CATrustedFingerprint and verification mode:VerifyStrict returns error": { + verificationMode: VerifyStrict, + peerCerts: []*x509.Certificate{testCerts["es-leaf"], testCerts["es-root-ca"]}, + serverName: "localhost", + expectedCallback: true, + CATrustedFingerprint: "INVALID HEX ENCODING", + expectingError: true, + CASHA256: []string{Fingerprint(testCerts["es-leaf"])}, + }, + } + + for name, test := range testcases { + t.Run(name, func(t *testing.T) { + cfg := &TLSConfig{ + Verification: test.verificationMode, + CATrustedFingerprint: test.CATrustedFingerprint, + CASha256: test.CASHA256, + } + + verifier := makeVerifyConnection(cfg) + if test.expectedCallback { + require.NotNil(t, verifier, "makeVerifyConnection returned a nil verifier") + } else { + require.Nil(t, verifier) + return + } + + err := verifier(tls.ConnectionState{ + PeerCertificates: test.peerCerts, + ServerName: test.serverName, + VerifiedChains: [][]*x509.Certificate{test.peerCerts}, + }) + if test.expectingError { + assert.Error(t, err) + } else { + assert.NoError(t, err) + } + }) + } } diff --git a/libbeat/common/useragent/useragent.go b/libbeat/common/useragent/useragent.go index fdff31c2dc1..a60533982ee 100644 --- a/libbeat/common/useragent/useragent.go +++ b/libbeat/common/useragent/useragent.go @@ -18,17 +18,30 @@ package useragent import ( - "fmt" "runtime" + "strings" "github.com/elastic/beats/v7/libbeat/version" ) // UserAgent takes the capitalized name of the current beat and returns // an RFC compliant user agent string for that beat. -func UserAgent(beatNameCapitalized string) string { - return fmt.Sprintf("Elastic-%s/%s (%s; %s; %s; %s)", - beatNameCapitalized, - version.GetDefaultVersion(), runtime.GOOS, runtime.GOARCH, - version.Commit(), version.BuildTime()) +func UserAgent(beatNameCapitalized string, additionalComments ...string) string { + var builder strings.Builder + builder.WriteString("Elastic-" + beatNameCapitalized + "/" + version.GetDefaultVersion() + " ") + uaValues := []string{ + runtime.GOOS, + runtime.GOARCH, + version.Commit(), + version.BuildTime().String(), + } + for _, val := range additionalComments { + if val != "" { + uaValues = append(uaValues, val) + } + } + builder.WriteByte('(') + builder.WriteString(strings.Join(uaValues, "; ")) + builder.WriteByte(')') + return builder.String() } diff --git a/libbeat/common/useragent/useragent_test.go b/libbeat/common/useragent/useragent_test.go index d55f20dde4b..9ca1951059f 100644 --- a/libbeat/common/useragent/useragent_test.go +++ b/libbeat/common/useragent/useragent_test.go @@ -27,4 +27,7 @@ import ( func TestUserAgent(t *testing.T) { ua := UserAgent("FakeBeat") assert.Regexp(t, regexp.MustCompile("^Elastic-FakeBeat"), ua) + + ua2 := UserAgent("FakeBeat", "integration_name/1.2.3") + assert.Regexp(t, regexp.MustCompile("; integration_name\\/1\\.2\\.3\\)$"), ua2) } diff --git a/libbeat/dashboards/modify_json.go b/libbeat/dashboards/modify_json.go index 204413280bb..2545e1fe02e 100644 --- a/libbeat/dashboards/modify_json.go +++ b/libbeat/dashboards/modify_json.go @@ -23,8 +23,6 @@ import ( "fmt" "regexp" - "github.com/pkg/errors" - "github.com/elastic/beats/v7/libbeat/common" "github.com/elastic/beats/v7/libbeat/logp" ) @@ -53,44 +51,14 @@ func ReplaceIndexInIndexPattern(index string, content common.MapStr) (err error) return nil } - list, ok := content["objects"] - if !ok { - return errors.New("empty index pattern") - } - - updateObject := func(obj common.MapStr) { - // This uses Put instead of DeepUpdate to avoid modifying types for - // inner objects. (DeepUpdate will replace maps with MapStr). - obj.Put("id", index) - // Only overwrite title if it exists. - if _, err := obj.GetValue("attributes.title"); err == nil { - obj.Put("attributes.title", index) - } + // This uses Put instead of DeepUpdate to avoid modifying types for + // inner objects. (DeepUpdate will replace maps with MapStr). + content.Put("id", index) + // Only overwrite title if it exists. + if _, err := content.GetValue("attributes.title"); err == nil { + content.Put("attributes.title", index) } - switch v := list.(type) { - case []interface{}: - for _, objIf := range v { - switch obj := objIf.(type) { - case common.MapStr: - updateObject(obj) - case map[string]interface{}: - updateObject(obj) - default: - return errors.Errorf("index pattern object has unexpected type %T", v) - } - } - case []map[string]interface{}: - for _, obj := range v { - updateObject(obj) - } - case []common.MapStr: - for _, obj := range v { - updateObject(obj) - } - default: - return errors.Errorf("index pattern objects have unexpected type %T", v) - } return nil } diff --git a/libbeat/dashboards/modify_json_test.go b/libbeat/dashboards/modify_json_test.go index 389e8b416a7..7981dac8c57 100644 --- a/libbeat/dashboards/modify_json_test.go +++ b/libbeat/dashboards/modify_json_test.go @@ -124,118 +124,68 @@ func TestReplaceIndexInIndexPattern(t *testing.T) { index string expected common.MapStr }{ - { - title: "Replace in []interface(map).map", - input: common.MapStr{"objects": []interface{}{map[string]interface{}{ - "id": "phonybeat-*", - "type": "index-pattern", - "attributes": map[string]interface{}{ - "title": "phonybeat-*", - "timeFieldName": "@timestamp", - }}}}, - index: "otherindex-*", - expected: common.MapStr{"objects": []interface{}{map[string]interface{}{ - "id": "otherindex-*", - "type": "index-pattern", - "attributes": map[string]interface{}{ - "title": "otherindex-*", - "timeFieldName": "@timestamp", - }}}}, - }, - { - title: "Replace in []interface(map).mapstr", - input: common.MapStr{"objects": []interface{}{map[string]interface{}{ - "id": "phonybeat-*", - "type": "index-pattern", - "attributes": common.MapStr{ - "title": "phonybeat-*", - "timeFieldName": "@timestamp", - }}}}, - index: "otherindex-*", - expected: common.MapStr{"objects": []interface{}{map[string]interface{}{ - "id": "otherindex-*", - "type": "index-pattern", - "attributes": common.MapStr{ - "title": "otherindex-*", - "timeFieldName": "@timestamp", - }}}}, - }, - { - title: "Replace in []map.mapstr", - input: common.MapStr{"objects": []map[string]interface{}{{ - "id": "phonybeat-*", - "type": "index-pattern", - "attributes": common.MapStr{ - "title": "phonybeat-*", - "timeFieldName": "@timestamp", - }}}}, - index: "otherindex-*", - expected: common.MapStr{"objects": []map[string]interface{}{{ - "id": "otherindex-*", - "type": "index-pattern", - "attributes": common.MapStr{ - "title": "otherindex-*", - "timeFieldName": "@timestamp", - }}}}, - }, { title: "Replace in []mapstr.mapstr", - input: common.MapStr{"objects": []common.MapStr{{ + input: common.MapStr{ "id": "phonybeat-*", "type": "index-pattern", "attributes": common.MapStr{ "title": "phonybeat-*", "timeFieldName": "@timestamp", - }}}}, + }}, index: "otherindex-*", - expected: common.MapStr{"objects": []common.MapStr{{ + expected: common.MapStr{ "id": "otherindex-*", "type": "index-pattern", "attributes": common.MapStr{ "title": "otherindex-*", "timeFieldName": "@timestamp", - }}}}, + }}, }, { title: "Replace in []mapstr.interface(mapstr)", - input: common.MapStr{"objects": []common.MapStr{{ + input: common.MapStr{ "id": "phonybeat-*", "type": "index-pattern", "attributes": interface{}(common.MapStr{ "title": "phonybeat-*", "timeFieldName": "@timestamp", - })}}}, + })}, index: "otherindex-*", - expected: common.MapStr{"objects": []common.MapStr{{ + expected: common.MapStr{ "id": "otherindex-*", "type": "index-pattern", "attributes": interface{}(common.MapStr{ "title": "otherindex-*", "timeFieldName": "@timestamp", - })}}}, + })}, }, { title: "Do not create missing attributes", - input: common.MapStr{"objects": []common.MapStr{{ - "id": "phonybeat-*", - "type": "index-pattern", - }}}, + input: common.MapStr{ + "attributes": common.MapStr{}, + "id": "phonybeat-*", + "type": "index-pattern", + }, index: "otherindex-*", - expected: common.MapStr{"objects": []common.MapStr{{ - "id": "otherindex-*", - "type": "index-pattern", - }}}, + expected: common.MapStr{ + "attributes": common.MapStr{}, + "id": "otherindex-*", + "type": "index-pattern", + }, }, { title: "Create missing id", - input: common.MapStr{"objects": []common.MapStr{{ - "type": "index-pattern", - }}}, + input: common.MapStr{ + "attributes": common.MapStr{}, + "type": "index-pattern", + }, index: "otherindex-*", - expected: common.MapStr{"objects": []common.MapStr{{ - "id": "otherindex-*", - "type": "index-pattern", - }}}, + expected: common.MapStr{ + "attributes": common.MapStr{}, + "id": "otherindex-*", + "type": "index-pattern", + }, }, } diff --git a/libbeat/docs/command-reference.asciidoc b/libbeat/docs/command-reference.asciidoc index 833f698682d..eddee911d7f 100644 --- a/libbeat/docs/command-reference.asciidoc +++ b/libbeat/docs/command-reference.asciidoc @@ -19,6 +19,7 @@ :apikey-command-short-desc: Manage API Keys for communication between APM agents and server. +ifndef::export_pipeline[] ifndef::serverless[] ifndef::no_dashboards[] :export-command-short-desc: Exports the configuration, index template, ILM policy, or a dashboard to stdout @@ -32,6 +33,11 @@ endif::serverless[] ifdef::serverless[] :export-command-short-desc: Exports the configuration, index template, or {cloudformation-ref} template to stdout endif::serverless[] +endif::export_pipeline[] + +ifdef::export_pipeline[] +:export-command-short-desc: Exports the configuration, index template, pipeline, or ILM policy to stdout +endif::export_pipeline[] :help-command-short-desc: Shows help for any command :keystore-command-short-desc: Manages the <> @@ -262,6 +268,7 @@ endif::[] [[export-command]] ==== `export` command +ifndef::export_pipeline[] ifndef::serverless[] ifndef::no_dashboards[] {export-command-short-desc}. You can use this @@ -281,6 +288,14 @@ ifdef::serverless[] command to quickly view your configuration, see the contents of the index template and the ILM policy, or export an CloudFormation template. endif::serverless[] +endif::export_pipeline[] + +ifdef::export_pipeline[] +{export-command-short-desc}. You can use this +command to quickly view your configuration, see the contents of the index +template and the ILM policy, export a dashboard from {kib}, or export ingest +pipelines. +endif::export_pipeline[] *SYNOPSIS* @@ -336,6 +351,14 @@ ifdef::serverless[] Exports an {cloudformation-ref} template to stdout. endif::serverless[] +ifdef::export_pipeline[] +[[pipeline-subcommand]] +*`pipeline`*:: +Exports the ingest piplines. You must specify the `--es.version` to which +the pipelines should be exported. You can optionally specify `--dir` to control +where the pipelines are written. +endif::export_pipeline[] + *FLAGS* *`--es.version VERSION`*:: @@ -706,7 +729,8 @@ endif::[] *`--system.hostfs MOUNT_POINT`*:: -Specifies the mount point of the host's filesystem for use in monitoring a host. +Specifies the mount point of the host's filesystem for use in monitoring a host. +This flag is depricated, and an alternate hostfs should be specified via the `hostfs` module config value. ifeval::["{beatname_lc}"=="packetbeat"] @@ -802,16 +826,6 @@ ifdef::apm-server[] Registers the <> definitions set in `ingest/pipeline/definition.json`. endif::apm-server[] -*`--template`*:: -deprecated:[7.2] -Sets up the index template only. -It is recommended to use `--index-management` instead. - -*`--ilm-policy`*:: -deprecated:[7.2] -Sets up the index lifecycle management policy. -It is recommended to use `--index-management` instead. - {global-flags} *EXAMPLES* diff --git a/libbeat/docs/getting-started.asciidoc b/libbeat/docs/getting-started.asciidoc index 5291f755e5b..7bb7043ae70 100644 --- a/libbeat/docs/getting-started.asciidoc +++ b/libbeat/docs/getting-started.asciidoc @@ -7,11 +7,10 @@ Each Beat is a separately installable product. To learn how to get started, see: * {filebeat-ref}/filebeat-installation-configuration.html[Filebeat] * {functionbeat-ref}/functionbeat-installation-configuration.html[Functionbeat] * {heartbeat-ref}/heartbeat-installation-configuration.html[Heartbeat] -* {journalbeat-ref}/journalbeat-installation-configuration.html[Journalbeat] * {metricbeat-ref}/metricbeat-installation-configuration.html[Metricbeat] * {packetbeat-ref}/packetbeat-installation-configuration.html[Packetbeat] * {winlogbeat-ref}/winlogbeat-installation-configuration.html[Winlogbeat] If you're planning to use the {metrics-app} or the {logs-app} in {kib}, see {observability-guide}/analyze-metrics.html[Analyze metrics] -and {observability-guide}/monitor-logs.html[Monitor logs]. \ No newline at end of file +and {observability-guide}/monitor-logs.html[Monitor logs]. diff --git a/libbeat/docs/howto/load-index-templates.asciidoc b/libbeat/docs/howto/load-index-templates.asciidoc index 885432a2671..f62efecdc04 100644 --- a/libbeat/docs/howto/load-index-templates.asciidoc +++ b/libbeat/docs/howto/load-index-templates.asciidoc @@ -224,7 +224,7 @@ PS > Invoke-RestMethod -Method Delete "http://localhost:9200/{beatname_lc}-*" ---------------------------------------------------------------------- endif::win_os[] -This command deletes all indices that match the pattern +{beat_default_index_prefix}-*+. +This command deletes all indices that match the pattern +{beat_default_index_prefix}+. Before running this command, make sure you want to delete all indices that match the pattern. diff --git a/libbeat/docs/loggingconfig.asciidoc b/libbeat/docs/loggingconfig.asciidoc index 4b47c45d5fb..b5443d2d978 100644 --- a/libbeat/docs/loggingconfig.asciidoc +++ b/libbeat/docs/loggingconfig.asciidoc @@ -32,7 +32,7 @@ logging.files: path: /var/log/{beatname_lc} name: {beatname_lc} keepfiles: 7 - permissions: 0644 + permissions: 0640 ---- endif::win_only[] @@ -45,7 +45,7 @@ logging.files: path: C:{backslash}ProgramData{backslash}{beatname_lc}{backslash}Logs name: {beatname_lc} keepfiles: 7 - permissions: 0644 + permissions: 0640 ---- endif::win_only[] @@ -231,12 +231,15 @@ The permissions mask to apply when rotating log files. The default value is expressed in octal notation. In Go, numbers in octal notation must start with '0'. +The most permissive mask allowed is 0640. If a higher permissions mask is +specified via this setting, it will be subject to an umask of 0027. + +This option is not supported on Windows. + Examples: -* 0644: give read and write access to the file owner, and read access to all others. +* 0640: give read and write access to the file owner, and read access to members of the group associated with the file. * 0600: give read and write access to the file owner, and no access to all others. -* 0664: give read and write access to the file owner and members of the group -associated with the file, as well as read access to all other users. [float] ==== `logging.files.interval` @@ -246,15 +249,6 @@ Intervals must be at least 1s. Values of 1m, 1h, 24h, 7*24h, 30*24h, and 365*24h are boundary-aligned with minutes, hours, days, weeks, months, and years as reported by the local system clock. All other intervals are calculated from the unix epoch. Defaults to disabled. - -[float] -==== `logging.files.suffix` - -When a log rotation happens it can either rename older files with -an incresing index if `count` is configured. The other option is `date` -that appends the current date and time to the end of the filename. -When the log is rotated a new file is created and older files -remain untouched. endif::serverless[] [float] diff --git a/libbeat/docs/monitoring/monitoring-internal-collection.asciidoc b/libbeat/docs/monitoring/monitoring-internal-collection.asciidoc index 3263777c9f4..f626ed93a3c 100644 --- a/libbeat/docs/monitoring/monitoring-internal-collection.asciidoc +++ b/libbeat/docs/monitoring/monitoring-internal-collection.asciidoc @@ -85,7 +85,7 @@ monitoring: <1> This setting identifies the {es} cluster under which the monitoring data for this {beatname_uc} instance will appear in the Stack Monitoring UI. To get a cluster's `cluster_uuid`, -call the `GET /` API against that cluster. +call the `GET /` API against that production cluster. <2> This setting identifies the hosts and port numbers of {es} nodes that are part of the monitoring cluster. <3> Specify one of `api_key` or `username`/`password`. diff --git a/libbeat/docs/overview.asciidoc b/libbeat/docs/overview.asciidoc index bdc46aaaf28..c76aa8558e5 100644 --- a/libbeat/docs/overview.asciidoc +++ b/libbeat/docs/overview.asciidoc @@ -8,10 +8,9 @@ for capturing: [horizontal] Audit data:: https://www.elastic.co/products/beats/auditbeat[Auditbeat] -Log files:: https://www.elastic.co/products/beats/filebeat[Filebeat] +Log files and journals:: https://www.elastic.co/products/beats/filebeat[Filebeat] Cloud data:: https://www.elastic.co/products/beats/functionbeat[Functionbeat] Availability:: https://www.elastic.co/products/beats/heartbeat[Heartbeat] -Systemd journals:: https://www.elastic.co/downloads/beats/journalbeat[Journalbeat] Metrics:: https://www.elastic.co/products/beats/metricbeat[Metricbeat] Network traffic:: https://www.elastic.co/products/beats/packetbeat[Packetbeat] Windows event logs:: https://www.elastic.co/products/beats/winlogbeat[Winlogbeat] diff --git a/libbeat/docs/queueconfig.asciidoc b/libbeat/docs/queueconfig.asciidoc index 054379e1b20..fb930831dac 100644 --- a/libbeat/docs/queueconfig.asciidoc +++ b/libbeat/docs/queueconfig.asciidoc @@ -196,166 +196,3 @@ too many errors or overloading the host system if the target disk becomes unavailable for an extended time. The default value is `30s` (thirty seconds). - - -[float] -[[configuration-internal-queue-spool]] -=== Configure the file spool queue - -beta[] - -NOTE: The file spool queue is a deprecated feature offered as-is for backwards compatibility. The supported way to queue events in persistent storage is the disk queue. - -The file spool queue stores all events in an on disk ring buffer. The spool -has a write buffer, which new events are written to. Events written to the -spool are forwarded to the outputs, only after the write buffer has been -flushed successfully. - -The spool waits for the output to acknowledge or drop events. If the spool is -full, no new events can be inserted. The spool will block. Space is freed only -after a signal from the output has been received. - -On disk, the spool divides a file into pages. The `file.page_size` setting -configures the file's page size at file creation time. The optimal page size depends -on the effective block size, used by the underlying file system. - -This sample configuration enables the spool with all default settings (See -<> for defaults) and the -default file path: - -[source,yaml] ------------------------------------------------------------------------------- -queue.spool: ~ ------------------------------------------------------------------------------- - -This sample configuration creates a spool of 512MiB, with 16KiB pages. The -write buffer is flushed if 10MiB of contents, or 1024 events have been -written. If the oldest available event has been waiting for 5s in the write -buffer, the buffer will be flushed as well: - -[source,yaml] ------------------------------------------------------------------------------- -queue.spool: - file: - path: "${path.data}/spool.dat" - size: 512MiB - page_size: 16KiB - write: - buffer_size: 10MiB - flush.timeout: 5s - flush.events: 1024 ------------------------------------------------------------------------------- - -[float] -[[configuration-internal-queue-spool-reference]] -==== Configuration options - -You can specify the following options in the `queue.spool` section of the -+{beatname_lc}.yml+ config file: - -[float] -===== `file.path` - -The spool file path. The file is created on startup, if it does not exist. - -The default value is "${path.data}/spool.dat". - -[float] -===== `file.permissions` - -The file permissions. The permissions are applied when the file is -created. In case the file already exists, the file permissions are compared -with `file.permissions`. The spool file is not opened if the actual file -permissions are more permissive then configured. - -The default value is 0600. - - -[float] -===== `file.size` - -Spool file size. - -The default value is 100 MiB. - -NOTE: The size should be much larger then the expected event sizes -and write buffer size. Otherwise the queue will block, because it has not -enough space. - -NOTE: The file size cannot be changed once the file has been generated. This -limitation will be removed in the future. - -[float] -===== `file.page_size` - -The file's page size. - -The spool file is split into pages of `page_size`. All I/O -operations operate on complete pages. - -The default value is 4096 (4KiB). - -NOTE: This setting should match the file system's minimum block size. If the -`page_size` is not a multiple of the file system's block size, the file system -might create additional read operations on writes. - -NOTE: The page size is only set at file creation time. It cannot be changed -afterwards. - -[float] -===== `file.prealloc` - -If `prealloc` is set to `true`, truncate is used to reserve the space up to -`file.size`. This setting is only used when the file is created. - -The file will dynamically grow, if `prealloc` is set to false. The spool -blocks, if `prealloc` is `false` and the system is out of disk space. - -The default value is `true`. - -[float] -===== `write.buffer_size` - -The write buffer size. The write buffer is flushed, once the buffer size is exceeded. - -Very big events are allowed to be bigger then the configured buffer size. But -the write buffer will be flushed right after the event has been serialized. - -The default value is 1MiB. - -[float] -===== `write.codec` - -The event encoding used for serialized events. Valid values are `json` and `cbor`. - -The default value is `cbor`. - -[float] -===== `write.flush.timeout` - -Maximum wait time of the oldest event in the write buffer. If set to 0, the -write buffer will only be flushed once `write.flush.events` or `write.buffer_size` is fulfilled. - -The default value is 1s. - -[float] -===== `write.flush.events` - -Number of buffered events. The write buffer is flushed once the limit is reached. - -The default value is 16384. - -[float] -===== `read.flush.timeout` - -The spool reader tries to read up to the output's `bulk_max_size` events at once. - -If `read.flush.timeout` is set to 0s, all available events are forwarded -immediately to the output. - -If `read.flush.timeout` is set to a value bigger then 0s, the spool will wait -for more events to be flushed. Events are forwarded to the output if -`bulk_max_size` events have been read or the oldest read event has been waiting -for the configured duration. - -The default value is 0s. diff --git a/libbeat/docs/release-notes/breaking/breaking-7.16.asciidoc b/libbeat/docs/release-notes/breaking/breaking-7.16.asciidoc new file mode 100644 index 00000000000..29e82e73337 --- /dev/null +++ b/libbeat/docs/release-notes/breaking/breaking-7.16.asciidoc @@ -0,0 +1,42 @@ +[[breaking-changes-7.16]] + +=== Breaking changes in 7.16 +++++ +7.16 +++++ + +See the <> for a complete list of changes, +including changes to beta or experimental functionality. + +//NOTE: The notable-breaking-changes tagged regions are re-used in the +//Installation and Upgrade Guide + +// tag::notable-breaking-changes[] + +[discrete] +==== {journalbeat} is removed in 7.16 + +{journalbeat}, a lightweight shipper for collecting logs written by the Journald +system service, is removed in 7.16. This functionality is instead provided as +a {filebeat} input. If you're currently using {journalbeat}, you should +use the `journald` input in {filebeat} instead. For more information, refer to +the +{filebeat-ref}/filebeat-input-journald.html[Journald input] documentation. + +If you're using {agent} instead of {beats}, you can collect Journald logs by +adding the *Custom Journald logs* integration to your agent policy. For more +information, refer to +{fleet-guide}/add-integration-to-policy.html[Add an {agent} integration to a policy]. + +//TODO: Add pointer to the integrations docs for custom journald logs when +//available. + +[discrete] +==== Custom {beats} generator is deprecated in 7.16 + +The generator code for creating custom {beats} is deprecated in 7.16.0 and will +be removed in 8.0.0. You can continue to build custom {beats} using the +generators available in 7.16, or refer to existing {beats} as working examples. + +// end::notable-breaking-changes[] + diff --git a/libbeat/docs/release-notes/breaking/breaking.asciidoc b/libbeat/docs/release-notes/breaking/breaking.asciidoc index f2f71da0579..6fb7e893460 100644 --- a/libbeat/docs/release-notes/breaking/breaking.asciidoc +++ b/libbeat/docs/release-notes/breaking/breaking.asciidoc @@ -11,6 +11,8 @@ changes, but there are breaking changes between major versions (e.g. 6.x to See the following topics for a description of breaking changes: +* <> + * <> * <> @@ -43,6 +45,8 @@ See the following topics for a description of breaking changes: * <> +include::breaking-7.16.asciidoc[] + include::breaking-7.15.asciidoc[] include::breaking-7.14.asciidoc[] diff --git a/libbeat/docs/release.asciidoc b/libbeat/docs/release.asciidoc index aed042ea25b..0255a23c698 100644 --- a/libbeat/docs/release.asciidoc +++ b/libbeat/docs/release.asciidoc @@ -8,9 +8,14 @@ This section summarizes the changes in each release. Also read <> for more detail about changes that affect upgrade. +* <> * <> * <> * <> +* <> +* <> +* <> +* <> * <> * <> * <> diff --git a/libbeat/docs/shared-autodiscover.asciidoc b/libbeat/docs/shared-autodiscover.asciidoc index 5b863f4307d..40492d1e0ac 100644 --- a/libbeat/docs/shared-autodiscover.asciidoc +++ b/libbeat/docs/shared-autodiscover.asciidoc @@ -23,6 +23,23 @@ start/stop events. This ensures you don't need to worry about state, but only de The Docker autodiscover provider watches for Docker containers to start and stop. +It has the following settings: + +`host`:: (Optional) Docker socket (UNIX or TCP socket). It uses +`unix:///var/run/docker.sock` by default. +`ssl`:: (Optional) SSL configuration to use when connecting to the Docker +socket. +`cleanup_timeout`:: (Optional) Specify the time of inactivity before stopping the +running configuration for a container, +ifeval::["{beatname_lc}"=="filebeat"] + 60s by default. +endif::[] +ifeval::["{beatname_lc}"!="filebeat"] + disabled by default. +endif::[] +`labels.dedot`:: (Optional) Default to be false. If set to true, replace dots in + labels with `_`. + These are the fields available within config templating. The `docker.*` fields will be available on each emitted event. event: @@ -109,13 +126,24 @@ autodiscover.providers: paths: - "/mnt/logs/${data.docker.container.id}/*.log" ------------------------------------------------------------------------------------- +======================================= +endif::[] -It has the following settings: -`host`:: (Optional) Docker socket (UNIX or TCP socket). It uses -`unix:///var/run/docker.sock` by default. -`ssl`:: (Optional) SSL configuration to use when connecting to the Docker -socket. +[float] +===== Kubernetes + +The Kubernetes autodiscover provider watches for Kubernetes nodes, pods, services to start, update, and stop. + +The `kubernetes` autodiscover provider has the following configuration settings: + +`node`:: (Optional) Specify the node to scope {beatname_lc} to in case it + cannot be accurately detected, as when running {beatname_lc} in host network + mode. +`namespace`:: (Optional) Select the namespace from which to collect the + metadata. If it is not set, the processor collects metadata from all + namespaces. It is unset by default. The namespace configuration only applies to + kubernetes resources that are namespace scoped. `cleanup_timeout`:: (Optional) Specify the time of inactivity before stopping the running configuration for a container, ifeval::["{beatname_lc}"=="filebeat"] @@ -124,17 +152,57 @@ endif::[] ifeval::["{beatname_lc}"!="filebeat"] disabled by default. endif::[] -`labels.dedot`:: (Optional) Default to be false. If set to true, replace dots in - labels with `_`. +`kube_config`:: (Optional) Use given config file as configuration for Kubernetes + client. If kube_config is not set, KUBECONFIG environment variable will be + checked and if not present it will fall back to InCluster. +`kube_client_options`:: (Optional) Additional options can be configured for Kubernetes + client. Currently client QPS and burst are supported, if not set Kubernetes client's + https://pkg.go.dev/k8s.io/client-go/rest#pkg-constants[default QPS and burst] will be used. + Example: +["source","yaml",subs="attributes"] +------------------------------------------------------------------------------------- + kube_client_options: + qps: 5 + burst: 10 +------------------------------------------------------------------------------------- -======================================= -endif::[] +`resource`:: (Optional) Select the resource to do discovery on. Currently supported + Kubernetes resources are `pod`, `service` and `node`. If not configured `resource` + defaults to `pod`. +`scope`:: (Optional) Specify at what level autodiscover needs to be done at. `scope` can + either take `node` or `cluster` as values. `node` scope allows discovery of resources in + the specified node. `cluster` scope allows cluster wide discovery. Only `pod` and `node` resources + can be discovered at node scope. +`add_resource_metadata`:: (Optional) Specify labels and annotations filters for the extra metadata coming from Node and Namespace. + `add_resource_metadata` can be done for `node` or `namespace`. By default all labels will be included + while annotations are not added by default. This settings are useful when labels' and annotations' + storing requires special handling to avoid overloading the storage output. The enrichment of `node` or `namespace` metadata + can be individually disabled by setting `enabled: false`. If resource is `pod` and it is created from a `deployment`, by default + the deployment name is added, this can be disabled by set to `false`. + Example: +["source","yaml",subs="attributes"] +------------------------------------------------------------------------------------- + add_resource_metadata: + namespace: + include_labels: ["namespacelabel1"] + node: + include_labels: ["nodelabel2"] + include_annotations: ["nodeannotation1"] + deployment: false +------------------------------------------------------------------------------------- -[float] -===== Kubernetes +`unique`:: (Optional) Defaults to `false`. Marking an autodiscover provider as unique results into + making the provider to enable the provided templates only when it will gain the leader lease. + This setting can only be combined with `cluster` scope. When `unique` is enabled enabled, `resource` + and `add_resource_metadata` settings are not taken into account. +`leader_lease`:: (Optional) Defaults to +{beatname_lc}-cluster-leader+. This will be name of the lock lease. + One can monitor the status of the lease with `kubectl describe lease beats-cluster-leader`. + Different Beats that refer to the same leader lease will be competitors in holding the lease + and only one will be elected as leader each time. -The Kubernetes autodiscover provider watches for Kubernetes nodes, pods, services to start, update, and stop. +The configuration of templates and conditions is similar to that of the Docker provider. Configuration templates can +contain variables from the autodiscover event. They can be accessed under data namespace. These are the fields available within config templating. The `kubernetes.*` fields will be available on each emitted event. @@ -211,75 +279,6 @@ For example: } ------------------------------------------------------------------------------------- -The configuration of templates and conditions is similar to that of the Docker provider. Configuration templates can -contain variables from the autodiscover event. They can be accessed under data namespace. - -The `kubernetes` autodiscover provider has the following configuration settings: - -`node`:: (Optional) Specify the node to scope {beatname_lc} to in case it - cannot be accurately detected, as when running {beatname_lc} in host network - mode. -`namespace`:: (Optional) Select the namespace from which to collect the - metadata. If it is not set, the processor collects metadata from all - namespaces. It is unset by default. The namespace configuration only applies to - kubernetes resources that are namespace scoped. -`cleanup_timeout`:: (Optional) Specify the time of inactivity before stopping the -running configuration for a container, -ifeval::["{beatname_lc}"=="filebeat"] - 60s by default. -endif::[] -ifeval::["{beatname_lc}"!="filebeat"] - disabled by default. -endif::[] -`kube_config`:: (Optional) Use given config file as configuration for Kubernetes - client. If kube_config is not set, KUBECONFIG environment variable will be - checked and if not present it will fall back to InCluster. -`kube_client_options`:: (Optional) Additional options can be configured for Kubernetes - client. Currently client QPS and burst are supported, if not set Kubernetes client's - https://pkg.go.dev/k8s.io/client-go/rest#pkg-constants[default QPS and burst] will be used. - Example: -["source","yaml",subs="attributes"] -------------------------------------------------------------------------------------- - kube_client_options: - qps: 5 - burst: 10 -------------------------------------------------------------------------------------- - -`resource`:: (Optional) Select the resource to do discovery on. Currently supported - Kubernetes resources are `pod`, `service` and `node`. If not configured `resource` - defaults to `pod`. -`scope`:: (Optional) Specify at what level autodiscover needs to be done at. `scope` can - either take `node` or `cluster` as values. `node` scope allows discovery of resources in - the specified node. `cluster` scope allows cluster wide discovery. Only `pod` and `node` resources - can be discovered at node scope. -`add_resource_metadata`:: (Optional) Specify labels and annotations filters for the extra metadata coming from Node and Namespace. - `add_resource_metadata` can be done for `node` or `namespace`. By default all labels will be included - while annotations are not added by default. This settings are useful when labels' and annotations' - storing requires special handling to avoid overloading the storage output. The enrichment of `node` or `namespace` metadata - can be individually disabled by setting `enabled: false`. If resource is `pod` and it is created from a `deployment`, by default - the deployment name is added, this can be disabled by set to `false`. - Example: - -["source","yaml",subs="attributes"] -------------------------------------------------------------------------------------- - add_resource_metadata: - namespace: - include_labels: ["namespacelabel1"] - node: - include_labels: ["nodelabel2"] - include_annotations: ["nodeannotation1"] - deployment: false -------------------------------------------------------------------------------------- - -`unique`:: (Optional) Defaults to `false`. Marking an autodiscover provider as unique results into - making the provider to enable the provided templates only when it will gain the leader lease. - This setting can only be combined with `cluster` scope. When `unique` is enabled enabled, `resource` - and `add_resource_metadata` settings are not taken into account. -`leader_lease`:: (Optional) Defaults to `{beatname_lc}-cluster-leader`. This will be name of the lock lease. - One can monitor the status of the lease with `kubectl describe lease beats-cluster-leader`. - Different Beats that refer to the same leader lease will be competitors in holding the lease - and only one will be elected as leader each time. - ifeval::["{beatname_lc}"=="metricbeat"] Example: @@ -317,6 +316,19 @@ ifdef::autodiscoverJolokia[] The Jolokia autodiscover provider uses Jolokia Discovery to find agents running in your host or your network. +The configuration of this provider consists in a set of network interfaces, as +well as a set of templates as in other providers. The network interfaces will be +the ones used for discovery probes, each item of `interfaces` has these settings: + +`name`:: the name of the interface (e.g. `br0`), it can contain a wildcard + as suffix to apply the same settings to multiple network interfaces of + the same type (e.g. `br*`). +`interval`:: time between probes (defaults to 10s) + `grace_period`:: time since the last reply to consider an instance stopped + (defaults to 30s) +`probe_timeout`:: max time to wait for responses since a probe is sent + (defaults to 1s) + Jolokia Discovery mechanism is supported by any Jolokia agent since version 1.2.0, it is enabled by default when Jolokia is included in the application as a JVM agent, but disabled in other cases as the OSGI or WAR (Java EE) agents. @@ -347,19 +359,6 @@ These are the available fields during within config templating. The `jolokia.*` * jolokia.server.version * jolokia.url -The configuration of this provider consists in a set of network interfaces, as -well as a set of templates as in other providers. The network interfaces will be -the ones used for discovery probes, they have these settings: - -`name`:: the name of the interface (e.g. `br0`), it can contain a wildcard - as suffix to apply the same settings to multiple network interfaces of - the same type (e.g. `br*`). -`interval`:: time between probes (defaults to 10s) - `grace_period`:: time since the last reply to consider an instance stopped - (defaults to 30s) -`probe_timeout`:: max time to wait for responses since a probe is sent - (defaults to 1s) - include::../../{beatname_lc}/docs/autodiscover-jolokia-config.asciidoc[] endif::autodiscoverJolokia[] @@ -418,6 +417,49 @@ experimental[] The Nomad autodiscover provider watches for Nomad jobs to start, update, and stop. +The `nomad` autodiscover provider has the following configuration settings: + +`address`:: (Optional) Specify the address of the Nomad agent. By default it will try to talk to a + Nomad agent running locally (`http://127.0.0.1:4646`). + +`region`:: (Optional) Region to use. If not provided, the default agent region is used. + +`namespace`:: (Optional) Namespace to use. If not provided the `default` namespace is used. + +`secret_id`:: (Optional) SecretID to use if ACL is enabled in Nomad. This is an +example ACL policy to apply to the token. + +[source,hcl] +---- +namespace "*" { + policy = "read" +} +node { + policy = "read" +} +agent { + policy = "read" +} +---- + +`node`:: (Optional) Specify the node to scope {beatname_lc} to in case it + cannot be accurately detected when `node` scope is used. + +`scope`:: (Optional) Specify at what level autodiscover needs to be done at. `scope` can + either take `node` or `cluster` as values. `node` scope allows discovery of resources in + the specified node. `cluster` scope allows cluster wide discovery. Defaults to `node`. + +`wait_time`:: (Optional) Limits how long a Watch will block. If not specified (or set to `0`) the + default configuration from the agent will be used. + +`allow_stale`:: (Optional) allows any Nomad server (non-leader) to service a read. This normally + means that the local node where filebeat is allocated will service filebeat's requests. + Defaults to `true`. + +The configuration of templates and conditions is similar to that of the Docker provider. +Configuration templates can contain variables from the autodiscover event. They can be accessed under +`data` namespace. + These are the available fields during config templating. The `nomad.*` fields will be available on each emitted event. @@ -482,49 +524,6 @@ For example: } ------------------------------------------------------------------------------------- -The configuration of templates and conditions is similar to that of the Docker provider. -Configuration templates can contain variables from the autodiscover event. They can be accessed under -`data` namespace. - -The `nomad` autodiscover provider has the following configuration settings: - -`address`:: (Optional) Specify the address of the Nomad agent. By default it will try to talk to a - Nomad agent running locally (`http://127.0.0.1:4646`). - -`region`:: (Optional) Region to use. If not provided, the default agent region is used. - -`namespace`:: (Optional) Namespace to use. If not provided the `default` namespace is used. - -`secret_id`:: (Optional) SecretID to use if ACL is enabled in Nomad. This is an -example ACL policy to apply to the token. - -[source,hcl] ----- -namespace "*" { - policy = "read" -} -node { - policy = "read" -} -agent { - policy = "read" -} ----- - -`node`:: (Optional) Specify the node to scope {beatname_lc} to in case it - cannot be accurately detected when `node` scope is used. - -`scope`:: (Optional) Specify at what level autodiscover needs to be done at. `scope` can - either take `node` or `cluster` as values. `node` scope allows discovery of resources in - the specified node. `cluster` scope allows cluster wide discovery. Defaults to `node`. - -`wait_time`:: (Optional) Limits how long a Watch will block. If not specified (or set to `0`) the - default configuration from the agent will be used. - -`allow_stale`:: (Optional) allows any Nomad server (non-leader) to service a read. This normally - means that the local node where filebeat is allocated will service filebeat's requests. - Defaults to `true`. - include::../../{beatname_lc}/docs/autodiscover-nomad-config.asciidoc[] endif::autodiscoverNomad[] diff --git a/libbeat/docs/shared-docker.asciidoc b/libbeat/docs/shared-docker.asciidoc index 2e7e04e6c7a..389bedb7b54 100644 --- a/libbeat/docs/shared-docker.asciidoc +++ b/libbeat/docs/shared-docker.asciidoc @@ -80,16 +80,6 @@ setup -E setup.kibana.host=kibana:5601 \ -------------------------------------------- endif::[] -ifeval::["{beatname_lc}"=="journalbeat"] -["source", "sh", subs="attributes"] --------------------------------------------- -docker run \ -{dockerimage} \ -setup -E setup.kibana.host=kibana:5601 \ --E output.elasticsearch.hosts=["elasticsearch:9200"] <1> <2> --------------------------------------------- -endif::[] - ifeval::["{beatname_lc}"=="packetbeat"] ["source", "sh", subs="attributes"] -------------------------------------------- @@ -161,24 +151,6 @@ docker run -d \ -------------------------------------------- endif::[] -ifeval::["{beatname_lc}"=="journalbeat"] -Make sure you include the path to the host's journal. The path might be -`/var/log/journal` or `/run/log/journal`. - -["source", "sh", subs="attributes"] --------------------------------------------- -sudo docker run -d \ - --name={beatname_lc} \ - --user=root \ - --volume="/var/log/journal:/var/log/journal" \ - --volume="/etc/machine-id:/etc/machine-id" \ - --volume="/run/systemd:/run/systemd" \ - --volume="/etc/hostname:/etc/hostname:ro" \ - {dockerimage} {beatname_lc} -e -strict.perms=false \ - -E output.elasticsearch.hosts=["elasticsearch:9200"] <1> <2> --------------------------------------------- -endif::[] - ifeval::["{beatname_lc}"=="metricbeat"] ["source", "sh", subs="attributes"] -------------------------------------------- diff --git a/libbeat/docs/shared-path-config.asciidoc b/libbeat/docs/shared-path-config.asciidoc index 33390ca7faa..44c4e6d2809 100644 --- a/libbeat/docs/shared-path-config.asciidoc +++ b/libbeat/docs/shared-path-config.asciidoc @@ -107,15 +107,15 @@ Example: path.logs: /var/log/beats ------------------------------------------------------------------------------ +ifeval::["{beatname_lc}"=="metricbeat"] [float] ==== `system.hostfs` Specifies the mount point of the host's filesystem for use in monitoring a host. This can either be set in the config, or with the `--system.hostfs` CLI flag. This is used for cgroup self-monitoring. -ifeval::["{beatname_lc}"=="metricbeat"] -This is also used by the system module to read files from `/proc` and `/sys`. -endif::[] +This is also used by the system module to read files from `/proc` and `/sys`. +This option is deprecated and will be removed in a future release. To set the filesystem root, use the `hostfs` flag inside the module-level config. Example: @@ -123,3 +123,4 @@ Example: ------------------------------------------------------------------------------ system.hostfs: /mount/rootfs ------------------------------------------------------------------------------ +endif::[] \ No newline at end of file diff --git a/libbeat/docs/shared-ssl-config.asciidoc b/libbeat/docs/shared-ssl-config.asciidoc index 1c20e6b8565..97a2605ef4b 100644 --- a/libbeat/docs/shared-ssl-config.asciidoc +++ b/libbeat/docs/shared-ssl-config.asciidoc @@ -377,6 +377,15 @@ production environments is strongly discouraged. + The default value is `full`. +[float] +[[ca_trusted_fingerprint]] +==== `ca_trusted_fingerprint` +A HEX encoded SHA-256 of a CA certificate. If this certificate is +present in the chain during the handshake, it will be added to the +`certificate_authorities` list and the handshake will continue +normaly. + + [discrete] [[ssl-server-config]] === Server configuration options diff --git a/libbeat/docs/tab-widgets/set-connection.asciidoc b/libbeat/docs/tab-widgets/set-connection.asciidoc index 571e9cec570..3d8c9014732 100644 --- a/libbeat/docs/tab-widgets/set-connection.asciidoc +++ b/libbeat/docs/tab-widgets/set-connection.asciidoc @@ -29,11 +29,22 @@ set the username and password of a user who is authorized to set up ["source","yaml",subs="attributes"] ---- output.elasticsearch: - hosts: ["myEShost:9200"] + hosts: ["https://myEShost:9200"] username: "{beatname_lc}_internal" password: "{pwd}" <1> + ssl: + enabled: true + ca_trusted_fingerprint: "b9a10bbe64ee9826abeda6546fc988c8bf798b41957c33d05db736716513dc9c" <2> ---- -<1> This examples shows a hard-coded password, but you should store sensitive +<1> This example shows a hard-coded password, but you should store sensitive +values +ifndef::serverless[] +in the {beatname_url}/keystore.html[secrets keystore]. +endif::[] +ifdef::serverless[] +in environment variables. +endif::[] +<2> This example shows a hard-coded fingerprint, but you should store sensitive values ifndef::serverless[] in the {beatname_url}/keystore.html[secrets keystore]. @@ -41,6 +52,16 @@ endif::[] ifdef::serverless[] in environment variables. endif::[] +The fingerprint is a HEX encoded SHA-256 of a CA certificate, +when you start {es} for the first time, security features such as +network encryption (TLS) for {es} are enabled by default. If you are +using the self-signed certificate generated by {es} when it is started +for the first time, you will need to add its fingerprint here. The +fingerprint is printed on {es} start up logs, or you can refer to {ref-80}/configuring-stack-security.html#_connect_clients_to_elasticsearch_5[connect clients to {es} +documentation] for other options on retrieving it. If you are +providing your own SSL certificate to {es} refer to +{beatname_url}/configuration-ssl.html#ssl-client-config[{beatname_uc} +documentation on how to setup SSL]. . If you plan to use our pre-built {kib} dashboards, configure the {kib} endpoint. Skip this step if {kib} is running on the same host as {es}. diff --git a/libbeat/docs/tab-widgets/start.asciidoc b/libbeat/docs/tab-widgets/start.asciidoc index 0dd2728d53c..5882655dec8 100644 --- a/libbeat/docs/tab-widgets/start.asciidoc +++ b/libbeat/docs/tab-widgets/start.asciidoc @@ -45,7 +45,7 @@ ifdef::has_modules_command[] ["source","sh",subs="attributes,callouts"] ---------------------------------------------------------------------- sudo chown root {beatname_lc}.yml <1> -sudo chown root modules.d/system.yml <1> +sudo chown root modules.d/{modulename}.yml <1> sudo ./{beatname_lc} -e ---------------------------------------------------------------------- <1> You'll be running {beatname_uc} as root, so you need to change ownership of the @@ -94,7 +94,7 @@ ifdef::has_modules_command[] ["source","sh",subs="attributes,callouts"] ---------------------------------------------------------------------- sudo chown root /usr/local/etc/{beatname_lc}/{beatname_lc}.yml <1> -sudo chown root /usr/local/etc/{beatname_lc}/modules.d/system.yml <1> +sudo chown root /usr/local/etc/{beatname_lc}/modules.d/{modulename}.yml <1> sudo {beatname_lc} -e ---------------------------------------------------------------------- <1> You'll be running {beatname_uc} as root, so you need to change ownership of the @@ -124,7 +124,7 @@ ifdef::has_modules_command[] ["source","sh",subs="attributes,callouts"] ---------------------------------------------------------------------- sudo chown root {beatname_lc}.yml <1> -sudo chown root modules.d/system.yml <1> +sudo chown root modules.d/{modulename}.yml <1> sudo ./{beatname_lc} -e ---------------------------------------------------------------------- <1> You'll be running {beatname_uc} as root, so you need to change ownership of the diff --git a/libbeat/docs/template-config.asciidoc b/libbeat/docs/template-config.asciidoc index 5699a46dd76..2ec64291b80 100644 --- a/libbeat/docs/template-config.asciidoc +++ b/libbeat/docs/template-config.asciidoc @@ -26,13 +26,6 @@ existing one. *`setup.template.enabled`*:: Set to false to disable template loading. If this is set to false, you must <>. -ifndef::apm-server[] -*`setup.template.type`*:: The type of template to use. Available options: `legacy` (default), index templates -before Elasticsearch v7.8. Use this to avoid breaking existing deployments. New options are `component` -and `index`. Selecting `component` loads a component template which can be included in new index templates. -The option `index` loads the new index template. -endif::[] - *`setup.template.name`*:: The name of the template. The default is +{beatname_lc}+. The {beatname_uc} version is always appended to the given name, so the final name is +{beatname_lc}-%{[{beat_version_key}]}+. @@ -44,17 +37,16 @@ name, so the final name is +{beatname_lc}-%{[{beat_version_key}]}+. // the example as expected. *`setup.template.pattern`*:: The template pattern to apply to the default index -settings. The default pattern is +{beat_default_index_prefix}-\*+. The {beatname_uc} version is always +settings. The default pattern is +{beat_default_index_prefix}+. The {beatname_uc} version is always included in the pattern, so the final pattern is -+{beat_default_index_prefix}-%{[{beat_version_key}]}-*+. The wildcard character `-*` is used to -match all daily indices. ++{beat_default_index_prefix}-%{[{beat_version_key}]}+. + Example: + ["source","yaml",subs="attributes"] ---------------------------------------------------------------------- setup.template.name: "{beatname_lc}" -setup.template.pattern: "{beat_default_index_prefix}-*" +setup.template.pattern: "{beat_default_index_prefix}" ---------------------------------------------------------------------- *`setup.template.fields`*:: The path to the YAML file describing the fields. The default is +fields.yml+. If a diff --git a/libbeat/docs/version.asciidoc b/libbeat/docs/version.asciidoc index 47386bc5ca1..a09f29c66bf 100644 --- a/libbeat/docs/version.asciidoc +++ b/libbeat/docs/version.asciidoc @@ -1,6 +1,6 @@ :stack-version: 8.0.0 :doc-branch: master -:go-version: 1.17.2 +:go-version: 1.17.5 :release-state: unreleased :python: 3.7 :docker: 1.12 diff --git a/libbeat/esleg/eslegclient/connection.go b/libbeat/esleg/eslegclient/connection.go index 8db37a9b0ef..d14ba8544f0 100644 --- a/libbeat/esleg/eslegclient/connection.go +++ b/libbeat/esleg/eslegclient/connection.go @@ -421,7 +421,11 @@ func (conn *Connection) execHTTPRequest(req *http.Request) (int, []byte, error) } for name, value := range conn.Headers { - req.Header.Add(name, value) + if name == "Content-Type" || name == "Accept" { + req.Header.Set(name, value) + } else { + req.Header.Add(name, value) + } } // The stlib will override the value in the header based on the configured `Host` diff --git a/libbeat/esleg/eslegclient/connection_test.go b/libbeat/esleg/eslegclient/connection_test.go index 72b78f27e1d..e0735ebe992 100644 --- a/libbeat/esleg/eslegclient/connection_test.go +++ b/libbeat/esleg/eslegclient/connection_test.go @@ -64,3 +64,39 @@ func (c *mockClient) CloseIdleConnections() {} func newMockClient() *mockClient { return &mockClient{} } + +func TestHeaders(t *testing.T) { + for _, td := range []struct { + input map[string]string + expected map[string][]string + }{ + {input: map[string]string{ + "Accept": "application/vnd.elasticsearch+json;compatible-with=7", + "Content-Type": "application/vnd.elasticsearch+json;compatible-with=7", + "X-My-Header": "true"}, + expected: map[string][]string{ + "Accept": {"application/vnd.elasticsearch+json;compatible-with=7"}, + "Content-Type": {"application/vnd.elasticsearch+json;compatible-with=7"}, + "X-My-Header": {"true"}}}, + {input: map[string]string{ + "X-My-Header": "true"}, + expected: map[string][]string{ + "Accept": {"application/json"}, + "X-My-Header": {"true"}}}, + } { + conn, err := NewConnection(ConnectionSettings{ + Headers: td.input, + }) + require.NoError(t, err) + + httpClient := newMockClient() + conn.HTTP = httpClient + + req, err := http.NewRequest("GET", "http://fakehost/some/path", nil) + require.NoError(t, err) + _, _, err = conn.execHTTPRequest(req) + require.NoError(t, err) + + require.Equal(t, req.Header, http.Header(td.expected)) + } +} diff --git a/libbeat/idxmgmt/ilm/client_handler.go b/libbeat/idxmgmt/ilm/client_handler.go index 9ec4cc218d0..4d2163091ae 100644 --- a/libbeat/idxmgmt/ilm/client_handler.go +++ b/libbeat/idxmgmt/ilm/client_handler.go @@ -18,9 +18,7 @@ package ilm import ( - "encoding/json" "fmt" - "net/url" "path" "github.com/elastic/beats/v7/libbeat/common" @@ -29,10 +27,6 @@ import ( // ClientHandler defines the interface between a remote service and the Manager. type ClientHandler interface { CheckILMEnabled(bool) (bool, error) - - HasAlias(name string) (bool, error) - CreateAlias(alias Alias) error - HasILMPolicy(name string) (bool, error) CreateILMPolicy(policy Policy) error } @@ -42,10 +36,14 @@ type ESClientHandler struct { client ESClient } +type VersionCheckerClient interface { + GetVersion() common.Version +} + // ESClient defines the minimal interface required for the Loader to -// prepare a policy and write alias. +// prepare a policy. type ESClient interface { - GetVersion() common.Version + VersionCheckerClient Request( method, path string, pipeline string, @@ -60,24 +58,17 @@ type FileClientHandler struct { } // FileClient defines the minimal interface required for the Loader to -// prepare a policy and write alias. +// prepare a policy. type FileClient interface { GetVersion() common.Version Write(component string, name string, body string) error } const ( - // esFeaturesPath is used to query Elasticsearch for availability of licensed - // features. - esFeaturesPath = "/_xpack" - esILMPath = "/_ilm/policy" - - esAliasPath = "/_alias" ) var ( - esMinILMVersion = common.MustNewVersion("6.6.0") esMinDefaultILMVersion = common.MustNewVersion("7.0.0") ) @@ -93,31 +84,7 @@ func NewFileClientHandler(c FileClient) *FileClientHandler { // CheckILMEnabled indicates whether or not ILM is supported for the configured mode and ES instance. func (h *ESClientHandler) CheckILMEnabled(enabled bool) (bool, error) { - if !enabled { - return false, nil - } - - ver := h.client.GetVersion() - if !checkILMVersion(h.client.GetVersion()) { - return false, errf(ErrESVersionNotSupported, "Elasticsearch %v does not support ILM", ver.String()) - } - - avail, enabledILM, err := h.checkILMSupport() - if err != nil { - return false, err - } - - if !avail { - if enabledILM { - return false, errOf(ErrESVersionNotSupported) - } - return false, nil - } - - if !enabledILM && enabled { - return false, errOf(ErrESILMDisabled) - } - return enabled, nil + return checkILMEnabled(enabled, h.client) } // CreateILMPolicy loads the given policy to Elasticsearch. @@ -139,110 +106,21 @@ func (h *ESClientHandler) HasILMPolicy(name string) (bool, error) { return status == 200, nil } -// HasAlias queries Elasticsearch to see if alias exists. If other resource -// with the same name exists, it returns an error. -func (h *ESClientHandler) HasAlias(name string) (bool, error) { - status, b, err := h.client.Request("GET", esAliasPath+"/"+name, "", nil, nil) - if err != nil && status != 404 { - return false, wrapErrf(err, ErrRequestFailed, - "failed to check for alias '%v': (status=%v) %s", name, status, b) - } - if status == 200 { - return true, nil - } - - // Alias doesn't exist, check if there is an index with the same name - status, b, err = h.client.Request("HEAD", "/"+name, "", nil, nil) - if err != nil && status != 404 { - return false, wrapErrf(err, ErrRequestFailed, - "failed to check for alias '%v': (status=%v) %s", name, status, b) - } - if status == 200 { - return false, errf(ErrInvalidAlias, - "resource '%v' exists, but it is not an alias", name) - } - return false, nil -} - -// CreateAlias sends request to Elasticsearch for creating alias. -func (h *ESClientHandler) CreateAlias(alias Alias) error { - // Escaping because of date pattern - // This always assume it's a date pattern by sourrounding it by <...> - firstIndex := fmt.Sprintf("<%s-%s>", alias.Name, alias.Pattern) - firstIndex = url.PathEscape(firstIndex) - - body := common.MapStr{ - "aliases": common.MapStr{ - alias.Name: common.MapStr{ - "is_write_index": true, - }, - }, - } - - // Note: actual aliases are accessible via the index - if _, res, err := h.client.Request("PUT", "/"+firstIndex, "", nil, body); err != nil { - // Creating the index may fail for multiple reasons, e.g. because - // the index exists, or because the write alias exists and points - // to another index. - if ok, err := h.HasAlias(alias.Name); err != nil { - // HasAlias fails if there is an index with the same name. - return err - } else if ok { - return errOf(ErrAliasAlreadyExists) - } - return wrapErrf(err, ErrAliasCreateFailed, "failed to create alias: %s", res) - } - return nil -} - -func (h *ESClientHandler) checkILMSupport() (avail, enabled bool, err error) { - var response struct { - Features struct { - ILM struct { - Available bool `json:"available"` - Enabled bool `json:"enabled"` - } `json:"ilm"` - } `json:"features"` - } - status, err := h.queryFeatures(&response) - if status == 400 { - // If we get a 400, it's assumed to be the OSS version of Elasticsearch - return false, false, nil - } - if err != nil { - return false, false, wrapErr(err, ErrILMCheckRequestFailed) - } - - avail = response.Features.ILM.Available - enabled = response.Features.ILM.Enabled - return avail, enabled, nil -} - -func (h *ESClientHandler) queryFeatures(to interface{}) (int, error) { - status, body, err := h.client.Request("GET", esFeaturesPath, "", nil, nil) - if status >= 400 || err != nil { - return status, err - } - - if to != nil { - if err := json.Unmarshal(body, to); err != nil { - return status, wrapErrf(err, ErrInvalidResponse, "failed to parse JSON response") - } - } - return status, nil -} - // CheckILMEnabled indicates whether or not ILM is supported for the configured mode and client version. func (h *FileClientHandler) CheckILMEnabled(enabled bool) (bool, error) { + return checkILMEnabled(enabled, h.client) +} + +func checkILMEnabled(enabled bool, c VersionCheckerClient) (bool, error) { if !enabled { return false, nil } - version := h.client.GetVersion() - if checkILMVersion(version) { - return enabled, nil + + ver := c.GetVersion() + if ver.LessThan(esMinDefaultILMVersion) { + return false, errf(ErrESVersionNotSupported, "Elasticsearch %v does not support ILM", ver.String()) } - return false, errf(ErrESVersionNotSupported, - "Elasticsearch %v does not support ILM", version.String()) + return true, nil } // CreateILMPolicy writes given policy to the configured file. @@ -258,20 +136,3 @@ func (h *FileClientHandler) CreateILMPolicy(policy Policy) error { func (h *FileClientHandler) HasILMPolicy(name string) (bool, error) { return false, nil } - -// CreateAlias is a noop implementation. -func (h *FileClientHandler) CreateAlias(alias Alias) error { - return nil -} - -// HasAlias always returns false. -func (h *FileClientHandler) HasAlias(name string) (bool, error) { - return false, nil -} - -// avail: indicates whether version supports ILM -// probe: in case version potentially supports ILM, check the combination of mode + version -// to indicate whether or not ILM support should be enabled or disabled -func checkILMVersion(ver common.Version) (avail bool) { - return !ver.LessThan(esMinILMVersion) -} diff --git a/libbeat/idxmgmt/ilm/client_handler_integration_test.go b/libbeat/idxmgmt/ilm/client_handler_integration_test.go index b6f2755fd3d..42b19cf44ae 100644 --- a/libbeat/idxmgmt/ilm/client_handler_integration_test.go +++ b/libbeat/idxmgmt/ilm/client_handler_integration_test.go @@ -104,100 +104,6 @@ func TestESClientHandler_ILMPolicy(t *testing.T) { }) } -func TestESClientHandler_Alias(t *testing.T) { - makeAlias := func(base string) ilm.Alias { - return ilm.Alias{ - Name: makeName(base), - Pattern: "{now/d}-000001", - } - } - - t.Run("does not exist", func(t *testing.T) { - name := makeName("esch-alias-no") - h := newESClientHandler(t) - b, err := h.HasAlias(name) - assert.NoError(t, err) - assert.False(t, b) - }) - - t.Run("create new", func(t *testing.T) { - alias := makeAlias("esch-alias-create") - h := newESClientHandler(t) - err := h.CreateAlias(alias) - assert.NoError(t, err) - - b, err := h.HasAlias(alias.Name) - assert.NoError(t, err) - assert.True(t, b) - }) - - t.Run("create index exists", func(t *testing.T) { - alias := makeAlias("esch-alias-2create") - h := newESClientHandler(t) - - err := h.CreateAlias(alias) - assert.NoError(t, err) - - // Second time around creating the alias, ErrAliasAlreadyExists is returned: - // the initial index already exists and the write alias points to it. - err = h.CreateAlias(alias) - require.Error(t, err) - assert.Equal(t, ilm.ErrAliasAlreadyExists, ilm.ErrReason(err)) - - b, err := h.HasAlias(alias.Name) - assert.NoError(t, err) - assert.True(t, b) - }) - - t.Run("create alias exists", func(t *testing.T) { - alias := makeAlias("esch-alias-2create") - alias.Pattern = "000001" // no date math, so we get predictable index names - h := newESClientHandler(t) - - err := h.CreateAlias(alias) - assert.NoError(t, err) - - // Rollover, so write alias points at -000002. - es := newRawESClient(t) - _, _, err = es.Request("POST", "/"+alias.Name+"/_rollover", "", nil, nil) - require.NoError(t, err) - - // Delete -000001, simulating ILM delete. - _, _, err = es.Request("DELETE", "/"+alias.Name+"-"+alias.Pattern, "", nil, nil) - require.NoError(t, err) - - // Second time around creating the alias, ErrAliasAlreadyExists is returned: - // initial index does not exist, but the write alias exists and points to - // another index. - err = h.CreateAlias(alias) - require.Error(t, err) - assert.Equal(t, ilm.ErrAliasAlreadyExists, ilm.ErrReason(err)) - - b, err := h.HasAlias(alias.Name) - assert.NoError(t, err) - assert.True(t, b) - }) - - t.Run("resource exists but is not an alias", func(t *testing.T) { - alias := makeAlias("esch-alias-3create") - - es := newRawESClient(t) - - _, _, err := es.Request("PUT", "/"+alias.Name, "", nil, nil) - require.NoError(t, err) - - h := newESClientHandler(t) - - b, err := h.HasAlias(alias.Name) - assert.Equal(t, ilm.ErrInvalidAlias, ilm.ErrReason(err)) - assert.False(t, b) - - err = h.CreateAlias(alias) - require.Error(t, err) - assert.Equal(t, ilm.ErrInvalidAlias, ilm.ErrReason(err)) - }) -} - func newESClientHandler(t *testing.T) ilm.ClientHandler { client := newRawESClient(t) return ilm.NewESClientHandler(client) diff --git a/libbeat/idxmgmt/ilm/config.go b/libbeat/idxmgmt/ilm/config.go index f8e25f22f5b..ea5cd9ac1e4 100644 --- a/libbeat/idxmgmt/ilm/config.go +++ b/libbeat/idxmgmt/ilm/config.go @@ -18,8 +18,6 @@ package ilm import ( - "fmt" - "github.com/elastic/beats/v7/libbeat/beat" "github.com/elastic/beats/v7/libbeat/common" "github.com/elastic/beats/v7/libbeat/common/fmtstr" @@ -27,11 +25,9 @@ import ( // Config is used for unpacking a common.Config. type Config struct { - Enabled bool `config:"enabled"` - PolicyName fmtstr.EventFormatString `config:"policy_name"` - PolicyFile string `config:"policy_file"` - RolloverAlias fmtstr.EventFormatString `config:"rollover_alias"` - Pattern string `config:"pattern"` + Enabled bool `config:"enabled"` + PolicyName fmtstr.EventFormatString `config:"policy_name"` + PolicyFile string `config:"policy_file"` // CheckExists can disable the check for an existing policy. Check required // read_ilm privileges. If check is disabled the policy will only be @@ -42,8 +38,6 @@ type Config struct { Overwrite bool `config:"overwrite"` } -const ilmDefaultPattern = "{now/d}-000001" - // DefaultPolicy defines the default policy to be used if no custom policy is // configured. // By default the policy contains not warm, cold, or delete phase. @@ -65,23 +59,16 @@ var DefaultPolicy = common.MapStr{ //Validate verifies that expected config options are given and valid func (cfg *Config) Validate() error { - if cfg.RolloverAlias.IsEmpty() && cfg.Enabled { - return fmt.Errorf("rollover_alias must be set when ILM is not disabled") - } return nil } func defaultConfig(info beat.Info) Config { - name := info.Beat + "-%{[agent.version]}" - aliasFmt := fmtstr.MustCompileEvent(name) policyFmt := fmtstr.MustCompileEvent(info.Beat) return Config{ - Enabled: true, - PolicyName: *policyFmt, - RolloverAlias: *aliasFmt, - Pattern: ilmDefaultPattern, - PolicyFile: "", - CheckExists: true, + Enabled: true, + PolicyName: *policyFmt, + PolicyFile: "", + CheckExists: true, } } diff --git a/libbeat/idxmgmt/ilm/error.go b/libbeat/idxmgmt/ilm/error.go index a430ea87c4b..b2e9830afd7 100644 --- a/libbeat/idxmgmt/ilm/error.go +++ b/libbeat/idxmgmt/ilm/error.go @@ -36,9 +36,6 @@ var ( ErrInvalidResponse = errors.New("invalid response received") ErrESILMDisabled = errors.New("ILM is disabled in Elasticsearch") ErrRequestFailed = errors.New("request failed") - ErrAliasAlreadyExists = errors.New("alias already exists") - ErrAliasCreateFailed = errors.New("failed to create write alias") - ErrInvalidAlias = errors.New("invalid alias") ErrOpNotAvailable = errors.New("operation not available") ) diff --git a/libbeat/idxmgmt/ilm/ilm.go b/libbeat/idxmgmt/ilm/ilm.go index a9e64e3cbd9..30d4e4f888a 100644 --- a/libbeat/idxmgmt/ilm/ilm.go +++ b/libbeat/idxmgmt/ilm/ilm.go @@ -33,12 +33,11 @@ import ( // SupportFactory is used to define a policy type to be used. type SupportFactory func(*logp.Logger, beat.Info, *common.Config) (Supporter, error) -// Supporter implements ILM support. For loading the policies and creating -// write alias a manager instance must be generated. +// Supporter implements ILM support. For loading the policies +// a manager instance must be generated. type Supporter interface { // Query settings Enabled() bool - Alias() Alias Policy() Policy Overwrite() bool @@ -51,8 +50,6 @@ type Supporter interface { type Manager interface { CheckEnabled() (bool, error) - EnsureAlias() error - // EnsurePolicy installs a policy if it does not exist. The policy is always // written if overwrite is set. // The created flag is set to true only if a new policy is created. `created` @@ -67,12 +64,6 @@ type Policy struct { Body common.MapStr } -// Alias describes the alias to be created in Elasticsearch. -type Alias struct { - Name string - Pattern string -} - // DefaultSupport configures a new default ILM support implementation. func DefaultSupport(log *logp.Logger, info beat.Info, config *common.Config) (Supporter, error) { cfg := defaultConfig(info) @@ -109,16 +100,6 @@ func StdSupport(log *logp.Logger, info beat.Info, config *common.Config) (Suppor return nil, errors.Wrap(err, "failed to read ilm policy name") } - rolloverAlias, err := applyStaticFmtstr(info, &cfg.RolloverAlias) - if err != nil { - return nil, errors.Wrap(err, "failed to read the ilm rollover alias") - } - - alias := Alias{ - Name: rolloverAlias, - Pattern: cfg.Pattern, - } - policy := Policy{ Name: name, Body: DefaultPolicy, @@ -137,7 +118,7 @@ func StdSupport(log *logp.Logger, info beat.Info, config *common.Config) (Suppor policy.Body = body } - return NewStdSupport(log, cfg.Enabled, alias, policy, cfg.Overwrite, cfg.CheckExists), nil + return NewStdSupport(log, cfg.Enabled, policy, cfg.Overwrite, cfg.CheckExists), nil } // NoopSupport configures a new noop ILM support implementation, diff --git a/libbeat/idxmgmt/ilm/ilm_test.go b/libbeat/idxmgmt/ilm/ilm_test.go index 196b48e08ba..d6e33c2a892 100644 --- a/libbeat/idxmgmt/ilm/ilm_test.go +++ b/libbeat/idxmgmt/ilm/ilm_test.go @@ -31,28 +31,13 @@ import ( func TestDefaultSupport_Init(t *testing.T) { info := beat.Info{Beat: "test", Version: "9.9.9"} - t.Run("with an empty rollover_alias", func(t *testing.T) { - _, err := DefaultSupport(nil, info, common.MustNewConfigFrom( - map[string]interface{}{ - "enabled": true, - "rollover_alias": "", - "pattern": "01", - "check_exists": false, - "overwrite": true, - }, - )) - require.Error(t, err) - }) - t.Run("with custom config", func(t *testing.T) { tmp, err := DefaultSupport(nil, info, common.MustNewConfigFrom( map[string]interface{}{ - "enabled": true, - "name": "test-%{[agent.version]}", - "rollover_alias": "alias", - "pattern": "01", - "check_exists": false, - "overwrite": true, + "enabled": true, + "name": "test-%{[agent.version]}", + "check_exists": false, + "overwrite": true, }, )) require.NoError(t, err) @@ -63,17 +48,14 @@ func TestDefaultSupport_Init(t *testing.T) { assert.Equal(false, s.checkExists) assert.Equal(true, s.Enabled()) assert.Equal(DefaultPolicy, common.MapStr(s.Policy().Body)) - assert.Equal(Alias{Name: "alias", Pattern: "01"}, s.Alias()) }) t.Run("with custom alias config with fieldref", func(t *testing.T) { tmp, err := DefaultSupport(nil, info, common.MustNewConfigFrom( map[string]interface{}{ - "enabled": true, - "rollover_alias": "alias-%{[agent.version]}", - "pattern": "01", - "check_exists": false, - "overwrite": true, + "enabled": true, + "check_exists": false, + "overwrite": true, }, )) require.NoError(t, err) @@ -84,7 +66,6 @@ func TestDefaultSupport_Init(t *testing.T) { assert.Equal(false, s.checkExists) assert.Equal(true, s.Enabled()) assert.Equal(DefaultPolicy, common.MapStr(s.Policy().Body)) - assert.Equal(Alias{Name: "alias-9.9.9", Pattern: "01"}, s.Alias()) }) t.Run("with default alias", func(t *testing.T) { @@ -104,7 +85,6 @@ func TestDefaultSupport_Init(t *testing.T) { assert.Equal(false, s.checkExists) assert.Equal(true, s.Enabled()) assert.Equal(DefaultPolicy, common.MapStr(s.Policy().Body)) - assert.Equal(Alias{Name: "test-9.9.9", Pattern: "01"}, s.Alias()) }) t.Run("load external policy", func(t *testing.T) { @@ -146,13 +126,6 @@ func TestDefaultSupport_Manager_Enabled(t *testing.T) { cfg: map[string]interface{}{"enabled": true}, enabled: true, }, - "fail enabled": { - calls: []onCall{ - onCheckILMEnabled(true).Return(false, nil), - }, - cfg: map[string]interface{}{"enabled": true}, - fail: ErrESILMDisabled, - }, "io error": { calls: []onCall{ onCheckILMEnabled(true).Return(false, errors.New("ups")), @@ -189,80 +162,6 @@ func TestDefaultSupport_Manager_Enabled(t *testing.T) { } } -func TestDefaultSupport_Manager_EnsureAlias(t *testing.T) { - alias := Alias{ - Name: "test-9.9.9", - Pattern: ilmDefaultPattern, - } - - cases := map[string]struct { - calls []onCall - cfg map[string]interface{} - fail error - }{ - "create new alias": { - calls: []onCall{ - onHasAlias(alias.Name).Return(false, nil), - onCreateAlias(alias).Return(nil), - }, - }, - "alias already exists": { - calls: []onCall{ - onHasAlias(alias.Name).Return(true, nil), - }, - }, - "fail": { - calls: []onCall{ - onHasAlias(alias.Name).Return(false, nil), - onCreateAlias(alias).Return(errOf(ErrRequestFailed)), - }, - fail: ErrRequestFailed, - }, - "overwrite non-existent": { - calls: []onCall{ - onCreateAlias(alias).Return(nil), - }, - fail: nil, - cfg: map[string]interface{}{"check_exists": true, "overwrite": true}, - }, - "try overwrite existing": { - calls: []onCall{ - onCreateAlias(alias).Return(errOf(ErrAliasAlreadyExists)), - }, - fail: nil, // we detect that that the alias exists, and call it a day. - cfg: map[string]interface{}{"check_exists": true, "overwrite": true}, - }, - "fail to overwrite": { - calls: []onCall{ - onCreateAlias(alias).Return(errOf(ErrAliasCreateFailed)), - }, - fail: ErrAliasCreateFailed, - cfg: map[string]interface{}{"check_exists": true, "overwrite": true}, - }, - } - - for name, test := range cases { - t.Run(name, func(t *testing.T) { - cfg := test.cfg - if cfg == nil { - cfg = map[string]interface{}{"alias": "test"} - } - - h := newMockHandler(test.calls...) - m := createManager(t, h, test.cfg) - err := m.EnsureAlias() - - if test.fail == nil { - require.NoError(t, err) - } else { - require.Error(t, err) - assert.Equal(t, test.fail, ErrReason(err)) - } - h.AssertExpectations(t) - }) - } -} - func TestDefaultSupport_Manager_EnsurePolicy(t *testing.T) { testPolicy := Policy{ Name: "test", diff --git a/libbeat/idxmgmt/ilm/mockapihandler_test.go b/libbeat/idxmgmt/ilm/mockapihandler_test.go index 79148d83f1b..b527ad118d7 100644 --- a/libbeat/idxmgmt/ilm/mockapihandler_test.go +++ b/libbeat/idxmgmt/ilm/mockapihandler_test.go @@ -50,18 +50,6 @@ func (h *mockHandler) CheckILMEnabled(enabled bool) (bool, error) { return args.Bool(0), args.Error(1) } -func onHasAlias(name string) onCall { return makeOnCall("HasAlias", name) } -func (h *mockHandler) HasAlias(name string) (bool, error) { - args := h.Called(name) - return args.Bool(0), args.Error(1) -} - -func onCreateAlias(alias Alias) onCall { return makeOnCall("CreateAlias", alias) } -func (h *mockHandler) CreateAlias(alias Alias) error { - args := h.Called(alias) - return args.Error(0) -} - func onHasILMPolicy(name string) onCall { return makeOnCall("HasILMPolicy", name) } func (h *mockHandler) HasILMPolicy(name string) (bool, error) { args := h.Called(name) diff --git a/libbeat/idxmgmt/ilm/noop.go b/libbeat/idxmgmt/ilm/noop.go index 20586a261d3..a06c173d567 100644 --- a/libbeat/idxmgmt/ilm/noop.go +++ b/libbeat/idxmgmt/ilm/noop.go @@ -26,17 +26,15 @@ type noopSupport struct{} type noopManager struct{} // NewNoopSupport creates a noop ILM implementation with ILM support being always -// disabled. Attempts to install a policy or create a write alias will fail. +// disabled. Attempts to install a policy will fail. func NewNoopSupport(info beat.Info, config *common.Config) (Supporter, error) { return (*noopSupport)(nil), nil } func (*noopSupport) Enabled() bool { return false } -func (*noopSupport) Alias() Alias { return Alias{} } func (*noopSupport) Policy() Policy { return Policy{} } func (*noopSupport) Overwrite() bool { return false } func (*noopSupport) Manager(_ ClientHandler) Manager { return (*noopManager)(nil) } func (*noopManager) CheckEnabled() (bool, error) { return false, nil } -func (*noopManager) EnsureAlias() error { return errOf(ErrOpNotAvailable) } func (*noopManager) EnsurePolicy(_ bool) (bool, error) { return false, errOf(ErrOpNotAvailable) } diff --git a/libbeat/idxmgmt/ilm/std.go b/libbeat/idxmgmt/ilm/std.go index 6363898a0a1..ef8a11f7f21 100644 --- a/libbeat/idxmgmt/ilm/std.go +++ b/libbeat/idxmgmt/ilm/std.go @@ -30,7 +30,6 @@ type stdSupport struct { overwrite bool checkExists bool - alias Alias policy Policy } @@ -53,7 +52,6 @@ var defaultCacheDuration = 5 * time.Minute func NewStdSupport( log *logp.Logger, enabled bool, - alias Alias, policy Policy, overwrite, checkExists bool, ) Supporter { @@ -62,13 +60,11 @@ func NewStdSupport( enabled: enabled, overwrite: overwrite, checkExists: checkExists, - alias: alias, policy: policy, } } func (s *stdSupport) Enabled() bool { return s.enabled } -func (s *stdSupport) Alias() Alias { return s.alias } func (s *stdSupport) Policy() Policy { return s.policy } func (s *stdSupport) Overwrite() bool { return s.overwrite } @@ -93,59 +89,11 @@ func (m *stdManager) CheckEnabled() (bool, error) { return ilmEnabled, err } - if !ilmEnabled && m.enabled { - return false, errOf(ErrESILMDisabled) - } - m.cache.Enabled = ilmEnabled m.cache.LastUpdate = time.Now() return ilmEnabled, nil } -func (m *stdManager) EnsureAlias() error { - log := m.log - if !m.checkExists { - log.Infof("Index alias is not checked as setup.ilm.check_exists is disabled") - return nil - } - - overwrite := m.Overwrite() - name := m.alias.Name - - var exists bool - if !overwrite { - var err error - exists, err = m.client.HasAlias(name) - if err != nil { - return err - } - } - - switch { - case exists && !overwrite: - log.Infof("Index Alias %v exists already.", name) - return nil - - case !exists || overwrite: - err := m.client.CreateAlias(m.alias) - if err != nil { - if ErrReason(err) != ErrAliasAlreadyExists { - log.Errorf("Index Alias %v setup failed: %v.", name, err) - return err - } - log.Infof("Index Alias %v exists already.", name) - return nil - } - - log.Infof("Index Alias %v successfully created.", name) - return nil - - default: - m.log.Infof("ILM index alias not created: exists=%v, overwrite=%v", exists, overwrite) - return nil - } -} - func (m *stdManager) EnsurePolicy(overwrite bool) (bool, error) { log := m.log if !m.checkExists { diff --git a/libbeat/idxmgmt/mockilm_test.go b/libbeat/idxmgmt/mockilm_test.go index d138b46e6a0..05ebbe87353 100644 --- a/libbeat/idxmgmt/mockilm_test.go +++ b/libbeat/idxmgmt/mockilm_test.go @@ -57,12 +57,6 @@ func (m *mockILMSupport) Enabled() bool { return args.Get(0).(bool) } -func onAlias() onCall { return makeOnCall("Alias") } -func (m *mockILMSupport) Alias() ilm.Alias { - args := m.Called() - return args.Get(0).(ilm.Alias) -} - func onPolicy() onCall { return makeOnCall("Policy") } func (m *mockILMSupport) Policy() ilm.Policy { args := m.Called() @@ -84,12 +78,6 @@ func (m *mockILMSupport) CheckEnabled() (bool, error) { return args.Bool(0), args.Error(1) } -func onEnsureAlias() onCall { return makeOnCall("EnsureAlias") } -func (m *mockILMSupport) EnsureAlias() error { - args := m.Called() - return args.Error(0) -} - func onEnsurePolicy() onCall { return makeOnCall("EnsurePolicy") } func (m *mockILMSupport) EnsurePolicy(overwrite bool) (bool, error) { args := m.Called() diff --git a/libbeat/idxmgmt/std.go b/libbeat/idxmgmt/std.go index 6cca4dad683..c9c86444358 100644 --- a/libbeat/idxmgmt/std.go +++ b/libbeat/idxmgmt/std.go @@ -61,13 +61,6 @@ type indexSelector struct { beatInfo beat.Info } -type ilmIndexSelector struct { - index outil.Selector - alias outil.Selector - st *indexState - beatInfo beat.Info -} - type componentType uint8 //go:generate stringer -linecomment -type componentType @@ -112,7 +105,7 @@ func newIndexSupport( return nil, err } - tmplCfg, err := unpackTemplateConfig(tmplConfig) + tmplCfg, err := unpackTemplateConfig(info, tmplConfig) if err != nil { return nil, err } @@ -123,7 +116,7 @@ func newIndexSupport( info: info, templateCfg: tmplCfg, migration: migration, - defaultIndex: fmt.Sprintf("%v-%v-%%{+yyyy.MM.dd}", info.IndexPrefix, info.Version), + defaultIndex: fmt.Sprintf("%v-%v", info.IndexPrefix, info.Version), }, nil } @@ -155,8 +148,6 @@ func (s *indexSupport) Manager( func (s *indexSupport) BuildSelector(cfg *common.Config) (outputs.IndexSelector, error) { var err error - log := s.log - // we construct our own configuration object based on the available settings // in cfg and defaultIndex. The configuration object provided must not be // modified. @@ -177,12 +168,6 @@ func (s *indexSupport) BuildSelector(cfg *common.Config) (outputs.IndexSelector, } } - if s.ilm.Enabled() { - alias := s.ilm.Alias().Name - log.Infof("Set %v to '%s' as ILM is enabled.", cfg.PathOf("index"), alias) - indexName = alias - } - // no index name configuration found yet -> define default index name based on // beat.Info provided to the indexSupport on during setup. if indexName == "" { @@ -213,19 +198,18 @@ func (m *indexManager) VerifySetup(loadTemplate, loadILM LoadMode) (bool, string m.support.templateCfg.Overwrite, loadTemplate) if ilmComponent.load && !templateComponent.load { - return false, "Loading ILM policy and write alias without loading template " + - "is not recommended. Check your configuration." + return false, "Loading ILM policy without loading template is not recommended. Check your configuration." } if templateComponent.load && !ilmComponent.load && ilmComponent.enabled { return false, "Loading template with ILM settings whithout loading ILM " + - "policy and alias can lead to issues and is not recommended. " + + "policy can lead to issues and is not recommended. " + "Check your configuration." } var warn string if !ilmComponent.load { - warn += "ILM policy and write alias loading not enabled.\n" + warn += "ILM policy loading not enabled.\n" } else if !ilmComponent.overwrite { warn += "Overwriting ILM policy is disabled. Set `setup.ilm.overwrite: true` for enabling.\n" } @@ -243,7 +227,7 @@ func (m *indexManager) Setup(loadTemplate, loadILM LoadMode) error { if err != nil { return err } - if withILM && loadILM.Enabled() { + if withILM { log.Info("Auto ILM enable success.") } @@ -269,7 +253,7 @@ func (m *indexManager) Setup(loadTemplate, loadILM LoadMode) error { tmplCfg.Overwrite, tmplCfg.Enabled = templateComponent.overwrite, templateComponent.enabled if ilmComponent.enabled { - tmplCfg, err = applyILMSettings(log, tmplCfg, m.support.ilm.Policy(), m.support.ilm.Alias()) + tmplCfg, err = applyILMSettings(log, tmplCfg, m.support.ilm.Policy()) if err != nil { return err } @@ -283,13 +267,6 @@ func (m *indexManager) Setup(loadTemplate, loadILM LoadMode) error { log.Info("Loaded index template.") } - if ilmComponent.load { - err := m.ilm.EnsureAlias() - if err != nil { - return err - } - } - return nil } @@ -309,20 +286,6 @@ func (m *indexManager) setupWithILM() (bool, error) { return withILM, nil } -func (s *ilmIndexSelector) Select(evt *beat.Event) (string, error) { - if idx := getEventCustomIndex(evt, s.beatInfo); idx != "" { - return idx, nil - } - - if s.st.withILM.Load() { - idx, err := s.alias.Select(evt) - return idx, err - } - - idx, err := s.index.Select(evt) - return idx, err -} - func (s indexSelector) Select(evt *beat.Event) (string, error) { if idx := getEventCustomIndex(evt, s.beatInfo); idx != "" { return idx, nil @@ -335,14 +298,8 @@ func getEventCustomIndex(evt *beat.Event, beatInfo beat.Info) string { return "" } - if alias, err := events.GetMetaStringValue(*evt, events.FieldMetaAlias); err == nil { - return strings.ToLower(alias) - } - if idx, err := events.GetMetaStringValue(*evt, events.FieldMetaIndex); err == nil { - ts := evt.Timestamp.UTC() - return fmt.Sprintf("%s-%d.%02d.%02d", - strings.ToLower(idx), ts.Year(), ts.Month(), ts.Day()) + return strings.ToLower(idx) } // This is functionally identical to Meta["alias"], returning the overriding @@ -356,8 +313,9 @@ func getEventCustomIndex(evt *beat.Event, beatInfo beat.Info) string { return "" } -func unpackTemplateConfig(cfg *common.Config) (config template.TemplateConfig, err error) { - config = template.DefaultConfig() +func unpackTemplateConfig(info beat.Info, cfg *common.Config) (config template.TemplateConfig, err error) { + config = template.DefaultConfig(info) + if cfg != nil { err = cfg.Unpack(&config) } @@ -368,32 +326,15 @@ func applyILMSettings( log *logp.Logger, tmpl template.TemplateConfig, policy ilm.Policy, - alias ilm.Alias, ) (template.TemplateConfig, error) { if !tmpl.Enabled { return tmpl, nil } - if alias.Name == "" { - return tmpl, errors.New("no ilm rollover alias configured") - } - if policy.Name == "" { return tmpl, errors.New("no ilm policy name configured") } - tmpl.Name = alias.Name - if log != nil { - log.Infof("Set setup.template.name to '%s' as ILM is enabled.", alias) - } - - tmpl.Pattern = fmt.Sprintf("%s-*", alias.Name) - if log != nil { - log.Infof("Set setup.template.pattern to '%s' as ILM is enabled.", tmpl.Pattern) - } - - // rollover_alias and lifecycle.name can't be configured and will be overwritten - // init/copy index settings idxSettings := tmpl.Settings.Index if idxSettings == nil { @@ -421,11 +362,6 @@ func applyILMSettings( } idxSettings["lifecycle"] = lifecycle - // add rollover_alias and name to index.lifecycle settings - if _, exists := lifecycle["rollover_alias"]; !exists { - log.Infof("Set settings.index.lifecycle.rollover_alias in template to %s as ILM is enabled.", alias) - lifecycle["rollover_alias"] = alias.Name - } if _, exists := lifecycle["name"]; !exists { log.Infof("Set settings.index.lifecycle.name in template to %s as ILM is enabled.", policy) lifecycle["name"] = policy.Name diff --git a/libbeat/idxmgmt/std_test.go b/libbeat/idxmgmt/std_test.go index 76b0ac9879e..8859204be91 100644 --- a/libbeat/idxmgmt/std_test.go +++ b/libbeat/idxmgmt/std_test.go @@ -18,7 +18,6 @@ package idxmgmt import ( - "fmt" "testing" "time" @@ -33,7 +32,7 @@ import ( ) type mockClientHandler struct { - alias, policy string + policy string expectsPolicy bool tmplCfg *template.TemplateConfig @@ -47,7 +46,6 @@ type mockCreateOp uint8 const ( mockCreatePolicy mockCreateOp = iota mockCreateTemplate - mockCreateAlias ) func TestDefaultSupport_Enabled(t *testing.T) { @@ -99,10 +97,9 @@ func TestDefaultSupport_BuildSelector(t *testing.T) { type nameFunc func(time.Time) string noILM := []onCall{onEnabled().Return(false)} - ilmTemplateSettings := func(alias, policy string) []onCall { + ilmTemplateSettings := func(policy string) []onCall { return []onCall{ onEnabled().Return(true), - onAlias().Return(ilm.Alias{Name: alias}), onPolicy().Return(ilm.Policy{Name: policy}), } } @@ -110,13 +107,6 @@ func TestDefaultSupport_BuildSelector(t *testing.T) { stable := func(s string) nameFunc { return func(_ time.Time) string { return s } } - dateIdx := func(base string) nameFunc { - return func(ts time.Time) string { - ts = ts.UTC() - ext := fmt.Sprintf("%d.%02d.%02d", ts.Year(), ts.Month(), ts.Day()) - return fmt.Sprintf("%v-%v", base, ext) - } - } cases := map[string]struct { ilmCalls []onCall @@ -135,26 +125,10 @@ func TestDefaultSupport_BuildSelector(t *testing.T) { cfg: map[string]interface{}{"index": "TeSt-%{[agent.version]}"}, want: stable("test-9.9.9"), }, - "event alias without ilm": { - ilmCalls: noILM, - cfg: map[string]interface{}{"index": "test-%{[agent.version]}"}, - want: stable("test"), - meta: common.MapStr{ - "alias": "test", - }, - }, - "event alias without ilm must be lowercae": { - ilmCalls: noILM, - cfg: map[string]interface{}{"index": "test-%{[agent.version]}"}, - want: stable("test"), - meta: common.MapStr{ - "alias": "Test", - }, - }, "event index without ilm": { ilmCalls: noILM, cfg: map[string]interface{}{"index": "test-%{[agent.version]}"}, - want: dateIdx("test"), + want: stable("test"), meta: common.MapStr{ "index": "test", }, @@ -162,47 +136,31 @@ func TestDefaultSupport_BuildSelector(t *testing.T) { "event index without ilm must be lowercase": { ilmCalls: noILM, cfg: map[string]interface{}{"index": "test-%{[agent.version]}"}, - want: dateIdx("test"), + want: stable("test"), meta: common.MapStr{ "index": "Test", }, }, "with ilm": { - ilmCalls: ilmTemplateSettings("test-9.9.9", "test-9.9.9"), - cfg: map[string]interface{}{"index": "wrong-%{[agent.version]}"}, + ilmCalls: ilmTemplateSettings("test-9.9.9"), + cfg: map[string]interface{}{"index": "test-%{[agent.version]}"}, want: stable("test-9.9.9"), }, "with ilm must be lowercase": { - ilmCalls: ilmTemplateSettings("Test-9.9.9", "Test-9.9.9"), - cfg: map[string]interface{}{"index": "wrong-%{[agent.version]}"}, - want: stable("test-9.9.9"), - }, - "event alias wit ilm": { - ilmCalls: ilmTemplateSettings("test-9.9.9", "test-9.9.9"), - cfg: map[string]interface{}{"index": "test-%{[agent.version]}"}, - want: stable("event-alias"), - meta: common.MapStr{ - "alias": "event-alias", - }, - }, - "event alias wit ilm must be lowercase": { - ilmCalls: ilmTemplateSettings("test-9.9.9", "test-9.9.9"), + ilmCalls: ilmTemplateSettings("Test-9.9.9"), cfg: map[string]interface{}{"index": "test-%{[agent.version]}"}, - want: stable("event-alias"), - meta: common.MapStr{ - "alias": "Event-alias", - }, + want: stable("test-9.9.9"), }, "event index with ilm": { - ilmCalls: ilmTemplateSettings("test-9.9.9", "test-9.9.9"), + ilmCalls: ilmTemplateSettings("test-9.9.9"), cfg: map[string]interface{}{"index": "test-%{[agent.version]}"}, - want: dateIdx("event-index"), + want: stable("event-index"), meta: common.MapStr{ "index": "event-index", }, }, "use indices": { - ilmCalls: ilmTemplateSettings("test-9.9.9", "test-9.9.9"), + ilmCalls: ilmTemplateSettings("test-9.9.9"), cfg: map[string]interface{}{ "index": "test-%{[agent.version]}", "indices": []map[string]interface{}{ @@ -212,7 +170,7 @@ func TestDefaultSupport_BuildSelector(t *testing.T) { want: stable("myindex"), }, "use indices settings must be lowercase": { - ilmCalls: ilmTemplateSettings("test-9.9.9", "test-9.9.9"), + ilmCalls: ilmTemplateSettings("test-9.9.9"), cfg: map[string]interface{}{ "index": "test-%{[agent.version]}", "indices": []map[string]interface{}{ @@ -260,7 +218,7 @@ func TestIndexManager_VerifySetup(t *testing.T) { }{ "load template with ilm without loading ilm": { ilmEnabled: true, tmplEnabled: true, loadILM: LoadModeDisabled, - warn: "whithout loading ILM policy and alias", + warn: "whithout loading ILM policy", }, "load ilm without template": { ilmEnabled: true, loadILM: LoadModeUnset, @@ -346,40 +304,36 @@ func TestIndexManager_Setup(t *testing.T) { } return &s } - defaultCfg := template.DefaultConfig() + info := beat.Info{Beat: "test", Version: "9.9.9"} + defaultCfg := template.DefaultConfig(info) cases := map[string]struct { cfg common.MapStr loadTemplate, loadILM LoadMode - err bool - tmplCfg *template.TemplateConfig - alias, policy string + err bool + tmplCfg *template.TemplateConfig + policy string }{ "template default ilm default": { - tmplCfg: cfgWith(template.DefaultConfig(), map[string]interface{}{ + tmplCfg: cfgWith(template.DefaultConfig(info), map[string]interface{}{ "overwrite": "true", "name": "test-9.9.9", - "pattern": "test-9.9.9-*", + "pattern": "test-9.9.9", "settings.index.lifecycle.name": "test", - "settings.index.lifecycle.rollover_alias": "test-9.9.9", }), - alias: "test-9.9.9", policy: "test", }, - "template default ilm default with alias and policy changed": { + "template default ilm default with policy changed": { cfg: common.MapStr{ - "setup.ilm.rollover_alias": "mocktest", - "setup.ilm.policy_name": "policy-keep", + "setup.ilm.policy_name": "policy-keep", }, - tmplCfg: cfgWith(template.DefaultConfig(), map[string]interface{}{ + tmplCfg: cfgWith(template.DefaultConfig(info), map[string]interface{}{ "overwrite": "true", - "name": "mocktest", - "pattern": "mocktest-*", + "name": "test-9.9.9", + "pattern": "test-9.9.9", "settings.index.lifecycle.name": "policy-keep", - "settings.index.lifecycle.rollover_alias": "mocktest", }), - alias: "mocktest", policy: "policy-keep", }, "template default ilm disabled": { @@ -394,16 +348,20 @@ func TestIndexManager_Setup(t *testing.T) { "setup.ilm.enabled": false, }, loadTemplate: LoadModeOverwrite, - tmplCfg: cfgWith(template.DefaultConfig(), map[string]interface{}{ + tmplCfg: cfgWith(template.DefaultConfig(info), map[string]interface{}{ "overwrite": "true", + "name": "test-9.9.9", + "pattern": "test-9.9.9", }), }, "template default loadMode Force ilm disabled": { cfg: common.MapStr{ "setup.ilm.enabled": false, + "name": "test-9.9.9", + "pattern": "test-9.9.9", }, loadTemplate: LoadModeForce, - tmplCfg: cfgWith(template.DefaultConfig(), map[string]interface{}{ + tmplCfg: cfgWith(template.DefaultConfig(info), map[string]interface{}{ "overwrite": "true", }), }, @@ -417,7 +375,6 @@ func TestIndexManager_Setup(t *testing.T) { cfg: common.MapStr{ "setup.template.enabled": false, }, - alias: "test-9.9.9", policy: "test", }, "template disabled ilm disabled, loadMode Overwrite": { @@ -433,22 +390,19 @@ func TestIndexManager_Setup(t *testing.T) { "setup.ilm.enabled": false, }, loadILM: LoadModeForce, - alias: "test-9.9.9", policy: "test", }, "template loadmode disabled ilm loadMode enabled": { loadTemplate: LoadModeDisabled, loadILM: LoadModeEnabled, - alias: "test-9.9.9", policy: "test", }, "template default ilm loadMode disabled": { loadILM: LoadModeDisabled, - tmplCfg: cfgWith(template.DefaultConfig(), map[string]interface{}{ + tmplCfg: cfgWith(template.DefaultConfig(info), map[string]interface{}{ "name": "test-9.9.9", - "pattern": "test-9.9.9-*", + "pattern": "test-9.9.9", "settings.index.lifecycle.name": "test", - "settings.index.lifecycle.rollover_alias": "test-9.9.9", }), }, "template loadmode disabled ilm loadmode disabled": { @@ -458,7 +412,6 @@ func TestIndexManager_Setup(t *testing.T) { } for name, test := range cases { t.Run(name, func(t *testing.T) { - info := beat.Info{Beat: "test", Version: "9.9.9"} factory := MakeDefaultSupport(ilm.StdSupport) im, err := factory(nil, info, common.MustNewConfigFrom(test.cfg)) require.NoError(t, err) @@ -477,7 +430,6 @@ func TestIndexManager_Setup(t *testing.T) { } else { assert.Equal(t, test.tmplCfg, clientHandler.tmplCfg) } - assert.Equal(t, test.alias, clientHandler.alias) assert.Equal(t, test.policy, clientHandler.policy) } }) @@ -485,7 +437,7 @@ func TestIndexManager_Setup(t *testing.T) { } func (op mockCreateOp) String() string { - names := []string{"create-policy", "create-template", "create-alias"} + names := []string{"create-policy", "create-template"} if int(op) > len(names) { return "unknown" } @@ -507,16 +459,6 @@ func (h *mockClientHandler) CheckILMEnabled(enabled bool) (bool, error) { return enabled, nil } -func (h *mockClientHandler) HasAlias(name string) (bool, error) { - return h.alias == name, nil -} - -func (h *mockClientHandler) CreateAlias(alias ilm.Alias) error { - h.recordOp(mockCreateAlias) - h.alias = alias.Name - return nil -} - func (h *mockClientHandler) HasILMPolicy(name string) (bool, error) { return h.policy == name, nil } diff --git a/libbeat/logp/config.go b/libbeat/logp/config.go index c5de43ae51a..1e82b6e7dd8 100644 --- a/libbeat/logp/config.go +++ b/libbeat/logp/config.go @@ -19,8 +19,6 @@ package logp import ( "time" - - "github.com/elastic/beats/v7/libbeat/common/file" ) // Config contains the configuration options for the logger. To create a Config @@ -47,15 +45,14 @@ type Config struct { // FileConfig contains the configuration options for the file output. type FileConfig struct { - Path string `config:"path" yaml:"path"` - Name string `config:"name" yaml:"name"` - Suffix file.SuffixType `config:"suffix" yaml:"suffix"` - MaxSize uint `config:"rotateeverybytes" yaml:"rotateeverybytes" validate:"min=1"` - MaxBackups uint `config:"keepfiles" yaml:"keepfiles" validate:"max=1024"` - Permissions uint32 `config:"permissions"` - Interval time.Duration `config:"interval"` - RotateOnStartup bool `config:"rotateonstartup"` - RedirectStderr bool `config:"redirect_stderr" yaml:"redirect_stderr"` + Path string `config:"path" yaml:"path"` + Name string `config:"name" yaml:"name"` + MaxSize uint `config:"rotateeverybytes" yaml:"rotateeverybytes" validate:"min=1"` + MaxBackups uint `config:"keepfiles" yaml:"keepfiles" validate:"max=1024"` + Permissions uint32 `config:"permissions"` + Interval time.Duration `config:"interval"` + RotateOnStartup bool `config:"rotateonstartup"` + RedirectStderr bool `config:"redirect_stderr" yaml:"redirect_stderr"` } // MetricsConfig contains configuration used by the monitor to output metrics into the logstream. @@ -76,7 +73,6 @@ func DefaultConfig(environment Environment) Config { return Config{ Level: defaultLevel, Files: FileConfig{ - Suffix: file.SuffixCount, MaxSize: 10 * 1024 * 1024, MaxBackups: 7, Permissions: 0600, diff --git a/libbeat/logp/core.go b/libbeat/logp/core.go index c85a5feeaec..552c81e9201 100644 --- a/libbeat/logp/core.go +++ b/libbeat/logp/core.go @@ -241,7 +241,6 @@ func makeFileOutput(cfg Config) (zapcore.Core, error) { file.Interval(cfg.Files.Interval), file.RotateOnStartup(cfg.Files.RotateOnStartup), file.RedirectStderr(cfg.Files.RedirectStderr), - file.Suffix(cfg.Files.Suffix), ) if err != nil { return nil, errors.Wrap(err, "failed to create file rotator") diff --git a/libbeat/logp/core_test.go b/libbeat/logp/core_test.go index 293f57098eb..f8537eb6aa7 100644 --- a/libbeat/logp/core_test.go +++ b/libbeat/logp/core_test.go @@ -153,7 +153,7 @@ func TestLoggingECSFields(t *testing.T) { Level: DebugLevel, development: true, Files: FileConfig{ - Name: "beat1.log", + Name: "beat1", }, } ToObserverOutput()(&cfg) diff --git a/libbeat/metric/system/cgroup/cgv2/io_helper_linux.go b/libbeat/metric/system/cgroup/cgv2/io_helper_linux.go index c56c903cfc8..b62709c7352 100644 --- a/libbeat/metric/system/cgroup/cgv2/io_helper_linux.go +++ b/libbeat/metric/system/cgroup/cgv2/io_helper_linux.go @@ -30,10 +30,13 @@ import ( // fetchDeviceName will attempt to find a device name associated with a major/minor pair // the bool indicates if a device was found. -func fetchDeviceName(major, minor uint64) (bool, string, error) { +func fetchDeviceName(major uint64, minor uint64) (bool, string, error) { // iterate over /dev/ and pull major and minor values found := false var devName string + var curMajor uint64 + var curMinor uint64 + var devID uint64 walkFunc := func(path string, d fs.DirEntry, err error) error { if d.IsDir() && path != "/dev/" { return fs.SkipDir @@ -49,12 +52,13 @@ func fetchDeviceName(major, minor uint64) (bool, string, error) { if !ok { return nil } - devID := infoT.Rdev + devID = uint64(infoT.Rdev) + // do some bitmapping to extract the major and minor device values // The odd duplicated logic here is to deal with 32 and 64 bit values. // see bits/sysmacros.h - curMajor := ((devID & 0xfffff00000000000) >> 32) | ((devID & 0x00000000000fff00) >> 8) - curMinor := ((devID & 0x00000000000000ff) >> 0) | ((devID & 0x00000ffffff00000) >> 12) + curMajor = ((devID & 0xfffff00000000000) >> 32) | ((devID & 0x00000000000fff00) >> 8) + curMinor = ((devID & 0x00000000000000ff) >> 0) | ((devID & 0x00000ffffff00000) >> 12) if curMajor == major && curMinor == minor { found = true devName = d.Name() diff --git a/libbeat/metric/system/cgroup/reader.go b/libbeat/metric/system/cgroup/reader.go index f8497de1b42..c8ea95bb371 100644 --- a/libbeat/metric/system/cgroup/reader.go +++ b/libbeat/metric/system/cgroup/reader.go @@ -21,12 +21,14 @@ import ( "fmt" "io/ioutil" "path/filepath" + "strconv" "strings" "github.com/pkg/errors" "github.com/elastic/beats/v7/libbeat/metric/system/cgroup/cgv1" "github.com/elastic/beats/v7/libbeat/metric/system/cgroup/cgv2" + "github.com/elastic/beats/v7/libbeat/metric/system/resolve" ) // StatsV1 contains metrics and limits from each of the cgroup subsystems. @@ -71,7 +73,7 @@ type mount struct { type Reader struct { // Mountpoint of the root filesystem. Defaults to / if not set. This can be // useful for example if you mount / as /rootfs inside of a container. - rootfsMountpoint string + rootfsMountpoint resolve.Resolver ignoreRootCgroups bool // Ignore a cgroup when its path is "/". cgroupsHierarchyOverride string cgroupMountpoints Mountpoints // Mountpoints for each subsystem (e.g. cpu, cpuacct, memory, blkio). @@ -81,8 +83,8 @@ type Reader struct { type ReaderOptions struct { // RootfsMountpoint holds the mountpoint of the root filesystem. // - // If unspecified, "/" is assumed. - RootfsMountpoint string + // pass + RootfsMountpoint resolve.Resolver // IgnoreRootCgroups ignores cgroup subsystem with the path "/". IgnoreRootCgroups bool @@ -98,7 +100,7 @@ type ReaderOptions struct { } // NewReader creates and returns a new Reader. -func NewReader(rootfsMountpoint string, ignoreRootCgroups bool) (*Reader, error) { +func NewReader(rootfsMountpoint resolve.Resolver, ignoreRootCgroups bool) (*Reader, error) { return NewReaderOptions(ReaderOptions{ RootfsMountpoint: rootfsMountpoint, IgnoreRootCgroups: ignoreRootCgroups, @@ -107,10 +109,6 @@ func NewReader(rootfsMountpoint string, ignoreRootCgroups bool) (*Reader, error) // NewReaderOptions creates and returns a new Reader with the given options. func NewReaderOptions(opts ReaderOptions) (*Reader, error) { - if opts.RootfsMountpoint == "" { - opts.RootfsMountpoint = "/" - } - // Determine what subsystems are supported by the kernel. subsystems, err := SupportedSubsystems(opts.RootfsMountpoint) // We can return a not-quite-an-error ErrCgroupsMissing here, so return the bare error. @@ -134,7 +132,8 @@ func NewReaderOptions(opts ReaderOptions) (*Reader, error) { // CgroupsVersion reports if the given PID is attached to a V1 or V2 controller func (r *Reader) CgroupsVersion(pid int) (CgroupsVersion, error) { - cgPath := filepath.Join(r.rootfsMountpoint, "/proc/", fmt.Sprintf("%d", pid), "cgroup") + cgPath := filepath.Join("/proc/", strconv.Itoa(pid), "cgroup") + cgPath = r.rootfsMountpoint.ResolveHostFS(cgPath) cgraw, err := ioutil.ReadFile(cgPath) if err != nil { return CgroupsV1, errors.Wrapf(err, "error reading %s", cgPath) @@ -227,7 +226,7 @@ func (r *Reader) GetV2StatsForProcess(pid int) (*StatsV2, error) { // ProcessCgroupPaths is a wrapper around Reader.ProcessCgroupPaths for libraries that only need the slimmer functionality from // the gosigar cgroups code. This does not have the same function signature, and consumers still need to distinguish between v1 and v2 cgroups. -func ProcessCgroupPaths(hostfs string, pid int) (PathList, error) { +func ProcessCgroupPaths(hostfs resolve.Resolver, pid int) (PathList, error) { reader, err := NewReader(hostfs, false) if err != nil { return PathList{}, errors.Wrap(err, "error creating cgroups reader") diff --git a/libbeat/metric/system/cgroup/reader_test.go b/libbeat/metric/system/cgroup/reader_test.go index bd539d30560..d6f707086ed 100644 --- a/libbeat/metric/system/cgroup/reader_test.go +++ b/libbeat/metric/system/cgroup/reader_test.go @@ -23,6 +23,8 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/elastic/beats/v7/libbeat/metric/system/resolve" ) const ( @@ -31,7 +33,7 @@ const ( ) func TestReaderGetStatsV1(t *testing.T) { - reader, err := NewReader("testdata/docker", true) + reader, err := NewReader(resolve.NewTestResolver("testdata/docker"), true) assert.NoError(t, err, "error in NewReader") stats, err := reader.GetV1StatsForProcess(985) @@ -67,7 +69,7 @@ func TestReaderGetStatsV1(t *testing.T) { } func TestReaderGetStatsV2(t *testing.T) { - reader, err := NewReader("testdata/docker", true) + reader, err := NewReader(resolve.NewTestResolver("testdata/docker"), true) assert.NoError(t, err, "error in NewReader") stats, err := reader.GetV2StatsForProcess(312) @@ -93,7 +95,7 @@ func TestReaderGetStatsHierarchyOverride(t *testing.T) { // within a Docker container. reader, err := NewReaderOptions(ReaderOptions{ - RootfsMountpoint: "testdata/docker", + RootfsMountpoint: resolve.NewTestResolver("testdata/docker"), IgnoreRootCgroups: false, CgroupsHierarchyOverride: "/", }) @@ -113,7 +115,7 @@ func TestReaderGetStatsHierarchyOverride(t *testing.T) { assert.NotZero(t, stats.CPU.CFS.Shares) reader2, err := NewReaderOptions(ReaderOptions{ - RootfsMountpoint: "testdata/docker", + RootfsMountpoint: resolve.NewTestResolver("testdata/docker"), IgnoreRootCgroups: true, CgroupsHierarchyOverride: "/system.slice/", }) diff --git a/libbeat/metric/system/cgroup/util.go b/libbeat/metric/system/cgroup/util.go index 70879b87738..2d1678b790b 100644 --- a/libbeat/metric/system/cgroup/util.go +++ b/libbeat/metric/system/cgroup/util.go @@ -29,6 +29,7 @@ import ( "github.com/pkg/errors" "github.com/elastic/beats/v7/libbeat/logp" + "github.com/elastic/beats/v7/libbeat/metric/system/resolve" ) var ( @@ -119,12 +120,8 @@ func parseMountinfoLine(line string) (mountinfo, error) { // SupportedSubsystems returns the subsystems that are supported by the // kernel. The returned map contains a entry for each subsystem. -func SupportedSubsystems(rootfsMountpoint string) (map[string]struct{}, error) { - if rootfsMountpoint == "" { - rootfsMountpoint = "/" - } - - cgroups, err := os.Open(filepath.Join(rootfsMountpoint, "proc", "cgroups")) +func SupportedSubsystems(rootfs resolve.Resolver) (map[string]struct{}, error) { + cgroups, err := os.Open(rootfs.ResolveHostFS("/proc/cgroups")) if err != nil { if os.IsNotExist(err) { return nil, ErrCgroupsMissing @@ -171,12 +168,9 @@ func SupportedSubsystems(rootfsMountpoint string) (map[string]struct{}, error) { // SubsystemMountpoints returns the mountpoints for each of the given subsystems. // The returned map contains the subsystem name as a key and the value is the // mountpoint. -func SubsystemMountpoints(rootfsMountpoint string, subsystems map[string]struct{}) (Mountpoints, error) { - if rootfsMountpoint == "" { - rootfsMountpoint = "/" - } +func SubsystemMountpoints(rootfs resolve.Resolver, subsystems map[string]struct{}) (Mountpoints, error) { - mountinfo, err := os.Open(filepath.Join(rootfsMountpoint, "proc", "self", "mountinfo")) + mountinfo, err := os.Open(rootfs.ResolveHostFS("/proc/self/mountinfo")) if err != nil { return Mountpoints{}, err } @@ -199,7 +193,8 @@ func SubsystemMountpoints(rootfsMountpoint string, subsystems map[string]struct{ return Mountpoints{}, err } - if !strings.HasPrefix(mount.mountpoint, rootfsMountpoint) { + // if the mountpoint from the subsystem has a different root than ours, it probably belongs to something else. + if !strings.HasPrefix(mount.mountpoint, rootfs.ResolveHostFS("")) { continue } @@ -237,7 +232,8 @@ func SubsystemMountpoints(rootfsMountpoint string, subsystems map[string]struct{ // ProcessCgroupPaths returns the cgroups to which a process belongs and the // pathname of the cgroup relative to the mountpoint of the subsystem. func (r Reader) ProcessCgroupPaths(pid int) (PathList, error) { - cgroup, err := os.Open(filepath.Join(r.rootfsMountpoint, "proc", strconv.Itoa(pid), "cgroup")) + cgroupPath := filepath.Join("proc", strconv.Itoa(pid), "cgroup") + cgroup, err := os.Open(r.rootfsMountpoint.ResolveHostFS(cgroupPath)) if err != nil { return PathList{}, err //return a blank error so other events can use any file not found errors } @@ -271,15 +267,14 @@ func (r Reader) ProcessCgroupPaths(pid int) (PathList, error) { // For this very annoying edge case, revert to the hostfs flag // If it's not set, warn the user that they've hit this. controllerPath := filepath.Join(r.cgroupMountpoints.V2Loc, path) - // Depending on the test environment, Hostfs can either be blank, or `/` - if r.cgroupMountpoints.V2Loc == "" && len(r.rootfsMountpoint) <= 1 { + if r.cgroupMountpoints.V2Loc == "" && !r.rootfsMountpoint.IsSet() { logp.L().Debugf(`PID %d contains a cgroups V2 path (%s) but no V2 mountpoint was found. This may be because metricbeat is running inside a container on a hybrid system. To monitor cgroups V2 processess in this way, mount the unified (V2) hierarchy inside -the container as /sys/fs/cgroup/unified and start metricbeat with --system.hostfs.`, pid, line) +the container as /sys/fs/cgroup/unified and start the system module with the hostfs setting.`, pid, line) continue - } else if r.cgroupMountpoints.V2Loc == "" && len(r.rootfsMountpoint) > 1 { - controllerPath = filepath.Join(r.rootfsMountpoint, "/sys/fs/cgroup/unified", path) + } else if r.cgroupMountpoints.V2Loc == "" && r.rootfsMountpoint.IsSet() { + controllerPath = r.rootfsMountpoint.ResolveHostFS(filepath.Join("/sys/fs/cgroup/unified", path)) } cgpaths, err := ioutil.ReadDir(controllerPath) diff --git a/libbeat/metric/system/cgroup/util_test.go b/libbeat/metric/system/cgroup/util_test.go index 8766ccb2e04..24ee5784989 100644 --- a/libbeat/metric/system/cgroup/util_test.go +++ b/libbeat/metric/system/cgroup/util_test.go @@ -26,6 +26,8 @@ import ( "testing" "github.com/stretchr/testify/assert" + + "github.com/elastic/beats/v7/libbeat/metric/system/resolve" ) const dockerTestData = "testdata/docker.zip" @@ -103,7 +105,7 @@ func exists(path string) (bool, error) { } func TestSupportedSubsystems(t *testing.T) { - subsystems, err := SupportedSubsystems("testdata/docker") + subsystems, err := SupportedSubsystems(resolve.NewTestResolver("testdata/docker")) if err != nil { t.Fatal(err) } @@ -126,7 +128,7 @@ func TestSupportedSubsystems(t *testing.T) { } func TestSupportedSubsystemsErrCgroupsMissing(t *testing.T) { - _, err := SupportedSubsystems("testdata/doesnotexist") + _, err := SupportedSubsystems(resolve.NewTestResolver("testdata/doesnotexist")) if err != ErrCgroupsMissing { t.Fatalf("expected ErrCgroupsMissing, but got %v", err) } @@ -144,7 +146,7 @@ func TestSubsystemMountpoints(t *testing.T) { subsystems["memory"] = struct{}{} subsystems["perf_event"] = struct{}{} - mountpoints, err := SubsystemMountpoints("testdata/docker", subsystems) + mountpoints, err := SubsystemMountpoints(resolve.NewTestResolver("testdata/docker"), subsystems) if err != nil { t.Fatal(err) } @@ -161,7 +163,7 @@ func TestSubsystemMountpoints(t *testing.T) { } func TestProcessCgroupPaths(t *testing.T) { - reader, err := NewReader("testdata/docker", false) + reader, err := NewReader(resolve.NewTestResolver("testdata/docker"), false) if err != nil { t.Fatalf("error in NewReader: %s", err) } @@ -185,7 +187,7 @@ func TestProcessCgroupPaths(t *testing.T) { } func TestProcessCgroupPathsV2(t *testing.T) { - reader, err := NewReader("testdata/docker", false) + reader, err := NewReader(resolve.NewTestResolver("testdata/docker"), false) if err != nil { t.Fatalf("error in NewReader: %s", err) } diff --git a/libbeat/metric/system/numcpu/cpu_linux.go b/libbeat/metric/system/numcpu/cpu_linux.go index d8f2e9f821c..af5a80f51a1 100644 --- a/libbeat/metric/system/numcpu/cpu_linux.go +++ b/libbeat/metric/system/numcpu/cpu_linux.go @@ -21,12 +21,9 @@ import ( "fmt" "io/ioutil" "os" - "path/filepath" "strings" "github.com/pkg/errors" - - "github.com/elastic/beats/v7/libbeat/paths" ) // getCPU implements NumCPU on linux @@ -45,20 +42,19 @@ func getCPU() (int, bool, error) { if isPresent { cpuPath = "/sys/devices/system/cpu/present" } - sysfspath := filepath.Join(paths.Paths.Hostfs, cpuPath) - rawFile, err := ioutil.ReadFile(sysfspath) + rawFile, err := ioutil.ReadFile(cpuPath) // if the file doesn't exist, assume it's a support issue and not a bug if errors.Is(err, os.ErrNotExist) { return -1, false, nil } if err != nil { - return -1, false, errors.Wrapf(err, "error reading file %s", sysfspath) + return -1, false, errors.Wrapf(err, "error reading file %s", cpuPath) } cpuCount, err := parseCPUList(string(rawFile)) if err != nil { - return -1, false, errors.Wrapf(err, "error parsing file %s", sysfspath) + return -1, false, errors.Wrapf(err, "error parsing file %s", cpuPath) } return cpuCount, true, nil } diff --git a/libbeat/metric/system/process/process.go b/libbeat/metric/system/process/process.go index b5a1f486d9d..a628690ae4b 100644 --- a/libbeat/metric/system/process/process.go +++ b/libbeat/metric/system/process/process.go @@ -462,6 +462,7 @@ func (procStats *Stats) Init() error { cgReader, err := cgroup.NewReaderOptions(procStats.CgroupOpts) if err == cgroup.ErrCgroupsMissing { logp.Warn("cgroup data collection will be disabled: %v", err) + procStats.EnableCgroups = false } else if err != nil { return errors.Wrap(err, "error initializing cgroup reader") } diff --git a/libbeat/metric/system/resolve/resolve.go b/libbeat/metric/system/resolve/resolve.go new file mode 100644 index 00000000000..3f919897f09 --- /dev/null +++ b/libbeat/metric/system/resolve/resolve.go @@ -0,0 +1,56 @@ +// Licensed to Elasticsearch B.V. under one or more contributor +// license agreements. See the NOTICE file distributed with +// this work for additional information regarding copyright +// ownership. Elasticsearch B.V. licenses this file to you 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 resolve + +import "path/filepath" + +// Resolver is an interface for HostFS resolvers. This is meant to be generic and (hopefully) future-proof way of dealing with a user-supplied root filesystem path. +// A resolver-style function serves two ends: +// 1) if we attempt to stop consumers from merely "saving off" a string, the underlying implementation can update hostfs values and pass the new paths along to consumers +// 2) This stops different bits of code from making different assumptions about what's in hostfs and otherwise treating the concept differently. It's easy to mix up "hostfs" and "procfs" and "sysfs" as concepts. +// A single resolver forces this logic to be a little more centralized. +type Resolver interface { + // ResolveHostFS Resolves a path based on a user-set HostFS flag, in cases where a user wants to monitor an alternate filesystem root + // If no user root has been set, it will return the input string + ResolveHostFS(string) string + // IsSet returns true if the user has set an alternate filesystem root + IsSet() bool +} + +// TestingResolver is a bare implementation of the resolver, for system tests that need a Resolver object or a test path for input files. +type TestingResolver struct { + path string + isSet bool +} + +// NewTestResolver returns a new resolver for internal testing, or other uses outside metricbeat modules. +func NewTestResolver(path string) TestingResolver { + if path == "" || path == "/" { + return TestingResolver{path: "/", isSet: false} + } + + return TestingResolver{path: path, isSet: true} +} + +func (t TestingResolver) ResolveHostFS(path string) string { + return filepath.Join(t.path, path) +} + +func (t TestingResolver) IsSet() bool { + return t.isSet +} diff --git a/libbeat/outputs/elasticsearch/client.go b/libbeat/outputs/elasticsearch/client.go index deab29c3dcd..0d9d619b9f5 100644 --- a/libbeat/outputs/elasticsearch/client.go +++ b/libbeat/outputs/elasticsearch/client.go @@ -38,6 +38,8 @@ import ( "github.com/elastic/beats/v7/libbeat/testing" ) +var errPayloadTooLarge = errors.New("the bulk payload is too large for the server. Consider to adjust `http.max_content_length` parameter in Elasticsearch or `bulk_max_size` in the beat. The batch has been dropped") + // Client is an elasticsearch client. type Client struct { conn eslegclient.Connection @@ -180,9 +182,13 @@ func (client *Client) Clone() *Client { func (client *Client) Publish(ctx context.Context, batch publisher.Batch) error { events := batch.Events() rest, err := client.publishEvents(ctx, events) - if len(rest) == 0 { + + switch { + case err == errPayloadTooLarge: + batch.Drop() + case len(rest) == 0: batch.ACK() - } else { + default: batch.RetryEvents(rest) } return err @@ -220,7 +226,11 @@ func (client *Client) publishEvents(ctx context.Context, data []publisher.Event) } status, result, sendErr := client.conn.Bulk(ctx, "", "", nil, bulkItems) + if sendErr != nil { + if status == http.StatusRequestEntityTooLarge { + sendErr = errPayloadTooLarge + } err := apm.CaptureError(ctx, fmt.Errorf("failed to perform any bulk index operations: %w", sendErr)) err.Send() client.log.Error(err) diff --git a/libbeat/outputs/elasticsearch/client_test.go b/libbeat/outputs/elasticsearch/client_test.go index 2a03d10481d..0a2ca672a7c 100644 --- a/libbeat/outputs/elasticsearch/client_test.go +++ b/libbeat/outputs/elasticsearch/client_test.go @@ -44,6 +44,103 @@ import ( "github.com/elastic/beats/v7/libbeat/version" ) +type testIndexSelector struct{} + +func (testIndexSelector) Select(event *beat.Event) (string, error) { + return "test", nil +} + +type batchMock struct { + // we embed the interface so we are able to implement the interface partially, + // only functions needed for tests are implemented + // if you use a function that is not implemented in the mock it will panic + publisher.Batch + events []publisher.Event + ack bool + drop bool + retryEvents []publisher.Event +} + +func (bm batchMock) Events() []publisher.Event { + return bm.events +} +func (bm *batchMock) ACK() { + bm.ack = true +} +func (bm *batchMock) Drop() { + bm.drop = true +} +func (bm *batchMock) RetryEvents(events []publisher.Event) { + bm.retryEvents = events +} + +func TestPublishStatusCode(t *testing.T) { + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) + defer cancel() + + event := publisher.Event{Content: beat.Event{Fields: common.MapStr{"field": 1}}} + events := []publisher.Event{event} + + t.Run("returns pre-defined error and drops batch when 413", func(t *testing.T) { + esMock := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusRequestEntityTooLarge) + w.Write([]byte("Request failed to get to the server (status code: 413)")) // actual response from ES + })) + defer esMock.Close() + + client, err := NewClient( + ClientSettings{ + ConnectionSettings: eslegclient.ConnectionSettings{ + URL: esMock.URL, + }, + Index: testIndexSelector{}, + }, + nil, + ) + assert.NoError(t, err) + + event := publisher.Event{Content: beat.Event{Fields: common.MapStr{"field": 1}}} + events := []publisher.Event{event} + batch := &batchMock{ + events: events, + } + + err = client.Publish(ctx, batch) + + assert.Error(t, err) + assert.Equal(t, errPayloadTooLarge, err, "should be a pre-defined error") + assert.True(t, batch.drop, "should must be dropped") + }) + + t.Run("retries the batch if bad HTTP status", func(t *testing.T) { + esMock := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusInternalServerError) + })) + defer esMock.Close() + + client, err := NewClient( + ClientSettings{ + ConnectionSettings: eslegclient.ConnectionSettings{ + URL: esMock.URL, + }, + Index: testIndexSelector{}, + }, + nil, + ) + assert.NoError(t, err) + + batch := &batchMock{ + events: events, + } + + err = client.Publish(ctx, batch) + + assert.Error(t, err) + assert.False(t, batch.ack, "should not be acknowledged") + assert.Len(t, batch.retryEvents, len(events), "all events should be in retry") + }) +} + func TestCollectPublishFailsNone(t *testing.T) { client, err := NewClient( ClientSettings{ diff --git a/libbeat/outputs/fileout/config.go b/libbeat/outputs/fileout/config.go index 28441c93bb0..e80f0a27be9 100644 --- a/libbeat/outputs/fileout/config.go +++ b/libbeat/outputs/fileout/config.go @@ -25,19 +25,17 @@ import ( ) type config struct { - Path string `config:"path"` - Filename string `config:"filename"` - Suffix file.SuffixType `config:"suffix"` - RotateEveryKb uint `config:"rotate_every_kb" validate:"min=1"` - NumberOfFiles uint `config:"number_of_files"` - Codec codec.Config `config:"codec"` - Permissions uint32 `config:"permissions"` - RotateOnStartup bool `config:"rotate_on_startup"` + Path string `config:"path"` + Filename string `config:"filename"` + RotateEveryKb uint `config:"rotate_every_kb" validate:"min=1"` + NumberOfFiles uint `config:"number_of_files"` + Codec codec.Config `config:"codec"` + Permissions uint32 `config:"permissions"` + RotateOnStartup bool `config:"rotate_on_startup"` } func defaultConfig() config { return config{ - Suffix: file.SuffixCount, NumberOfFiles: 7, RotateEveryKb: 10 * 1024, Permissions: 0600, diff --git a/libbeat/outputs/fileout/docs/fileout.asciidoc b/libbeat/outputs/fileout/docs/fileout.asciidoc index a0979f92ef5..f4dc7c5f95d 100644 --- a/libbeat/outputs/fileout/docs/fileout.asciidoc +++ b/libbeat/outputs/fileout/docs/fileout.asciidoc @@ -45,7 +45,8 @@ mandatory. ===== `filename` The name of the generated files. The default is set to the Beat name. For example, the files -generated by default for {beatname_uc} would be "{beatname_lc}", "{beatname_lc}.1", "{beatname_lc}.2", and so on. +generated by default for {beatname_uc} would be "{beatname_lc}-{{datetime}}.ndjson", "{beatname_lc}-{{datetime}}-1.ndjson", +"{beatname_lc}-{{datetime}}-2.ndjson", and so on. ===== `rotate_every_kb` diff --git a/libbeat/outputs/fileout/file.go b/libbeat/outputs/fileout/file.go index 48a65adc1c0..b4a10e38396 100644 --- a/libbeat/outputs/fileout/file.go +++ b/libbeat/outputs/fileout/file.go @@ -84,7 +84,6 @@ func (out *fileOutput) init(beat beat.Info, c config) error { var err error out.rotator, err = file.NewFileRotator( path, - file.Suffix(c.Suffix), file.MaxSizeBytes(c.RotateEveryKb*1024), file.MaxBackups(c.NumberOfFiles), file.Permissions(os.FileMode(c.Permissions)), diff --git a/libbeat/outputs/kafka/docs/kafka.asciidoc b/libbeat/outputs/kafka/docs/kafka.asciidoc index 85b467ab3f2..28892f57aa0 100644 --- a/libbeat/outputs/kafka/docs/kafka.asciidoc +++ b/libbeat/outputs/kafka/docs/kafka.asciidoc @@ -79,8 +79,6 @@ The password for connecting to Kafka. ===== `sasl.mechanism` -beta[] - The SASL mechanism to use when connecting to Kafka. It can be one of: * `PLAIN` for SASL/PLAIN. diff --git a/libbeat/outputs/outest/batch.go b/libbeat/outputs/outest/batch.go index 11d4bf1a266..4aeab9cbb5f 100644 --- a/libbeat/outputs/outest/batch.go +++ b/libbeat/outputs/outest/batch.go @@ -41,7 +41,6 @@ const ( BatchRetry BatchRetryEvents BatchCancelled - BatchCancelledEvents ) func NewBatch(in ...beat.Event) *Batch { @@ -76,10 +75,6 @@ func (b *Batch) Cancelled() { b.doSignal(BatchSignal{Tag: BatchCancelled}) } -func (b *Batch) CancelledEvents(events []publisher.Event) { - b.doSignal(BatchSignal{Tag: BatchCancelledEvents, Events: events}) -} - func (b *Batch) doSignal(sig BatchSignal) { b.Signals = append(b.Signals, sig) if b.OnSignal != nil { diff --git a/libbeat/paths/paths.go b/libbeat/paths/paths.go index 53cabb9f956..f73c0e34e97 100644 --- a/libbeat/paths/paths.go +++ b/libbeat/paths/paths.go @@ -28,8 +28,6 @@ // // path.config - Configuration files and Elasticsearch template default location // -// system.hostfs - supplies an alternate filesystem root for containerized environments -// // These settings can be set via the configuration file or via command line flags. // The CLI flags overwrite the configuration file options. // @@ -40,25 +38,17 @@ package paths import ( - "flag" "fmt" "os" "path/filepath" ) -var ( - // TODO: remove this flag in 8.0 since it should be replaced by system.hostfs configuration option (config.HostFS) - // HostFS is an alternate mountpoint for the filesytem root, for when metricbeat is running inside a container. - hostFS = flag.String("system.hostfs", "", "Mount point of the host's filesystem for use in monitoring a host from within a container") -) - // Path tracks user-configurable path locations and directories type Path struct { Home string Config string Data string Logs string - Hostfs string } // FileType is an enumeration type representing the file types. @@ -74,11 +64,6 @@ const ( Data FileType = "data" // Logs is the path to the beats logs directory Logs FileType = "logs" - // Hostfs is an alternate path to the filesystem root, - // used for system metrics that interact with procfs and sysfs. - // Unlike the other values here, this corrisponds to `system.hostfs` - // and not `path.hostfs`. - Hostfs FileType = "hostfs" ) // Paths is the Path singleton on which the top level functions from this @@ -135,31 +120,15 @@ func (paths *Path) initPaths(cfg *Path) error { paths.Logs = filepath.Join(paths.Home, "logs") } - if *hostFS != "" { - paths.Hostfs = *hostFS - } - - if paths.Hostfs == "" { - paths.Hostfs = "/" - } - return nil } -// IsCLISet returns true if the CLI system.hostfs value has been set -func IsCLISet() bool { - if *hostFS != "" { - return true - } - return false -} - // Resolve resolves a path to a location in one of the default // folders. For example, Resolve(Home, "test") returns an absolute // path for "test" in the home path. func (paths *Path) Resolve(fileType FileType, path string) string { // absolute paths are not changed for non-hostfs file types, since hostfs is a little odd - if filepath.IsAbs(path) && fileType != Hostfs { + if filepath.IsAbs(path) { return path } @@ -172,8 +141,6 @@ func (paths *Path) Resolve(fileType FileType, path string) string { return filepath.Join(paths.Data, path) case Logs: return filepath.Join(paths.Logs, path) - case Hostfs: - return filepath.Join(paths.Hostfs, path) default: panic(fmt.Sprintf("Unknown file type: %s", fileType)) } @@ -189,6 +156,6 @@ func Resolve(fileType FileType, path string) string { // String returns a textual representation func (paths *Path) String() string { - return fmt.Sprintf("Home path: [%s] Config path: [%s] Data path: [%s] Logs path: [%s] Hostfs Path: [%s]", - paths.Home, paths.Config, paths.Data, paths.Logs, paths.Hostfs) + return fmt.Sprintf("Home path: [%s] Config path: [%s] Data path: [%s] Logs path: [%s]", + paths.Home, paths.Config, paths.Data, paths.Logs) } diff --git a/libbeat/processors/actions/add_labels.go b/libbeat/processors/actions/add_labels.go index 76696659265..93096898960 100644 --- a/libbeat/processors/actions/add_labels.go +++ b/libbeat/processors/actions/add_labels.go @@ -41,10 +41,15 @@ func createAddLabels(c *common.Config) (processors.Processor, error) { }{} err := c.Unpack(&config) if err != nil { - return nil, fmt.Errorf("fail to unpack the add_fields configuration: %s", err) + return nil, fmt.Errorf("fail to unpack the add_fields configuration: %w", err) } - return makeFieldsProcessor(LabelsKey, config.Labels.Flatten(), true), nil + flatLabels, err := flattenLabels(config.Labels) + if err != nil { + return nil, fmt.Errorf("failed to flatten labels: %w", err) + } + + return makeFieldsProcessor(LabelsKey, flatLabels, true), nil } // NewAddLabels creates a new processor adding the given object to events. Set @@ -53,8 +58,32 @@ func createAddLabels(c *common.Config) (processors.Processor, error) { // If labels contains nested objects, NewAddLabels will flatten keys into labels by // by joining names with a dot ('.') . // The labels will be inserted into the 'labels' field. -func NewAddLabels(labels common.MapStr, shared bool) processors.Processor { +func NewAddLabels(labels common.MapStr, shared bool) (processors.Processor, error) { + flatLabels, err := flattenLabels(labels) + if err != nil { + return nil, fmt.Errorf("failed to flatten labels: %w", err) + } + return NewAddFields(common.MapStr{ - LabelsKey: labels.Flatten(), - }, shared, true) + LabelsKey: flatLabels, + }, shared, true), nil +} + +func flattenLabels(labels common.MapStr) (common.MapStr, error) { + labelConfig, err := common.NewConfigFrom(labels) + if err != nil { + return nil, err + } + + flatKeys := labelConfig.FlattenedKeys() + flatMap := make(common.MapStr, len(flatKeys)) + for _, k := range flatKeys { + v, err := labelConfig.String(k, -1) + if err != nil { + return nil, err + } + flatMap[k] = v + } + + return flatMap, nil } diff --git a/libbeat/processors/actions/add_labels_test.go b/libbeat/processors/actions/add_labels_test.go index 24ddcbab58f..ca9dd22a528 100644 --- a/libbeat/processors/actions/add_labels_test.go +++ b/libbeat/processors/actions/add_labels_test.go @@ -59,5 +59,16 @@ func TestAddLabels(t *testing.T) { `{add_labels.labels: {l2: b, lc: b}}`, ), }, + "add array": { + event: common.MapStr{}, + want: common.MapStr{ + "labels": common.MapStr{ + "array.0": "foo", + "array.1": "bar", + "array.2.hello": "world", + }, + }, + cfg: single(`{add_labels: {labels: {array: ["foo", "bar", {"hello": "world"}]}}}`), + }, }) } diff --git a/libbeat/processors/actions/decode_json_fields.go b/libbeat/processors/actions/decode_json_fields.go index 611b5b8d8e3..be852a47133 100644 --- a/libbeat/processors/actions/decode_json_fields.go +++ b/libbeat/processors/actions/decode_json_fields.go @@ -122,6 +122,11 @@ func (f *decodeJSONFields) Run(event *beat.Event) (*beat.Event, error) { if err != nil { f.logger.Debugf("Error trying to unmarshal %s", text) errs = append(errs, err.Error()) + event.SetErrorWithOption(common.MapStr{ + "message": "parsing input as JSON: " + err.Error(), + "data": text, + "field": field, + }, f.addErrorKey) continue } diff --git a/libbeat/processors/actions/decode_json_fields_test.go b/libbeat/processors/actions/decode_json_fields_test.go index 73d4f3a5fcc..f58efd29b46 100644 --- a/libbeat/processors/actions/decode_json_fields_test.go +++ b/libbeat/processors/actions/decode_json_fields_test.go @@ -491,6 +491,27 @@ func TestOverwriteMetadata(t *testing.T) { assert.Equal(t, expected, actual) } +func TestAddErrorToEventOnUnmarshalError(t *testing.T) { + testConfig := common.MustNewConfigFrom(map[string]interface{}{ + "fields": "message", + "add_error_key": true, + }) + + input := common.MapStr{ + "message": "Broken JSON [[", + } + + actual := getActualValue(t, testConfig, input) + + errObj, ok := actual["error"].(common.MapStr) + require.True(t, ok, "'error' field not present or of invalid type") + require.NotNil(t, actual["error"]) + + assert.Equal(t, "message", errObj["field"]) + assert.NotNil(t, errObj["data"]) + assert.NotNil(t, errObj["message"]) +} + func getActualValue(t *testing.T, config *common.Config, input common.MapStr) common.MapStr { log := logp.NewLogger("decode_json_fields_test") diff --git a/libbeat/processors/add_docker_metadata/add_docker_metadata.go b/libbeat/processors/add_docker_metadata/add_docker_metadata.go index ddea3c85b29..5282fc27e39 100644 --- a/libbeat/processors/add_docker_metadata/add_docker_metadata.go +++ b/libbeat/processors/add_docker_metadata/add_docker_metadata.go @@ -35,6 +35,7 @@ import ( "github.com/elastic/beats/v7/libbeat/common/safemapstr" "github.com/elastic/beats/v7/libbeat/logp" "github.com/elastic/beats/v7/libbeat/metric/system/cgroup" + "github.com/elastic/beats/v7/libbeat/metric/system/resolve" "github.com/elastic/beats/v7/libbeat/processors" "github.com/elastic/beats/v7/libbeat/processors/actions" ) @@ -59,11 +60,11 @@ type addDockerMetadata struct { fields []string sourceProcessor processors.Processor - pidFields []string // Field names that contain PIDs. - cgroups *common.Cache // Cache of PID (int) to cgropus (map[string]string). - hostFS string // Directory where /proc is found - dedot bool // If set to true, replace dots in labels with `_`. - dockerAvailable bool // If Docker exists in env, then it is set to true + pidFields []string // Field names that contain PIDs. + cgroups *common.Cache // Cache of PID (int) to cgropus (map[string]string). + hostFS resolve.Resolver // Directory where /proc is found + dedot bool // If set to true, replace dots in labels with `_`. + dockerAvailable bool // If Docker exists in env, then it is set to true } const selector = "add_docker_metadata" @@ -114,7 +115,7 @@ func buildDockerMetadataProcessor(log *logp.Logger, cfg *common.Config, watcherC fields: config.Fields, sourceProcessor: sourceProcessor, pidFields: config.MatchPIDs, - hostFS: config.HostFS, + hostFS: resolve.NewTestResolver(config.HostFS), dedot: config.DeDot, dockerAvailable: dockerAvailable, }, nil diff --git a/libbeat/processors/add_docker_metadata/add_docker_metadata_test.go b/libbeat/processors/add_docker_metadata/add_docker_metadata_test.go index 07f3fe232a2..edde24f4184 100644 --- a/libbeat/processors/add_docker_metadata/add_docker_metadata_test.go +++ b/libbeat/processors/add_docker_metadata/add_docker_metadata_test.go @@ -35,11 +35,12 @@ import ( "github.com/elastic/beats/v7/libbeat/common/docker" "github.com/elastic/beats/v7/libbeat/logp" "github.com/elastic/beats/v7/libbeat/metric/system/cgroup" + "github.com/elastic/beats/v7/libbeat/metric/system/resolve" ) func init() { // Stub out the procfs. - processCgroupPaths = func(_ string, pid int) (cgroup.PathList, error) { + processCgroupPaths = func(_ resolve.Resolver, pid int) (cgroup.PathList, error) { switch pid { case 1000: diff --git a/libbeat/processors/add_docker_metadata/config.go b/libbeat/processors/add_docker_metadata/config.go index c7844de0369..ddbf9b88796 100644 --- a/libbeat/processors/add_docker_metadata/config.go +++ b/libbeat/processors/add_docker_metadata/config.go @@ -35,7 +35,7 @@ type Config struct { MatchShortID bool `config:"match_short_id"` // Match to container short ID from a log path present in source field. SourceIndex int `config:"match_source_index"` // Index in the source path split by / to look for container ID. MatchPIDs []string `config:"match_pids"` // A list of fields containing process IDs (PIDs). - HostFS string `config:"system.hostfs"` // Specifies the mount point of the host’s filesystem for use in monitoring a host from within a container. + HostFS string `config:"hostfs"` // Specifies the mount point of the host’s filesystem for use in monitoring a host from within a container. DeDot bool `config:"labels.dedot"` // If set to true, replace dots in labels with `_`. // Annotations are kept after container is killed, until they haven't been diff --git a/libbeat/processors/add_kubernetes_metadata/_meta/fields.yml b/libbeat/processors/add_kubernetes_metadata/_meta/fields.yml index c390f48e1cf..80be2c80bba 100644 --- a/libbeat/processors/add_kubernetes_metadata/_meta/fields.yml +++ b/libbeat/processors/add_kubernetes_metadata/_meta/fields.yml @@ -25,28 +25,9 @@ Kubernetes Pod IP - name: namespace - type: group - fields: - - name: name - type: keyword - description: > - Kubernetes namespace name - - name: uuid - type: keyword - description: > - Kubernetes namespace uuid - - name: labels.* - type: object - object_type: keyword - object_type_mapping_type: "*" - description: > - Kubernetes namespace labels map - - name: annotations.* - type: object - object_type: keyword - object_type_mapping_type: "*" - description: > - Kubernetes namespace annotations map + type: keyword + description: > + Kubernetes namespace - name: node.name type: keyword diff --git a/libbeat/processors/add_kubernetes_metadata/config.go b/libbeat/processors/add_kubernetes_metadata/config.go index ecc9b5919fe..9365627f59f 100644 --- a/libbeat/processors/add_kubernetes_metadata/config.go +++ b/libbeat/processors/add_kubernetes_metadata/config.go @@ -52,11 +52,12 @@ type PluginConfig []map[string]common.Config func defaultKubernetesAnnotatorConfig() kubeAnnotatorConfig { return kubeAnnotatorConfig{ - SyncPeriod: 10 * time.Minute, - CleanupTimeout: 60 * time.Second, - DefaultMatchers: Enabled{true}, - DefaultIndexers: Enabled{true}, - Scope: "node", + SyncPeriod: 10 * time.Minute, + CleanupTimeout: 60 * time.Second, + DefaultMatchers: Enabled{true}, + DefaultIndexers: Enabled{true}, + Scope: "node", + AddResourceMetadata: metadata.GetDefaultResourceMetadataConfig(), } } diff --git a/libbeat/processors/add_kubernetes_metadata/indexers_test.go b/libbeat/processors/add_kubernetes_metadata/indexers_test.go index 058d838592a..9897a6534de 100644 --- a/libbeat/processors/add_kubernetes_metadata/indexers_test.go +++ b/libbeat/processors/add_kubernetes_metadata/indexers_test.go @@ -32,7 +32,8 @@ import ( "github.com/elastic/beats/v7/libbeat/common/kubernetes" ) -var metagen = metadata.NewPodMetadataGenerator(common.NewConfig(), nil, nil, nil, nil, true) +var addResourceMetadata = metadata.GetDefaultResourceMetadataConfig() +var metagen = metadata.NewPodMetadataGenerator(common.NewConfig(), nil, nil, nil, nil, addResourceMetadata) func TestPodIndexer(t *testing.T) { var testConfig = common.NewConfig() @@ -73,9 +74,7 @@ func TestPodIndexer(t *testing.T) { "labels": common.MapStr{ "labelkey": "labelvalue", }, - "namespace": common.MapStr{ - "name": "testns", - }, + "namespace": "testns", "node": common.MapStr{ "name": "testnode", }, @@ -92,7 +91,7 @@ func TestPodIndexer(t *testing.T) { func TestPodUIDIndexer(t *testing.T) { var testConfig = common.NewConfig() - metaGenWithPodUID := metadata.NewPodMetadataGenerator(common.NewConfig(), nil, nil, nil, nil, true) + metaGenWithPodUID := metadata.NewPodMetadataGenerator(common.NewConfig(), nil, nil, nil, nil, addResourceMetadata) podUIDIndexer, err := NewPodUIDIndexer(*testConfig, metaGenWithPodUID) assert.NoError(t, err) @@ -127,9 +126,7 @@ func TestPodUIDIndexer(t *testing.T) { "uid": "005f3b90-4b9d-12f8-acf0-31020a840133", "ip": "127.0.0.5", }, - "namespace": common.MapStr{ - "name": "testns", - }, + "namespace": "testns", "node": common.MapStr{ "name": "testnode", }, @@ -187,9 +184,7 @@ func TestContainerIndexer(t *testing.T) { "uid": "005f3b90-4b9d-12f8-acf0-31020a840133", "ip": "127.0.0.5", }, - "namespace": common.MapStr{ - "name": "testns", - }, + "namespace": "testns", "node": common.MapStr{ "name": "testnode", }, @@ -307,7 +302,7 @@ func TestFilteredGenMeta(t *testing.T) { }) assert.NoError(t, err) - filteredGen := metadata.NewPodMetadataGenerator(config, nil, nil, nil, nil, true) + filteredGen := metadata.NewPodMetadataGenerator(config, nil, nil, nil, nil, addResourceMetadata) podIndexer, err = NewPodNameIndexer(*testConfig, filteredGen) assert.NoError(t, err) @@ -344,7 +339,7 @@ func TestFilteredGenMetaExclusion(t *testing.T) { }) assert.NoError(t, err) - filteredGen := metadata.NewPodMetadataGenerator(config, nil, nil, nil, nil, true) + filteredGen := metadata.NewPodMetadataGenerator(config, nil, nil, nil, nil, addResourceMetadata) podIndexer, err := NewPodNameIndexer(*testConfig, filteredGen) assert.NoError(t, err) @@ -437,9 +432,7 @@ func TestIpPortIndexer(t *testing.T) { "uid": "005f3b90-4b9d-12f8-acf0-31020a840133", "ip": "1.2.3.4", }, - "namespace": common.MapStr{ - "name": "testns", - }, + "namespace": "testns", "node": common.MapStr{ "name": "testnode", }, diff --git a/libbeat/processors/add_kubernetes_metadata/kubernetes.go b/libbeat/processors/add_kubernetes_metadata/kubernetes.go index 2255bed3f6b..a4b40b9655d 100644 --- a/libbeat/processors/add_kubernetes_metadata/kubernetes.go +++ b/libbeat/processors/add_kubernetes_metadata/kubernetes.go @@ -191,9 +191,6 @@ func (k *kubernetesAnnotator) init(config kubeAnnotatorConfig, cfg *common.Confi } metaConf := config.AddResourceMetadata - if metaConf == nil { - metaConf = metadata.GetDefaultResourceMetadataConfig() - } options := kubernetes.WatchOptions{ SyncTimeout: config.SyncPeriod, diff --git a/libbeat/processors/add_process_metadata/add_process_metadata.go b/libbeat/processors/add_process_metadata/add_process_metadata.go index 0cc6a2ebc48..31b9fa9a9db 100644 --- a/libbeat/processors/add_process_metadata/add_process_metadata.go +++ b/libbeat/processors/add_process_metadata/add_process_metadata.go @@ -30,14 +30,17 @@ import ( "github.com/elastic/beats/v7/libbeat/common/atomic" "github.com/elastic/beats/v7/libbeat/logp" "github.com/elastic/beats/v7/libbeat/metric/system/cgroup" + "github.com/elastic/beats/v7/libbeat/metric/system/resolve" "github.com/elastic/beats/v7/libbeat/processors" jsprocessor "github.com/elastic/beats/v7/libbeat/processors/script/javascript/module/processor" ) const ( - processorName = "add_process_metadata" - cacheExpiration = time.Second * 30 - containerIDMapping = "container.id" + processorName = "add_process_metadata" + cacheExpiration = time.Second * 30 + cacheCapacity = 32 << 10 // maximum number of process cache entries. + cacheEvictionEffort = 10 // number of entries to sample for expiry eviction. + containerIDMapping = "container.id" ) var ( @@ -48,7 +51,7 @@ var ( // ErrNoProcess is returned when metadata for a process can't be collected. ErrNoProcess = errors.New("process not found") - procCache = newProcessCache(cacheExpiration, gosysinfoProvider{}) + procCache = newProcessCache(cacheExpiration, cacheCapacity, cacheEvictionEffort, gosysinfoProvider{}) processCgroupPaths = cgroup.ProcessCgroupPaths @@ -111,7 +114,6 @@ func newProcessMetadataProcessorWithProvider(cfg *common.Config, provider proces } mappings, err := config.getMappings() - if err != nil { return nil, errors.Wrapf(err, "error unpacking %v.target_fields", processorName) } @@ -134,11 +136,10 @@ func newProcessMetadataProcessorWithProvider(cfg *common.Config, provider proces p.cgroupsCache = common.NewCacheWithRemovalListener(config.CgroupCacheExpireTime, 100, evictionListener) p.cgroupsCache.StartJanitor(config.CgroupCacheExpireTime) - p.cidProvider = newCidProvider(config.HostPath, config.CgroupPrefixes, config.CgroupRegex, processCgroupPaths, p.cgroupsCache) + p.cidProvider = newCidProvider(resolve.NewTestResolver(config.HostPath), config.CgroupPrefixes, config.CgroupRegex, processCgroupPaths, p.cgroupsCache) } else { - p.cidProvider = newCidProvider(config.HostPath, config.CgroupPrefixes, config.CgroupRegex, processCgroupPaths, nil) + p.cidProvider = newCidProvider(resolve.NewTestResolver(config.HostPath), config.CgroupPrefixes, config.CgroupRegex, processCgroupPaths, nil) } - } if withCache { diff --git a/libbeat/processors/add_process_metadata/add_process_metadata_test.go b/libbeat/processors/add_process_metadata/add_process_metadata_test.go index 1238702d0f4..51f4a33172e 100644 --- a/libbeat/processors/add_process_metadata/add_process_metadata_test.go +++ b/libbeat/processors/add_process_metadata/add_process_metadata_test.go @@ -31,6 +31,7 @@ import ( "github.com/elastic/beats/v7/libbeat/common" "github.com/elastic/beats/v7/libbeat/logp" "github.com/elastic/beats/v7/libbeat/metric/system/cgroup" + "github.com/elastic/beats/v7/libbeat/metric/system/resolve" ) func TestAddProcessMetadata(t *testing.T) { @@ -74,7 +75,7 @@ func TestAddProcessMetadata(t *testing.T) { } // mock of the cgroup processCgroupPaths - processCgroupPaths = func(_ string, pid int) (cgroup.PathList, error) { + processCgroupPaths = func(_ resolve.Resolver, pid int) (cgroup.PathList, error) { testMap := map[int]cgroup.PathList{ 1: { @@ -758,7 +759,7 @@ func TestUsingCache(t *testing.T) { selfPID := os.Getpid() // mock of the cgroup processCgroupPaths - processCgroupPaths = func(_ string, pid int) (cgroup.PathList, error) { + processCgroupPaths = func(_ resolve.Resolver, pid int) (cgroup.PathList, error) { testStruct := cgroup.PathList{ V1: map[string]cgroup.ControllerPath{ @@ -1057,7 +1058,7 @@ func TestPIDToInt(t *testing.T) { } func TestV2CID(t *testing.T) { - processCgroupPaths = func(_ string, _ int) (cgroup.PathList, error) { + processCgroupPaths = func(_ resolve.Resolver, _ int) (cgroup.PathList, error) { testMap := cgroup.PathList{ V1: map[string]cgroup.ControllerPath{ "cpu": cgroup.ControllerPath{IsV2: true, ControllerPath: "system.slice/docker-2dcbab615aebfa9313feffc5cfdacd381543cfa04c6be3f39ac656e55ef34805.scope"}, @@ -1065,7 +1066,7 @@ func TestV2CID(t *testing.T) { } return testMap, nil } - provider := newCidProvider("", []string{}, "", processCgroupPaths, nil) + provider := newCidProvider(resolve.NewTestResolver(""), []string{}, "", processCgroupPaths, nil) result, err := provider.GetCid(1) assert.NoError(t, err) assert.Equal(t, "2dcbab615aebfa9313feffc5cfdacd381543cfa04c6be3f39ac656e55ef34805", result) diff --git a/libbeat/processors/add_process_metadata/cache.go b/libbeat/processors/add_process_metadata/cache.go index 0a8234fe0ca..e3435aa92af 100644 --- a/libbeat/processors/add_process_metadata/cache.go +++ b/libbeat/processors/add_process_metadata/cache.go @@ -29,16 +29,22 @@ type processCacheEntry struct { } type processCache struct { - cache map[int]processCacheEntry provider processMetadataProvider expiration time.Duration - rwMutex sync.RWMutex + + cap int // cap is the maximum number of elements the cache will hold. + effort int // effort is the number of entries to examine during expired element eviction. + + rwMutex sync.RWMutex // rwMutex protects the cache map. + cache map[int]processCacheEntry } -func newProcessCache(expiration time.Duration, provider processMetadataProvider) processCache { +func newProcessCache(expiration time.Duration, cap, effort int, provider processMetadataProvider) processCache { return processCache{ cache: make(map[int]processCacheEntry), expiration: expiration, + cap: cap, + effort: effort, provider: provider, } } @@ -58,6 +64,12 @@ func (pc *processCache) GetProcessMetadata(pid int) (*processMetadata, error) { if !valid { pc.rwMutex.Lock() defer pc.rwMutex.Unlock() + + pc.tryEvictExpired() + if len(pc.cache) >= pc.cap { + pc.evictRandomEntry() + } + // Make sure someone else didn't generate this entry while we were // waiting for the write lock if entry, valid = pc.getEntryUnlocked(pid); !valid { @@ -68,3 +80,27 @@ func (pc *processCache) GetProcessMetadata(pid int) (*processMetadata, error) { } return entry.metadata, entry.err } + +// tryEvictExpired implements a random sampling expired element cache +// eviction policy. +func (pc *processCache) tryEvictExpired() { + now := time.Now() + n := 0 + for pid, entry := range pc.cache { + if n >= pc.effort { + return + } + if now.After(entry.expiration) { + delete(pc.cache, pid) + } + n++ + } +} + +// evictRandomEntry implements a random cache eviction policy. +func (pc *processCache) evictRandomEntry() { + for pid := range pc.cache { + delete(pc.cache, pid) + return + } +} diff --git a/libbeat/processors/add_process_metadata/cache_test.go b/libbeat/processors/add_process_metadata/cache_test.go new file mode 100644 index 00000000000..9d9886d9932 --- /dev/null +++ b/libbeat/processors/add_process_metadata/cache_test.go @@ -0,0 +1,113 @@ +// Licensed to Elasticsearch B.V. under one or more contributor +// license agreements. See the NOTICE file distributed with +// this work for additional information regarding copyright +// ownership. Elasticsearch B.V. licenses this file to you 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 add_process_metadata + +import ( + "math/rand" + "testing" + "time" +) + +var cacheEvictionTests = []struct { + name string + + expire time.Duration + cap, effort int + + iters int + maxPID int + delay time.Duration +}{ + { + name: "small sparse", + expire: time.Millisecond, + cap: 100, + effort: 5, + iters: 1000, + maxPID: 100000, + delay: 2 * time.Millisecond, + }, + { + name: "small dense", + expire: time.Millisecond, + cap: 100, + effort: 5, + iters: 1000, + maxPID: 10, + delay: 2 * time.Millisecond, + }, + { + name: "large sparse", + expire: time.Millisecond, + cap: 100, + effort: 5, + iters: 10000, + maxPID: 100000, + delay: time.Millisecond / 10, + }, + { + name: "large dense", + expire: time.Millisecond, + cap: 100, + effort: 5, + iters: 10000, + maxPID: 10, + delay: time.Millisecond / 10, + }, + { + name: "huge sparse", + expire: time.Millisecond, + cap: 100, + effort: 5, + iters: 1000, + maxPID: 100000, + delay: time.Millisecond / 100, + }, + { + name: "huge dense", + expire: time.Millisecond, + cap: 100, + effort: 5, + iters: 1000, + maxPID: 10, + delay: time.Millisecond / 100, + }, +} + +func TestCacheEviction(t *testing.T) { + for _, test := range cacheEvictionTests { + rnd := rand.New(rand.NewSource(1)) + c := newProcessCache(test.expire, test.cap, test.effort, emptyProvider{}) + + for i := 0; i < test.iters; i++ { + pid := rnd.Intn(test.maxPID) + c.GetProcessMetadata(pid) + if len(c.cache) > test.cap { + t.Errorf("cache overflow for %s after %d iterations", test.name, i) + break + } + time.Sleep(test.delay) + } + } +} + +type emptyProvider struct{} + +func (emptyProvider) GetProcessMetadata(pid int) (*processMetadata, error) { + return &processMetadata{pid: pid}, nil +} diff --git a/libbeat/processors/add_process_metadata/gosigar_cid_provider.go b/libbeat/processors/add_process_metadata/gosigar_cid_provider.go index 98aafaebd2f..2064648242c 100644 --- a/libbeat/processors/add_process_metadata/gosigar_cid_provider.go +++ b/libbeat/processors/add_process_metadata/gosigar_cid_provider.go @@ -28,6 +28,7 @@ import ( "github.com/elastic/beats/v7/libbeat/common" "github.com/elastic/beats/v7/libbeat/logp" "github.com/elastic/beats/v7/libbeat/metric/system/cgroup" + "github.com/elastic/beats/v7/libbeat/metric/system/resolve" ) const ( @@ -36,11 +37,11 @@ const ( type gosigarCidProvider struct { log *logp.Logger - hostPath string + hostPath resolve.Resolver cgroupPrefixes []string cgroupRegex string cidRegex *regexp.Regexp - processCgroupPaths func(string, int) (cgroup.PathList, error) + processCgroupPaths func(resolve.Resolver, int) (cgroup.PathList, error) pidCidCache *common.Cache } @@ -72,7 +73,7 @@ func (p gosigarCidProvider) GetCid(pid int) (result string, err error) { return cid, nil } -func newCidProvider(hostPath string, cgroupPrefixes []string, cgroupRegex string, processCgroupPaths func(string, int) (cgroup.PathList, error), pidCidCache *common.Cache) gosigarCidProvider { +func newCidProvider(hostPath resolve.Resolver, cgroupPrefixes []string, cgroupRegex string, processCgroupPaths func(resolve.Resolver, int) (cgroup.PathList, error), pidCidCache *common.Cache) gosigarCidProvider { return gosigarCidProvider{ log: logp.NewLogger(providerName), hostPath: hostPath, diff --git a/libbeat/processors/decode_csv_fields/docs/decode_csv_fields.asciidoc b/libbeat/processors/decode_csv_fields/docs/decode_csv_fields.asciidoc index 53cc3787543..11746040970 100644 --- a/libbeat/processors/decode_csv_fields/docs/decode_csv_fields.asciidoc +++ b/libbeat/processors/decode_csv_fields/docs/decode_csv_fields.asciidoc @@ -9,7 +9,7 @@ experimental[] The `decode_csv_fields` processor decodes fields containing records in comma-separated format (CSV). It will output the values as an array of strings. -This processor is available for Filebeat and Journalbeat. +This processor is available for Filebeat. [source,yaml] ----------------------------------------------------- diff --git a/libbeat/publisher/event.go b/libbeat/publisher/event.go index 29625319e7c..e127d012d87 100644 --- a/libbeat/publisher/event.go +++ b/libbeat/publisher/event.go @@ -24,17 +24,25 @@ import ( // Batch is used to pass a batch of events to the outputs and asynchronously listening // for signals from these outpts. After a batch is processed (completed or -// errors), one of the signal methods must be called. +// errors), one of the signal methods must be called. In normal operation +// every batch will eventually receive an ACK() or a Drop(). type Batch interface { Events() []Event - // signals + // All events have been acknowledged by the output. ACK() + + // Give up on these events permanently without sending. Drop() + + // Try sending this batch again Retry() + + // Try sending the events in this list again; all others are acknowledged. RetryEvents(events []Event) + + // Send was aborted, try again but don't decrease the batch's TTL counter. Cancelled() - CancelledEvents(events []Event) } // Event is used by the publisher pipeline and broker to pass additional diff --git a/libbeat/publisher/includes/includes.go b/libbeat/publisher/includes/includes.go index a14dd16d3ba..befc0e93d43 100644 --- a/libbeat/publisher/includes/includes.go +++ b/libbeat/publisher/includes/includes.go @@ -29,5 +29,4 @@ import ( _ "github.com/elastic/beats/v7/libbeat/outputs/redis" _ "github.com/elastic/beats/v7/libbeat/publisher/queue/diskqueue" _ "github.com/elastic/beats/v7/libbeat/publisher/queue/memqueue" - _ "github.com/elastic/beats/v7/libbeat/publisher/queue/spool" ) diff --git a/libbeat/publisher/pipeline/client.go b/libbeat/publisher/pipeline/client.go index edb5a3f1eb3..29d243257d1 100644 --- a/libbeat/publisher/pipeline/client.go +++ b/libbeat/publisher/pipeline/client.go @@ -201,7 +201,6 @@ func (c *client) logger() *logp.Logger { } func (c *client) onClosing() { - c.pipeline.observer.clientClosing() if c.eventer != nil { c.eventer.Closing() } diff --git a/libbeat/publisher/pipeline/output.go b/libbeat/publisher/pipeline/client_worker.go similarity index 93% rename from libbeat/publisher/pipeline/output.go rename to libbeat/publisher/pipeline/client_worker.go index 00c3fc54281..008d774303d 100644 --- a/libbeat/publisher/pipeline/output.go +++ b/libbeat/publisher/pipeline/client_worker.go @@ -29,9 +29,8 @@ import ( ) type worker struct { - id uint observer outputObserver - qu workQueue + qu chan publisher.Batch done chan struct{} } @@ -46,14 +45,12 @@ type netClientWorker struct { worker client outputs.NetworkClient - batchSize int - batchSizer func() int - logger logger + logger logger tracer *apm.Tracer } -func makeClientWorker(observer outputObserver, qu workQueue, client outputs.Client, logger logger, tracer *apm.Tracer) outputWorker { +func makeClientWorker(observer outputObserver, qu chan publisher.Batch, client outputs.Client, logger logger, tracer *apm.Tracer) outputWorker { w := worker{ observer: observer, qu: qu, @@ -102,7 +99,6 @@ func (w *clientWorker) run() { if batch == nil { continue } - w.observer.outBatchSend(len(batch.Events())) if err := w.client.Publish(context.TODO(), batch); err != nil { return } diff --git a/libbeat/publisher/pipeline/output_test.go b/libbeat/publisher/pipeline/client_worker_test.go similarity index 91% rename from libbeat/publisher/pipeline/output_test.go rename to libbeat/publisher/pipeline/client_worker_test.go index 7bde6e137ab..921847ab0be 100644 --- a/libbeat/publisher/pipeline/output_test.go +++ b/libbeat/publisher/pipeline/client_worker_test.go @@ -52,8 +52,8 @@ func TestMakeClientWorker(t *testing.T) { logger := makeBufLogger(t) - wqu := makeWorkQueue() - retryer := newRetryer(logger, nilObserver, wqu, nil) + workQueue := make(chan publisher.Batch) + retryer := newStandaloneRetryer(workQueue) defer retryer.close() var published atomic.Uint @@ -64,13 +64,13 @@ func TestMakeClientWorker(t *testing.T) { client := ctor(publishFn) - worker := makeClientWorker(nilObserver, wqu, client, logger, nil) + worker := makeClientWorker(nilObserver, workQueue, client, logger, nil) defer worker.Close() for i := uint(0); i < numBatches; i++ { batch := randomBatch(50, 150).withRetryer(retryer) numEvents += uint(len(batch.Events())) - wqu <- batch + workQueue <- batch } // Give some time for events to be published @@ -114,14 +114,16 @@ func TestReplaceClientWorker(t *testing.T) { logger := makeBufLogger(t) - wqu := makeWorkQueue() - retryer := newRetryer(logger, nilObserver, wqu, nil) + workQueue := make(chan publisher.Batch) + retryer := newStandaloneRetryer(workQueue) defer retryer.close() var batches []publisher.Batch var numEvents int for i := uint(0); i < numBatches; i++ { - batch := randomBatch(minEventsInBatch, maxEventsInBatch).withRetryer(retryer) + batch := randomBatch( + minEventsInBatch, maxEventsInBatch, + ).withRetryer(retryer) batch.events[0].Content.Private = i numEvents += batch.Len() batches = append(batches, batch) @@ -133,7 +135,7 @@ func TestReplaceClientWorker(t *testing.T) { defer wg.Done() for _, batch := range batches { t.Logf("publish batch: %v", batch.(*mockBatch).events[0].Content.Private) - wqu <- batch + workQueue <- batch } }() @@ -156,7 +158,7 @@ func TestReplaceClientWorker(t *testing.T) { } client := ctor(blockingPublishFn) - worker := makeClientWorker(nilObserver, wqu, client, logger, nil) + worker := makeClientWorker(nilObserver, workQueue, client, logger, nil) // Allow the worker to make *some* progress before we close it timeout := 10 * time.Second @@ -183,7 +185,7 @@ func TestReplaceClientWorker(t *testing.T) { } client = ctor(countingPublishFn) - makeClientWorker(nilObserver, wqu, client, logger, nil) + makeClientWorker(nilObserver, workQueue, client, logger, nil) wg.Wait() // Make sure that all events have eventually been published @@ -214,8 +216,8 @@ func TestMakeClientTracer(t *testing.T) { logger := makeBufLogger(t) - wqu := makeWorkQueue() - retryer := newRetryer(logger, nilObserver, wqu, nil) + workQueue := make(chan publisher.Batch) + retryer := newStandaloneRetryer(workQueue) defer retryer.close() var published atomic.Uint @@ -229,13 +231,13 @@ func TestMakeClientTracer(t *testing.T) { recorder := apmtest.NewRecordingTracer() defer recorder.Close() - worker := makeClientWorker(nilObserver, wqu, client, logger, recorder.Tracer) + worker := makeClientWorker(nilObserver, workQueue, client, logger, recorder.Tracer) defer worker.Close() for i := 0; i < numBatches; i++ { batch := randomBatch(10, 15).withRetryer(retryer) numEvents += uint(len(batch.Events())) - wqu <- batch + workQueue <- batch } // Give some time for events to be published diff --git a/libbeat/publisher/pipeline/consumer.go b/libbeat/publisher/pipeline/consumer.go index d8f4288b011..242cb62409b 100644 --- a/libbeat/publisher/pipeline/consumer.go +++ b/libbeat/publisher/pipeline/consumer.go @@ -18,206 +18,221 @@ package pipeline import ( - "errors" "sync" - "github.com/elastic/beats/v7/libbeat/common/atomic" "github.com/elastic/beats/v7/libbeat/logp" + "github.com/elastic/beats/v7/libbeat/publisher" "github.com/elastic/beats/v7/libbeat/publisher/queue" ) // eventConsumer collects and forwards events from the queue to the outputs work queue. -// The eventConsumer is managed by the controller and receives additional pause signals -// from the retryer in case of too many events failing to be send or if retryer -// is receiving cancelled batches from outputs to be closed on output reloading. +// It accepts retry requests from batches it vends, which will resend them +// to the next available output. type eventConsumer struct { logger *logp.Logger - ctx *batchContext - pause atomic.Bool - wait atomic.Bool - sig chan consumerSignal - wg sync.WaitGroup + // eventConsumer calls the observer methods eventsRetry and eventsDropped. + observer outputObserver - queue queue.Queue - consumer queue.Consumer + // When the output changes, the new target is sent to the worker routine + // on this channel. Clients should call eventConsumer.setTarget(). + targetChan chan consumerTarget - out *outputGroup -} + // Failed batches are sent to this channel to retry. Clients should call + // eventConsumer.retry(). + retryChan chan retryRequest -type consumerSignal struct { - tag consumerEventTag - consumer queue.Consumer - out *outputGroup -} + // Closing this channel signals consumer shutdown. Clients should call + // eventConsumer.close(). + done chan struct{} -type consumerEventTag uint8 + // This waitgroup is released when this eventConsumer's worker + // goroutines return. + wg sync.WaitGroup -const ( - sigConsumerCheck consumerEventTag = iota - sigConsumerUpdateOutput - sigConsumerUpdateInput - sigStop -) + // The queue the eventConsumer will retrieve batches from. + queue queue.Queue +} -var errStopped = errors.New("stopped") +// consumerTarget specifies the output channel and parameters needed for +// eventConsumer to generate a batch. +type consumerTarget struct { + ch chan publisher.Batch + timeToLive int + batchSize int +} + +// retryRequest is used by ttlBatch to add itself back to the eventConsumer +// queue for distribution to an output. +type retryRequest struct { + batch *ttlBatch + decreaseTTL bool +} func newEventConsumer( log *logp.Logger, queue queue.Queue, - ctx *batchContext, + observer outputObserver, ) *eventConsumer { - consumer := queue.Consumer() c := &eventConsumer{ - logger: log, - sig: make(chan consumerSignal, 3), - out: nil, - + logger: log, + observer: observer, queue: queue, - consumer: consumer, - ctx: ctx, - } - c.pause.Store(true) + targetChan: make(chan consumerTarget), + retryChan: make(chan retryRequest), + done: make(chan struct{}), + } c.wg.Add(1) go func() { defer c.wg.Done() - c.loop(consumer) + c.run() }() return c } -func (c *eventConsumer) close() { - c.consumer.Close() - c.sig <- consumerSignal{tag: sigStop} - c.wg.Wait() -} +func (c *eventConsumer) run() { + log := c.logger -func (c *eventConsumer) sigWait() { - c.wait.Store(true) - c.sigHint() -} + log.Debug("start pipeline event consumer") -func (c *eventConsumer) sigUnWait() { - c.wait.Store(false) - c.sigHint() -} + // Create a queueReader to run our queue fetches in the background + c.wg.Add(1) + queueReader := makeQueueReader() + go func() { + defer c.wg.Done() + queueReader.run(log) + }() -func (c *eventConsumer) sigPause() { - c.pause.Store(true) - c.sigHint() -} + var ( + // Whether there's an outstanding request to queueReader + pendingRead bool -func (c *eventConsumer) sigContinue() { - c.pause.Store(false) - c.sigHint() -} + // The batches waiting to be retried. + retryBatches []*ttlBatch -func (c *eventConsumer) sigHint() { - // send signal to unblock a consumer trying to publish events. - // With flags being set atomically, multiple signals can be compressed into one - // signal -> drop if queue is not empty - select { - case c.sig <- consumerSignal{tag: sigConsumerCheck}: - default: - } -} + // The batch read from the queue and waiting to be sent, if any + queueBatch *ttlBatch -func (c *eventConsumer) updOutput(grp *outputGroup) { - // close consumer to break consumer worker from pipeline - c.consumer.Close() + // The output channel (and associated parameters) that will receive + // the batches we're loading. + target consumerTarget - // update output - c.sig <- consumerSignal{ - tag: sigConsumerUpdateOutput, - out: grp, - } + // The queue.Consumer we get the raw batches from. Reset whenever + // the target changes. + consumer queue.Consumer = c.queue.Consumer() + ) - // update eventConsumer with new queue connection - c.consumer = c.queue.Consumer() - c.sig <- consumerSignal{ - tag: sigConsumerUpdateInput, - consumer: c.consumer, - } -} +outerLoop: + for { + // If possible, start reading the next batch in the background. + if queueBatch == nil && !pendingRead { + pendingRead = true + queueReader.req <- queueReaderRequest{ + consumer: consumer, + retryer: c, + batchSize: target.batchSize, + timeToLive: target.timeToLive, + } + } -func (c *eventConsumer) loop(consumer queue.Consumer) { - log := c.logger + var active *ttlBatch + // Choose the active batch: if we have batches to retry, use the first + // one. Otherwise, use a new batch if we have one. + if len(retryBatches) > 0 { + active = retryBatches[0] + } else if queueBatch != nil { + active = queueBatch + } - log.Debug("start pipeline event consumer") + // If we have a batch, we'll point the output channel at the target + // and try to send to it. Otherwise, it will remain nil, and sends + // to it will always block, so the output case of the select below + // will be ignored. + var outputChan chan publisher.Batch + if active != nil { + outputChan = target.ch + } - var ( - out workQueue - batch Batch - paused = true - ) + // Now we can block until the next state change. + select { + case outputChan <- active: + // Successfully sent a batch to the output workers + if len(retryBatches) > 0 { + // This was a retry, report it to the observer + c.observer.eventsRetry(len(active.Events())) + retryBatches = retryBatches[1:] + } else { + // This was directly from the queue, clear the value so we can + // fetch a new one + queueBatch = nil + } - handleSignal := func(sig consumerSignal) error { - switch sig.tag { - case sigStop: - return errStopped + case target = <-c.targetChan: - case sigConsumerCheck: + case queueBatch = <-queueReader.resp: + pendingRead = false - case sigConsumerUpdateOutput: - c.out = sig.out + case req := <-c.retryChan: + alive := true + if req.decreaseTTL { + countFailed := len(req.batch.Events()) - case sigConsumerUpdateInput: - consumer = sig.consumer - } + alive = req.batch.reduceTTL() - paused = c.paused() - if c.out != nil && batch != nil { - out = c.out.workQueue - } else { - out = nil - } - return nil - } + countDropped := countFailed - len(req.batch.Events()) + c.observer.eventsDropped(countDropped) - for { - if !paused && c.out != nil && consumer != nil && batch == nil { - out = c.out.workQueue - queueBatch, err := consumer.Get(c.out.batchSize) - if err != nil { - out = nil - consumer = nil - continue - } - if queueBatch != nil { - batch = newBatch(c.ctx, queueBatch, c.out.timeToLive) + if !alive { + log.Info("Drop batch") + req.batch.Drop() + continue + } } + retryBatches = append(retryBatches, req.batch) - paused = c.paused() - if paused || batch == nil { - out = nil - } + case <-c.done: + break outerLoop } + } - select { - case sig := <-c.sig: - if err := handleSignal(sig); err != nil { - return - } - continue - default: - } + // Close the queue.Consumer, otherwise queueReader can get blocked + // waiting on a read. + consumer.Close() - select { - case sig := <-c.sig: - if err := handleSignal(sig); err != nil { - return - } - case out <- batch: - batch = nil - if paused { - out = nil - } + // Close the queueReader request channel so it knows to shutdown. + close(queueReader.req) + + // If there's an outstanding request, we need to read the response + // to unblock it, but we won't pass on the value. + if pendingRead { + batch := <-queueReader.resp + if batch != nil { + // Inform any listeners that we couldn't deliver this batch. + batch.Drop() } } } -func (c *eventConsumer) paused() bool { - return c.pause.Load() || c.wait.Load() +func (c *eventConsumer) setTarget(target consumerTarget) { + select { + case c.targetChan <- target: + case <-c.done: + } +} + +func (c *eventConsumer) retry(batch *ttlBatch, decreaseTTL bool) { + select { + case c.retryChan <- retryRequest{batch: batch, decreaseTTL: decreaseTTL}: + // The batch is back in eventConsumer's retry queue + case <-c.done: + // The consumer has already shut down, drop the batch + batch.Drop() + } +} + +func (c *eventConsumer) close() { + close(c.done) + c.wg.Wait() } diff --git a/libbeat/publisher/pipeline/controller.go b/libbeat/publisher/pipeline/controller.go index 2a15ea86e16..3a7089e0f81 100644 --- a/libbeat/publisher/pipeline/controller.go +++ b/libbeat/publisher/pipeline/controller.go @@ -36,25 +36,24 @@ type outputController struct { monitors Monitors observer outputObserver - queue queue.Queue - workQueue workQueue + workQueue chan publisher.Batch - retryer *retryer consumer *eventConsumer out *outputGroup } // outputGroup configures a group of load balanced outputs with shared work queue. type outputGroup struct { - workQueue workQueue + // workQueue is a channel that receives event batches that + // are ready to send. Each output worker in outputs reads from + // workQueue for events to send. + workQueue chan publisher.Batch outputs []outputWorker batchSize int timeToLive int // event lifetime } -type workQueue chan publisher.Batch - // outputWorker instances pass events from the shared workQueue to the outputs.Client // instances. type outputWorker interface { @@ -67,29 +66,17 @@ func newOutputController( observer outputObserver, queue queue.Queue, ) *outputController { - c := &outputController{ + return &outputController{ beat: beat, monitors: monitors, observer: observer, - queue: queue, - workQueue: makeWorkQueue(), + workQueue: make(chan publisher.Batch), + consumer: newEventConsumer(monitors.Logger, queue, observer), } - - ctx := &batchContext{} - c.consumer = newEventConsumer(monitors.Logger, queue, ctx) - c.retryer = newRetryer(monitors.Logger, observer, c.workQueue, c.consumer) - ctx.observer = observer - ctx.retryer = c.retryer - - c.consumer.sigContinue() - - return c } func (c *outputController) Close() error { - c.consumer.sigPause() c.consumer.close() - c.retryer.close() close(c.workQueue) if c.out != nil { @@ -97,11 +84,21 @@ func (c *outputController) Close() error { out.Close() } } - return nil } func (c *outputController) Set(outGrp outputs.Group) { + // Set consumer to empty target to pause it while we reload + c.consumer.setTarget(consumerTarget{}) + + // Close old outputWorkers, so they send their remaining events + // back to eventConsumer's retry channel + if c.out != nil { + for _, w := range c.out.outputs { + w.Close() + } + } + // create new output group with the shared work queue clients := outGrp.Clients worker := make([]outputWorker, len(clients)) @@ -116,35 +113,15 @@ func (c *outputController) Set(outGrp outputs.Group) { batchSize: outGrp.BatchSize, } - // update consumer and retryer - c.consumer.sigPause() - if c.out != nil { - for range c.out.outputs { - c.retryer.sigOutputRemoved() - } - } - for range clients { - c.retryer.sigOutputAdded() - } - c.consumer.updOutput(grp) - - // close old group, so events are send to new workQueue via retryer - if c.out != nil { - for _, w := range c.out.outputs { - w.Close() - } - } - c.out = grp - // restart consumer (potentially blocked by retryer) - c.consumer.sigContinue() - - c.observer.updateOutputGroup() -} - -func makeWorkQueue() workQueue { - return workQueue(make(chan publisher.Batch, 0)) + // Resume consumer targeting the new work queue + c.consumer.setTarget( + consumerTarget{ + ch: c.workQueue, + batchSize: grp.batchSize, + timeToLive: grp.timeToLive, + }) } // Reload the output diff --git a/libbeat/publisher/pipeline/monitoring.go b/libbeat/publisher/pipeline/monitoring.go index edcfb75a535..754ea030855 100644 --- a/libbeat/publisher/pipeline/monitoring.go +++ b/libbeat/publisher/pipeline/monitoring.go @@ -30,7 +30,6 @@ type observer interface { type pipelineObserver interface { clientConnected() - clientClosing() clientClosed() } @@ -47,12 +46,8 @@ type queueObserver interface { } type outputObserver interface { - updateOutputGroup() - eventsFailed(int) eventsDropped(int) eventsRetry(int) - outBatchSend(int) - outBatchACKed(int) } // metricsObserver is used by many component in the publisher pipeline, to report @@ -119,9 +114,6 @@ func (o *metricsObserver) cleanup() { // (pipeline) pipeline did finish creating a new client instance func (o *metricsObserver) clientConnected() { o.vars.clients.Inc() } -// (client) close being called on client -func (o *metricsObserver) clientClosing() {} - // (client) client finished processing close func (o *metricsObserver) clientClosed() { o.vars.clients.Dec() } @@ -171,12 +163,6 @@ func (o *metricsObserver) queueMaxEvents(n int) { // pipeline output events // -// (controller) new output group is about to be loaded -func (o *metricsObserver) updateOutputGroup() {} - -// (retryer) new failed batch has been received -func (o *metricsObserver) eventsFailed(int) {} - // (retryer) number of events dropped by retryer func (o *metricsObserver) eventsDropped(n int) { o.vars.dropped.Add(uint64(n)) @@ -187,19 +173,12 @@ func (o *metricsObserver) eventsRetry(n int) { o.vars.retry.Add(uint64(n)) } -// (output) number of events to be forwarded to the output client -func (o *metricsObserver) outBatchSend(int) {} - -// (output) number of events acked by the output batch -func (o *metricsObserver) outBatchACKed(int) {} - type emptyObserver struct{} var nilObserver observer = (*emptyObserver)(nil) func (*emptyObserver) cleanup() {} func (*emptyObserver) clientConnected() {} -func (*emptyObserver) clientClosing() {} func (*emptyObserver) clientClosed() {} func (*emptyObserver) newEvent() {} func (*emptyObserver) filteredEvent() {} @@ -207,9 +186,5 @@ func (*emptyObserver) publishedEvent() {} func (*emptyObserver) failedPublishEvent() {} func (*emptyObserver) queueACKed(n int) {} func (*emptyObserver) queueMaxEvents(int) {} -func (*emptyObserver) updateOutputGroup() {} -func (*emptyObserver) eventsFailed(int) {} func (*emptyObserver) eventsDropped(int) {} func (*emptyObserver) eventsRetry(int) {} -func (*emptyObserver) outBatchSend(int) {} -func (*emptyObserver) outBatchACKed(int) {} diff --git a/libbeat/publisher/pipeline/pipeline.go b/libbeat/publisher/pipeline/pipeline.go index be3a5e66362..c7e7f0b47fb 100644 --- a/libbeat/publisher/pipeline/pipeline.go +++ b/libbeat/publisher/pipeline/pipeline.go @@ -70,9 +70,6 @@ type Pipeline struct { waitCloseTimeout time.Duration waitCloser *waitCloser - // pipeline ack - eventSema *sema - // closeRef signal propagation support guardStartSigPropagation sync.Once sigNewClient chan *client @@ -185,7 +182,6 @@ func New( maxEvents = 64000 } p.observer.queueMaxEvents(maxEvents) - p.eventSema = newSema(maxEvents) p.output = newOutputController(beat, monitors, p.observer, p.queue) p.output.Set(out) diff --git a/libbeat/publisher/pipeline/queue_reader.go b/libbeat/publisher/pipeline/queue_reader.go new file mode 100644 index 00000000000..10f724ce5b5 --- /dev/null +++ b/libbeat/publisher/pipeline/queue_reader.go @@ -0,0 +1,63 @@ +// Licensed to Elasticsearch B.V. under one or more contributor +// license agreements. See the NOTICE file distributed with +// this work for additional information regarding copyright +// ownership. Elasticsearch B.V. licenses this file to you 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 pipeline + +import ( + "github.com/elastic/beats/v7/libbeat/logp" + "github.com/elastic/beats/v7/libbeat/publisher/queue" +) + +// queueReader is a standalone stateless helper goroutine to dispatch +// reads of the queue without blocking eventConsumer's main loop. +type queueReader struct { + req chan queueReaderRequest // "give me a batch for this target" + resp chan *ttlBatch // "here is your batch, or nil" +} + +type queueReaderRequest struct { + consumer queue.Consumer + retryer retryer + batchSize int + timeToLive int +} + +func makeQueueReader() queueReader { + qr := queueReader{ + req: make(chan queueReaderRequest, 1), + resp: make(chan *ttlBatch), + } + return qr +} + +func (qr *queueReader) run(logger *logp.Logger) { + logger.Debug("pipeline event consumer queue reader: start") + for { + req, ok := <-qr.req + if !ok { + // The request channel is closed, we're shutting down + logger.Debug("pipeline event consumer queue reader: stop") + return + } + queueBatch, _ := req.consumer.Get(req.batchSize) + var batch *ttlBatch + if queueBatch != nil { + batch = newBatch(req.retryer, queueBatch, req.timeToLive) + } + qr.resp <- batch + } +} diff --git a/libbeat/publisher/pipeline/retry.go b/libbeat/publisher/pipeline/retry.go deleted file mode 100644 index 77f439f2fad..00000000000 --- a/libbeat/publisher/pipeline/retry.go +++ /dev/null @@ -1,231 +0,0 @@ -// Licensed to Elasticsearch B.V. under one or more contributor -// license agreements. See the NOTICE file distributed with -// this work for additional information regarding copyright -// ownership. Elasticsearch B.V. licenses this file to you 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 pipeline - -import ( - "sync" -) - -// retryer is responsible for accepting and managing failed send attempts. It -// will also accept not yet published events from outputs being dynamically closed -// by the controller. Cancelled batches will be forwarded to the new workQueue, -// without updating the events retry counters. -// If too many batches (number of outputs/3) are stored in the retry buffer, -// will the consumer be paused, until some batches have been processed by some -// outputs. -type retryer struct { - logger logger - observer outputObserver - - done chan struct{} - - consumer interruptor - - sig chan retryerSignal - out workQueue - in retryQueue - doneWaiter sync.WaitGroup -} - -type interruptor interface { - sigWait() - sigUnWait() -} - -type retryQueue chan batchEvent - -type retryerSignal struct { - tag retryerEventTag - channel workQueue -} - -type batchEvent struct { - tag retryerBatchTag - batch Batch -} - -type retryerEventTag uint8 - -const ( - sigRetryerOutputAdded retryerEventTag = iota - sigRetryerOutputRemoved - sigRetryerUpdateOutput -) - -type retryerBatchTag uint8 - -const ( - retryBatch retryerBatchTag = iota - cancelledBatch -) - -func newRetryer( - log logger, - observer outputObserver, - out workQueue, - c interruptor, -) *retryer { - r := &retryer{ - logger: log, - observer: observer, - done: make(chan struct{}), - sig: make(chan retryerSignal, 3), - in: retryQueue(make(chan batchEvent, 3)), - out: out, - consumer: c, - doneWaiter: sync.WaitGroup{}, - } - r.doneWaiter.Add(1) - go r.loop() - return r -} - -func (r *retryer) close() { - close(r.done) - //Block until loop() is properly closed - r.doneWaiter.Wait() -} - -func (r *retryer) sigOutputAdded() { - r.sig <- retryerSignal{tag: sigRetryerOutputAdded} -} - -func (r *retryer) sigOutputRemoved() { - r.sig <- retryerSignal{tag: sigRetryerOutputRemoved} -} - -func (r *retryer) retry(b Batch) { - r.in <- batchEvent{tag: retryBatch, batch: b} -} - -func (r *retryer) cancelled(b Batch) { - r.in <- batchEvent{tag: cancelledBatch, batch: b} -} - -func (r *retryer) loop() { - defer r.doneWaiter.Done() - var ( - out workQueue - consumerBlocked bool - - active Batch - activeSize int - buffer []Batch - numOutputs int - - log = r.logger - ) - - for { - select { - case <-r.done: - return - case evt := <-r.in: - var ( - countFailed int - countDropped int - batch = evt.batch - countRetry = len(batch.Events()) - alive = true - ) - - if evt.tag == retryBatch { - countFailed = len(batch.Events()) - r.observer.eventsFailed(countFailed) - - alive = batch.reduceTTL() - - countRetry = len(batch.Events()) - countDropped = countFailed - countRetry - r.observer.eventsDropped(countDropped) - } - - if !alive { - log.Info("Drop batch") - batch.Drop() - } else { - out = r.out - buffer = append(buffer, batch) - out = r.out - active = buffer[0] - activeSize = len(active.Events()) - if !consumerBlocked { - consumerBlocked = r.checkConsumerBlock(numOutputs, len(buffer)) - } - } - - case out <- active: - r.observer.eventsRetry(activeSize) - - buffer = buffer[1:] - active, activeSize = nil, 0 - - if len(buffer) == 0 { - out = nil - } else { - active = buffer[0] - activeSize = len(active.Events()) - } - - if consumerBlocked { - consumerBlocked = r.checkConsumerBlock(numOutputs, len(buffer)) - } - - case sig := <-r.sig: - switch sig.tag { - case sigRetryerOutputAdded: - numOutputs++ - if consumerBlocked { - consumerBlocked = r.checkConsumerBlock(numOutputs, len(buffer)) - } - case sigRetryerOutputRemoved: - numOutputs-- - if !consumerBlocked { - consumerBlocked = r.checkConsumerBlock(numOutputs, len(buffer)) - } - } - } - } -} - -func (r *retryer) checkConsumerBlock(numOutputs, numBatches int) bool { - consumerBlocked := blockConsumer(numOutputs, numBatches) - if r.consumer == nil { - return consumerBlocked - } - - if consumerBlocked { - r.logger.Info("retryer: send wait signal to consumer") - if r.consumer != nil { - r.consumer.sigWait() - } - r.logger.Info(" done") - } else { - r.logger.Info("retryer: send unwait signal to consumer") - if r.consumer != nil { - r.consumer.sigUnWait() - } - r.logger.Info(" done") - } - - return consumerBlocked -} - -func blockConsumer(numOutputs, numBatches int) bool { - return numBatches/3 >= numOutputs -} diff --git a/libbeat/publisher/pipeline/stress/configs/pipeline/small_spool.yml b/libbeat/publisher/pipeline/stress/configs/pipeline/small_spool.yml deleted file mode 100644 index d5f999440e3..00000000000 --- a/libbeat/publisher/pipeline/stress/configs/pipeline/small_spool.yml +++ /dev/null @@ -1,11 +0,0 @@ -pipeline.queue.spool: - file: - path: ${test.tmpdir}/${test.name}-spool.dat - size: 1MiB - page_size: 4KiB - prealloc: true - write: - buffer_size: 16KiB - flush_timeout: 100ms - read: - flush_timeout: 0 diff --git a/libbeat/publisher/pipeline/stress/stress_test.go b/libbeat/publisher/pipeline/stress/stress_test.go index b12af68681f..c0afcc3a021 100644 --- a/libbeat/publisher/pipeline/stress/stress_test.go +++ b/libbeat/publisher/pipeline/stress/stress_test.go @@ -34,7 +34,6 @@ import ( "github.com/elastic/beats/v7/libbeat/common" "github.com/elastic/beats/v7/libbeat/publisher/pipeline/stress" _ "github.com/elastic/beats/v7/libbeat/publisher/queue/memqueue" - _ "github.com/elastic/beats/v7/libbeat/publisher/queue/spool" ) // additional flags diff --git a/x-pack/functionbeat/function/core/sync_client.go b/libbeat/publisher/pipeline/sync_client.go similarity index 75% rename from x-pack/functionbeat/function/core/sync_client.go rename to libbeat/publisher/pipeline/sync_client.go index cc1b0c37f57..464143b3149 100644 --- a/x-pack/functionbeat/function/core/sync_client.go +++ b/libbeat/publisher/pipeline/sync_client.go @@ -1,8 +1,21 @@ -// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one -// or more contributor license agreements. Licensed under the Elastic License; -// you may not use this file except in compliance with the Elastic License. - -package core +// Licensed to Elasticsearch B.V. under one or more contributor +// license agreements. See the NOTICE file distributed with +// this work for additional information regarding copyright +// ownership. Elasticsearch B.V. licenses this file to you 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 pipeline import ( "sync" @@ -14,9 +27,8 @@ import ( ) // Client implements the interface used by all the functionbeat function, we only implement a synchronous -// client. This interface superseed the core beat.Client interface inside functionbeat because our publish -// and publishAll methods can return an error. -type Client interface { +// client. This interface superseed the core beat.Client interface and can return errors on publish. +type ISyncClient interface { // Publish accepts a unique events and will publish it to the pipeline. Publish(beat.Event) error diff --git a/x-pack/functionbeat/function/core/sync_client_test.go b/libbeat/publisher/pipeline/sync_client_test.go similarity index 73% rename from x-pack/functionbeat/function/core/sync_client_test.go rename to libbeat/publisher/pipeline/sync_client_test.go index 4d5284eeb5c..69a42164e1c 100644 --- a/x-pack/functionbeat/function/core/sync_client_test.go +++ b/libbeat/publisher/pipeline/sync_client_test.go @@ -1,8 +1,21 @@ -// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one -// or more contributor license agreements. Licensed under the Elastic License; -// you may not use this file except in compliance with the Elastic License. - -package core +// Licensed to Elasticsearch B.V. under one or more contributor +// license agreements. See the NOTICE file distributed with +// this work for additional information regarding copyright +// ownership. Elasticsearch B.V. licenses this file to you 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 pipeline import ( "testing" diff --git a/libbeat/publisher/pipeline/testing.go b/libbeat/publisher/pipeline/testing.go index 431b2a6e39e..75250ece0f1 100644 --- a/libbeat/publisher/pipeline/testing.go +++ b/libbeat/publisher/pipeline/testing.go @@ -25,7 +25,6 @@ import ( "github.com/elastic/beats/v7/libbeat/outputs" "github.com/elastic/beats/v7/libbeat/publisher" - "github.com/elastic/beats/v7/libbeat/publisher/queue" ) type mockPublishFn func(publisher.Batch) error @@ -54,24 +53,6 @@ type mockNetworkClient struct { func (c *mockNetworkClient) Connect() error { return nil } -type mockQueue struct{} - -func (q mockQueue) Close() error { return nil } -func (q mockQueue) BufferConfig() queue.BufferConfig { return queue.BufferConfig{} } -func (q mockQueue) Producer(cfg queue.ProducerConfig) queue.Producer { return mockProducer{} } -func (q mockQueue) Consumer() queue.Consumer { return mockConsumer{} } - -type mockProducer struct{} - -func (p mockProducer) Publish(event publisher.Event) bool { return true } -func (p mockProducer) TryPublish(event publisher.Event) bool { return true } -func (p mockProducer) Cancel() int { return 0 } - -type mockConsumer struct{} - -func (c mockConsumer) Get(eventCount int) (queue.Batch, error) { return &batch{}, nil } -func (c mockConsumer) Close() error { return nil } - type mockBatch struct { mu sync.Mutex events []publisher.Event @@ -81,7 +62,6 @@ type mockBatch struct { onDrop func() onRetry func() onCancelled func() - onReduceTTL func() bool } func (b *mockBatch) Events() []publisher.Event { @@ -95,23 +75,12 @@ func (b *mockBatch) ACK() { signalFn(b.onACK) } func (b *mockBatch) Drop() { signalFn(b.onDrop) } func (b *mockBatch) Retry() { signalFn(b.onRetry) } func (b *mockBatch) Cancelled() { signalFn(b.onCancelled) } + func (b *mockBatch) RetryEvents(events []publisher.Event) { b.updateEvents(events) signalFn(b.onRetry) } -func (b *mockBatch) reduceTTL() bool { - if b.onReduceTTL != nil { - return b.onReduceTTL() - } - return true -} - -func (b *mockBatch) CancelledEvents(events []publisher.Event) { - b.updateEvents(events) - signalFn(b.onCancelled) -} - func (b *mockBatch) updateEvents(events []publisher.Event) { b.mu.Lock() defer b.mu.Unlock() @@ -124,17 +93,63 @@ func (b *mockBatch) Len() int { return len(b.events) } -func (b *mockBatch) withRetryer(r *retryer) *mockBatch { - return &mockBatch{ - events: b.events, - onACK: b.onACK, - onDrop: b.onDrop, - onRetry: func() { r.retry(b) }, - onCancelled: func() { r.cancelled(b) }, - onReduceTTL: b.onReduceTTL, +func (b *mockBatch) withRetryer(r standaloneRetryer) *mockBatch { + wrapper := &mockBatch{ + events: b.events, + onACK: b.onACK, + onDrop: b.onDrop, + } + wrapper.onRetry = func() { r.retryChan <- wrapper } + wrapper.onCancelled = func() { r.retryChan <- wrapper } + return wrapper +} + +// standaloneRetryer is a helper that can be used to simulate retry +// behavior when unit testing outputWorker without a full pipeline. (In +// a live pipeline the retry calls are handled by the eventConsumer). +type standaloneRetryer struct { + workQueue chan publisher.Batch + retryChan chan publisher.Batch + done chan struct{} +} + +func newStandaloneRetryer(workQueue chan publisher.Batch) standaloneRetryer { + sr := standaloneRetryer{ + workQueue: workQueue, + retryChan: make(chan publisher.Batch), + done: make(chan struct{}), + } + go sr.run() + return sr +} + +func (sr standaloneRetryer) run() { + var batches []publisher.Batch + for { + var active publisher.Batch + var outChan chan publisher.Batch + // If we have a batch to send, set the batch and output channel. + // Otherwise they'll be nil, and the select statement below will + // ignore them. + if len(batches) > 0 { + active = batches[0] + outChan = sr.workQueue + } + select { + case batch := <-sr.retryChan: + batches = append(batches, batch) + case outChan <- active: + batches = batches[1:] + case <-sr.done: + return + } } } +func (sr standaloneRetryer) close() { + close(sr.done) +} + func signalFn(fn func()) { if fn != nil { fn() diff --git a/libbeat/publisher/pipeline/batch.go b/libbeat/publisher/pipeline/ttl_batch.go similarity index 63% rename from libbeat/publisher/pipeline/batch.go rename to libbeat/publisher/pipeline/ttl_batch.go index 54ba2058d74..4b3bdb6489b 100644 --- a/libbeat/publisher/pipeline/batch.go +++ b/libbeat/publisher/pipeline/ttl_batch.go @@ -24,99 +24,81 @@ import ( "github.com/elastic/beats/v7/libbeat/publisher/queue" ) -type Batch interface { - publisher.Batch - - reduceTTL() bool +type retryer interface { + retry(batch *ttlBatch, decreaseTTL bool) } -type batch struct { +type ttlBatch struct { original queue.Batch - ctx *batchContext - ttl int - events []publisher.Event -} -type batchContext struct { - observer outputObserver - retryer *retryer + // The internal hook back to the eventConsumer, used to implement the + // publisher.Batch retry interface. + retryer retryer + + // How many retries until we drop this batch. -1 means it can't be dropped. + ttl int + + // The cached events returned from original.Events(). If some but not + // all of the events are ACKed, those ones are removed from the list. + events []publisher.Event } var batchPool = sync.Pool{ New: func() interface{} { - return &batch{} + return &ttlBatch{} }, } -func newBatch(ctx *batchContext, original queue.Batch, ttl int) *batch { +func newBatch(retryer retryer, original queue.Batch, ttl int) *ttlBatch { if original == nil { panic("empty batch") } - b := batchPool.Get().(*batch) - *b = batch{ + b := batchPool.Get().(*ttlBatch) + *b = ttlBatch{ original: original, - ctx: ctx, + retryer: retryer, ttl: ttl, events: original.Events(), } return b } -func releaseBatch(b *batch) { - *b = batch{} // clear batch +func releaseBatch(b *ttlBatch) { + *b = ttlBatch{} // clear batch batchPool.Put(b) } -func (b *batch) Events() []publisher.Event { +func (b *ttlBatch) Events() []publisher.Event { return b.events } -func (b *batch) ACK() { - if b.ctx != nil { - b.ctx.observer.outBatchACKed(len(b.events)) - } +func (b *ttlBatch) ACK() { b.original.ACK() releaseBatch(b) } -func (b *batch) Drop() { +func (b *ttlBatch) Drop() { b.original.ACK() releaseBatch(b) } -func (b *batch) Retry() { - b.ctx.retryer.retry(b) +func (b *ttlBatch) Retry() { + b.retryer.retry(b, true) } -func (b *batch) Cancelled() { - b.ctx.retryer.cancelled(b) +func (b *ttlBatch) Cancelled() { + b.retryer.retry(b, false) } -func (b *batch) RetryEvents(events []publisher.Event) { - b.updEvents(events) - b.Retry() -} - -func (b *batch) CancelledEvents(events []publisher.Event) { - b.updEvents(events) - b.Cancelled() -} - -func (b *batch) updEvents(events []publisher.Event) { - l1 := len(b.events) - l2 := len(events) - if l1 > l2 { - // report subset of events not to be retried as ACKed - b.ctx.observer.outBatchACKed(l1 - l2) - } - +func (b *ttlBatch) RetryEvents(events []publisher.Event) { b.events = events + b.Retry() } // reduceTTL reduces the time to live for all events that have no 'guaranteed' // sending requirements. reduceTTL returns true if the batch is still alive. -func (b *batch) reduceTTL() bool { +func (b *ttlBatch) reduceTTL() bool { if b.ttl <= 0 { return true } diff --git a/libbeat/publisher/pipeline/util.go b/libbeat/publisher/pipeline/util.go deleted file mode 100644 index db656f4ae9e..00000000000 --- a/libbeat/publisher/pipeline/util.go +++ /dev/null @@ -1,55 +0,0 @@ -// Licensed to Elasticsearch B.V. under one or more contributor -// license agreements. See the NOTICE file distributed with -// this work for additional information regarding copyright -// ownership. Elasticsearch B.V. licenses this file to you 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 pipeline - -import "sync" - -type sema struct { - // simulate cancellable counting semaphore using counter + mutex + cond - mutex sync.Mutex - cond sync.Cond - count, max int -} - -func newSema(max int) *sema { - s := &sema{max: max} - s.cond.L = &s.mutex - return s -} - -func (s *sema) inc() { - s.mutex.Lock() - for s.count == s.max { - s.cond.Wait() - } - s.mutex.Unlock() -} - -func (s *sema) release(n int) { - s.mutex.Lock() - old := s.count - s.count -= n - if old == s.max { - if n == 1 { - s.cond.Signal() - } else { - s.cond.Broadcast() - } - } - s.mutex.Unlock() -} diff --git a/libbeat/publisher/processing/processors.go b/libbeat/publisher/processing/processors.go index 19111b6aff9..cac9d356153 100644 --- a/libbeat/publisher/processing/processors.go +++ b/libbeat/publisher/processing/processors.go @@ -21,6 +21,7 @@ import ( "fmt" "strings" "sync" + "time" "github.com/joeshaw/multierror" @@ -51,6 +52,11 @@ func newGeneralizeProcessor(keepNull bool) *processorFn { return nil, nil } + // data streams require @timestamp field + if event.Timestamp.IsZero() { + event.Timestamp = time.Now() + } + fields := g.Convert(event.Fields) if fields == nil { logger.Error("fail to convert to generic event") diff --git a/libbeat/publisher/queue/spool/codec.go b/libbeat/publisher/queue/spool/codec.go deleted file mode 100644 index 69f693a4817..00000000000 --- a/libbeat/publisher/queue/spool/codec.go +++ /dev/null @@ -1,203 +0,0 @@ -// Licensed to Elasticsearch B.V. under one or more contributor -// license agreements. See the NOTICE file distributed with -// this work for additional information regarding copyright -// ownership. Elasticsearch B.V. licenses this file to you 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 spool - -import ( - "bytes" - "fmt" - "time" - - "github.com/elastic/beats/v7/libbeat/beat" - "github.com/elastic/beats/v7/libbeat/common" - "github.com/elastic/beats/v7/libbeat/outputs/codec" - "github.com/elastic/beats/v7/libbeat/publisher" - "github.com/elastic/go-structform" - "github.com/elastic/go-structform/cborl" - "github.com/elastic/go-structform/gotype" - "github.com/elastic/go-structform/json" - "github.com/elastic/go-structform/ubjson" -) - -type encoder struct { - buf bytes.Buffer - folder *gotype.Iterator - codec codecID -} - -type decoder struct { - buf []byte - - json *json.Parser - cborl *cborl.Parser - ubjson *ubjson.Parser - unfolder *gotype.Unfolder -} - -type codecID uint8 - -type entry struct { - Timestamp int64 - Flags uint8 - Meta common.MapStr - Fields common.MapStr -} - -const ( - // Note: Never change order. Codec IDs must be not change in the future. Only - // adding new IDs is allowed. - codecUnknown codecID = iota - codecJSON - codecUBJSON - codecCBORL - - flagGuaranteed uint8 = 1 << 0 -) - -func newEncoder(codec codecID) (*encoder, error) { - switch codec { - case codecJSON, codecCBORL, codecUBJSON: - break - default: - return nil, fmt.Errorf("unknown codec type '%v'", codec) - } - - e := &encoder{codec: codec} - e.reset() - return e, nil -} - -func (e *encoder) reset() { - e.folder = nil - - var visitor structform.Visitor - switch e.codec { - case codecJSON: - visitor = json.NewVisitor(&e.buf) - case codecCBORL: - visitor = cborl.NewVisitor(&e.buf) - case codecUBJSON: - visitor = ubjson.NewVisitor(&e.buf) - default: - panic("no codec configured") - } - - folder, err := gotype.NewIterator(visitor, - gotype.Folders( - codec.MakeTimestampEncoder(), - codec.MakeBCTimestampEncoder(), - ), - ) - if err != nil { - panic(err) - } - - e.folder = folder -} - -func (e *encoder) encode(event *publisher.Event) ([]byte, error) { - e.buf.Reset() - e.buf.WriteByte(byte(e.codec)) - - var flags uint8 - if (event.Flags & publisher.GuaranteedSend) == publisher.GuaranteedSend { - flags = flagGuaranteed - } - - err := e.folder.Fold(entry{ - Timestamp: event.Content.Timestamp.UTC().UnixNano(), - Flags: flags, - Meta: event.Content.Meta, - Fields: event.Content.Fields, - }) - if err != nil { - e.reset() - return nil, err - } - - return e.buf.Bytes(), nil -} - -func newDecoder() *decoder { - d := &decoder{} - d.reset() - return d -} - -func (d *decoder) reset() { - unfolder, err := gotype.NewUnfolder(nil) - if err != nil { - panic(err) // can not happen - } - - d.unfolder = unfolder - d.json = json.NewParser(unfolder) - d.cborl = cborl.NewParser(unfolder) - d.ubjson = ubjson.NewParser(unfolder) -} - -// Buffer prepares the read buffer to hold the next event of n bytes. -func (d *decoder) Buffer(n int) []byte { - if cap(d.buf) > n { - d.buf = d.buf[:n] - } else { - d.buf = make([]byte, n) - } - return d.buf -} - -func (d *decoder) Decode() (publisher.Event, error) { - var ( - to entry - err error - codec = codecID(d.buf[0]) - contents = d.buf[1:] - ) - - d.unfolder.SetTarget(&to) - defer d.unfolder.Reset() - - switch codec { - case codecJSON: - err = d.json.Parse(contents) - case codecUBJSON: - err = d.ubjson.Parse(contents) - case codecCBORL: - err = d.cborl.Parse(contents) - default: - return publisher.Event{}, fmt.Errorf("unknown codec type '%v'", codec) - } - - if err != nil { - d.reset() // reset parser just in case - return publisher.Event{}, err - } - - var flags publisher.EventFlags - if (to.Flags & flagGuaranteed) != 0 { - flags |= publisher.GuaranteedSend - } - - return publisher.Event{ - Flags: flags, - Content: beat.Event{ - Timestamp: time.Unix(0, to.Timestamp), - Fields: to.Fields, - Meta: to.Meta, - }, - }, nil -} diff --git a/libbeat/publisher/queue/spool/codec_test.go b/libbeat/publisher/queue/spool/codec_test.go deleted file mode 100644 index 6460985f6c3..00000000000 --- a/libbeat/publisher/queue/spool/codec_test.go +++ /dev/null @@ -1,76 +0,0 @@ -// Licensed to Elasticsearch B.V. under one or more contributor -// license agreements. See the NOTICE file distributed with -// this work for additional information regarding copyright -// ownership. Elasticsearch B.V. licenses this file to you 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 spool - -import ( - "testing" - "time" - - "github.com/stretchr/testify/assert" - - "github.com/elastic/beats/v7/libbeat/beat" - "github.com/elastic/beats/v7/libbeat/common" - "github.com/elastic/beats/v7/libbeat/publisher" -) - -func TestEncodeDecode(t *testing.T) { - tests := map[string]codecID{ - "json": codecJSON, - "ubjson": codecUBJSON, - "cborl": codecCBORL, - } - - fieldTimeStr := "2020-01-14T20:33:23.779Z" - fieldTime, _ := time.Parse(time.RFC3339Nano, fieldTimeStr) - event := publisher.Event{ - Content: beat.Event{ - Timestamp: time.Now().Round(0), - Fields: common.MapStr{ - "time": fieldTime, - "commontime": common.Time(fieldTime), - }, - }, - } - expected := publisher.Event{ - Content: beat.Event{ - Timestamp: event.Content.Timestamp, - Fields: common.MapStr{ - "time": fieldTime.Format(time.RFC3339Nano), - "commontime": common.Time(fieldTime).String(), - }, - }, - } - - for name, codec := range tests { - t.Run(name, func(t *testing.T) { - encoder, err := newEncoder(codec) - assert.NoError(t, err) - - encoded, err := encoder.encode(&event) - assert.NoError(t, err) - - decoder := newDecoder() - decoder.buf = encoded - - observed, err := decoder.Decode() - assert.NoError(t, err) - - assert.Equal(t, expected, observed) - }) - } -} diff --git a/libbeat/publisher/queue/spool/config.go b/libbeat/publisher/queue/spool/config.go deleted file mode 100644 index 1d9d9a3299d..00000000000 --- a/libbeat/publisher/queue/spool/config.go +++ /dev/null @@ -1,129 +0,0 @@ -// Licensed to Elasticsearch B.V. under one or more contributor -// license agreements. See the NOTICE file distributed with -// this work for additional information regarding copyright -// ownership. Elasticsearch B.V. licenses this file to you 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 spool - -import ( - "errors" - "fmt" - "os" - "strings" - "time" - - "github.com/dustin/go-humanize" - "github.com/joeshaw/multierror" - - "github.com/elastic/beats/v7/libbeat/common/cfgtype" -) - -type config struct { - File pathConfig `config:"file"` - Write writeConfig `config:"write"` - Read readConfig `config:"read"` -} - -type pathConfig struct { - Path string `config:"path"` - Permissions os.FileMode `config:"permissions"` - MaxSize cfgtype.ByteSize `config:"size"` - PageSize cfgtype.ByteSize `config:"page_size"` - Prealloc bool `config:"prealloc"` -} - -type writeConfig struct { - BufferSize cfgtype.ByteSize `config:"buffer_size"` - FlushEvents int `config:"flush.events"` - FlushTimeout time.Duration `config:"flush.timeout"` - Codec codecID `config:"codec"` -} - -type readConfig struct { - FlushTimeout time.Duration `config:"flush.timeout"` -} - -func defaultConfig() config { - return config{ - File: pathConfig{ - Path: "", - Permissions: 0600, - MaxSize: 100 * humanize.MiByte, - PageSize: 4 * humanize.KiByte, - Prealloc: true, - }, - Write: writeConfig{ - BufferSize: 1 * humanize.MiByte, - FlushTimeout: 1 * time.Second, - FlushEvents: 16 * 1024, - Codec: codecCBORL, - }, - Read: readConfig{ - FlushTimeout: 0, - }, - } -} - -func (c *pathConfig) Validate() error { - var errs multierror.Errors - - if c.MaxSize < humanize.MiByte { - errs = append(errs, errors.New("max size must be larger 1MiB")) - } - - if !c.Permissions.IsRegular() { - errs = append(errs, fmt.Errorf("permissions %v are not regular file permissions", c.Permissions.String())) - } else { - m := c.Permissions.Perm() - if (m & 0400) == 0 { - errs = append(errs, errors.New("file must be readable by current user")) - } - if (m & 0200) == 0 { - errs = append(errs, errors.New("file must be writable by current user")) - } - } - - // TODO: good 'limit' on pageSize? - - if c.PageSize >= c.MaxSize { - errs = append(errs, fmt.Errorf("page_size (%v) must be less then size (%v)", c.PageSize, c.MaxSize)) - } - - return errs.Err() -} - -func (c *writeConfig) Validate() error { - return nil -} - -func (c *readConfig) Validate() error { - return nil -} - -func (c *codecID) Unpack(value string) error { - ids := map[string]codecID{ - "json": codecJSON, - "ubjson": codecUBJSON, - "cbor": codecCBORL, - } - - id, exists := ids[strings.ToLower(value)] - if !exists { - return fmt.Errorf("codec '%v' not available", value) - } - - *c = id - return nil -} diff --git a/libbeat/publisher/queue/spool/consume.go b/libbeat/publisher/queue/spool/consume.go deleted file mode 100644 index 74f3058f739..00000000000 --- a/libbeat/publisher/queue/spool/consume.go +++ /dev/null @@ -1,139 +0,0 @@ -// Licensed to Elasticsearch B.V. under one or more contributor -// license agreements. See the NOTICE file distributed with -// this work for additional information regarding copyright -// ownership. Elasticsearch B.V. licenses this file to you 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 spool - -import ( - "errors" - "io" - - "github.com/elastic/beats/v7/libbeat/common/atomic" - "github.com/elastic/beats/v7/libbeat/publisher" - "github.com/elastic/beats/v7/libbeat/publisher/queue" -) - -type consumer struct { - ctx *spoolCtx - closed atomic.Bool - done chan struct{} - - resp chan getResponse - requ chan getRequest -} - -type batch struct { - events []publisher.Event - state ackState - ack chan batchAckMsg -} - -type ackState uint8 - -const ( - batchActive ackState = iota - batchACK -) - -func newConsumer(ctx *spoolCtx, requ chan getRequest) *consumer { - return &consumer{ - ctx: ctx, - closed: atomic.MakeBool(false), - done: make(chan struct{}), - - // internal API - resp: make(chan getResponse), - requ: requ, - } -} - -func (c *consumer) Close() error { - if c.closed.Swap(true) { - return errors.New("already closed") - } - - close(c.done) - return nil -} - -func (c *consumer) Closed() bool { - return c.closed.Load() || c.ctx.Closed() -} - -func (c *consumer) Get(sz int) (queue.Batch, error) { - log := c.ctx.logger - - if c.Closed() { - return nil, io.EOF - } - - var resp getResponse - for { - select { - case <-c.ctx.Done(): - return nil, io.EOF - - case <-c.done: - return nil, io.EOF - - case c.requ <- getRequest{sz: sz, resp: c.resp}: - } - - resp = <-c.resp - err := resp.err - if err == nil { - break - } - - if err != errRetry { - log.Debug("consumer: error response:", err) - return nil, err - } - } - - log.Debug("consumer: received batch:", len(resp.buf)) - return &batch{ - events: resp.buf, - state: batchActive, - ack: resp.ack, - }, nil -} - -func (b *batch) Events() []publisher.Event { - if b.state != batchActive { - panic("Get Events from inactive batch") - } - return b.events -} - -func (b *batch) ACK() { - if b.state != batchActive { - switch b.state { - case batchACK: - panic("Can not acknowledge already acknowledged batch") - default: - panic("inactive batch") - } - } - - b.report() -} - -func (b *batch) report() { - if b.ack != nil { - b.ack <- batchAckMsg{} - } -} diff --git a/libbeat/publisher/queue/spool/inbroker.go b/libbeat/publisher/queue/spool/inbroker.go deleted file mode 100644 index b165f2a152b..00000000000 --- a/libbeat/publisher/queue/spool/inbroker.go +++ /dev/null @@ -1,550 +0,0 @@ -// Licensed to Elasticsearch B.V. under one or more contributor -// license agreements. See the NOTICE file distributed with -// this work for additional information regarding copyright -// ownership. Elasticsearch B.V. licenses this file to you 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 spool - -import ( - "fmt" - "math" - "time" - - "github.com/elastic/beats/v7/libbeat/publisher/queue" - "github.com/elastic/go-txfile/pq" -) - -type inBroker struct { - ctx *spoolCtx - ackListener queue.ACKListener - - // active state handler - state func(*inBroker) bool - - // api channels - events chan pushRequest - pubCancel chan producerCancelRequest - - // queue signaling - sigACK chan struct{} - sigFlush chan uint - ackDone chan struct{} - - // queue state - queue *pq.Queue - writer *pq.Writer - clientStates clientStates - - // Event contents, that still needs to be send to the queue. An event is - // pending if it has been serialized, but not added to the write buffer in - // full, as some I/O operation on the write buffer failed. - // => - // - keep pointer to yet unwritten event contents - // - do not accept any events if pending is not nil - // - wait for signal from reader/queue-gc to retry writing the pending - // events contents - pending []byte - - bufferedEvents uint // number of buffered events - - // flush settings - timer *timer - flushEvents uint - - enc *encoder -} - -const ( - inSigChannelSize = 3 - inEventChannelSize = 20 -) - -func newInBroker( - ctx *spoolCtx, - ackListener queue.ACKListener, - qu *pq.Queue, - codec codecID, - flushTimeout time.Duration, - flushEvents uint, -) (*inBroker, error) { - enc, err := newEncoder(codec) - if err != nil { - return nil, err - } - - writer, err := qu.Writer() - if err != nil { - return nil, err - } - - b := &inBroker{ - ctx: ctx, - ackListener: ackListener, - state: (*inBroker).stateEmpty, - - // API - events: make(chan pushRequest, inEventChannelSize), - pubCancel: make(chan producerCancelRequest), - sigACK: make(chan struct{}, inSigChannelSize), - sigFlush: make(chan uint, inSigChannelSize), - ackDone: make(chan struct{}), - - // queue state - queue: qu, - writer: writer, - clientStates: clientStates{}, - pending: nil, - bufferedEvents: 0, - - // internal - timer: newTimer(flushTimeout), - flushEvents: flushEvents, - enc: enc, - } - - ctx.Go(b.eventLoop) - ctx.Go(b.ackLoop) - return b, nil -} - -func (b *inBroker) Producer(cfg queue.ProducerConfig) queue.Producer { - return newProducer(b.ctx, b.pubCancel, b.events, cfg.ACK, cfg.OnDrop, cfg.DropOnCancel) -} - -// onFlush is run whenever the queue flushes it's write buffer. The callback is -// run in the same go-routine as the Flush was executed from. -// Only the (*inBroker).eventLoop triggers a flush. -func (b *inBroker) onFlush(n uint) { - log := b.ctx.logger - log.Debug("inbroker: onFlush ", n) - - if n == 0 { - return - } - - if b.ackListener != nil { - b.ackListener.OnACK(int(n)) - } - b.ctx.logger.Debug("inbroker: flushed events:", n) - b.bufferedEvents -= n - b.sigFlush <- n -} - -// onACK is run whenever the queue releases ACKed events. The number of acked -// events and freed pages will is reported. -// Flush events are forward to the brokers eventloop, so to give the broker a -// chance to retry writing in case it has been blocked on a full queue. -func (b *inBroker) onACK(events, pages uint) { - if pages > 0 { - b.sigACK <- struct{}{} - } -} - -func (b *inBroker) ackLoop() { - log := b.ctx.logger - - log.Debug("start flush ack loop") - defer log.Debug("stop flush ack loop") - - for { - var n uint - select { - case <-b.ackDone: - return - - case n = <-b.sigFlush: - log.Debug("inbroker: receive flush", n) - states := b.clientStates.Pop(int(n)) - b.sendACKs(states) - } - } -} - -// sendACKs returns the range of ACKed/Flushed events to the individual -// producers ACK handlers. -func (b *inBroker) sendACKs(states []clientState) { - log := b.ctx.logger - - // reverse iteration on client states, so to report ranges of ACKed events - // only once. - N := len(states) - total := 0 - for i := N - 1; i != -1; i-- { - st := &states[i] - if st.state == nil { - continue - } - - count := (st.seq - st.state.lastACK) - if count == 0 || count > math.MaxUint32/2 { - // seq number comparison did underflow. This happens only if st.seq has - // already been acknowledged - // log.Debug("seq number already acked: ", st.seq) - - st.state = nil - continue - } - - log.Debugf("broker ACK events: count=%v, start-seq=%v, end-seq=%v\n", - count, - st.state.lastACK+1, - st.seq, - ) - - total += int(count) - if total > N { - panic(fmt.Sprintf("Too many events acked (expected=%v, total=%v)", - N, total, - )) - } - - // report range of ACKed events - st.state.ackCB(int(count)) - st.state.lastACK = st.seq - st.state = nil - } -} - -func (b *inBroker) eventLoop() { - log := b.ctx.logger - log.Info("spool input eventloop start") - defer log.Info("spool input eventloop stop") - - // notify ackLoop to stop only after eventLoop has finished (after last flush) - defer close(b.ackDone) - defer b.eventloopShutdown() - - for { - ok := b.state(b) - if !ok { - break - } - } -} - -func (b *inBroker) eventloopShutdown() { - // try to flush events/buffers on shutdown. - if b.bufferedEvents == 0 { - return - } - - // Try to flush pending events. - w := b.writer - for len(b.pending) > 0 { - n, err := w.Write(b.pending) - b.pending = b.pending[n:] - if err != nil { - return - } - } - w.Flush() -} - -// stateEmpty is the brokers active state if the write buffer is empty and the -// queue did not block on write or flush operations. -// ACKs from the output are ignored, as events can still be added to the write -// buffer. -// -// stateEmpty transitions: -// -> stateEmpty if serializing the event failed -// -> stateWithTimer if event is written to buffer without flush -// => start timer -// -> stateBlocked if queue did return an error on write (Flush failed) -func (b *inBroker) stateEmpty() bool { - log := b.ctx.logger - - select { - case <-b.ctx.Done(): - return false - - case req := <-b.events: - log.Debug("inbroker (stateEmpty): new event") - - buf, st, err := b.encodeEvent(&req) - if err != nil { - log.Debug(" inbroker (stateEmpty): encode failed") - b.respondDrop(&req) - break - } - - // write/flush failed -> block until space in file becomes available - err = b.addEvent(buf, st) - if err != nil { - log.Debug(" inbroker: append failed, blocking") - b.state = (*inBroker).stateBlocked - break - } - - // start flush timer - if b.flushEvents > 0 && b.bufferedEvents == b.flushEvents { - log.Debug(" inbroker (stateEmpty): flush events") - err := b.flushBuffer() - if err != nil { - log.Debug(" inbroker (stateEmpty): flush failed, blocking") - b.state = (*inBroker).stateBlocked - } - break - - } else if b.bufferedEvents > 0 { - log.Debug(" inbroker (stateEmpty): start flush timer") - b.timer.Start() - b.state = (*inBroker).stateWithTimer - } - - case req := <-b.pubCancel: - b.handleCancel(&req) - - case <-b.sigACK: - // ignore ACKs as long as we can write without blocking - } - - return true -} - -// stateWithTimer is the brokers active state, if the write buffer is not empty. -// The flush timer is enabled as long as the broker is in this state. -// ACKs from the output are ignored, as events can still be added to the write -// buffer. -// -// stateWithTimer transitions: -// -> stateWithTimer -// - if serializing failed -// - if event is added to buffer, without flush -// - flush, but more events are available in the buffer (might reset timer) -// -> stateEmpty if all events have been flushed -// -> stateBlocked if queue did return an error on write/flush (Flush failed) -func (b *inBroker) stateWithTimer() bool { - log := b.ctx.logger - - select { - case <-b.ctx.Done(): - return false - - case req := <-b.events: - log.Debug("inbroker (stateWithTimer): new event") - - buf, st, err := b.encodeEvent(&req) - if err != nil { - log.Debug(" inbroker (stateWithTimer): encode failed") - b.respondDrop(&req) - break - } - - count := b.bufferedEvents - err = b.addEvent(buf, st) - if err != nil { - log.Debug(" inbroker (stateWithTimer): append failed, blocking") - b.state = (*inBroker).stateBlocked - break - } - - flushed := b.bufferedEvents < count - if !flushed && b.flushEvents > 0 && b.bufferedEvents == b.flushEvents { - err := b.flushBuffer() - if err != nil { - log.Debug(" inbroker (stateWithTimer): flush failed, blocking") - b.state = (*inBroker).stateBlocked - break - } - - flushed = true - } - - if !flushed { - break - } - - // write buffer has been flushed, reset timer and broker state - log.Debug(" inbroker (stateWithTimer): buffer flushed") - if b.bufferedEvents == 0 { - b.timer.Stop(false) - b.state = (*inBroker).stateEmpty - } else { - // restart timer, as new event is most likely the only event buffered - // -> reduce IO - log.Debug(" inbroker (stateWithTimer): start flush timer") - b.timer.Restart() - } - - case req := <-b.pubCancel: - b.handleCancel(&req) - - case <-b.timer.C: - log.Debug("inbroker (stateWithTimer): flush timeout", b.bufferedEvents) - - b.timer.Stop(true) - - err := b.flushBuffer() - if err != nil { - log.Debug(" inbroker (stateWithTimer): flush failed, blocking") - b.state = (*inBroker).stateBlocked - break - } - - log.Debug(" inbroker (stateWithTimer): flush succeeded") - - if b.bufferedEvents > 0 { - // flush did not push all events? Restart timer. - log.Debug(" inbroker (stateWithTimer): start flush timer", b.bufferedEvents) - b.timer.Start() - break - } - - b.state = (*inBroker).stateEmpty - - case <-b.sigACK: - // ignore ACKs as long as we can write without blocking - } - - return true -} - -// stateBlocked is the brokers active state if the write buffer can not accept -// any new events. -// The broker will wait for an ACK signal from the outputs and retry flushing, -// in the hope of enough memory being available to flush the buffers. -// If flush did succeed, we try to add the pending event. -// For the time the broker is in this state, no events from any producers will -// be accepted. Thusly all producers will block. Closing a producer, unblocks -// the producer. The producers event (after close) might be processed or -// ignored in the future. -// -// stateBlocked transitions: -// -> stateEmpty if flush was successful and write buffer is empty -// -> stateWithTimer if flush was successful, but we still have some pending events -// -> stateBlocked if flush failed (still not enough space) -func (b *inBroker) stateBlocked() bool { - log := b.ctx.logger - - select { - case <-b.ctx.Done(): - return false - - case req := <-b.pubCancel: - b.handleCancel(&req) - - case <-b.sigACK: - // TODO: - // Have write buffer report number of unallocated pages and take number - // of freed pages into account before retrying. This way no transaction - // must be created if it's already clear the flush will not succeed. - - log.Debug("inbroker (stateBlocked): ACK event from queue -> try to unblock") - - err := b.flushBuffer() - if err != nil { - log.Debug(" inbroker (stateBlocked): flush failed, blocking") - break - } - - if len(b.pending) > 0 { - tmp := b.pending - b.pending = nil - err := b.writeEvent(tmp) - if err != nil || len(b.pending) > 0 { - log.Debugf("writing pending event failed: %+v", err) - break - } - } - - if b.bufferedEvents == 0 { - b.state = (*inBroker).stateEmpty - break - } - - b.timer.Start() - log.Debug(" inbroker (stateBlocked): start flush timer") - b.state = (*inBroker).stateWithTimer - } - - return true -} - -func (b *inBroker) handleCancel(req *producerCancelRequest) { - // mark state as cancelled, so to not accept any new events - // from the state object. - if st := req.state; st != nil { - st.cancelled = true - } - - if req.resp != nil { - req.resp <- producerCancelResponse{removed: 0} - } -} - -func (b *inBroker) encodeEvent(req *pushRequest) ([]byte, clientState, error) { - buf, err := b.enc.encode(&req.event) - if err != nil { - return nil, clientState{}, err - } - - if req.state == nil { - return buf, clientState{}, nil - } - - return buf, clientState{seq: req.seq, state: req.state}, nil -} - -func (b *inBroker) respondDrop(req *pushRequest) { - if req.state != nil { - if cb := req.state.dropCB; cb != nil { - cb(req.event.Content) - } - } -} - -func (b *inBroker) addEvent(buf []byte, st clientState) error { - log := b.ctx.logger - - b.bufferedEvents++ - log.Debug(" inbroker: add event of size", len(buf), b.bufferedEvents) - - count := b.clientStates.Add(st) - log.Debug(" add event -> active:", count) - - err := b.writeEvent(buf) - log.Debugf(" inbroker write -> events=%v, err=%+v ", b.bufferedEvents, err) - - return err -} - -func (b *inBroker) writeEvent(buf []byte) error { - log := b.ctx.logger - - // append event to queue - w := b.writer - n, err := w.Write(buf) - buf = buf[n:] - if len(buf) > 0 { - b.pending = buf - } else if err == nil { - log.Debug("writer: finalize event in buffer") - err = w.Next() - } - - if err != nil { - log.Debugf("Appending event content to write buffer failed with %+v", err) - } - return err -} - -func (b *inBroker) flushBuffer() error { - err := b.writer.Flush() - if err != nil { - log := b.ctx.logger - log.Errorf("Spool flush failed with: %+v", err) - } - return err -} diff --git a/libbeat/publisher/queue/spool/internal_api.go b/libbeat/publisher/queue/spool/internal_api.go deleted file mode 100644 index a6fd97102d4..00000000000 --- a/libbeat/publisher/queue/spool/internal_api.go +++ /dev/null @@ -1,61 +0,0 @@ -// Licensed to Elasticsearch B.V. under one or more contributor -// license agreements. See the NOTICE file distributed with -// this work for additional information regarding copyright -// ownership. Elasticsearch B.V. licenses this file to you 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 spool - -import ( - "github.com/elastic/beats/v7/libbeat/publisher" -) - -// producer -> broker API -type ( - pushRequest struct { - event publisher.Event - seq uint32 - state *produceState - } - - producerCancelRequest struct { - state *produceState - resp chan producerCancelResponse - } - - producerCancelResponse struct { - removed int - } -) - -// consumer -> broker API - -type ( - getRequest struct { - sz int // request sz events from the broker - resp chan getResponse // channel to send response to - } - - getResponse struct { - ack chan batchAckMsg - err error - buf []publisher.Event - } - - batchAckMsg struct{} - - batchCancelRequest struct { - // ack *ackChan - } -) diff --git a/libbeat/publisher/queue/spool/log.go b/libbeat/publisher/queue/spool/log.go deleted file mode 100644 index 64150366b53..00000000000 --- a/libbeat/publisher/queue/spool/log.go +++ /dev/null @@ -1,71 +0,0 @@ -// Licensed to Elasticsearch B.V. under one or more contributor -// license agreements. See the NOTICE file distributed with -// this work for additional information regarding copyright -// ownership. Elasticsearch B.V. licenses this file to you 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 spool - -import ( - "fmt" - "sync" - - "github.com/elastic/beats/v7/libbeat/logp" -) - -type logger interface { - Debug(...interface{}) - Debugf(string, ...interface{}) - - Info(...interface{}) - Infof(string, ...interface{}) - - Error(...interface{}) - Errorf(string, ...interface{}) -} - -var _defaultLogger struct { - singleton logger - init sync.Once -} - -func defaultLogger() logger { - _defaultLogger.init.Do(func() { - _defaultLogger.singleton = logp.NewLogger("spool") - }) - return _defaultLogger.singleton -} - -// func defaultLogger() logger { return (*outLogger)(nil) } - -type outLogger struct{} - -func (l *outLogger) Debug(vs ...interface{}) { l.report("Debug", vs) } -func (l *outLogger) Debugf(fmt string, vs ...interface{}) { l.reportf("Debug: ", fmt, vs) } - -func (l *outLogger) Info(vs ...interface{}) { l.report("Info", vs) } -func (l *outLogger) Infof(fmt string, vs ...interface{}) { l.reportf("Info", fmt, vs) } - -func (l *outLogger) Error(vs ...interface{}) { l.report("Error", vs) } -func (l *outLogger) Errorf(fmt string, vs ...interface{}) { l.reportf("Error", fmt, vs) } - -func (l *outLogger) report(level string, vs []interface{}) { - args := append([]interface{}{level, ":"}, vs...) - fmt.Println(args...) -} - -func (*outLogger) reportf(level string, str string, vs []interface{}) { - str = level + ": " + str - fmt.Printf(str, vs...) -} diff --git a/libbeat/publisher/queue/spool/module.go b/libbeat/publisher/queue/spool/module.go deleted file mode 100644 index acf22145c4b..00000000000 --- a/libbeat/publisher/queue/spool/module.go +++ /dev/null @@ -1,80 +0,0 @@ -// Licensed to Elasticsearch B.V. under one or more contributor -// license agreements. See the NOTICE file distributed with -// this work for additional information regarding copyright -// ownership. Elasticsearch B.V. licenses this file to you 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 spool - -import ( - "github.com/elastic/beats/v7/libbeat/common" - "github.com/elastic/beats/v7/libbeat/common/cfgwarn" - "github.com/elastic/beats/v7/libbeat/feature" - "github.com/elastic/beats/v7/libbeat/logp" - "github.com/elastic/beats/v7/libbeat/paths" - "github.com/elastic/beats/v7/libbeat/publisher/queue" - "github.com/elastic/go-txfile" -) - -func init() { - queue.RegisterQueueType( - "spool", - create, - feature.MakeDetails( - "Disk spool", - "Buffer events in disk spool before sending to the output.", - feature.Beta)) -} - -func create( - ackListener queue.ACKListener, logp *logp.Logger, cfg *common.Config, inQueueSize int, -) (queue.Queue, error) { - cfgwarn.Beta("Spooling to disk is beta") - - config := defaultConfig() - if err := cfg.Unpack(&config); err != nil { - return nil, err - } - - path := config.File.Path - if path == "" { - path = paths.Resolve(paths.Data, "spool.dat") - } - - flushEvents := uint(0) - if count := config.Write.FlushEvents; count > 0 { - flushEvents = uint(count) - } - - var log logger = logp - if logp == nil { - log = defaultLogger() - } - - return newDiskSpool(log, path, settings{ - ACKListener: ackListener, - Mode: config.File.Permissions, - WriteBuffer: uint(config.Write.BufferSize), - WriteFlushTimeout: config.Write.FlushTimeout, - WriteFlushEvents: flushEvents, - ReadFlushTimeout: config.Read.FlushTimeout, - Codec: config.Write.Codec, - File: txfile.Options{ - MaxSize: uint64(config.File.MaxSize), - PageSize: uint32(config.File.PageSize), - Prealloc: config.File.Prealloc, - Readonly: false, - }, - }) -} diff --git a/libbeat/publisher/queue/spool/outbroker.go b/libbeat/publisher/queue/spool/outbroker.go deleted file mode 100644 index 409b2cde388..00000000000 --- a/libbeat/publisher/queue/spool/outbroker.go +++ /dev/null @@ -1,536 +0,0 @@ -// Licensed to Elasticsearch B.V. under one or more contributor -// license agreements. See the NOTICE file distributed with -// this work for additional information regarding copyright -// ownership. Elasticsearch B.V. licenses this file to you 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 spool - -import ( - "errors" - "sync" - "time" - - "github.com/elastic/beats/v7/libbeat/publisher" - "github.com/elastic/go-txfile/pq" -) - -type outBroker struct { - ctx *spoolCtx - state func(*outBroker) bool - - // internal API - sigFlushed chan uint - get chan getRequest - - // ack signaling - pendingACKs chanList // list of pending batches to be forwarded to the ackLoop - scheduledACKs chan chanList // shared channel for forwarding batches to ackLoop - schedACKs chan chanList // active ack forwarding channel, as used by broker (nil if pendingACKs is empty) - - // queue state - queue *pq.Queue - reader *pq.Reader - available uint // number of available events. getRequests are only accepted if available > 0 - events []publisher.Event - required int - total int - active getRequest - - // internal - timer *timer - dec *decoder -} - -type chanList struct { - head *ackChan - tail *ackChan -} - -type ackChan struct { - next *ackChan - ch chan batchAckMsg - total int // total number of events to ACK with this batch -} - -const ( - // maximum number of events if getRequest size is <0 - maxEvents = 2048 - - outSigChannelSize = 3 -) - -var ackChanPool = sync.Pool{ - New: func() interface{} { - return &ackChan{ - ch: make(chan batchAckMsg, 1), - } - }, -} - -var errRetry = errors.New("retry") - -func newOutBroker(ctx *spoolCtx, qu *pq.Queue, flushTimeout time.Duration) (*outBroker, error) { - reader := qu.Reader() - - var ( - avail uint - err error - ) - func() { - if err = reader.Begin(); err != nil { - return - } - defer reader.Done() - avail, err = reader.Available() - }() - if err != nil { - return nil, err - } - - b := &outBroker{ - ctx: ctx, - state: nil, - - // API - sigFlushed: make(chan uint, outSigChannelSize), - get: make(chan getRequest), - - // ack signaling - pendingACKs: chanList{}, - scheduledACKs: make(chan chanList), - schedACKs: nil, - - // queue state - queue: qu, - reader: reader, - available: avail, - events: nil, - required: 0, - total: 0, - active: getRequest{}, - - // internal - timer: newTimer(flushTimeout), - dec: newDecoder(), - } - - b.initState() - ctx.Go(b.eventLoop) - ctx.Go(b.ackLoop) - return b, nil -} - -func (b *outBroker) Consumer() *consumer { - return newConsumer(b.ctx, b.get) -} - -// onFlush is run whenever the queue flushes it's write buffer. The callback is -// run in the same go-routine as the Flush was executed from. -func (b *outBroker) onFlush(n uint) { - if n > 0 { - select { - case <-b.ctx.Done(): // ignore flush messages on shutdown - - case b.sigFlushed <- n: - - } - } -} - -// onACK is run whenever the queue releases ACKed events. The number of acked -// events and freed pages will is reported. -func (b *outBroker) onACK(events, pages uint) { -} - -func (b *outBroker) ackLoop() { - log := b.ctx.logger - - log.Debug("start output ack loop") - defer log.Debug("stop output ack loop") - - var ackList chanList // list of pending acks - for { - select { - case <-b.ctx.Done(): - return - - case lst := <-b.scheduledACKs: - ackList.concat(&lst) - - case <-ackList.channel(): - ackCh := ackList.pop() - - for { - log.Debugf("receive ACK of %v events\n", ackCh.total) - err := b.queue.ACK(uint(ackCh.total)) - if err != nil { - log.Debugf("ack failed with: %+v", err) - time.Sleep(1 * time.Second) - continue - } - - log.Debug("ACK succeeded") - break - } - - releaseACKChan(ackCh) - } - } -} - -func (b *outBroker) eventLoop() { - for { - ok := b.state(b) - if !ok { - break - } - } -} - -// initState resets the brokers state to the initial state and clears -// buffers/points from last state updates. -func (b *outBroker) initState() { - b.events = nil - b.required = 0 - b.total = 0 - b.active = getRequest{} - if b.available == 0 { - b.state = (*outBroker).stateWaitEvents - } else { - b.state = (*outBroker).stateActive - } -} - -// stateWaitEvents is the brokers state if the queue is empty. -// The broker waits for new events and does not accept and consumer requests. -// -// stateWaitEvents transitions: -// -> stateActive: if a queue flush signal has been received -func (b *outBroker) stateWaitEvents() bool { - log := b.ctx.logger - log.Debug("outbroker (stateWaitEvents): waiting for new events") - - select { - case <-b.ctx.Done(): - return false - - case n := <-b.sigFlushed: - log.Debug("outbroker (stateWaitEvents): flush event", n) - b.available += n - b.state = (*outBroker).stateActive - - case b.schedACKs <- b.pendingACKs: - b.handleACKsScheduled() - } - - return true -} - -// stateActive is the brokers initial state, waiting for consumer to request -// new events. -// Flush signals from the input are ignored. -// -// stateActive transitions: -// -> stateActive: if consumer event get request has been fulfilled (N events -// copied or 0 timeout) -// -> stateWaitEvents: if queue is empty after read -// -> stateWithTimer: if only small number of events are available and flush -// timeout is configured. -func (b *outBroker) stateActive() bool { - log := b.ctx.logger - - select { - case <-b.ctx.Done(): - return false - - case n := <-b.sigFlushed: - b.available += n - - case b.schedACKs <- b.pendingACKs: - b.handleACKsScheduled() - - case req := <-b.get: - var events []publisher.Event - required := maxEvents - if req.sz > 0 { - events = make([]publisher.Event, 0, req.sz) - required = req.sz - } - - log.Debug("outbroker (stateActive): get request", required) - - var err error - var total int - events, total, err = b.collectEvents(events, required) - required -= len(events) - b.available -= uint(total) - - log.Debug(" outbroker (stateActive): events collected", len(events), total, err) - - // forward error to consumer and continue with current state - if err != nil { - log.Debug(" outbroker (stateActive): return error") - b.returnError(req, events, total, err) - b.initState() - break - } - - // enough events? Return - if required == 0 || (len(events) > 0 && b.timer.Zero()) { - log.Debug(" outbroker (stateActive): return events") - b.returnEvents(req, events, total) - b.initState() // prepare for next request - break - } - - // If no events have been decoded, signal an error to the consumer to retry. - // Meanwhile reinitialize state, waiting for more events. - if len(events) == 0 { - b.returnError(req, nil, total, errRetry) - b.initState() - break - } - - // not enough events -> start timer and try to collect more - b.events = events - b.required = required - b.active = req - b.total = total - b.timer.Start() - log.Debug(" outbroker (stateActive): switch to stateWithTimer") - b.state = (*outBroker).stateWithTimer - } - - return true -} - -// stateWithTimer is the brokers active state, if the events read is less then -// the minimal number of requested events. -// Once the timer triggers or more events have been consumed, the get response -// will be send to the consumer. -// -// stateWithTimer transitions: -// -> stateWithTimer: if some, but not enough events have been read from the -// queue -// -> stateActive: if the timer triggers or enough events have been returned -// to the consumer -func (b *outBroker) stateWithTimer() bool { - log := b.ctx.logger - - select { - case <-b.ctx.Done(): - return false - - case b.schedACKs <- b.pendingACKs: - b.handleACKsScheduled() - - case <-b.timer.C: - b.timer.Stop(true) - log.Debug("outbroker (stateWithTimer): flush timer") - b.returnEvents(b.active, b.events, b.total) - - log.Debug("outbroker (stateWithTimer): switch to stateActive") - b.initState() - - case n := <-b.sigFlushed: - // yay, more events \o/ - - b.available += n - - L := len(b.events) - required := b.required - events, total, err := b.collectEvents(b.events, required) - b.available -= uint(total) - collected := len(events) - L - required -= collected - total += b.total - - log.Debug(" outbroker (stateWithTimer): events collected", len(events), total, err) - - // continue with stateWithTimer? - if err == nil && required > 0 { - b.events = events - b.total = total - b.required = required - log.Debug(" outbroker (stateWithTimer): switch to stateWithTimer") - break - } - - // done serving consumer request - b.timer.Stop(false) - if err != nil { - log.Debug(" outbroker (stateWithTimer): return error") - b.returnError(b.active, events, total, err) - } else { - log.Debug(" outbroker (stateWithTimer): return events") - b.returnEvents(b.active, events, total) - } - - log.Debug("outbroker (stateWithTimer): switch to stateActive") - b.initState() - } - - return true -} - -func (b *outBroker) handleACKsScheduled() { - b.schedACKs = nil - b.pendingACKs = chanList{} -} - -func (b *outBroker) newACKChan(total int) *ackChan { - ackCh := newACKChan(total) - b.pendingACKs.append(ackCh) - b.schedACKs = b.scheduledACKs - return ackCh -} - -// signalDrop forwards an ACK of total events to the ackloop. -// The batch is marked as ACKed by the output. -// signalDrop is used to free space in the queue, in case -// a continuous set of events has been dropped due to decoding errors. -func (b *outBroker) signalDrop(total int) { - ackCh := b.newACKChan(total) - ackCh.ch <- batchAckMsg{} -} - -func (b *outBroker) returnEvents(req getRequest, events []publisher.Event, total int) { - ackCh := b.newACKChan(total) - req.resp <- getResponse{ - ack: ackCh.ch, - err: nil, - buf: events, - } -} - -func (b *outBroker) returnError( - req getRequest, - events []publisher.Event, - total int, - err error, -) { - var ch chan batchAckMsg - - if len(events) == 0 && total > 0 { - b.signalDrop(total) - } - if len(events) > 0 { - ackCh := b.newACKChan(total) - ch = ackCh.ch - } - - req.resp <- getResponse{ - ack: ch, - err: err, - buf: events, - } -} - -func (b *outBroker) collectEvents( - events []publisher.Event, - N int, -) ([]publisher.Event, int, error) { - log := b.ctx.logger - reader := b.reader - - // ensure all read operations happen within same transaction - err := reader.Begin() - if err != nil { - return nil, 0, err - } - defer reader.Done() - - count := 0 - for N > 0 { - sz, err := reader.Next() - if sz <= 0 || err != nil { - return events, count, err - } - - count++ - - buf := b.dec.Buffer(sz) - _, err = reader.Read(buf) - if err != nil { - return events, count, err - } - - event, err := b.dec.Decode() - if err != nil { - log.Debug("Failed to decode event from spool: %v", err) - continue - } - - events = append(events, event) - N-- - } - - return events, count, nil -} - -func newACKChan(total int) *ackChan { - c := ackChanPool.Get().(*ackChan) - c.next = nil - c.total = total - return c -} - -func releaseACKChan(c *ackChan) { - c.next = nil - ackChanPool.Put(c) -} - -func (l *chanList) append(ch *ackChan) { - if l.head == nil { - l.head = ch - } else { - l.tail.next = ch - } - l.tail = ch -} - -func (l *chanList) concat(other *chanList) { - if other.head == nil { - return - } - - if l.head == nil { - *l = *other - return - } - - l.tail.next = other.head - l.tail = other.tail -} - -func (l *chanList) channel() chan batchAckMsg { - if l.head == nil { - return nil - } - return l.head.ch -} - -func (l *chanList) pop() *ackChan { - ch := l.head - if ch != nil { - l.head = ch.next - if l.head == nil { - l.tail = nil - } - } - - ch.next = nil - return ch -} diff --git a/libbeat/publisher/queue/spool/produce.go b/libbeat/publisher/queue/spool/produce.go deleted file mode 100644 index 6a74d93b1c6..00000000000 --- a/libbeat/publisher/queue/spool/produce.go +++ /dev/null @@ -1,203 +0,0 @@ -// Licensed to Elasticsearch B.V. under one or more contributor -// license agreements. See the NOTICE file distributed with -// this work for additional information regarding copyright -// ownership. Elasticsearch B.V. licenses this file to you 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 spool - -import ( - "sync" - - "github.com/elastic/beats/v7/libbeat/beat" - "github.com/elastic/beats/v7/libbeat/publisher" - "github.com/elastic/beats/v7/libbeat/publisher/queue" -) - -// forgetfulProducer forwards event to the inBroker. The forgetfulProducer -// provides no event ACK handling and no callbacks. -type forgetfulProducer struct { - openState openState -} - -// ackProducer forwards events to the inBroker. The ackBroker provides -// functionality for ACK/Drop callbacks. -type ackProducer struct { - dropOnCancel bool - seq uint32 - state produceState - openState openState - pubCancel chan producerCancelRequest -} - -// openState tracks the producer->inBroker connection state. -type openState struct { - ctx *spoolCtx - done chan struct{} - events chan pushRequest -} - -// produceState holds the ackProducer internal callback and event ACK state -// shared between ackProducer instances and inBroker instances. -// The state is used to compute the number of per producer ACKed events and -// executing locally configured callbacks. -type produceState struct { - ackCB ackHandler - dropCB func(beat.Event) - cancelled bool - lastACK uint32 -} - -type ackHandler func(count int) - -type clientStates struct { - mux sync.Mutex - clients []clientState -} - -type clientState struct { - seq uint32 // event sequence number - state *produceState // the producer it's state used to compute and signal the ACK count -} - -func newProducer( - ctx *spoolCtx, - pubCancel chan producerCancelRequest, - events chan pushRequest, - ackCB ackHandler, - dropCB func(beat.Event), - dropOnCancel bool, -) queue.Producer { - openState := openState{ - ctx: ctx, - done: make(chan struct{}), - events: events, - } - - if ackCB == nil { - return &forgetfulProducer{openState: openState} - } - - p := &ackProducer{ - seq: 1, - dropOnCancel: dropOnCancel, - openState: openState, - pubCancel: pubCancel, - } - p.state.ackCB = ackCB - p.state.dropCB = dropCB - return p -} - -func (p *forgetfulProducer) Publish(event publisher.Event) bool { - return p.openState.publish(p.makeRequest(event)) -} - -func (p *forgetfulProducer) TryPublish(event publisher.Event) bool { - return p.openState.tryPublish(p.makeRequest(event)) -} - -func (p *forgetfulProducer) makeRequest(event publisher.Event) pushRequest { - return pushRequest{event: event} -} - -func (p *forgetfulProducer) Cancel() int { - p.openState.Close() - return 0 -} - -func (p *ackProducer) Publish(event publisher.Event) bool { - return p.updSeq(p.openState.publish(p.makeRequest(event))) -} - -func (p *ackProducer) TryPublish(event publisher.Event) bool { - return p.updSeq(p.openState.tryPublish(p.makeRequest(event))) -} - -func (p *ackProducer) Cancel() int { - p.openState.Close() - - if p.dropOnCancel { - ch := make(chan producerCancelResponse) - p.pubCancel <- producerCancelRequest{ - state: &p.state, - resp: ch, - } - - // wait for cancel to being processed - resp := <-ch - return resp.removed - } - return 0 -} - -func (p *ackProducer) updSeq(ok bool) bool { - if ok { - p.seq++ - } - return ok -} - -func (p *ackProducer) makeRequest(event publisher.Event) pushRequest { - return pushRequest{event: event, seq: p.seq, state: &p.state} -} - -func (st *openState) Close() { - close(st.done) -} - -func (st *openState) publish(req pushRequest) bool { - select { - case st.events <- req: - return true - case <-st.done: - st.events = nil - return false - } -} - -func (st *openState) tryPublish(req pushRequest) bool { - select { - case st.events <- req: - return true - case <-st.done: - st.events = nil - return false - default: - log := st.ctx.logger - log.Debugf("Dropping event, queue is blocked (seq=%v) ", req.seq) - return false - } -} - -func (s *clientStates) Add(st clientState) int { - s.mux.Lock() - s.clients = append(s.clients, st) - l := len(s.clients) - s.mux.Unlock() - return l -} - -func (s *clientStates) RemoveLast() { - s.mux.Lock() - s.clients = s.clients[:len(s.clients)-1] - s.mux.Unlock() -} - -func (s *clientStates) Pop(n int) (states []clientState) { - s.mux.Lock() - states, s.clients = s.clients[:n], s.clients[n:] - s.mux.Unlock() - return states -} diff --git a/libbeat/publisher/queue/spool/spool.go b/libbeat/publisher/queue/spool/spool.go deleted file mode 100644 index c796170fdc7..00000000000 --- a/libbeat/publisher/queue/spool/spool.go +++ /dev/null @@ -1,250 +0,0 @@ -// Licensed to Elasticsearch B.V. under one or more contributor -// license agreements. See the NOTICE file distributed with -// this work for additional information regarding copyright -// ownership. Elasticsearch B.V. licenses this file to you 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 spool - -import ( - "fmt" - "os" - "runtime" - "sync" - "time" - - "github.com/pkg/errors" - - "github.com/elastic/beats/v7/libbeat/common/atomic" - "github.com/elastic/beats/v7/libbeat/publisher/queue" - "github.com/elastic/go-txfile" - "github.com/elastic/go-txfile/pq" -) - -// diskSpool implements an on-disk queue.Queue. -type diskSpool struct { - // producer/input support - inCtx *spoolCtx - inBroker *inBroker - - // consumer/output support - outCtx *spoolCtx - outBroker *outBroker - - queue *pq.Queue - file *txfile.File -} - -type spoolCtx struct { - logger logger - wg sync.WaitGroup - active atomic.Bool - done chan struct{} -} - -// settings configure a new spool to be created. -type settings struct { - Mode os.FileMode - - File txfile.Options - - // Queue write buffer size. If a single event is bigger then the - // write-buffer, the write-buffer will grow. In this case will the write - // buffer be flushed and reset to its original size. - WriteBuffer uint - - ACKListener queue.ACKListener - - WriteFlushTimeout time.Duration - WriteFlushEvents uint - ReadFlushTimeout time.Duration - - Codec codecID -} - -const minInFlushTimeout = 100 * time.Millisecond -const minOutFlushTimeout = 0 * time.Millisecond - -// newDiskSpool creates and initializes a new file based queue. -func newDiskSpool(logger logger, path string, settings settings) (*diskSpool, error) { - mode := settings.Mode - if mode == 0 { - mode = os.ModePerm - } - - ok := false - inCtx := newSpoolCtx(logger) - outCtx := newSpoolCtx(logger) - defer ifNotOK(&ok, inCtx.Close) - defer ifNotOK(&ok, outCtx.Close) - - if info, err := os.Lstat(path); err != nil { - if !os.IsNotExist(err) { - return nil, err - } - } else if runtime.GOOS != "windows" { - perm := info.Mode().Perm() - cfgPerm := settings.Mode.Perm() - - // check if file has permissions set, that must not be set via config - if (perm | cfgPerm) != cfgPerm { - return nil, fmt.Errorf("file permissions for '%v' must be more strict (required permissions: %v, actual permissions: %v)", - path, cfgPerm, perm) - } - } - - f, err := txfile.Open(path, mode, settings.File) - if err != nil { - return nil, errors.Wrapf(err, "spool queue: failed to open file at path '%s'", path) - } - defer ifNotOK(&ok, ignoreErr(f.Close)) - - queueDelegate, err := pq.NewStandaloneDelegate(f) - if err != nil { - return nil, err - } - - spool := &diskSpool{ - inCtx: inCtx, - outCtx: outCtx, - } - - queue, err := pq.New(queueDelegate, pq.Settings{ - WriteBuffer: settings.WriteBuffer, - Flushed: spool.onFlush, - ACKed: spool.onACK, - }) - if err != nil { - return nil, err - } - defer ifNotOK(&ok, ignoreErr(queue.Close)) - - inFlushTimeout := settings.WriteFlushTimeout - if inFlushTimeout < minInFlushTimeout { - inFlushTimeout = minInFlushTimeout - } - inBroker, err := newInBroker( - inCtx, settings.ACKListener, queue, settings.Codec, - inFlushTimeout, settings.WriteFlushEvents) - if err != nil { - return nil, err - } - - outFlushTimeout := settings.ReadFlushTimeout - if outFlushTimeout < minOutFlushTimeout { - outFlushTimeout = minOutFlushTimeout - } - outBroker, err := newOutBroker(outCtx, queue, outFlushTimeout) - if err != nil { - return nil, err - } - - ok = true - spool.queue = queue - spool.inBroker = inBroker - spool.outBroker = outBroker - spool.file = f - return spool, nil -} - -// Close shuts down the queue and closes the used file. -func (s *diskSpool) Close() error { - // stop all workers (waits for all workers to be finished) - s.outCtx.Close() - s.inCtx.Close() - - // close queue (potentially flushing write buffer) - err := s.queue.Close() - - // finally unmap and close file - s.file.Close() - - return err -} - -// BufferConfig returns the queue initial buffer settings. -func (s *diskSpool) BufferConfig() queue.BufferConfig { - return queue.BufferConfig{MaxEvents: -1} -} - -// Producer creates a new queue producer for publishing events. -func (s *diskSpool) Producer(cfg queue.ProducerConfig) queue.Producer { - return s.inBroker.Producer(cfg) -} - -// Consumer creates a new queue consumer for consuming and acking events. -func (s *diskSpool) Consumer() queue.Consumer { - return s.outBroker.Consumer() -} - -// onFlush is run whenever the queue signals it's write buffer being flushed. -// Flush events are forwarded to all workers. -// The onFlush callback is directly called by the queue writer (same go-routine) -// on Write or Flush operations. -func (s *diskSpool) onFlush(n uint) { - s.inBroker.onFlush(n) - s.outBroker.onFlush(n) -} - -// onACK is run whenever the queue signals events being acked and removed from -// the queue. -// ACK events are forwarded to all workers. -func (s *diskSpool) onACK(events, pages uint) { - s.inBroker.onACK(events, pages) -} - -func newSpoolCtx(logger logger) *spoolCtx { - return &spoolCtx{ - logger: logger, - active: atomic.MakeBool(true), - done: make(chan struct{}), - } -} - -func (ctx *spoolCtx) Close() { - if ctx.active.CAS(true, false) { - close(ctx.done) - ctx.wg.Wait() - } -} - -func (ctx *spoolCtx) Done() <-chan struct{} { - return ctx.done -} - -func (ctx *spoolCtx) Open() bool { - return ctx.active.Load() -} - -func (ctx *spoolCtx) Closed() bool { - return !ctx.Open() -} - -func (ctx *spoolCtx) Go(fn func()) { - ctx.wg.Add(1) - go func() { - defer ctx.wg.Done() - fn() - }() -} - -func ifNotOK(b *bool, fn func()) { - if !(*b) { - fn() - } -} - -func ignoreErr(fn func() error) func() { - return func() { fn() } -} diff --git a/libbeat/publisher/queue/spool/spool_test.go b/libbeat/publisher/queue/spool/spool_test.go deleted file mode 100644 index b5947152d9a..00000000000 --- a/libbeat/publisher/queue/spool/spool_test.go +++ /dev/null @@ -1,159 +0,0 @@ -// Licensed to Elasticsearch B.V. under one or more contributor -// license agreements. See the NOTICE file distributed with -// this work for additional information regarding copyright -// ownership. Elasticsearch B.V. licenses this file to you 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 spool - -import ( - "flag" - "fmt" - "math/rand" - "testing" - "time" - - humanize "github.com/dustin/go-humanize" - - "github.com/elastic/beats/v7/libbeat/publisher/queue" - "github.com/elastic/beats/v7/libbeat/publisher/queue/queuetest" - "github.com/elastic/go-txfile" - "github.com/elastic/go-txfile/txfiletest" -) - -var seed int64 -var debug bool - -type testQueue struct { - *diskSpool - teardown func() -} - -type testLogger struct { - t *testing.T -} - -type silentLogger struct{} - -func init() { - flag.Int64Var(&seed, "seed", time.Now().UnixNano(), "test random seed") - flag.BoolVar(&debug, "noisy", false, "print test logs to console") -} - -func TestProduceConsumer(t *testing.T) { - maxEvents := 4096 - minEvents := 32 - - rand.Seed(seed) - events := rand.Intn(maxEvents-minEvents) + minEvents - batchSize := rand.Intn(events-8) + 4 - - t.Log("seed: ", seed) - t.Log("events: ", events) - t.Log("batchSize: ", batchSize) - - testWith := func(factory queuetest.QueueFactory) func(t *testing.T) { - return func(test *testing.T) { - t.Run("single", func(t *testing.T) { - queuetest.TestSingleProducerConsumer(t, events, batchSize, factory) - }) - t.Run("multi", func(t *testing.T) { - queuetest.TestMultiProducerConsumer(t, events, batchSize, factory) - }) - } - } - - testWith(makeTestQueue( - 128*humanize.KiByte, 4*humanize.KiByte, 16*humanize.KiByte, - 100*time.Millisecond, - ))(t) -} - -func makeTestQueue( - maxSize, pageSize, writeBuffer uint, - flushTimeout time.Duration, -) func(*testing.T) queue.Queue { - return func(t *testing.T) queue.Queue { - if debug { - fmt.Println("Test:", t.Name()) - } - - ok := false - path, cleanPath := txfiletest.SetupPath(t, "") - defer func() { - if !ok { - cleanPath() - } - }() - - var logger logger - if debug { - logger = &testLogger{t} - } else { - logger = new(silentLogger) - } - - spool, err := newDiskSpool(logger, path, settings{ - WriteBuffer: writeBuffer, - WriteFlushTimeout: flushTimeout, - Codec: codecCBORL, - File: txfile.Options{ - MaxSize: uint64(maxSize), - PageSize: uint32(pageSize), - Prealloc: true, - Readonly: false, - }, - }) - if err != nil { - t.Fatal(err) - } - - tq := &testQueue{diskSpool: spool, teardown: cleanPath} - return tq - } -} - -func (t *testQueue) Close() error { - err := t.diskSpool.Close() - t.teardown() - return err -} - -func (l *testLogger) Debug(vs ...interface{}) { l.report("Debug", vs) } -func (l *testLogger) Debugf(fmt string, vs ...interface{}) { l.reportf("Debug: ", fmt, vs) } - -func (l *testLogger) Info(vs ...interface{}) { l.report("Info", vs) } -func (l *testLogger) Infof(fmt string, vs ...interface{}) { l.reportf("Info", fmt, vs) } - -func (l *testLogger) Error(vs ...interface{}) { l.report("Error", vs) } -func (l *testLogger) Errorf(fmt string, vs ...interface{}) { l.reportf("Error", fmt, vs) } - -func (l *testLogger) report(level string, vs []interface{}) { - args := append([]interface{}{level, ":"}, vs...) - l.t.Log(args...) - fmt.Println(args...) -} - -func (l *testLogger) reportf(level string, str string, vs []interface{}) { - str = level + ": " + str - l.t.Logf(str, vs...) - fmt.Printf(str, vs...) -} - -func (*silentLogger) Debug(vs ...interface{}) {} -func (*silentLogger) Debugf(fmt string, vs ...interface{}) {} -func (*silentLogger) Info(vs ...interface{}) {} -func (*silentLogger) Infof(fmt string, vs ...interface{}) {} -func (*silentLogger) Error(vs ...interface{}) {} -func (*silentLogger) Errorf(fmt string, vs ...interface{}) {} diff --git a/libbeat/publisher/queue/spool/timer.go b/libbeat/publisher/queue/spool/timer.go deleted file mode 100644 index 9f08dcfc69a..00000000000 --- a/libbeat/publisher/queue/spool/timer.go +++ /dev/null @@ -1,72 +0,0 @@ -// Licensed to Elasticsearch B.V. under one or more contributor -// license agreements. See the NOTICE file distributed with -// this work for additional information regarding copyright -// ownership. Elasticsearch B.V. licenses this file to you 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 spool - -import ( - "time" -) - -type timer struct { - // flush timer - timer *time.Timer - C <-chan time.Time - duration time.Duration -} - -func newTimer(duration time.Duration) *timer { - stdtimer := time.NewTimer(duration) - if !stdtimer.Stop() { - <-stdtimer.C - } - - return &timer{ - timer: stdtimer, - C: nil, - duration: duration, - } -} - -func (t *timer) Zero() bool { - return t.duration == 0 -} - -func (t *timer) Restart() { - t.Stop(false) - t.Start() -} - -func (t *timer) Start() { - if t.C != nil { - return - } - - t.timer.Reset(t.duration) - t.C = t.timer.C -} - -func (t *timer) Stop(triggered bool) { - if t.C == nil { - return - } - - if !triggered && !t.timer.Stop() { - <-t.C - } - - t.C = nil -} diff --git a/libbeat/reader/message.go b/libbeat/reader/message.go index 79116bfcfad..0eae606f80b 100644 --- a/libbeat/reader/message.go +++ b/libbeat/reader/message.go @@ -31,7 +31,8 @@ type Message struct { Content []byte // actual content read Bytes int // total number of bytes read to generate the message Fields common.MapStr // optional fields that can be added by reader - Meta common.MapStr + Meta common.MapStr // deprecated + Private interface{} } // IsEmpty returns true in case the message is empty diff --git a/libbeat/reader/readfile/line_terminator.go b/libbeat/reader/readfile/line_terminator.go index 68ab24736c2..bcd82e36741 100644 --- a/libbeat/reader/readfile/line_terminator.go +++ b/libbeat/reader/readfile/line_terminator.go @@ -44,6 +44,8 @@ const ( LineSeparator // ParagraphSeparator is the unicode char PS ParagraphSeparator + // NullTerminator + NullTerminator ) var ( @@ -57,6 +59,7 @@ var ( "next_line": NextLine, "line_separator": LineSeparator, "paragraph_separator": ParagraphSeparator, + "null_terminator": NullTerminator, } lineTerminatorCharacters = map[LineTerminator][]byte{ @@ -69,6 +72,7 @@ var ( NextLine: []byte{'\u0085'}, LineSeparator: []byte("\u2028"), ParagraphSeparator: []byte("\u2029"), + NullTerminator: []byte{'\u0000'}, } ) diff --git a/libbeat/scripts/Makefile b/libbeat/scripts/Makefile index 00d3231c371..7b16cf7cea8 100755 --- a/libbeat/scripts/Makefile +++ b/libbeat/scripts/Makefile @@ -141,11 +141,9 @@ ${BEAT_NAME}.test: $(GOFILES_ALL) .PHONY: crosscompile crosscompile: ## @build Cross-compile beat for the OS'es specified in GOX_OS variable. The binaries are placed in the build/bin directory. crosscompile: $(GOFILES) -ifneq ($(shell [[ $(BEAT_NAME) == journalbeat ]] && echo true ),true) go ${INSTALL_CMD} github.com/mitchellh/gox mkdir -p ${BUILD_DIR}/bin gox -output="${BUILD_DIR}/bin/{{.Dir}}-{{.OS}}-{{.Arch}}" -os="$(strip $(GOX_OS))" -osarch="$(strip $(GOX_OSARCH))" ${GOX_FLAGS} -endif .PHONY: check check: check-headers mage ## @build Checks project and source code if everything is according to standard diff --git a/libbeat/scripts/cmd/stress_pipeline/main.go b/libbeat/scripts/cmd/stress_pipeline/main.go index 49ba19c686c..2b32ad596a9 100644 --- a/libbeat/scripts/cmd/stress_pipeline/main.go +++ b/libbeat/scripts/cmd/stress_pipeline/main.go @@ -35,7 +35,6 @@ import ( "github.com/elastic/beats/v7/libbeat/paths" "github.com/elastic/beats/v7/libbeat/publisher/pipeline/stress" _ "github.com/elastic/beats/v7/libbeat/publisher/queue/memqueue" - _ "github.com/elastic/beats/v7/libbeat/publisher/queue/spool" "github.com/elastic/beats/v7/libbeat/service" ) diff --git a/libbeat/template/config.go b/libbeat/template/config.go index 7eb6ff522f4..4f9fe2348c7 100644 --- a/libbeat/template/config.go +++ b/libbeat/template/config.go @@ -18,27 +18,10 @@ package template import ( - "fmt" - + "github.com/elastic/beats/v7/libbeat/beat" "github.com/elastic/beats/v7/libbeat/mapping" ) -const ( - IndexTemplateLegacy IndexTemplateType = iota - IndexTemplateComponent - IndexTemplateIndex -) - -var ( - templateTypes = map[string]IndexTemplateType{ - "legacy": IndexTemplateLegacy, - "component": IndexTemplateComponent, - "index": IndexTemplateIndex, - } -) - -type IndexTemplateType uint8 - // TemplateConfig holds config information about the Elasticsearch template type TemplateConfig struct { Enabled bool `config:"enabled"` @@ -50,12 +33,10 @@ type TemplateConfig struct { Path string `config:"path"` Name string `config:"name"` } `config:"json"` - AppendFields mapping.Fields `config:"append_fields"` - Overwrite bool `config:"overwrite"` - Settings TemplateSettings `config:"settings"` - Order int `config:"order"` - Priority int `config:"priority"` - Type IndexTemplateType `config:"type"` + AppendFields mapping.Fields `config:"append_fields"` + Overwrite bool `config:"overwrite"` + Settings TemplateSettings `config:"settings"` + Priority int `config:"priority"` } // TemplateSettings are part of the Elasticsearch template and hold index and source specific information. @@ -65,28 +46,12 @@ type TemplateSettings struct { } // DefaultConfig for index template -func DefaultConfig() TemplateConfig { +func DefaultConfig(info beat.Info) TemplateConfig { return TemplateConfig{ + Name: info.Beat + "-" + info.Version, + Pattern: info.Beat + "-" + info.Version, Enabled: true, Fields: "", - Type: IndexTemplateLegacy, - Order: 1, Priority: 150, } } - -func (t *IndexTemplateType) Unpack(v string) error { - if v == "" { - *t = IndexTemplateLegacy - return nil - } - - var tt IndexTemplateType - var ok bool - if tt, ok = templateTypes[v]; !ok { - return fmt.Errorf("unknown index template type: %s", v) - } - *t = tt - - return nil -} diff --git a/libbeat/template/load.go b/libbeat/template/load.go index 0ecbc291268..1900d8f5a75 100644 --- a/libbeat/template/load.go +++ b/libbeat/template/load.go @@ -24,7 +24,6 @@ import ( "io/ioutil" "net/http" "os" - "strings" "github.com/elastic/beats/v7/libbeat/beat" "github.com/elastic/beats/v7/libbeat/common" @@ -32,14 +31,6 @@ import ( "github.com/elastic/beats/v7/libbeat/paths" ) -var ( - templateLoaderPath = map[IndexTemplateType]string{ - IndexTemplateLegacy: "/_template/", - IndexTemplateComponent: "/_component_template/", - IndexTemplateIndex: "/_index_template/", - } -) - // Loader interface for loading templates. type Loader interface { Load(config TemplateConfig, info beat.Info, fields []byte, migration bool) error @@ -114,7 +105,7 @@ func (l *ESLoader) Load(config TemplateConfig, info beat.Info, fields []byte, mi templateName = config.JSON.Name } - exists, err := l.templateExists(templateName, config.Type) + exists, err := l.checkExistsTemplate(templateName) if err != nil { return fmt.Errorf("failure while checking if template exists: %w", err) } @@ -129,7 +120,7 @@ func (l *ESLoader) Load(config TemplateConfig, info beat.Info, fields []byte, mi if err != nil { return err } - if err := l.loadTemplate(templateName, config.Type, body); err != nil { + if err := l.loadTemplate(templateName, body); err != nil { return fmt.Errorf("failed to load template: %w", err) } l.log.Infof("Template with name %q loaded.", templateName) @@ -139,12 +130,10 @@ func (l *ESLoader) Load(config TemplateConfig, info beat.Info, fields []byte, mi // loadTemplate loads a template into Elasticsearch overwriting the existing // template if it exists. If you wish to not overwrite an existing template // then use CheckTemplate prior to calling this method. -func (l *ESLoader) loadTemplate(templateName string, templateType IndexTemplateType, template map[string]interface{}) error { +func (l *ESLoader) loadTemplate(templateName string, template map[string]interface{}) error { l.log.Infof("Try loading template %s to Elasticsearch", templateName) - clientVersion := l.client.GetVersion() - path := templateLoaderPath[templateType] + templateName - params := esVersionParams(clientVersion) - status, body, err := l.client.Request("PUT", path, "", params, template) + path := "/_index_template/" + templateName + status, body, err := l.client.Request("PUT", path, "", nil, template) if err != nil { return fmt.Errorf("couldn't load template: %v. Response body: %s", err, body) } @@ -154,52 +143,21 @@ func (l *ESLoader) loadTemplate(templateName string, templateType IndexTemplateT return nil } -func (l *ESLoader) templateExists(templateName string, templateType IndexTemplateType) (bool, error) { - if templateType == IndexTemplateComponent { - return l.checkExistsComponentTemplate(templateName) - } - return l.checkExistsTemplate(templateName) -} - // existsTemplate checks if a given template already exist, using the -// `_cat/templates/` API. +// `/_index_template/` API. // // An error is returned if the loader failed to execute the request, or a // status code indicating some problems is encountered. func (l *ESLoader) checkExistsTemplate(name string) (bool, error) { - status, body, err := l.client.Request("GET", "/_cat/templates/"+name, "", nil, nil) + status, _, err := l.client.Request("HEAD", "/_index_template/"+name, "", nil, nil) + if status == http.StatusNotFound { + return false, nil + } if err != nil { return false, err } - // Elasticsearch API returns 200, even if the template does not exists. We - // need to validate the body to be sure the template is actually known. Any - // status code other than 200 will be treated as error. - if status != http.StatusOK { - return false, &StatusError{status: status} - } - return strings.Contains(string(body), name), nil -} - -// existsComponentTemplate checks if a component template exists by querying -// the `_component_template/` API. -// -// The resource is assumed as present if a 200 OK status is returned and missing if a 404 is returned. -// Other status codes or IO errors during the request are reported as error. -func (l *ESLoader) checkExistsComponentTemplate(name string) (bool, error) { - status, _, err := l.client.Request("GET", "/_component_template/"+name, "", nil, nil) - - switch status { - case http.StatusNotFound: - return false, nil - case http.StatusOK: - return true, nil - default: - if err == nil { - err = &StatusError{status: status} - } - return false, err - } + return true, nil } // Load reads the template from the config, creates the template body and prints it to the configured file. @@ -247,7 +205,8 @@ func (b *templateBuilder) buildBody(tmpl *Template, config TemplateConfig, field return b.buildBodyFromFile(tmpl, config) } if fields == nil { - return b.buildMinimalTemplate(tmpl) + b.log.Debug("Load minimal template") + return tmpl.LoadMinimal(), nil } return b.buildBodyFromFields(tmpl, fields) } @@ -290,25 +249,6 @@ func (b *templateBuilder) buildBodyFromFields(tmpl *Template, fields []byte) (co return body, nil } -func (b *templateBuilder) buildMinimalTemplate(tmpl *Template) (common.MapStr, error) { - b.log.Debug("Load minimal template") - body, err := tmpl.LoadMinimal() - if err != nil { - return nil, fmt.Errorf("error creating mimimal template: %v", err) - } - return body, nil -} - func (e *StatusError) Error() string { return fmt.Sprintf("request failed with http status code %v", e.status) } - -func esVersionParams(ver common.Version) map[string]string { - if ver.Major == 6 && ver.Minor == 7 { - return map[string]string{ - "include_type_name": "true", - } - } - - return nil -} diff --git a/libbeat/template/load_integration_test.go b/libbeat/template/load_integration_test.go index 371991810e4..07caf39c3e7 100644 --- a/libbeat/template/load_integration_test.go +++ b/libbeat/template/load_integration_test.go @@ -67,13 +67,13 @@ func newTestSetup(t *testing.T, cfg TemplateConfig) *testSetup { t.Fatal(err) } s := testSetup{t: t, client: client, loader: NewESLoader(client), config: cfg} - client.Request("DELETE", templateLoaderPath[cfg.Type]+cfg.Name, "", nil, nil) + client.Request("DELETE", "/_index_template/"+cfg.Name, "", nil, nil) s.requireTemplateDoesNotExist("") return &s } func (ts *testSetup) mustLoadTemplate(body map[string]interface{}) { - err := ts.loader.loadTemplate(ts.config.Name, ts.config.Type, body) + err := ts.loader.loadTemplate(ts.config.Name, body) require.NoError(ts.t, err) ts.requireTemplateExists("") } @@ -103,16 +103,21 @@ func (ts *testSetup) requireTemplateExists(name string) { if name == "" { name = ts.config.Name } - exists, err := ts.loader.templateExists(name, ts.config.Type) + exists, err := ts.loader.checkExistsTemplate(name) require.NoError(ts.t, err, "failed to query template status") - require.True(ts.t, exists, "template must exist") + require.True(ts.t, exists, "template must exist: %s", name) +} + +func (ts *testSetup) cleanupTemplate(name string) { + ts.client.Request("DELETE", "/_index_template/"+name, "", nil, nil) + ts.requireTemplateDoesNotExist(name) } func (ts *testSetup) requireTemplateDoesNotExist(name string) { if name == "" { name = ts.config.Name } - exists, err := ts.loader.templateExists(name, ts.config.Type) + exists, err := ts.loader.checkExistsTemplate(name) require.NoError(ts.t, err, "failed to query template status") require.False(ts.t, exists, "template must not exist") } @@ -146,14 +151,14 @@ func TestESLoader_Load(t *testing.T) { t.Run("disabled", func(t *testing.T) { setup.load(nil) - tmpl := getTemplate(t, setup.client, setup.config.Name, setup.config.Type) + tmpl := getTemplate(t, setup.client, setup.config.Name) assert.Equal(t, true, tmpl.SourceEnabled()) }) t.Run("enabled", func(t *testing.T) { setup.config.Overwrite = true setup.load(nil) - tmpl := getTemplate(t, setup.client, setup.config.Name, setup.config.Type) + tmpl := getTemplate(t, setup.client, setup.config.Name) assert.Equal(t, false, tmpl.SourceEnabled()) }) }) @@ -172,6 +177,7 @@ func TestESLoader_Load(t *testing.T) { }{Enabled: true, Path: path(t, []string{"testdata", "fields.json"}), Name: nameJSON} setup.load(nil) setup.requireTemplateExists(nameJSON) + setup.cleanupTemplate(nameJSON) }) t.Run("load template successful", func(t *testing.T) { @@ -188,26 +194,17 @@ func TestESLoader_Load(t *testing.T) { fields: fields, properties: []string{"foo", "bar"}, }, - "default config with fields and component": { - cfg: TemplateConfig{Enabled: true, Type: IndexTemplateComponent}, - fields: fields, - properties: []string{"foo", "bar"}, - }, "minimal template": { cfg: TemplateConfig{Enabled: true}, fields: nil, }, - "minimal template component": { - cfg: TemplateConfig{Enabled: true, Type: IndexTemplateComponent}, - fields: nil, - }, "fields from file": { cfg: TemplateConfig{Enabled: true, Fields: path(t, []string{"testdata", "fields.yml"})}, fields: fields, - properties: []string{"object", "keyword", "alias", "migration_alias_false", "object_disabled"}, + properties: []string{"object", "keyword", "alias", "migration_alias_false", "object_disabled", "@timestamp"}, }, "fields from json": { - cfg: TemplateConfig{Enabled: true, Name: "json-template", JSON: struct { + cfg: TemplateConfig{Enabled: true, JSON: struct { Enabled bool `config:"enabled"` Path string `config:"path"` Name string `config:"name"` @@ -217,12 +214,15 @@ func TestESLoader_Load(t *testing.T) { }, } { t.Run(run, func(t *testing.T) { + if data.cfg.JSON.Enabled { + data.cfg.Name = data.cfg.JSON.Name + } setup := newTestSetup(t, data.cfg) setup.mustLoad(data.fields) // Fetch properties - tmpl := getTemplate(t, setup.client, setup.config.Name, setup.config.Type) - val, err := tmpl.GetValue("mappings.properties") + tmpl := getTemplate(t, setup.client, setup.config.Name) + val, err := tmpl.GetValue("template.mappings.properties") if data.properties == nil { assert.Error(t, err) } else { @@ -235,6 +235,7 @@ func TestESLoader_Load(t *testing.T) { } assert.ElementsMatch(t, properties, data.properties) } + setup.cleanupTemplate(setup.config.Name) }) } }) @@ -250,7 +251,7 @@ func TestLoadInvalidTemplate(t *testing.T) { // Try to load invalid template template := map[string]interface{}{"json": "invalid"} - err := setup.loader.loadTemplate(setup.config.Name, setup.config.Type, template) + err := setup.loader.loadTemplate(setup.config.Name, template) assert.Error(t, err) setup.requireTemplateDoesNotExist("") } @@ -276,7 +277,7 @@ func TestTemplateSettings(t *testing.T) { setup.mustLoadFromFile([]string{"..", "fields.yml"}) // Check that it contains the mapping - templateJSON := getTemplate(t, setup.client, setup.config.Name, setup.config.Type) + templateJSON := getTemplate(t, setup.client, setup.config.Name) assert.Equal(t, 1, templateJSON.NumberOfShards()) assert.Equal(t, false, templateJSON.SourceEnabled()) } @@ -287,8 +288,9 @@ var dataTests = []struct { }{ { data: common.MapStr{ - "keyword": "test keyword", - "array": [...]int{1, 2, 3}, + "@timestamp": time.Now(), + "keyword": "test keyword", + "array": [...]int{1, 2, 3}, "object": common.MapStr{ "hello": "world", }, @@ -314,6 +316,7 @@ var dataTests = []struct { { // tests enabled: false values data: common.MapStr{ + "@timestamp": time.Now(), "array_disabled": [...]int{1, 2, 3}, "object_disabled": common.MapStr{ "hello": "world", @@ -340,8 +343,8 @@ func TestTemplateWithData(t *testing.T) { } } -func getTemplate(t *testing.T, client ESClient, templateName string, templateType IndexTemplateType) testTemplate { - status, body, err := client.Request("GET", templateLoaderPath[templateType]+templateName, "", nil, nil) +func getTemplate(t *testing.T, client ESClient, templateName string) testTemplate { + status, body, err := client.Request("GET", "/_index_template/"+templateName, "", nil, nil) require.NoError(t, err) require.Equal(t, status, 200) @@ -350,29 +353,19 @@ func getTemplate(t *testing.T, client ESClient, templateName string, templateTyp require.NoError(t, err) require.NotNil(t, response) - if templateType == IndexTemplateComponent { - var tmpl map[string]interface{} - components := response["component_templates"].([]interface{}) - for _, ct := range components { - componentTemplate := ct.(map[string]interface{})["component_template"].(map[string]interface{}) - tmpl = componentTemplate["template"].(map[string]interface{}) - } - return testTemplate{ - t: t, - client: client, - MapStr: common.MapStr(tmpl), - } - } + templates, _ := response.GetValue("index_templates") + templatesList, _ := templates.([]interface{}) + templateElem := templatesList[0].(map[string]interface{}) return testTemplate{ t: t, client: client, - MapStr: common.MapStr(response[templateName].(map[string]interface{})), + MapStr: common.MapStr(templateElem["index_template"].(map[string]interface{})), } } func (tt *testTemplate) SourceEnabled() bool { - key := fmt.Sprintf("mappings._source.enabled") + key := fmt.Sprintf("template.mappings._source.enabled") // _source.enabled is true if it's missing (default) b, _ := tt.HasKey(key) @@ -390,7 +383,7 @@ func (tt *testTemplate) SourceEnabled() bool { } func (tt *testTemplate) NumberOfShards() int { - val, err := tt.GetValue("settings.index.number_of_shards") + val, err := tt.GetValue("template.settings.index.number_of_shards") require.NoError(tt.t, err) i, err := strconv.Atoi(val.(string)) diff --git a/libbeat/template/load_test.go b/libbeat/template/load_test.go index 017f53639fa..429cf7382ab 100644 --- a/libbeat/template/load_test.go +++ b/libbeat/template/load_test.go @@ -32,8 +32,7 @@ import ( func TestFileLoader_Load(t *testing.T) { ver := "7.0.0" prefix := "mock" - order := 1 - info := beat.Info{Version: ver, IndexPrefix: prefix} + info := beat.Info{Beat: "mock", Version: ver, IndexPrefix: prefix} tmplName := fmt.Sprintf("%s-%s", prefix, ver) for name, test := range map[string]struct { @@ -45,39 +44,47 @@ func TestFileLoader_Load(t *testing.T) { }{ "load minimal config info": { body: common.MapStr{ - "index_patterns": []string{"mock-7.0.0-*"}, - "order": order, - "settings": common.MapStr{"index": nil}, + "index_patterns": []string{"mock-7.0.0"}, + "data_stream": struct{}{}, + "priority": 150, + "template": common.MapStr{ + "settings": common.MapStr{"index": nil}}, }, }, "load minimal config with index settings": { settings: TemplateSettings{Index: common.MapStr{"code": "best_compression"}}, body: common.MapStr{ - "index_patterns": []string{"mock-7.0.0-*"}, - "order": order, - "settings": common.MapStr{"index": common.MapStr{"code": "best_compression"}}, + "index_patterns": []string{"mock-7.0.0"}, + "data_stream": struct{}{}, + "priority": 150, + "template": common.MapStr{ + "settings": common.MapStr{"index": common.MapStr{"code": "best_compression"}}}, }, }, "load minimal config with source settings": { settings: TemplateSettings{Source: common.MapStr{"enabled": false}}, body: common.MapStr{ - "index_patterns": []string{"mock-7.0.0-*"}, - "order": order, - "settings": common.MapStr{"index": nil}, - "mappings": common.MapStr{ - "_source": common.MapStr{"enabled": false}, - "_meta": common.MapStr{"beat": prefix, "version": ver}, - "date_detection": false, - "dynamic_templates": nil, - "properties": nil, - }, + "index_patterns": []string{"mock-7.0.0"}, + "data_stream": struct{}{}, + "priority": 150, + "template": common.MapStr{ + "settings": common.MapStr{"index": nil}, + "mappings": common.MapStr{ + "_source": common.MapStr{"enabled": false}, + "_meta": common.MapStr{"beat": prefix, "version": ver}, + "date_detection": false, + "dynamic_templates": nil, + "properties": nil, + }}, }, }, "load config and in-line analyzer fields": { body: common.MapStr{ - "index_patterns": []string{"mock-7.0.0-*"}, - "order": order, - "settings": common.MapStr{"index": nil}, + "index_patterns": []string{"mock-7.0.0"}, + "data_stream": struct{}{}, + "priority": 150, + "template": common.MapStr{ + "settings": common.MapStr{"index": nil}}, }, fields: []byte(`- key: test title: Test fields.yml with analyzer @@ -103,65 +110,66 @@ func TestFileLoader_Load(t *testing.T) { analyzer: simple `), want: common.MapStr{ - "index_patterns": []string{ - "mock-7.0.0-*", - }, - "order": 1, - "mappings": common.MapStr{ - "_meta": common.MapStr{ - "version": "7.0.0", - "beat": "mock", - }, - "date_detection": false, - "dynamic_templates": []common.MapStr{ - { - "strings_as_keyword": common.MapStr{ - "mapping": common.MapStr{ - "ignore_above": 1024, - "type": "keyword", + "index_patterns": []string{"mock-7.0.0"}, + "data_stream": struct{}{}, + "priority": 150, + "template": common.MapStr{ + "mappings": common.MapStr{ + "_meta": common.MapStr{ + "version": "7.0.0", + "beat": "mock", + }, + "date_detection": false, + "dynamic_templates": []common.MapStr{ + { + "strings_as_keyword": common.MapStr{ + "mapping": common.MapStr{ + "ignore_above": 1024, + "type": "keyword", + }, + "match_mapping_type": "string", }, - "match_mapping_type": "string", }, }, - }, - "properties": common.MapStr{ - "code_block_text": common.MapStr{ - "type": "text", - "norms": false, - "analyzer": "test_powershell", - }, - "script_block_text": common.MapStr{ - "type": "text", - "norms": false, - "analyzer": "test_powershell", - }, - "standard_text": common.MapStr{ - "type": "text", - "norms": false, - "analyzer": "simple", + "properties": common.MapStr{ + "code_block_text": common.MapStr{ + "type": "text", + "norms": false, + "analyzer": "test_powershell", + }, + "script_block_text": common.MapStr{ + "type": "text", + "norms": false, + "analyzer": "test_powershell", + }, + "standard_text": common.MapStr{ + "type": "text", + "norms": false, + "analyzer": "simple", + }, }, }, - }, - "settings": common.MapStr{ - "index": common.MapStr{ - "refresh_interval": "5s", - "mapping": common.MapStr{ - "total_fields": common.MapStr{ - "limit": 10000, + "settings": common.MapStr{ + "index": common.MapStr{ + "refresh_interval": "5s", + "mapping": common.MapStr{ + "total_fields": common.MapStr{ + "limit": 10000, + }, }, - }, - "query": common.MapStr{ - "default_field": []string{ - "fields.*", + "query": common.MapStr{ + "default_field": []string{ + "fields.*", + }, }, + "max_docvalue_fields_search": 200, }, - "max_docvalue_fields_search": 200, - }, - "analysis": common.MapStr{ - "analyzer": common.MapStr{ - "test_powershell": map[string]interface{}{ - "type": "pattern", - "pattern": "[\\W&&[^-]]+", + "analysis": common.MapStr{ + "analyzer": common.MapStr{ + "test_powershell": map[string]interface{}{ + "type": "pattern", + "pattern": "[\\W&&[^-]]+", + }, }, }, }, @@ -170,8 +178,7 @@ func TestFileLoader_Load(t *testing.T) { }, "load config and in-line analyzer fields with name collision": { body: common.MapStr{ - "index_patterns": []string{"mock-7.0.0-*"}, - "order": order, + "index_patterns": []string{"mock-7.0.0"}, "settings": common.MapStr{"index": nil}, }, fields: []byte(`- key: test @@ -205,7 +212,7 @@ func TestFileLoader_Load(t *testing.T) { require.NoError(t, err) fl := NewFileLoader(fc) - cfg := DefaultConfig() + cfg := DefaultConfig(info) cfg.Settings = test.settings err = fl.Load(cfg, info, test.fields, false) diff --git a/libbeat/template/processor.go b/libbeat/template/processor.go index a9489a35a11..9e4214ac04e 100644 --- a/libbeat/template/processor.go +++ b/libbeat/template/processor.go @@ -31,7 +31,6 @@ import ( const DefaultField = false var ( - minVersionAlias = common.MustNewVersion("6.4.0") minVersionFieldMeta = common.MustNewVersion("7.6.0") minVersionHistogram = common.MustNewVersion("7.6.0") minVersionWildcard = common.MustNewVersion("7.9.0") @@ -137,7 +136,7 @@ func (p *Processor) Process(fields mapping.Fields, state *fieldState, output, an if *field.DefaultField { switch field.Type { - case "", "keyword", "text": + case "", "keyword", "text", "match_only_text", "wildcard": addToDefaultFields(&field) } } @@ -204,11 +203,6 @@ func (p *Processor) scaledFloat(f *mapping.Field, params ...common.MapStr) commo property := p.getDefaultProperties(f) property["type"] = "scaled_float" - if p.EsVersion.IsMajor(2) { - property["type"] = "float" - return property - } - // Set scaling factor scalingFactor := defaultScalingFactor if f.ScalingFactor != 0 && len(f.ObjectTypeParams) == 0 { @@ -270,22 +264,12 @@ func (p *Processor) halfFloat(f *mapping.Field) common.MapStr { property := p.getDefaultProperties(f) property["type"] = "half_float" - if p.EsVersion.IsMajor(2) { - property["type"] = "float" - } return property } func (p *Processor) ip(f *mapping.Field) common.MapStr { property := p.getDefaultProperties(f) - property["type"] = "ip" - - if p.EsVersion.IsMajor(2) { - property["type"] = "string" - property["ignore_above"] = 1024 - property["index"] = "not_analyzed" - } return property } @@ -319,11 +303,6 @@ func (p *Processor) keyword(f *mapping.Field, analyzers common.MapStr) common.Ma property["ignore_above"] = f.IgnoreAbove } - if p.EsVersion.IsMajor(2) { - property["type"] = "string" - property["index"] = "not_analyzed" - } - if len(f.MultiFields) > 0 { fields := common.MapStr{} p.Process(f.MultiFields, stateFromField(f), fields, analyzers) @@ -360,18 +339,8 @@ func (p *Processor) text(f *mapping.Field, analyzers common.MapStr) (properties properties["type"] = "text" - if p.EsVersion.IsMajor(2) { - properties["type"] = "string" - properties["index"] = "analyzed" - if !f.Norms { - properties["norms"] = common.MapStr{ - "enabled": false, - } - } - } else { - if !f.Norms { - properties["norms"] = false - } + if !f.Norms { + properties["norms"] = false } if f.Analyzer.Name != "" { @@ -426,11 +395,6 @@ func (p *Processor) array(f *mapping.Field) common.MapStr { } func (p *Processor) alias(f *mapping.Field) common.MapStr { - // Aliases were introduced in Elasticsearch 6.4, ignore if unsupported - if p.EsVersion.LessThan(minVersionAlias) { - return nil - } - // In case migration is disabled and it's a migration alias, field is not created if !p.Migration && f.MigrationAlias { return nil @@ -483,11 +447,6 @@ func (p *Processor) object(f *mapping.Field) common.MapStr { matchingType = matchType("*", otp.ObjectTypeMappingType) case "text": dynProperties["type"] = "text" - - if p.EsVersion.IsMajor(2) { - dynProperties["type"] = "string" - dynProperties["index"] = "analyzed" - } matchingType = matchType("string", otp.ObjectTypeMappingType) case "keyword": dynProperties["type"] = otp.ObjectType diff --git a/libbeat/template/processor_test.go b/libbeat/template/processor_test.go index c686f2e4738..4b35da89815 100644 --- a/libbeat/template/processor_test.go +++ b/libbeat/template/processor_test.go @@ -33,9 +33,6 @@ func TestProcessor(t *testing.T) { trueVar := true p := &Processor{EsVersion: *common.MustNewVersion("7.0.0")} migrationP := &Processor{EsVersion: *common.MustNewVersion("7.0.0"), Migration: true} - pEsVersion2 := &Processor{EsVersion: *common.MustNewVersion("2.0.0")} - pEsVersion64 := &Processor{EsVersion: *common.MustNewVersion("6.4.0")} - pEsVersion63 := &Processor{EsVersion: *common.MustNewVersion("6.3.6")} pEsVersion76 := &Processor{EsVersion: *common.MustNewVersion("7.6.0")} tests := []struct { @@ -81,10 +78,6 @@ func TestProcessor(t *testing.T) { "scaling_factor": 10, }, }, - { - output: pEsVersion2.scaledFloat(&mapping.Field{Type: "scaled_float"}), - expected: common.MapStr{"type": "float"}, - }, { output: p.object(&mapping.Field{Type: "object", Enabled: &falseVar}), expected: common.MapStr{ @@ -111,15 +104,6 @@ func TestProcessor(t *testing.T) { output: p.array(&mapping.Field{Type: "array", Index: &falseVar, ObjectType: "keyword"}), expected: common.MapStr{"index": false, "type": "keyword"}, }, - { - output: pEsVersion64.alias(&mapping.Field{Type: "alias", AliasPath: "a.b"}), - expected: common.MapStr{"path": "a.b", "type": "alias"}, - }, - { - // alias unsupported in ES < 6.4 - output: pEsVersion63.alias(&mapping.Field{Type: "alias", AliasPath: "a.b"}), - expected: nil, - }, { output: p.object(&mapping.Field{Type: "object", Enabled: &falseVar}), expected: common.MapStr{ @@ -735,6 +719,18 @@ func TestProcessDefaultField(t *testing.T) { }, }, }, + // Ensure that text_only_keyword fields can be added to default_field + mapping.Field{ + Name: "a_match_only_text_field", + Type: "match_only_text", + DefaultField: &enableDefaultField, + }, + // Ensure that wildcard fields can be added to default_field + mapping.Field{ + Name: "a_wildcard_field", + Type: "wildcard", + DefaultField: &enableDefaultField, + }, } version, err := common.NewVersion("7.0.0") @@ -750,6 +746,8 @@ func TestProcessDefaultField(t *testing.T) { } expectedFields := []string{ + "a_match_only_text_field", + "a_wildcard_field", "bar", "nested.bar", "nested.foo", diff --git a/libbeat/template/template.go b/libbeat/template/template.go index 291d128d0f4..af032487303 100644 --- a/libbeat/template/template.go +++ b/libbeat/template/template.go @@ -51,7 +51,6 @@ type Template struct { esVersion common.Version config TemplateConfig migration bool - templateType IndexTemplateType order int priority int } @@ -71,13 +70,17 @@ func New( } name := config.Name + if config.JSON.Enabled { + name = config.JSON.Name + } + if name == "" { name = fmt.Sprintf("%s-%s", beatName, bV.String()) } pattern := config.Pattern if pattern == "" { - pattern = name + "-*" + pattern = name + "*" } event := &beat.Event{ @@ -132,8 +135,6 @@ func New( beatName: beatName, config: config, migration: migration, - templateType: config.Type, - order: config.Order, priority: config.Priority, }, nil } @@ -188,56 +189,25 @@ func (t *Template) LoadBytes(data []byte) (common.MapStr, error) { } // LoadMinimal loads the template only with the given configuration -func (t *Template) LoadMinimal() (common.MapStr, error) { - var m common.MapStr - switch t.templateType { - case IndexTemplateLegacy: - m = t.loadMinimalLegacy() - case IndexTemplateComponent: - m = t.loadMinimalComponent() - case IndexTemplateIndex: - m = t.loadMinimalIndex() - default: - return nil, fmt.Errorf("unknown template type %v", t.templateType) - } - +func (t *Template) LoadMinimal() common.MapStr { + templ := common.MapStr{} if t.config.Settings.Source != nil { - m["mappings"] = buildMappings( - t.beatVersion, t.esVersion, t.beatName, + templ["mappings"] = buildMappings( + t.beatVersion, t.beatName, nil, nil, common.MapStr(t.config.Settings.Source)) } - - return m, nil -} - -func (t *Template) loadMinimalLegacy() common.MapStr { - keyPattern, patterns := buildPatternSettings(t.esVersion, t.GetPattern()) - return common.MapStr{ - keyPattern: patterns, - "order": t.order, - "settings": common.MapStr{ - "index": t.config.Settings.Index, - }, + templ["settings"] = common.MapStr{ + "index": t.config.Settings.Index, } -} - -func (t *Template) loadMinimalComponent() common.MapStr { return common.MapStr{ - "template": common.MapStr{ - "settings": common.MapStr{ - "index": t.config.Settings.Index, - }, - }, + "template": templ, + "data_stream": struct{}{}, + "priority": t.priority, + "index_patterns": []string{t.GetPattern()}, } } -func (t *Template) loadMinimalIndex() common.MapStr { - m := t.loadMinimalComponent() - m["priority"] = t.priority - return m -} - // GetName returns the name of the template func (t *Template) GetName() string { return t.name @@ -251,45 +221,19 @@ func (t *Template) GetPattern() string { // Generate generates the full template // The default values are taken from the default variable. func (t *Template) Generate(properties, analyzers common.MapStr, dynamicTemplates []common.MapStr) common.MapStr { - switch t.templateType { - case IndexTemplateLegacy: - return t.generateLegacy(properties, analyzers, dynamicTemplates) - case IndexTemplateComponent: - return t.generateComponent(properties, analyzers, dynamicTemplates) - case IndexTemplateIndex: - return t.generateIndex(properties, analyzers, dynamicTemplates) - } - return nil -} + tmpl := t.generateComponent(properties, analyzers, dynamicTemplates) + tmpl["data_stream"] = struct{}{} + tmpl["priority"] = t.priority + tmpl["index_patterns"] = []string{t.GetPattern()} + return tmpl -func (t *Template) generateLegacy(properties, analyzers common.MapStr, dynamicTemplates []common.MapStr) common.MapStr { - keyPattern, patterns := buildPatternSettings(t.esVersion, t.GetPattern()) - m := common.MapStr{ - keyPattern: patterns, - "order": t.order, - "mappings": buildMappings( - t.beatVersion, t.esVersion, t.beatName, - properties, - append(dynamicTemplates, buildDynTmpl(t.esVersion)), - common.MapStr(t.config.Settings.Source)), - "settings": common.MapStr{ - "index": buildIdxSettings( - t.esVersion, - t.config.Settings.Index, - ), - }, - } - if len(analyzers) != 0 { - m.Put("settings.analysis.analyzer", analyzers) - } - return m } func (t *Template) generateComponent(properties, analyzers common.MapStr, dynamicTemplates []common.MapStr) common.MapStr { m := common.MapStr{ "template": common.MapStr{ "mappings": buildMappings( - t.beatVersion, t.esVersion, t.beatName, + t.beatVersion, t.beatName, properties, append(dynamicTemplates, buildDynTmpl(t.esVersion)), common.MapStr(t.config.Settings.Source)), @@ -302,28 +246,13 @@ func (t *Template) generateComponent(properties, analyzers common.MapStr, dynami }, } if len(analyzers) != 0 { - m.Put("settings.analysis.analyzer", analyzers) + m.Put("template.settings.analysis.analyzer", analyzers) } return m } -func (t *Template) generateIndex(properties, analyzers common.MapStr, dynamicTemplates []common.MapStr) common.MapStr { - tmpl := t.generateComponent(properties, analyzers, dynamicTemplates) - tmpl["priority"] = t.priority - keyPattern, patterns := buildPatternSettings(t.esVersion, t.GetPattern()) - tmpl[keyPattern] = patterns - return tmpl -} - -func buildPatternSettings(ver common.Version, pattern string) (string, interface{}) { - if ver.Major < 6 { - return "template", pattern - } - return "index_patterns", []string{pattern} -} - func buildMappings( - beatVersion, esVersion common.Version, + beatVersion common.Version, beatName string, properties common.MapStr, dynTmpls []common.MapStr, @@ -343,41 +272,16 @@ func buildMappings( mapping["_source"] = source } - major := esVersion.Major - switch { - case major == 2: - mapping.Put("_all.norms.enabled", false) - mapping = common.MapStr{ - "_default_": mapping, - } - case major < 6: - mapping = common.MapStr{ - "_default_": mapping, - } - case major == 6: - mapping = common.MapStr{ - "doc": mapping, - } - case major >= 7: - // keep typeless structure - } - return mapping } func buildDynTmpl(ver common.Version) common.MapStr { - strMapping := common.MapStr{ - "ignore_above": 1024, - "type": "keyword", - } - if ver.Major == 2 { - strMapping["type"] = "string" - strMapping["index"] = "not_analyzed" - } - return common.MapStr{ "strings_as_keyword": common.MapStr{ - "mapping": strMapping, + "mapping": common.MapStr{ + "ignore_above": 1024, + "type": "keyword", + }, "match_mapping_type": "string", }, } @@ -393,25 +297,14 @@ func buildIdxSettings(ver common.Version, userSettings common.MapStr) common.Map }, } - // number_of_routing shards is only supported for ES version >= 6.1 - // If ES >= 7.0 we can exclude this setting as well. - version61, _ := common.NewVersion("6.1.0") - if !ver.LessThan(version61) && ver.Major < 7 { - indexSettings.Put("number_of_routing_shards", defaultNumberOfRoutingShards) - } - - if ver.Major >= 7 { - // copy defaultFields, as defaultFields is shared global slice. - fields := make([]string, len(defaultFields)) - copy(fields, defaultFields) - fields = append(fields, "fields.*") + // copy defaultFields, as defaultFields is shared global slice. + fields := make([]string, len(defaultFields)) + copy(fields, defaultFields) + fields = append(fields, "fields.*") - indexSettings.Put("query.default_field", fields) - } + indexSettings.Put("query.default_field", fields) - if ver.Major >= 6 { - indexSettings.Put("max_docvalue_fields_search", defaultMaxDocvalueFieldsSearch) - } + indexSettings.Put("max_docvalue_fields_search", defaultMaxDocvalueFieldsSearch) indexSettings.DeepUpdate(userSettings) return indexSettings diff --git a/libbeat/template/template_test.go b/libbeat/template/template_test.go index 27223ecf6bd..e2430e25ede 100644 --- a/libbeat/template/template_test.go +++ b/libbeat/template/template_test.go @@ -26,6 +26,7 @@ import ( "github.com/stretchr/testify/assert" + "github.com/elastic/beats/v7/libbeat/beat" "github.com/elastic/beats/v7/libbeat/common" "github.com/elastic/beats/v7/libbeat/version" ) @@ -39,30 +40,13 @@ type testTemplate struct { func TestNumberOfRoutingShards(t *testing.T) { const notPresent = 0 // setting missing indicator const settingKey = "number_of_routing_shards" - const fullKey = "settings.index." + settingKey + const fullKey = "template.settings.index." + settingKey cases := map[string]struct { esVersion string set int want int }{ - "Do not set default for older version than 6.1": { - esVersion: "6.0.0", - want: notPresent, - }, - "Default present if ES 6.1.0 is used": { - esVersion: "6.1.0", - want: 30, - }, - "Default present for newer ES 6.x version": { - esVersion: "6.8.2", - want: 30, - }, - "Can overwrite default for ES 6.x": { - esVersion: "6.1.0", - set: 1024, - want: 1024, - }, "Do not set by default for ES 7.x": { esVersion: "7.0.0", want: notPresent, @@ -108,29 +92,20 @@ func TestNumberOfRoutingShards(t *testing.T) { func TestTemplate(t *testing.T) { currentVersion := getVersion("") - - t.Run("for ES 6.x", func(t *testing.T) { - template := createTestTemplate(t, currentVersion, "6.4.0", DefaultConfig()) - template.Assert("index_patterns", []string{"testbeat-" + currentVersion + "-*"}) - template.Assert("order", 1) - template.Assert("mappings.doc._meta", common.MapStr{"beat": "testbeat", "version": currentVersion}) - template.Assert("settings.index.max_docvalue_fields_search", 200) - }) + info := beat.Info{Beat: "testbeat", Version: currentVersion} t.Run("for ES 7.x", func(t *testing.T) { - template := createTestTemplate(t, currentVersion, "7.2.0", DefaultConfig()) - template.Assert("index_patterns", []string{"testbeat-" + currentVersion + "-*"}) - template.Assert("order", 1) - template.Assert("mappings._meta", common.MapStr{"beat": "testbeat", "version": currentVersion}) - template.Assert("settings.index.max_docvalue_fields_search", 200) + template := createTestTemplate(t, currentVersion, "7.10.0", DefaultConfig(info)) + template.Assert("index_patterns", []string{"testbeat-" + currentVersion}) + template.Assert("template.mappings._meta", common.MapStr{"beat": "testbeat", "version": currentVersion}) + template.Assert("template.settings.index.max_docvalue_fields_search", 200) }) t.Run("for ES 8.x", func(t *testing.T) { - template := createTestTemplate(t, currentVersion, "8.0.0", DefaultConfig()) - template.Assert("index_patterns", []string{"testbeat-" + currentVersion + "-*"}) - template.Assert("order", 1) - template.Assert("mappings._meta", common.MapStr{"beat": "testbeat", "version": currentVersion}) - template.Assert("settings.index.max_docvalue_fields_search", 200) + template := createTestTemplate(t, currentVersion, "8.0.0", DefaultConfig(info)) + template.Assert("index_patterns", []string{"testbeat-" + currentVersion}) + template.Assert("template.mappings._meta", common.MapStr{"beat": "testbeat", "version": currentVersion}) + template.Assert("template.settings.index.max_docvalue_fields_search", 200) }) } diff --git a/libbeat/template/testdata/fields.json b/libbeat/template/testdata/fields.json index d95b7a7dabe..01894247b8e 100644 --- a/libbeat/template/testdata/fields.json +++ b/libbeat/template/testdata/fields.json @@ -1,15 +1,17 @@ { "index_patterns": ["foo"], - "settings": { - "number_of_shards": 1 - }, - "mappings": { - "_source": { - "enabled": false + "template": { + "settings": { + "number_of_shards": 1 }, - "properties": { - "host_name": { - "type": "keyword" + "mappings": { + "_source": { + "enabled": false + }, + "properties": { + "host_name": { + "type": "keyword" + } } } } diff --git a/libbeat/template/testdata/fields.yml b/libbeat/template/testdata/fields.yml index afceaeaae69..fcfe105b5e5 100644 --- a/libbeat/template/testdata/fields.yml +++ b/libbeat/template/testdata/fields.yml @@ -3,6 +3,8 @@ description: > Contains all types for testing fields: + - name: '@timestamp' + type: date - name: object type: object diff --git a/libbeat/tests/files/template.json b/libbeat/tests/files/template.json index 655613e32d0..6ebbcfe211d 100644 --- a/libbeat/tests/files/template.json +++ b/libbeat/tests/files/template.json @@ -1,19 +1,21 @@ { "index_patterns": ["bla"], - "settings": { - "number_of_shards": 1 - }, - "mappings": { - "_source": { - "enabled": false + "template": { + "settings": { + "number_of_shards": 1 }, - "properties": { - "host_name": { - "type": "keyword" + "mappings": { + "_source": { + "enabled": false }, - "created_at": { - "type": "date", - "format": "EEE MMM dd HH:mm:ss Z YYYY" + "properties": { + "host_name": { + "type": "keyword" + }, + "created_at": { + "type": "date", + "format": "EEE MMM dd HH:mm:ss Z YYYY" + } } } } diff --git a/libbeat/tests/resources/goroutines.go b/libbeat/tests/resources/goroutines.go index 7ab2c6803ae..7c9ab170dff 100644 --- a/libbeat/tests/resources/goroutines.go +++ b/libbeat/tests/resources/goroutines.go @@ -52,21 +52,24 @@ func NewGoroutinesChecker() GoroutinesChecker { // was created func (c GoroutinesChecker) Check(t testing.TB) { t.Helper() - err := c.check(t) + err := c.check() if err != nil { + dumpGoroutines() t.Error(err) } } -func (c GoroutinesChecker) check(t testing.TB) error { - after := c.WaitUntilOriginalCount() - if after == 0 { - return nil - } - +func dumpGoroutines() { profile := pprof.Lookup("goroutine") profile.WriteTo(os.Stdout, 2) - return fmt.Errorf("Possible goroutines leak, before: %d, after: %d", c.before, after) +} + +func (c GoroutinesChecker) check() error { + after, err := c.WaitUntilOriginalCount() + if err == ErrTimeout { + return fmt.Errorf("possible goroutines leak, before: %d, after: %d", c.before, after) + } + return err } // CallAndCheckGoroutines calls a function and checks if it has increased @@ -78,21 +81,29 @@ func CallAndCheckGoroutines(t testing.TB, f func()) { c.Check(t) } +// ErrTimeout is the error returned when WaitUntilOriginalCount timeouts. +var ErrTimeout = fmt.Errorf("timeout waiting for finalization of goroutines") + // WaitUntilOriginalCount waits until the original number of goroutines are -// present before we has created the resource checker. -func (c GoroutinesChecker) WaitUntilOriginalCount() int { +// present before we created the resource checker. +// It returns the number of goroutines after the check and a timeout error +// in case the wait has expired. +func (c GoroutinesChecker) WaitUntilOriginalCount() (int, error) { timeout := time.Now().Add(c.FinalizationTimeout) + var after int for time.Now().Before(timeout) { after = runtime.NumGoroutine() if after <= c.before { - return 0 + return after, nil } time.Sleep(10 * time.Millisecond) } - return after + return after, ErrTimeout } +// WaitUntilIncreased waits till the number of goroutines is n plus the number +// before creating the checker. func (c *GoroutinesChecker) WaitUntilIncreased(n int) { for runtime.NumGoroutine() < c.before+n { time.Sleep(10 * time.Millisecond) diff --git a/libbeat/tests/resources/goroutines_test.go b/libbeat/tests/resources/goroutines_test.go index 7f146318a66..369ba0c1ad1 100644 --- a/libbeat/tests/resources/goroutines_test.go +++ b/libbeat/tests/resources/goroutines_test.go @@ -25,54 +25,45 @@ import ( ) func TestGoroutinesChecker(t *testing.T) { - block := make(chan struct{}) - defer close(block) - cases := []struct { title string - test func() + test func(ctl *goroutineTesterControl) timeout time.Duration fail bool }{ { title: "no goroutines", - test: func() {}, + test: func(ctl *goroutineTesterControl) {}, }, { title: "fast goroutine", - test: func() { - started := make(chan struct{}) - go func() { - started <- struct{}{} - }() - <-started + test: func(ctl *goroutineTesterControl) { + ctl.startGoroutine(func() {}) }, }, - /* Skipped due to flakyness: https://github.com/elastic/beats/issues/12692 { title: "blocked goroutine", - test: func() { - started := make(chan struct{}) - go func() { - started <- struct{}{} - <-block - }() - <-started + test: func(ctl *goroutineTesterControl) { + ctl.startGoroutine(func() { + ctl.block() + }) }, - timeout: 500 * time.Millisecond, + timeout: 10 * time.Millisecond, fail: true, }, - */ } for _, c := range cases { t.Run(c.title, func(t *testing.T) { + ctl := newControl() + defer ctl.cleanup(t) + goroutines := NewGoroutinesChecker() if c.timeout > 0 { goroutines.FinalizationTimeout = c.timeout } - c.test() - err := goroutines.check(t) + c.test(ctl) + err := goroutines.check() if c.fail { assert.Error(t, err) } else { @@ -81,3 +72,39 @@ func TestGoroutinesChecker(t *testing.T) { }) } } + +// goroutineTesterControl helps keeping track of goroutines started for each test case. +type goroutineTesterControl struct { + checker GoroutinesChecker + blocker chan struct{} +} + +func newControl() *goroutineTesterControl { + return &goroutineTesterControl{ + checker: NewGoroutinesChecker(), + blocker: make(chan struct{}), + } +} + +// startGoroutine ensures that a goroutine is started before continuing. +func (c *goroutineTesterControl) startGoroutine(f func()) { + started := make(chan struct{}) + go func() { + started <- struct{}{} + f() + }() + <-started +} + +// block blocks forever (being "ever" the life of the test). +func (c *goroutineTesterControl) block() { + <-c.blocker +} + +// cleanup ensures that all started goroutines are finished. +func (c *goroutineTesterControl) cleanup(t *testing.T) { + close(c.blocker) + if _, err := c.checker.WaitUntilOriginalCount(); err != nil { + t.Fatal("goroutines in test cases should be started using startGoroutine") + } +} diff --git a/libbeat/tests/system/base.py b/libbeat/tests/system/base.py index 7fd9f1dbb49..a768d80e31e 100644 --- a/libbeat/tests/system/base.py +++ b/libbeat/tests/system/base.py @@ -1,9 +1,11 @@ import os +from datetime import datetime from beat.beat import TestCase from elasticsearch import Elasticsearch, NotFoundError class BaseTest(TestCase): + today = datetime.now().strftime("%Y%m%d") @classmethod def setUpClass(self): diff --git a/libbeat/tests/system/beat/beat.py b/libbeat/tests/system/beat/beat.py index 195741b1d31..e7a2c60640a 100644 --- a/libbeat/tests/system/beat/beat.py +++ b/libbeat/tests/system/beat/beat.py @@ -119,6 +119,7 @@ def __del__(self): class TestCase(unittest.TestCase, ComposeMixin): + today = datetime.now().strftime("%Y%m%d") @classmethod def setUpClass(self): @@ -207,7 +208,7 @@ def start_beat(self, config = self.beat_name + ".yml" if output is None: - output = self.beat_name + ".log" + output = self.beat_name + "-" + self.today + ".ndjson" args = [cmd, "-systemTest"] if os.getenv("TEST_COVERAGE") == "true": @@ -264,7 +265,7 @@ def read_output(self, # Init defaults if output_file is None: - output_file = "output/" + self.beat_name + output_file = "output/" + self.beat_name + "-" + self.today + ".ndjson" jsons = [] with open(os.path.join(self.working_dir, output_file), "r", encoding="utf_8") as f: @@ -288,7 +289,7 @@ def read_output_json(self, output_file=None): # Init defaults if output_file is None: - output_file = "output/" + self.beat_name + output_file = "output/" + self.beat_name + "-" + self.today + ".ndjson" jsons = [] with open(os.path.join(self.working_dir, output_file), "r", encoding="utf_8") as f: @@ -368,7 +369,7 @@ def get_log(self, logfile=None): Returns the log as a string. """ if logfile is None: - logfile = self.beat_name + ".log" + logfile = self.beat_name + "-" + self.today + ".ndjson" with open(os.path.join(self.working_dir, logfile), 'r', encoding="utf_8") as f: data = f.read() @@ -380,7 +381,7 @@ def get_log_lines(self, logfile=None): Returns the log lines as a list of strings """ if logfile is None: - logfile = self.beat_name + ".log" + logfile = self.beat_name + "-" + self.today + ".ndjson" with open(os.path.join(self.working_dir, logfile), 'r', encoding="utf_8") as f: data = f.readlines() @@ -417,8 +418,9 @@ def log_contains_count(self, msg, logfile=None, ignore_case=False): # Init defaults if logfile is None: - logfile = self.beat_name + ".log" + logfile = self.beat_name + "-" + self.today + ".ndjson" + print("logfile", logfile, self.working_dir) try: with open(os.path.join(self.working_dir, logfile), "r", encoding="utf_8") as f: for line in f: @@ -430,7 +432,8 @@ def log_contains_count(self, msg, logfile=None, ignore_case=False): line = line.lower() if line.find(msg) >= 0: counter = counter + 1 - except IOError: + except IOError as e: + print(e) counter = -1 return counter @@ -442,7 +445,7 @@ def log_contains_countmap(self, pattern, capture_group, logfile=None): counts = {} if logfile is None: - logfile = self.beat_name + ".log" + logfile = self.beat_name + "-" + self.today + ".ndjson" try: with open(os.path.join(self.working_dir, logfile), "r", encoding="utf_8") as f: @@ -462,7 +465,7 @@ def log_contains_countmap(self, pattern, capture_group, logfile=None): def output_lines(self, output_file=None): """ Count number of lines in a file.""" if output_file is None: - output_file = "output/" + self.beat_name + output_file = "output/" + self.beat_name + "-" + self.today + ".ndjson" try: with open(os.path.join(self.working_dir, output_file), "r", encoding="utf_8") as f: @@ -477,7 +480,7 @@ def output_has(self, lines, output_file=None): # Init defaults if output_file is None: - output_file = "output/" + self.beat_name + output_file = "output/" + self.beat_name + "-" + self.today + ".ndjson" try: with open(os.path.join(self.working_dir, output_file, ), "r", encoding="utf_8") as f: @@ -492,7 +495,7 @@ def output_is_empty(self, output_file=None): # Init defaults if output_file is None: - output_file = "output/" + self.beat_name + output_file = "output/" + self.beat_name + "-" + self.today + ".ndjson" try: with open(os.path.join(self.working_dir, output_file, ), "r", encoding="utf_8") as f: @@ -656,7 +659,7 @@ def output_count(self, pred, output_file=None): # Init defaults if output_file is None: - output_file = "output/" + self.beat_name + output_file = "output/" + self.beat_name + "-" + self.today + ".ndjson" try: with open(os.path.join(self.working_dir, output_file), "r", encoding="utf_8") as f: diff --git a/libbeat/tests/system/beat/common_tests.py b/libbeat/tests/system/beat/common_tests.py index f5bccf2968d..a5caff92c9a 100644 --- a/libbeat/tests/system/beat/common_tests.py +++ b/libbeat/tests/system/beat/common_tests.py @@ -58,7 +58,12 @@ def test_export_template(self): """ output = self.run_export_cmd("template") js = json.loads(output) - assert "index_patterns" in js and "mappings" in js + assert "index_patterns" in js + assert "template" in js + assert "priority" in js + assert "order" not in js + assert "mappings" in js["template"] + assert "settings" in js["template"] def test_export_index_pattern(self): """ diff --git a/libbeat/tests/system/config/libbeat.yml.j2 b/libbeat/tests/system/config/libbeat.yml.j2 index edfc178eea8..e6d62a5eae6 100644 --- a/libbeat/tests/system/config/libbeat.yml.j2 +++ b/libbeat/tests/system/config/libbeat.yml.j2 @@ -31,9 +31,6 @@ setup.ilm: {% if ilm.pattern %} pattern: {{ ilm.pattern }} {% endif %} - {% if ilm.rollover_alias %} - rollover_alias: {{ ilm.rollover_alias }} - {% endif %} {% endif %} #================================ Processors ===================================== diff --git a/libbeat/tests/system/idxmgmt.py b/libbeat/tests/system/idxmgmt.py index f789b919bc2..6da6a077c71 100644 --- a/libbeat/tests/system/idxmgmt.py +++ b/libbeat/tests/system/idxmgmt.py @@ -9,35 +9,45 @@ class IdxMgmt(unittest.TestCase): def __init__(self, client, index): self._client = client self._index = index if index != '' and index != '*' else 'mockbeat' + self.patterns = [self.default_pattern(), "1", datetime.datetime.now().strftime("%Y.%m.%d")] def needs_init(self, s): return s == '' or s == '*' - def delete(self, indices=[], policies=[]): - indices = list([x for x in indices if x != '']) - if not indices: - indices == [self._index] + def delete(self, indices=[], policies=[], data_streams=[]): + for ds in data_streams: + self.delete_data_stream(ds) + self.delete_template(template=ds) for i in indices: self.delete_index_and_alias(i) self.delete_template(template=i) for i in [x for x in policies if x != '']: self.delete_policy(i) + def delete_data_stream(self, data_stream): + try: + resp = self._client.transport.perform_request('DELETE', '/_data_stream/' + data_stream) + except NotFoundError: + pass + def delete_index_and_alias(self, index=""): if self.needs_init(index): index = self._index - try: - self._client.transport.perform_request('DELETE', "/" + index + "*") - except NotFoundError: - pass + for pattern in self.patterns: + index_with_pattern = index+"-"+pattern + try: + self._client.indices.delete(index_with_pattern) + self._client.indices.delete_alias(index, index_with_pattern) + except NotFoundError: + continue def delete_template(self, template=""): if self.needs_init(template): template = self._index try: - self._client.transport.perform_request('DELETE', "/_template/" + template + "*") + self._client.transport.perform_request('DELETE', "/_index_template/" + template) except NotFoundError: pass @@ -54,12 +64,7 @@ def delete_policy(self, policy): def assert_index_template_not_loaded(self, template): with pytest.raises(NotFoundError): - self._client.transport.perform_request('GET', '/_template/' + template) - - def assert_legacy_index_template_loaded(self, template): - resp = self._client.transport.perform_request('GET', '/_template/' + template) - assert template in resp - assert "lifecycle" not in resp[template]["settings"]["index"] + self._client.transport.perform_request('GET', '/_index_template/' + template) def assert_index_template_loaded(self, template): resp = self._client.transport.perform_request('GET', '/_index_template/' + template) @@ -69,40 +74,20 @@ def assert_index_template_loaded(self, template): found = True assert found - def assert_component_template_loaded(self, template): - resp = self._client.transport.perform_request('GET', '/_component_template/' + template) - found = False - print(resp) - for index_template in resp['component_templates']: + def assert_data_stream_created(self, data_stream): + try: + resp = self._client.transport.perform_request('GET', '/_data_stream/' + data_stream) + except NotFoundError: + assert False + + def assert_index_template_index_pattern(self, template, index_pattern): + resp = self._client.transport.perform_request('GET', '/_index_template/' + template) + for index_template in resp['index_templates']: if index_template['name'] == template: + assert index_pattern == index_template['index_template']['index_patterns'] found = True assert found - def assert_ilm_template_loaded(self, template, policy, alias): - resp = self._client.transport.perform_request('GET', '/_template/' + template) - assert resp[template]["settings"]["index"]["lifecycle"]["name"] == policy - assert resp[template]["settings"]["index"]["lifecycle"]["rollover_alias"] == alias - - def assert_index_template_index_pattern(self, template, index_pattern): - resp = self._client.transport.perform_request('GET', '/_template/' + template) - assert template in resp - assert resp[template]["index_patterns"] == index_pattern - - def assert_alias_not_created(self, alias): - resp = self._client.transport.perform_request('GET', '/_alias') - for name, entry in resp.items(): - if alias not in name: - continue - assert entry["aliases"] == {}, entry["aliases"] - - def assert_alias_created(self, alias, pattern=None): - if pattern is None: - pattern = self.default_pattern() - name = alias + "-" + pattern - resp = self._client.transport.perform_request('GET', '/_alias/' + alias) - assert name in resp - assert resp[name]["aliases"][alias]["is_write_index"] == True - def assert_policy_not_created(self, policy): with pytest.raises(NotFoundError): self._client.transport.perform_request('GET', '/_ilm/policy/' + policy) @@ -113,22 +98,14 @@ def assert_policy_created(self, policy): assert resp[policy]["policy"]["phases"]["hot"]["actions"]["rollover"]["max_size"] == "50gb" assert resp[policy]["policy"]["phases"]["hot"]["actions"]["rollover"]["max_age"] == "30d" - def assert_docs_written_to_alias(self, alias, pattern=None): + def assert_docs_written_to_data_stream(self, data_stream): # Refresh the indices to guarantee all documents are available # through the _search API. self._client.transport.perform_request('POST', '/_refresh') - if pattern is None: - pattern = self.default_pattern() - name = alias + "-" + pattern - data = self._client.transport.perform_request('GET', '/' + name + '/_search') + data = self._client.transport.perform_request('GET', '/' + data_stream + '/_search') self.assertGreater(data["hits"]["total"]["value"], 0) def default_pattern(self): d = datetime.datetime.now().strftime("%Y.%m.%d") return d + "-000001" - - def index_for(self, alias, pattern=None): - if pattern is None: - pattern = self.default_pattern() - return "{}-{}".format(alias, pattern) diff --git a/libbeat/tests/system/template/template.go b/libbeat/tests/system/template/template.go index ed284a6ff79..7467f5b60fb 100644 --- a/libbeat/tests/system/template/template.go +++ b/libbeat/tests/system/template/template.go @@ -65,10 +65,10 @@ func testTemplateDefaultFieldLength(beatName string, elasticLicensed bool) func( templateMap := tmpl.Generate(fields, nil, nil) - v, _ := templateMap.GetValue("settings.index.query.default_field") + v, _ := templateMap.GetValue("template.settings.index.query.default_field") defaultValue, ok := v.([]string) if !ok { - t.Fatalf("settings.index.query.default_field value has an unexpected type: %T", v) + t.Fatalf("template.settings.index.query.default_field value has an unexpected type: %T", v) } if len(defaultValue) > MaxDefaultFieldLength { diff --git a/libbeat/tests/system/test_base.py b/libbeat/tests/system/test_base.py index 97615e7ec00..fbb8b324f16 100644 --- a/libbeat/tests/system/test_base.py +++ b/libbeat/tests/system/test_base.py @@ -165,8 +165,7 @@ def run(): # remove log, restart beat and check meta file did not change # and same UUID is used in log output. - - os.remove(os.path.join(self.working_dir, "mockbeat.log")) + os.remove(os.path.join(self.working_dir, "mockbeat-" + self.today + ".ndjson")) meta1 = run() assert self.log_contains("Beat ID: {}".format(meta1["uuid"])) diff --git a/libbeat/tests/system/test_cmd_setup_index_management.py b/libbeat/tests/system/test_cmd_setup_index_management.py index cd6d19eefbe..2abe8828175 100644 --- a/libbeat/tests/system/test_cmd_setup_index_management.py +++ b/libbeat/tests/system/test_cmd_setup_index_management.py @@ -21,28 +21,29 @@ def setUp(self): self.cmd = "--index-management" # auto-derived default settings, if nothing else is set self.policy_name = self.beat_name - self.index_name = self.alias_name = self.beat_name + "-9.9.9" + self.data_stream = self.beat_name + "-9.9.9" - self.custom_alias = self.beat_name + "_foo" self.custom_policy = self.beat_name + "_bar" self.custom_template = self.beat_name + "_foobar" self.es = self.es_client() - self.idxmgmt = IdxMgmt(self.es, self.index_name) - self.idxmgmt.delete(indices=[self.custom_alias, self.index_name, self.custom_policy], - policies=[self.policy_name, self.custom_policy]) + self.idxmgmt = IdxMgmt(self.es, self.data_stream) + self.idxmgmt.delete(indices=[], + policies=[self.policy_name, self.custom_policy], + data_streams=[self.data_stream]) logging.getLogger("urllib3").setLevel(logging.WARNING) logging.getLogger("elasticsearch").setLevel(logging.ERROR) def tearDown(self): - self.idxmgmt.delete(indices=[self.custom_alias, self.index_name, self.custom_policy], - policies=[self.policy_name, self.custom_policy]) + self.idxmgmt.delete(indices=[], + policies=[self.policy_name, self.custom_policy], + data_streams=[self.data_stream]) def render_config(self, **kwargs): self.render_config_template( elasticsearch={"hosts": self.get_elasticsearch_url()}, - es_template_name=self.index_name, + es_template_name=self.data_stream, **kwargs ) @@ -57,45 +58,24 @@ def test_setup_default(self): extra_args=["setup", self.cmd]) assert exit_code == 0 - self.idxmgmt.assert_ilm_template_loaded(self.alias_name, self.policy_name, self.alias_name) - self.idxmgmt.assert_index_template_index_pattern(self.index_name, [self.index_name + "-*"]) - self.idxmgmt.assert_docs_written_to_alias(self.alias_name) - self.idxmgmt.assert_alias_created(self.alias_name) + self.idxmgmt.assert_index_template_loaded(self.data_stream) + self.idxmgmt.assert_index_template_index_pattern(self.data_stream, [self.data_stream]) self.idxmgmt.assert_policy_created(self.policy_name) - @unittest.skipUnless(INTEGRATION_TESTS, "integration test") - @pytest.mark.tag('integration') - def test_setup_default(self): - """ - Test setup --index-management with default config - """ - self.render_config() - exit_code = self.run_beat(logging_args=["-v", "-d", "*"], - extra_args=["setup", self.cmd]) - - assert exit_code == 0 - self.idxmgmt.assert_ilm_template_loaded(self.alias_name, self.policy_name, self.alias_name) - self.idxmgmt.assert_index_template_index_pattern(self.index_name, [self.index_name + "-*"]) - self.idxmgmt.assert_alias_created(self.alias_name) - self.idxmgmt.assert_policy_created(self.policy_name) - # try deleting policy needs to raise an error as it is in use - with pytest.raises(RequestError): - self.idxmgmt.delete_policy(self.policy_name) - @unittest.skipUnless(INTEGRATION_TESTS, "integration test") @pytest.mark.tag('integration') def test_setup_template_disabled(self): """ Test setup --index-management when ilm disabled """ + self.render_config() - exit_code = self.run_beat(logging_args=["-v", "-d", "*"], + exit_code = self.run_beat(logging_args=["-v", "-e", "-d", "*"], extra_args=["setup", self.cmd, "-E", "setup.template.enabled=false"]) assert exit_code == 0 - self.idxmgmt.assert_index_template_not_loaded(self.index_name) - self.idxmgmt.assert_alias_created(self.index_name) + self.idxmgmt.assert_index_template_not_loaded(self.data_stream+"ba") self.idxmgmt.assert_policy_created(self.policy_name) @unittest.skipUnless(INTEGRATION_TESTS, "integration test") @@ -110,8 +90,7 @@ def test_setup_ilm_disabled(self): "-E", "setup.ilm.enabled=false"]) assert exit_code == 0 - self.idxmgmt.assert_legacy_index_template_loaded(self.index_name) - self.idxmgmt.assert_alias_not_created(self.alias_name) + self.idxmgmt.assert_index_template_loaded(self.data_stream) self.idxmgmt.assert_policy_not_created(self.policy_name) @unittest.skipUnless(INTEGRATION_TESTS, "integration test") @@ -126,7 +105,7 @@ def test_setup_policy_name(self): "-E", "setup.ilm.policy_name=" + self.custom_policy]) assert exit_code == 0 - self.idxmgmt.assert_ilm_template_loaded(self.alias_name, self.custom_policy, self.alias_name) + self.idxmgmt.assert_index_template_loaded(self.data_stream) self.idxmgmt.assert_policy_created(self.custom_policy) @unittest.skipUnless(INTEGRATION_TESTS, "integration test") @@ -176,58 +155,6 @@ def test_setup_ilm_policy_no_overwrite(self): assert "delete" not in resp[policy_name]["policy"]["phases"] assert "hot" in resp[policy_name]["policy"]["phases"] - @unittest.skipUnless(INTEGRATION_TESTS, "integration test") - @pytest.mark.tag('integration') - def test_setup_rollover_alias(self): - """ - Test setup --index-management when ilm.rollover_alias is configured - """ - self.render_config() - exit_code = self.run_beat(logging_args=["-v", "-d", "*"], - extra_args=["setup", self.cmd, - "-E", "setup.ilm.rollover_alias=" + self.custom_alias]) - - assert exit_code == 0 - self.idxmgmt.assert_ilm_template_loaded(self.custom_alias, self.policy_name, self.custom_alias) - self.idxmgmt.assert_index_template_index_pattern(self.custom_alias, [self.custom_alias + "-*"]) - self.idxmgmt.assert_alias_created(self.custom_alias) - - @unittest.skipUnless(INTEGRATION_TESTS, "integration test") - @pytest.mark.tag('integration') - def test_setup_rollover_alias_with_fieldref(self): - """ - Test setup --index-management when ilm.rollover_alias is configured and using field reference. - """ - aliasFieldRef = "%{[agent.name]}-myalias" - self.render_config() - exit_code = self.run_beat(logging_args=["-v", "-d", "*"], - extra_args=["setup", self.cmd, - "-E", "setup.ilm.rollover_alias=" + aliasFieldRef]) - - self.custom_alias = self.beat_name + "-myalias" - - assert exit_code == 0 - self.idxmgmt.assert_ilm_template_loaded(self.custom_alias, self.policy_name, self.custom_alias) - self.idxmgmt.assert_index_template_index_pattern(self.custom_alias, [self.custom_alias + "-*"]) - self.idxmgmt.assert_alias_created(self.custom_alias) - - @unittest.skipUnless(INTEGRATION_TESTS, "integration test") - @pytest.mark.tag('integration') - def test_setup_template_name_and_pattern(self): - """ - Test setup --index-management ignores template.name and template.pattern when ilm is enabled - """ - self.render_config() - exit_code = self.run_beat(logging_args=["-v", "-d", "*"], - extra_args=["setup", self.cmd, - "-E", "setup.template.name=" + self.custom_template, - "-E", "setup.template.pattern=" + self.custom_template + "*"]) - - assert exit_code == 0 - self.idxmgmt.assert_ilm_template_loaded(self.alias_name, self.policy_name, self.alias_name) - self.idxmgmt.assert_index_template_index_pattern(self.alias_name, [self.alias_name + "-*"]) - self.idxmgmt.assert_alias_created(self.alias_name) - @unittest.skipUnless(INTEGRATION_TESTS, "integration test") @pytest.mark.tag('integration') def test_setup_template_name_and_pattern_on_ilm_disabled(self): @@ -242,9 +169,8 @@ def test_setup_template_name_and_pattern_on_ilm_disabled(self): "-E", "setup.template.pattern=" + self.custom_template + "*"]) assert exit_code == 0 - self.idxmgmt.assert_legacy_index_template_loaded(self.custom_template) + self.idxmgmt.assert_index_template_loaded(self.custom_template) self.idxmgmt.assert_index_template_index_pattern(self.custom_template, [self.custom_template + "*"]) - self.idxmgmt.assert_alias_not_created(self.alias_name) self.idxmgmt.assert_policy_not_created(self.policy_name) @unittest.skipUnless(INTEGRATION_TESTS, "integration test") @@ -261,13 +187,17 @@ def test_setup_template_with_opts(self): "-E", "setup.template.settings.index.number_of_shards=2"]) assert exit_code == 0 - self.idxmgmt.assert_legacy_index_template_loaded(self.index_name) + self.idxmgmt.assert_index_template_loaded(self.data_stream) # check that settings are overwritten - resp = self.es.transport.perform_request('GET', '/_template/' + self.index_name) - assert self.index_name in resp - index = resp[self.index_name]["settings"]["index"] - assert index["number_of_shards"] == "2", index["number_of_shards"] + resp = self.es.transport.perform_request('GET', '/_index_template/' + self.data_stream) + found = False + for index_template in resp["index_templates"]: + if self.data_stream == index_template["name"]: + found = True + index = index_template["index_template"]["template"]["settings"]["index"] + assert index["number_of_shards"] == "2", index["number_of_shards"] + assert found @unittest.skipUnless(INTEGRATION_TESTS, "integration test") @pytest.mark.tag('integration') @@ -281,22 +211,29 @@ def test_setup_overwrite_template_on_ilm_policy_created(self): exit_code = self.run_beat(logging_args=["-v", "-d", "*"], extra_args=["setup", self.cmd, "-E", "setup.ilm.enabled=false", - "-E", "setup.template.name=" + self.custom_alias, - "-E", "setup.template.pattern=" + self.custom_alias + "*"]) + "-E", "setup.template.priority=160", + "-E", "setup.template.name=" + self.custom_template, + "-E", "setup.template.pattern=" + self.custom_template + "*"]) assert exit_code == 0 - self.idxmgmt.assert_legacy_index_template_loaded(self.custom_alias) + self.idxmgmt.assert_index_template_loaded(self.custom_template) self.idxmgmt.assert_policy_not_created(self.policy_name) # ensure ilm policy is created, triggering overwriting existing template - exit_code = self.run_beat(extra_args=["setup", self.cmd, - "-E", "setup.template.overwrite=false", - "-E", "setup.template.settings.index.number_of_shards=2", - "-E", "setup.ilm.rollover_alias=" + self.custom_alias]) + exit_code = self.run_beat(extra_args=["setup", "-d", "*", self.cmd, + "-E", "setup.template.overwrite=true", + "-E", "setup.template.name=" + self.custom_template, + "-E", "setup.template.pattern=" + self.custom_template + "*", + "-E", "setup.template.settings.index.number_of_shards=2"]) assert exit_code == 0 - self.idxmgmt.assert_ilm_template_loaded(self.custom_alias, self.policy_name, self.custom_alias) + self.idxmgmt.assert_index_template_loaded(self.custom_template) self.idxmgmt.assert_policy_created(self.policy_name) # check that template was overwritten - resp = self.es.transport.perform_request('GET', '/_template/' + self.custom_alias) - assert self.custom_alias in resp - index = resp[self.custom_alias]["settings"]["index"] - assert index["number_of_shards"] == "2", index["number_of_shards"] + resp = self.es.transport.perform_request('GET', '/_index_template/' + self.custom_template) + + found = False + for index_template in resp["index_templates"]: + if index_template["name"] == self.custom_template: + found = True + index = index_template["index_template"]["template"]["settings"]["index"] + assert index["number_of_shards"] == "2", index["number_of_shards"] + assert found diff --git a/libbeat/tests/system/test_dashboard.py b/libbeat/tests/system/test_dashboard.py index 338e832b045..e02a644213e 100644 --- a/libbeat/tests/system/test_dashboard.py +++ b/libbeat/tests/system/test_dashboard.py @@ -208,6 +208,7 @@ def test_dev_tool_export_dashboard_by_id_unknown_id(self): assert p.returncode != 0 + @unittest.skip("Failing test: https://github.com/elastic/beats/issues/29327") @unittest.skipUnless(INTEGRATION_TESTS, "integration test") @pytest.mark.tag('integration') def test_dev_tool_export_dashboard_by_id_from_space(self): diff --git a/libbeat/tests/system/test_ilm.py b/libbeat/tests/system/test_ilm.py index 12c79fad61d..461fc0212f0 100644 --- a/libbeat/tests/system/test_ilm.py +++ b/libbeat/tests/system/test_ilm.py @@ -21,23 +21,24 @@ class TestRunILM(BaseTest): def setUp(self): super(TestRunILM, self).setUp() - self.alias_name = self.index_name = self.beat_name + "-9.9.9" + self.data_stream = self.beat_name + "-9.9.9" self.policy_name = self.beat_name - self.custom_alias = self.beat_name + "_foo" self.custom_policy = self.beat_name + "_bar" self.es = self.es_client() - self.idxmgmt = IdxMgmt(self.es, self.index_name) - self.idxmgmt.delete(indices=[self.custom_alias, self.index_name, self.custom_policy], - policies=[self.policy_name, self.custom_policy]) + self.idxmgmt = IdxMgmt(self.es, self.data_stream) + self.idxmgmt.delete(indices=[], + policies=[self.policy_name, self.custom_policy], + data_streams=[self.data_stream]) def tearDown(self): - self.idxmgmt.delete(indices=[self.custom_alias, self.index_name, self.custom_policy], - policies=[self.policy_name, self.custom_policy]) + self.idxmgmt.delete(indices=[], + policies=[self.policy_name, self.custom_policy], + data_streams=[self.data_stream]) def render_config(self, **kwargs): self.render_config_template( elasticsearch={"hosts": self.get_elasticsearch_url()}, - es_template_name=self.index_name, + es_template_name=self.data_stream, **kwargs ) @@ -45,7 +46,7 @@ def render_config(self, **kwargs): @pytest.mark.tag('integration') def test_ilm_default(self): """ - Test ilm default settings to load ilm policy, write alias and ilm template + Test ilm default settings to load ilm policy, data stream template """ self.render_config() proc = self.start_beat() @@ -54,10 +55,9 @@ def test_ilm_default(self): self.wait_until(lambda: self.log_contains("PublishEvents: 1 events have been published")) proc.check_kill_and_wait() - self.idxmgmt.assert_ilm_template_loaded(self.alias_name, self.policy_name, self.alias_name) - self.idxmgmt.assert_alias_created(self.alias_name) + self.idxmgmt.assert_data_stream_created(self.data_stream) self.idxmgmt.assert_policy_created(self.policy_name) - self.idxmgmt.assert_docs_written_to_alias(self.alias_name) + self.idxmgmt.assert_docs_written_to_data_stream(self.data_stream) @unittest.skipUnless(INTEGRATION_TESTS, "integration test") @pytest.mark.tag('integration') @@ -72,9 +72,9 @@ def test_ilm_disabled(self): self.wait_until(lambda: self.log_contains("PublishEvents: 1 events have been published")) proc.check_kill_and_wait() - self.idxmgmt.assert_legacy_index_template_loaded(self.index_name) - self.idxmgmt.assert_alias_not_created(self.alias_name) + self.idxmgmt.assert_index_template_loaded(self.data_stream) self.idxmgmt.assert_policy_not_created(self.policy_name) + self.idxmgmt.assert_docs_written_to_data_stream(self.data_stream) @unittest.skipUnless(INTEGRATION_TESTS, "integration test") @pytest.mark.tag('integration') @@ -92,71 +92,10 @@ def test_policy_name(self): self.wait_until(lambda: self.log_contains("PublishEvents: 1 events have been published")) proc.check_kill_and_wait() - self.idxmgmt.assert_ilm_template_loaded(self.alias_name, policy_name, self.alias_name) - self.idxmgmt.assert_docs_written_to_alias(self.alias_name) + self.idxmgmt.assert_index_template_loaded(self.data_stream) + self.idxmgmt.assert_docs_written_to_data_stream(self.data_stream) self.idxmgmt.assert_policy_created(policy_name) - @unittest.skipUnless(INTEGRATION_TESTS, "integration test") - @pytest.mark.tag('integration') - def test_rollover_alias(self): - """ - Test settings ilm rollover alias - """ - - self.render_config(ilm={"enabled": True, "rollover_alias": self.custom_alias}) - - proc = self.start_beat() - self.wait_until(lambda: self.log_contains("mockbeat start running.")) - self.wait_until(lambda: self.log_contains(MSG_ILM_POLICY_LOADED)) - self.wait_until(lambda: self.log_contains("PublishEvents: 1 events have been published")) - proc.check_kill_and_wait() - - self.idxmgmt.assert_ilm_template_loaded(self.custom_alias, self.policy_name, self.custom_alias) - self.idxmgmt.assert_docs_written_to_alias(self.custom_alias) - self.idxmgmt.assert_alias_created(self.custom_alias) - - @unittest.skipUnless(INTEGRATION_TESTS, "integration test") - @pytest.mark.tag('integration') - def test_pattern(self): - """ - Test setting ilm pattern - """ - - pattern = "1" - self.render_config(ilm={"enabled": True, "pattern": pattern}) - - proc = self.start_beat() - self.wait_until(lambda: self.log_contains("mockbeat start running.")) - self.wait_until(lambda: self.log_contains(MSG_ILM_POLICY_LOADED)) - self.wait_until(lambda: self.log_contains("PublishEvents: 1 events have been published")) - proc.check_kill_and_wait() - - self.idxmgmt.assert_ilm_template_loaded(self.alias_name, self.policy_name, self.alias_name) - self.idxmgmt.assert_alias_created(self.alias_name, pattern=pattern) - self.idxmgmt.assert_docs_written_to_alias(self.alias_name, pattern=pattern) - - @unittest.skipUnless(INTEGRATION_TESTS, "integration test") - @pytest.mark.tag('integration') - def test_pattern_date(self): - """ - Test setting ilm pattern with date - """ - - pattern = "'{now/d}'" - self.render_config(ilm={"enabled": True, "pattern": pattern}) - - proc = self.start_beat() - self.wait_until(lambda: self.log_contains("mockbeat start running.")) - self.wait_until(lambda: self.log_contains(MSG_ILM_POLICY_LOADED)) - self.wait_until(lambda: self.log_contains("PublishEvents: 1 events have been published")) - proc.check_kill_and_wait() - - resolved_pattern = datetime.datetime.now().strftime("%Y.%m.%d") - - self.idxmgmt.assert_ilm_template_loaded(self.alias_name, self.policy_name, self.alias_name) - self.idxmgmt.assert_alias_created(self.alias_name, pattern=resolved_pattern) - self.idxmgmt.assert_docs_written_to_alias(self.alias_name, pattern=resolved_pattern) - class TestCommandSetupILMPolicy(BaseTest): """ @@ -168,46 +107,30 @@ def setUp(self): self.setupCmd = "--index-management" - self.alias_name = self.index_name = self.beat_name + "-9.9.9" + self.data_stream = self.beat_name + "-9.9.9" self.policy_name = self.beat_name - self.custom_alias = self.beat_name + "_foo" self.custom_policy = self.beat_name + "_bar" self.es = self.es_client() - self.idxmgmt = IdxMgmt(self.es, self.index_name) - self.idxmgmt.delete(indices=[self.custom_alias, self.index_name, self.custom_policy], - policies=[self.policy_name, self.custom_policy]) + self.idxmgmt = IdxMgmt(self.es, self.data_stream) + self.idxmgmt.delete(indices=[], + policies=[self.policy_name, self.custom_policy], + data_streams=[self.data_stream]) logging.getLogger("urllib3").setLevel(logging.WARNING) logging.getLogger("elasticsearch").setLevel(logging.ERROR) def tearDown(self): - self.idxmgmt.delete(indices=[self.custom_alias, self.index_name, self.custom_policy], - policies=[self.policy_name, self.custom_policy]) + self.idxmgmt.delete(indices=[], + policies=[self.policy_name, self.custom_policy], + data_streams=[self.data_stream]) def render_config(self, **kwargs): self.render_config_template( elasticsearch={"hosts": self.get_elasticsearch_url()}, - es_template_name=self.index_name, + es_template_name=self.data_stream, **kwargs ) - @unittest.skipUnless(INTEGRATION_TESTS, "integration test") - @pytest.mark.tag('integration') - def test_setup_ilm_policy_and_template(self): - """ - Test combination of ilm policy and template setup - """ - self.render_config() - - # NOTE: --template is deprecated for 8.0.0./ - exit_code = self.run_beat(logging_args=["-v", "-d", "*"], - extra_args=["setup", self.setupCmd, "--template"]) - - assert exit_code == 0 - self.idxmgmt.assert_ilm_template_loaded(self.alias_name, self.policy_name, self.alias_name) - self.idxmgmt.assert_alias_created(self.alias_name) - self.idxmgmt.assert_policy_created(self.policy_name) - @unittest.skipUnless(INTEGRATION_TESTS, "integration test") @pytest.mark.tag('integration') def test_setup_ilm_default(self): @@ -220,9 +143,7 @@ def test_setup_ilm_default(self): extra_args=["setup", self.setupCmd]) assert exit_code == 0 - self.idxmgmt.assert_ilm_template_loaded(self.alias_name, self.policy_name, self.alias_name) - self.idxmgmt.assert_index_template_index_pattern(self.alias_name, [self.alias_name + "-*"]) - self.idxmgmt.assert_alias_created(self.alias_name) + self.idxmgmt.assert_index_template_index_pattern(self.data_stream, [self.data_stream]) self.idxmgmt.assert_policy_created(self.policy_name) @unittest.skipUnless(INTEGRATION_TESTS, "integration test") @@ -238,8 +159,7 @@ def test_setup_ilm_disabled(self): "-E", "setup.ilm.enabled=false"]) assert exit_code == 0 - self.idxmgmt.assert_legacy_index_template_loaded(self.index_name) - self.idxmgmt.assert_alias_not_created(self.alias_name) + self.idxmgmt.assert_index_template_loaded(self.data_stream) self.idxmgmt.assert_policy_not_created(self.policy_name) @unittest.skipUnless(INTEGRATION_TESTS, "integration test") @@ -255,25 +175,9 @@ def test_policy_name(self): "-E", "setup.ilm.policy_name=" + self.custom_policy]) assert exit_code == 0 - self.idxmgmt.assert_ilm_template_loaded(self.alias_name, self.custom_policy, self.alias_name) + self.idxmgmt.assert_index_template_loaded(self.data_stream) self.idxmgmt.assert_policy_created(self.custom_policy) - @unittest.skipUnless(INTEGRATION_TESTS, "integration test") - @pytest.mark.tag('integration') - def test_rollover_alias(self): - """ - Test ilm policy setup when rollover_alias is configured - """ - self.render_config() - - exit_code = self.run_beat(logging_args=["-v", "-d", "*"], - extra_args=["setup", self.setupCmd, - "-E", "setup.ilm.rollover_alias=" + self.custom_alias]) - - assert exit_code == 0 - self.idxmgmt.assert_ilm_template_loaded(self.custom_alias, self.policy_name, self.custom_alias) - self.idxmgmt.assert_alias_created(self.custom_alias) - class TestCommandExportILMPolicy(BaseTest): """ @@ -294,9 +198,6 @@ def assert_log_contains_policy(self): assert self.log_contains('"max_age": "30d"') assert self.log_contains('"max_size": "50gb"') - def assert_log_contains_write_alias(self): - assert self.log_contains(re.compile('Index Alias .* successfully created.')) - def test_default(self): """ Test ilm-policy export with default config @@ -307,7 +208,6 @@ def test_default(self): assert exit_code == 0 self.assert_log_contains_policy() - self.assert_log_contains_write_alias() def test_load_disabled(self): """ @@ -319,7 +219,6 @@ def test_load_disabled(self): assert exit_code == 0 self.assert_log_contains_policy() - self.assert_log_contains_write_alias() def test_changed_policy_name(self): """ @@ -332,7 +231,6 @@ def test_changed_policy_name(self): assert exit_code == 0 self.assert_log_contains_policy() - self.assert_log_contains_write_alias() def test_export_to_file_absolute_path(self): """ diff --git a/libbeat/tests/system/test_logging.py b/libbeat/tests/system/test_logging.py index 4295bfd1776..4380e25b55c 100644 --- a/libbeat/tests/system/test_logging.py +++ b/libbeat/tests/system/test_logging.py @@ -39,11 +39,11 @@ def test_file_default(self): """ self.run_beat_with_args("Mockbeat is alive!", logging_args=[]) - self.assert_contains_ecs_log(logfile="logs/mockbeat") + self.assert_contains_ecs_log(logfile="logs/mockbeat-"+self.today+".ndjson") def test_file_ecs(self): """ logs to file with ECS format """ self.run_beat_with_args("Mockbeat is alive!") - self.assert_contains_ecs_log(logfile="logs/mockbeat") + self.assert_contains_ecs_log(logfile="logs/mockbeat-"+self.today+".ndjson") diff --git a/libbeat/tests/system/test_template.py b/libbeat/tests/system/test_template.py index cc80e284f4e..abed68332a8 100644 --- a/libbeat/tests/system/test_template.py +++ b/libbeat/tests/system/test_template.py @@ -110,7 +110,7 @@ def test_json_template(self): self.wait_until(lambda: self.log_contains('Template with name \\\"bla\\\" loaded.')) proc.check_kill_and_wait() - result = es.transport.perform_request('GET', '/_template/' + template_name) + result = es.transport.perform_request('GET', '/_index_template/' + template_name) assert len(result) == 1 def get_host(self): @@ -125,14 +125,14 @@ class TestRunTemplate(BaseTest): def setUp(self): super(TestRunTemplate, self).setUp() # auto-derived default settings, if nothing else is set - self.index_name = self.beat_name + "-9.9.9" + self.data_stream = self.beat_name + "-9.9.9" self.es = self.es_client() - self.idxmgmt = IdxMgmt(self.es, self.index_name) - self.idxmgmt.delete(indices=[self.index_name]) + self.idxmgmt = IdxMgmt(self.es, self.data_stream) + self.idxmgmt.delete(data_streams=[self.data_stream]) def tearDown(self): - self.idxmgmt.delete(indices=[self.index_name]) + self.idxmgmt.delete(data_streams=[self.data_stream]) def render_config(self, **kwargs): self.render_config_template( @@ -153,9 +153,8 @@ def test_template_default(self): self.wait_until(lambda: self.log_contains("PublishEvents: 1 events have been published")) proc.check_kill_and_wait() - self.idxmgmt.assert_ilm_template_loaded(self.index_name, self.beat_name, self.index_name) - self.idxmgmt.assert_alias_created(self.index_name) - self.idxmgmt.assert_docs_written_to_alias(self.index_name) + self.idxmgmt.assert_index_template_loaded(self.data_stream) + self.idxmgmt.assert_docs_written_to_data_stream(self.data_stream) @unittest.skipUnless(INTEGRATION_TESTS, "integration test") @pytest.mark.tag('integration') @@ -169,7 +168,7 @@ def test_template_disabled(self): self.wait_until(lambda: self.log_contains("PublishEvents: 1 events have been published")) proc.check_kill_and_wait() - self.idxmgmt.assert_index_template_not_loaded(self.index_name) + self.idxmgmt.assert_index_template_not_loaded(self.data_stream) class TestCommandSetupTemplate(BaseTest): @@ -181,19 +180,18 @@ def setUp(self): super(TestCommandSetupTemplate, self).setUp() # auto-derived default settings, if nothing else is set - self.setupCmd = "--template" - self.index_name = self.beat_name + "-9.9.9" - self.custom_alias = self.beat_name + "_foo" + self.setupCmd = "--index-management" + self.data_stream = self.beat_name + "-9.9.9" self.policy_name = self.beat_name self.es = self.es_client() - self.idxmgmt = IdxMgmt(self.es, self.index_name) - self.idxmgmt.delete(indices=[self.custom_alias, self.index_name], policies=[self.policy_name]) + self.idxmgmt = IdxMgmt(self.es, self.data_stream) + self.idxmgmt.delete(indices=[self.data_stream], policies=[self.policy_name]) logging.getLogger("urllib3").setLevel(logging.WARNING) logging.getLogger("elasticsearch").setLevel(logging.ERROR) def tearDown(self): - self.idxmgmt.delete(indices=[self.custom_alias, self.index_name], policies=[self.policy_name]) + self.idxmgmt.delete(indices=[self.data_stream], policies=[self.policy_name]) def render_config(self, **kwargs): self.render_config_template( @@ -209,11 +207,10 @@ def test_setup(self): """ self.render_config() exit_code = self.run_beat(logging_args=["-v", "-d", "*"], - extra_args=["setup", self.setupCmd, "--ilm-policy"]) + extra_args=["setup", self.setupCmd]) assert exit_code == 0 - self.idxmgmt.assert_ilm_template_loaded(self.index_name, self.policy_name, self.index_name) - self.idxmgmt.assert_alias_created(self.index_name) + self.idxmgmt.assert_index_template_loaded(self.data_stream) self.idxmgmt.assert_policy_created(self.policy_name) @unittest.skipUnless(INTEGRATION_TESTS, "integration test") @@ -227,12 +224,9 @@ def test_setup_template_default(self): extra_args=["setup", self.setupCmd]) assert exit_code == 0 - self.idxmgmt.assert_ilm_template_loaded(self.index_name, self.policy_name, self.index_name) - self.idxmgmt.assert_index_template_index_pattern(self.index_name, [self.index_name + "-*"]) + self.idxmgmt.assert_index_template_loaded(self.data_stream) + self.idxmgmt.assert_index_template_index_pattern(self.data_stream, [self.data_stream]) - # when running `setup --template` - # write_alias and rollover_policy related to ILM are also created - self.idxmgmt.assert_alias_created(self.index_name) self.idxmgmt.assert_policy_created(self.policy_name) @unittest.skipUnless(INTEGRATION_TESTS, "integration test") @@ -247,11 +241,8 @@ def test_setup_template_disabled(self): "-E", "setup.template.enabled=false"]) assert exit_code == 0 - self.idxmgmt.assert_index_template_not_loaded(self.index_name) + self.idxmgmt.assert_index_template_not_loaded(self.data_stream) - # when running `setup --template` and `setup.template.enabled=false` - # write_alias and rollover_policy related to ILM are still created - self.idxmgmt.assert_alias_created(self.index_name) self.idxmgmt.assert_policy_created(self.policy_name) @unittest.skipUnless(INTEGRATION_TESTS, "integration test") @@ -267,28 +258,17 @@ def test_setup_template_with_opts(self): "-E", "setup.template.settings.index.number_of_shards=2"]) assert exit_code == 0 - self.idxmgmt.assert_legacy_index_template_loaded(self.index_name) + self.idxmgmt.assert_index_template_loaded(self.data_stream) # check that settings are overwritten - resp = self.es.transport.perform_request('GET', '/_template/' + self.index_name) - assert self.index_name in resp - index = resp[self.index_name]["settings"]["index"] - assert index["number_of_shards"] == "2", index["number_of_shards"] - - @unittest.skipUnless(INTEGRATION_TESTS, "integration test") - @pytest.mark.tag('integration') - def test_setup_template_with_ilm_changed_pattern(self): - """ - Test template setup with changed ilm.rollover_alias config - """ - self.render_config() - exit_code = self.run_beat(logging_args=["-v", "-d", "*"], - extra_args=["setup", self.setupCmd, - "-E", "setup.ilm.rollover_alias=" + self.custom_alias]) - - assert exit_code == 0 - self.idxmgmt.assert_ilm_template_loaded(self.custom_alias, self.policy_name, self.custom_alias) - self.idxmgmt.assert_index_template_index_pattern(self.custom_alias, [self.custom_alias + "-*"]) + resp = self.es.transport.perform_request('GET', '/_index_template/' + self.data_stream) + found = False + for index_template in resp["index_templates"]: + if self.data_stream == index_template["name"]: + found = True + index = index_template["index_template"]["template"]["settings"]["index"] + assert index["number_of_shards"] == "2", index["number_of_shards"] + assert found @unittest.skipUnless(INTEGRATION_TESTS, "integration test") @pytest.mark.tag('integration') @@ -297,58 +277,20 @@ def test_template_created_on_ilm_policy_created(self): Test template setup overwrites template when new ilm policy is created """ - # ensure template with ilm rollover_alias name is created, but ilm policy not yet self.render_config() exit_code = self.run_beat(logging_args=["-v", "-d", "*"], extra_args=["setup", self.setupCmd, - "-E", "setup.ilm.enabled=false", - "-E", "setup.template.name=" + self.custom_alias, - "-E", "setup.template.pattern=" + self.custom_alias + "*"]) + "-E", "setup.ilm.enabled=false"]) assert exit_code == 0 - self.idxmgmt.assert_legacy_index_template_loaded(self.custom_alias) + self.idxmgmt.assert_index_template_loaded(self.data_stream) self.idxmgmt.assert_policy_not_created(self.policy_name) # ensure ilm policy is created, triggering overwriting existing template exit_code = self.run_beat(extra_args=["setup", self.setupCmd, "-E", "setup.template.overwrite=false", - "-E", "setup.template.settings.index.number_of_shards=2", - "-E", "setup.ilm.rollover_alias=" + self.custom_alias]) + "-E", "setup.template.settings.index.number_of_shards=2"]) assert exit_code == 0 - self.idxmgmt.assert_ilm_template_loaded(self.custom_alias, self.policy_name, self.custom_alias) self.idxmgmt.assert_policy_created(self.policy_name) - # check that template was overwritten - resp = self.es.transport.perform_request('GET', '/_template/' + self.custom_alias) - assert self.custom_alias in resp - index = resp[self.custom_alias]["settings"]["index"] - assert index["number_of_shards"] == "2", index["number_of_shards"] - - @unittest.skipUnless(INTEGRATION_TESTS, "integration test") - @pytest.mark.tag('integration') - def test_setup_template_index(self): - """ - Test template setup of new index templates - """ - self.render_config() - exit_code = self.run_beat(logging_args=["-v", "-d", "*"], - extra_args=["setup", self.setupCmd, - "-E", "setup.template.type=index"]) - - assert exit_code == 0 - self.idxmgmt.assert_index_template_loaded(self.index_name) - - @unittest.skipUnless(INTEGRATION_TESTS, "integration test") - @pytest.mark.tag('integration') - def test_setup_template_component(self): - """ - Test template setup of component index templates - """ - self.render_config() - exit_code = self.run_beat(logging_args=["-v", "-d", "*"], - extra_args=["setup", self.setupCmd, - "-E", "setup.template.type=component"]) - - assert exit_code == 0 - self.idxmgmt.assert_component_template_loaded(self.index_name) class TestCommandExportTemplate(BaseTest): @@ -379,23 +321,7 @@ def test_default(self): config=self.config) assert exit_code == 0 - self.assert_log_contains_template(self.template_name + "-*") - - def test_changed_index_pattern(self): - """ - Test export template with changed index pattern - """ - self.render_config_template(self.beat_name, self.output, - fields=self.output) - alias_name = "mockbeat-ilm-index-pattern" - - exit_code = self.run_beat( - extra_args=["export", "template", - "-E", "setup.ilm.rollover_alias=" + alias_name], - config=self.config) - - assert exit_code == 0 - self.assert_log_contains_template(alias_name + "-*") + self.assert_log_contains_template(self.template_name) def test_load_disabled(self): """ @@ -408,7 +334,7 @@ def test_load_disabled(self): config=self.config) assert exit_code == 0 - self.assert_log_contains_template(self.template_name + "-*") + self.assert_log_contains_template(self.template_name) def test_export_to_file_absolute_path(self): """ @@ -428,7 +354,7 @@ def test_export_to_file_absolute_path(self): with open(file) as f: template = json.load(f) assert 'index_patterns' in template - assert template['index_patterns'] == [self.template_name + '-*'], template + assert template['index_patterns'] == [self.template_name], template os.remove(file) @@ -451,6 +377,6 @@ def test_export_to_file_relative_path(self): with open(file) as f: template = json.load(f) assert 'index_patterns' in template - assert template['index_patterns'] == [self.template_name + '-*'], template + assert template['index_patterns'] == [self.template_name], template os.remove(file) diff --git a/libbeat/tests/system/test_umask.py b/libbeat/tests/system/test_umask.py index e78214e2d9c..d6a7b7f391c 100644 --- a/libbeat/tests/system/test_umask.py +++ b/libbeat/tests/system/test_umask.py @@ -30,7 +30,7 @@ def test_output_file_perms(self): """ Test that output file permissions respect default umask """ - output_file_path = os.path.join(self.working_dir, "output", "mockbeat") + output_file_path = os.path.join(self.working_dir, "output", "mockbeat-" + self.today + ".ndjson") perms = stat.S_IMODE(os.lstat(output_file_path).st_mode) self.assertEqual(perms, self.output_file_permissions & ~TestUmask.DEFAULT_UMASK) diff --git a/metricbeat/Dockerfile b/metricbeat/Dockerfile index 0e9f1d08d14..e1c97b72d36 100644 --- a/metricbeat/Dockerfile +++ b/metricbeat/Dockerfile @@ -1,8 +1,8 @@ -FROM golang:1.17.2 +FROM golang:1.17.5 RUN \ apt update \ - && apt install -qq -y --no-install-recommends \ + && DEBIAN_FRONTEND=noninteractive apt-get install -qq -y --no-install-recommends \ netcat \ python3 \ python3-dev \ diff --git a/metricbeat/Jenkinsfile.yml b/metricbeat/Jenkinsfile.yml index 3a66f3e29a7..e7ce5009caf 100644 --- a/metricbeat/Jenkinsfile.yml +++ b/metricbeat/Jenkinsfile.yml @@ -38,7 +38,7 @@ stages: macos: mage: "mage build unitTest" platforms: ## override default label in this specific stage. - - "macosx&&x86_64" + - "orka && darwin && poc" when: ## Override the top-level when. comments: - "/test metricbeat for macos" diff --git a/metricbeat/docs/fields.asciidoc b/metricbeat/docs/fields.asciidoc index 9e2489352e1..2a866020d37 100644 --- a/metricbeat/docs/fields.asciidoc +++ b/metricbeat/docs/fields.asciidoc @@ -6736,7 +6736,7 @@ alias to: beat.stats.apm_server.acm.response.errors.unauthorized -- type: alias -alias to: beat.stats.beat.host +alias to: beat.stats.info.host -- @@ -6745,7 +6745,7 @@ alias to: beat.stats.beat.host -- type: alias -alias to: beat.stats.beat.name +alias to: beat.stats.info.name -- @@ -6754,7 +6754,7 @@ alias to: beat.stats.beat.name -- type: alias -alias to: beat.stats.beat.type +alias to: beat.stats.info.type -- @@ -6763,7 +6763,7 @@ alias to: beat.stats.beat.type -- type: alias -alias to: beat.stats.beat.uuid +alias to: beat.stats.info.uuid -- @@ -6772,7 +6772,7 @@ alias to: beat.stats.beat.uuid -- type: alias -alias to: beat.stats.beat.version +alias to: beat.stats.info.version -- @@ -7535,6 +7535,13 @@ type: keyword -- +*`beat.elasticsearch.cluster.id`*:: ++ +-- +type: keyword + +-- + [float] === state @@ -8273,6 +8280,42 @@ type: long -- +*`beat.stats.info.name`*:: ++ +-- +type: keyword + +-- + +*`beat.stats.info.host`*:: ++ +-- +type: keyword + +-- + +*`beat.stats.info.type`*:: ++ +-- +type: keyword + +-- + +*`beat.stats.info.uuid`*:: ++ +-- +type: keyword + +-- + +*`beat.stats.info.version`*:: ++ +-- +type: keyword + +-- + + *`beat.stats.beat.name`*:: + -- @@ -8671,6 +8714,13 @@ type: short -- +*`beat.stats.libbeat.config.reloads`*:: ++ +-- +type: short + +-- + [float] === output @@ -40612,6 +40662,13 @@ alias to: service.id -- +*`kibana.elasticsearch.cluster.id`*:: ++ +-- +type: keyword + +-- + [float] === settings @@ -41165,47 +41222,16 @@ type: ip -- - -*`kubernetes.namespace.name`*:: -+ --- -Kubernetes namespace name - - -type: keyword - --- - -*`kubernetes.namespace.uuid`*:: +*`kubernetes.namespace`*:: + -- -Kubernetes namespace uuid +Kubernetes namespace type: keyword -- -*`kubernetes.namespace.labels.*`*:: -+ --- -Kubernetes namespace labels map - - -type: object - --- - -*`kubernetes.namespace.annotations.*`*:: -+ --- -Kubernetes namespace annotations map - - -type: object - --- - *`kubernetes.node.name`*:: + -- @@ -41954,6 +41980,18 @@ format: bytes -- +*`kubernetes.container.memory.workingset.limit.pct`*:: ++ +-- +Working set memory usage as a percentage of the defined limit for the container (or total node allocatable memory if unlimited) + + +type: scaled_float + +format: percent + +-- + *`kubernetes.container.memory.pagefaults`*:: + -- @@ -43018,6 +43056,18 @@ format: bytes -- +*`kubernetes.pod.memory.working_set.limit.pct`*:: ++ +-- +Working set memory usage as a percentage of the defined limit for the pod containers (or total node allocatable memory if unlimited) + + +type: scaled_float + +format: percent + +-- + *`kubernetes.pod.memory.rss.bytes`*:: + @@ -46275,6 +46325,13 @@ alias to: logstash.node.state.pipeline.hash -- +*`logstash.elasticsearch.cluster.id`*:: ++ +-- +type: keyword + +-- + [float] === node diff --git a/metricbeat/docs/getting-started.asciidoc b/metricbeat/docs/getting-started.asciidoc index a300cb43c98..9cd837dfc42 100644 --- a/metricbeat/docs/getting-started.asciidoc +++ b/metricbeat/docs/getting-started.asciidoc @@ -1,4 +1,4 @@ -:modulename: apache mysql +:modulename: nginx [id="{beatname_lc}-installation-configuration"] == {beatname_uc} quick start: installation and configuration @@ -82,8 +82,8 @@ include::{libbeat-dir}/tab-widgets/list-modules-widget.asciidoc[] default configuration without enabling additional modules, {beatname_uc} collects system metrics only. + -The following command enables the `apache` and `mysql` configs in the -`modules.d` directory: +The following command enables the +{modulename}+ config in the `modules.d` +directory: + -- include::{libbeat-dir}/tab-widgets/enable-modules-widget.asciidoc[] @@ -92,7 +92,7 @@ include::{libbeat-dir}/tab-widgets/enable-modules-widget.asciidoc[] See the <> to learn more about this command. If you are using a Docker image, see <>. -. In the module configs under `modules.d`, change the module settings to match +. In the module config under `modules.d`, change the module settings to match your environment. See <> for more about available settings. diff --git a/metricbeat/docs/modules/aws.asciidoc b/metricbeat/docs/modules/aws.asciidoc index 75991b5bd09..e0fa06851e5 100644 --- a/metricbeat/docs/modules/aws.asciidoc +++ b/metricbeat/docs/modules/aws.asciidoc @@ -68,6 +68,24 @@ If endpoint is specified, `regions` config becomes required. For example: - ec2 ---- +* *fips_enabled* + +Enforces the use of FIPS service endpoints. See <> for more information. + +[source,yaml] +---- +- module: aws + period: 5m + fips_enabled: true + regions: + - us-east-1 + - us-east-2 + - us-west-1 + - us-west-2 + metricsets: + - ec2 +---- + The aws module comes with a predefined dashboard. For example: image::./images/metricbeat-aws-overview.png[] diff --git a/metricbeat/docs/modules/kubernetes.asciidoc b/metricbeat/docs/modules/kubernetes.asciidoc index e7b82455189..e237f16781b 100644 --- a/metricbeat/docs/modules/kubernetes.asciidoc +++ b/metricbeat/docs/modules/kubernetes.asciidoc @@ -155,7 +155,7 @@ roleRef: === Compatibility The Kubernetes module is tested with the following versions of Kubernetes: -1.14.x, 1.17.x, 1.18.x, 1.19.x, 1.20.x, 1.21.x +1.18.x, 1.19.x, 1.20.x, 1.21.x, 1.22.x, 1.23.x [float] === Dashboard @@ -222,6 +222,16 @@ metricbeat.modules: # If kube_config is not set, KUBECONFIG environment variable will be checked # and if not present it will fall back to InCluster #kube_config: ~/.kube/config + # To configure additionally node and namespace metadata, added to pod, service and container resource types, + # `add_resource_metadata` can be defined. + # By default all labels will be included while annotations are not added by default. + # add_resource_metadata: + # namespace: + # include_labels: ["namespacelabel1"] + # node: + # include_labels: ["nodelabel2"] + # include_annotations: ["nodeannotation1"] + # deployment: false # Kubernetes client QPS and burst can be configured additionally #kube_client_options: # qps: 5 @@ -256,6 +266,38 @@ metricbeat.modules: # If kube_config is not set, KUBECONFIG environment variable will be checked # and if not present it will fall back to InCluster #kube_config: ~/.kube/config + # To configure additionally node and namespace metadata, added to pod, service and container resource types, + # `add_resource_metadata` can be defined. + # By default all labels will be included while annotations are not added by default. + # add_resource_metadata: + # namespace: + # include_labels: ["namespacelabel1"] + # node: + # include_labels: ["nodelabel2"] + # include_annotations: ["nodeannotation1"] + # deployment: false + # Kubernetes client QPS and burst can be configured additionally + #kube_client_options: + # qps: 5 + # burst: 10 + +# Kubernetes Events +- module: kubernetes + enabled: true + metricsets: + - event + period: 10s + # Skip events older than Metricbeat's statup time is enabled by default. + # Setting to false the skip_older setting will stop filtering older events. + # This setting is also useful went Event's timestamps are not populated properly. + #skip_older: false + # If kube_config is not set, KUBECONFIG environment variable will be checked + # and if not present it will fall back to InCluster + #kube_config: ~/.kube/config + # Set the namespace to watch for events + #namespace: staging + # Set the sync period of the watchers + #sync_period: 10m # Kubernetes client QPS and burst can be configured additionally #kube_client_options: # qps: 5 @@ -273,8 +315,6 @@ metricbeat.modules: - /var/run/secrets/kubernetes.io/serviceaccount/ca.crt period: 30s - - # Kubernetes proxy server # (when running metricbeat locally at hosts or as a daemonset + host network) - module: kubernetes diff --git a/metricbeat/docs/modules/system.asciidoc b/metricbeat/docs/modules/system.asciidoc index 61498eb9932..225285b3264 100644 --- a/metricbeat/docs/modules/system.asciidoc +++ b/metricbeat/docs/modules/system.asciidoc @@ -185,7 +185,7 @@ metricbeat.modules: processes: ['.*'] # Configure the mount point of the host’s filesystem for use in monitoring a host from within a container - #system.hostfs: "/hostfs" + #hostfs: "/hostfs" # Configure the metric types that are included by these metricsets. cpu.metrics: ["percentages","normalized_percentages"] # The other available option is ticks. diff --git a/metricbeat/docs/running-on-docker.asciidoc b/metricbeat/docs/running-on-docker.asciidoc index c51f1314bee..cc7c8c5b650 100644 --- a/metricbeat/docs/running-on-docker.asciidoc +++ b/metricbeat/docs/running-on-docker.asciidoc @@ -28,16 +28,16 @@ are isolated as much as possible from the host, the data inside of the container's `/proc` is different than the host's `/proc`. To account for this, you can mount the host's `/proc` filesystem inside of the container and tell Metricbeat to look inside the `/hostfs` directory when looking for `/proc` by -using the `-system.hostfs=/hostfs` CLI flag. +using the `hostfs=/hostfs` config value. <2> By default, cgroup reporting is enabled for the <>, so you need to mount the host's cgroup mountpoints within the container. They need to be -mounted inside the directory specified by the `-system.hostfs` CLI flag. +mounted inside the directory specified by the `hostfs` config value. <3> If you want to be able to monitor filesystems from the host by using the <>, then those filesystems need to be mounted inside of the container. They can be mounted at any location. <4> The <> uses data from `/proc/net/dev`, or -`/hostfs/proc/net/dev` when using `-system.hostfs=/hostfs`. The only way +`/hostfs/proc/net/dev` when using `hostfs=/hostfs`. The only way to make this file contain the host's network devices is to use the `--net=host` flag. This is due to Linux namespacing; simply bind mounting the host's `/proc` to `/hostfs/proc` is not sufficient. diff --git a/metricbeat/helper/elastic/elastic.go b/metricbeat/helper/elastic/elastic.go index 81216bb0e39..837ff615064 100644 --- a/metricbeat/helper/elastic/elastic.go +++ b/metricbeat/helper/elastic/elastic.go @@ -79,7 +79,7 @@ func (p Product) String() string { // MakeXPackMonitoringIndexName method returns the name of the monitoring index for // a given product { elasticsearch, kibana, logstash, beats } func MakeXPackMonitoringIndexName(product Product) string { - const version = "7" + const version = "8" return fmt.Sprintf(".monitoring-%v-%v-mb", product.xPackMonitoringIndexString(), version) } diff --git a/metricbeat/helper/elastic/elastic_test.go b/metricbeat/helper/elastic/elastic_test.go index 26f6d4723d5..57f62d0d4d8 100644 --- a/metricbeat/helper/elastic/elastic_test.go +++ b/metricbeat/helper/elastic/elastic_test.go @@ -38,22 +38,22 @@ func TestMakeXPackMonitoringIndexName(t *testing.T) { { "Elasticsearch monitoring index", Elasticsearch, - ".monitoring-es-7-mb", + ".monitoring-es-8-mb", }, { "Kibana monitoring index", Kibana, - ".monitoring-kibana-7-mb", + ".monitoring-kibana-8-mb", }, { "Logstash monitoring index", Logstash, - ".monitoring-logstash-7-mb", + ".monitoring-logstash-8-mb", }, { "Beats monitoring index", Beats, - ".monitoring-beats-7-mb", + ".monitoring-beats-8-mb", }, } diff --git a/metricbeat/helper/server/udp/udp.go b/metricbeat/helper/server/udp/udp.go index e19f8697519..6bec8489b46 100644 --- a/metricbeat/helper/server/udp/udp.go +++ b/metricbeat/helper/server/udp/udp.go @@ -71,6 +71,10 @@ func NewUdpServer(base mb.BaseMetricSet) (server.Server, error) { }, nil } +func (g *UdpServer) GetHost() string { + return g.udpaddr.String() +} + func (g *UdpServer) Start() error { listener, err := net.ListenUDP("udp", g.udpaddr) if err != nil { diff --git a/metricbeat/include/fields/fields.go b/metricbeat/include/fields/fields.go index f3cf04b8ba1..ff66aa3b03c 100644 --- a/metricbeat/include/fields/fields.go +++ b/metricbeat/include/fields/fields.go @@ -32,5 +32,5 @@ func init() { // AssetFieldsYml returns asset data. // This is the base64 encoded zlib format compressed contents of fields.yml. func AssetFieldsYml() string { - return "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" + return "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" } diff --git a/metricbeat/internal/metrics/cpu/metrics.go b/metricbeat/internal/metrics/cpu/metrics.go index 931111f1bfe..75fa38d62d7 100644 --- a/metricbeat/internal/metrics/cpu/metrics.go +++ b/metricbeat/internal/metrics/cpu/metrics.go @@ -21,6 +21,7 @@ import ( "github.com/pkg/errors" "github.com/elastic/beats/v7/libbeat/common" + "github.com/elastic/beats/v7/libbeat/metric/system/resolve" "github.com/elastic/beats/v7/libbeat/opt" ) @@ -69,12 +70,12 @@ calculate CPU percentages, as we average usage across a time period. // Monitor is used to monitor the overall CPU usage of the system over time. type Monitor struct { lastSample CPUMetrics - Hostfs string + Hostfs resolve.Resolver } // New returns a new CPU metrics monitor // Hostfs is only relevant on linux and freebsd. -func New(hostfs string) *Monitor { +func New(hostfs resolve.Resolver) *Monitor { return &Monitor{Hostfs: hostfs} } diff --git a/metricbeat/internal/metrics/cpu/metrics_aix.go b/metricbeat/internal/metrics/cpu/metrics_aix.go index a746e1bd0b2..022e69ea601 100644 --- a/metricbeat/internal/metrics/cpu/metrics_aix.go +++ b/metricbeat/internal/metrics/cpu/metrics_aix.go @@ -38,6 +38,7 @@ import ( "github.com/pkg/errors" + "github.com/elastic/beats/v7/libbeat/metric/system/resolve" "github.com/elastic/beats/v7/libbeat/opt" ) @@ -59,7 +60,7 @@ func tick2msec(val uint64) uint64 { } // Get returns a metrics object for CPU data -func Get(_ string) (CPUMetrics, error) { +func Get(_ resolve.Resolver) (CPUMetrics, error) { totals, err := getCPUTotals() if err != nil { diff --git a/metricbeat/internal/metrics/cpu/metrics_darwin.go b/metricbeat/internal/metrics/cpu/metrics_darwin.go index 6e18bb70761..7fe680687df 100644 --- a/metricbeat/internal/metrics/cpu/metrics_darwin.go +++ b/metricbeat/internal/metrics/cpu/metrics_darwin.go @@ -21,11 +21,12 @@ import ( "github.com/pkg/errors" "github.com/shirou/gopsutil/cpu" + "github.com/elastic/beats/v7/libbeat/metric/system/resolve" "github.com/elastic/beats/v7/libbeat/opt" ) // Get is the Darwin implementation of Get -func Get(_ string) (CPUMetrics, error) { +func Get(_ resolve.Resolver) (CPUMetrics, error) { // We're using the gopsutil library here. // The code used by both gosigar and go-sysinfo appears to be // the same code as gopsutil, including copy-pasted comments. diff --git a/metricbeat/internal/metrics/cpu/metrics_openbsd.go b/metricbeat/internal/metrics/cpu/metrics_openbsd.go index b0d386bc3fe..15969d906da 100644 --- a/metricbeat/internal/metrics/cpu/metrics_openbsd.go +++ b/metricbeat/internal/metrics/cpu/metrics_openbsd.go @@ -36,11 +36,12 @@ import ( "syscall" "unsafe" + "github.com/elastic/beats/v7/libbeat/metric/system/resolve" "github.com/elastic/beats/v7/libbeat/opt" ) // Get is the OpenBSD implementation of get -func Get(_ string) (CPUMetrics, error) { +func Get(_ resolve.Resolver) (CPUMetrics, error) { // see man 2 sysctl loadGlobal := [C.CPUSTATES]C.long{ diff --git a/metricbeat/internal/metrics/cpu/metrics_procfs_common.go b/metricbeat/internal/metrics/cpu/metrics_procfs_common.go index 3d5b36b5d74..be86cb1213c 100644 --- a/metricbeat/internal/metrics/cpu/metrics_procfs_common.go +++ b/metricbeat/internal/metrics/cpu/metrics_procfs_common.go @@ -23,16 +23,18 @@ package cpu import ( "bufio" "os" - "path/filepath" "strconv" "github.com/pkg/errors" + + "github.com/elastic/beats/v7/libbeat/metric/system/resolve" ) // Get returns a metrics object for CPU data -func Get(procfs string) (CPUMetrics, error) { - path := filepath.Join(procfs, "/proc/stat") +func Get(procfs resolve.Resolver) (CPUMetrics, error) { + path := procfs.ResolveHostFS("/proc/stat") fd, err := os.Open(path) + defer fd.Close() if err != nil { return CPUMetrics{}, errors.Wrapf(err, "error opening file %s", path) } diff --git a/metricbeat/internal/metrics/cpu/metrics_test.go b/metricbeat/internal/metrics/cpu/metrics_test.go index 3a89afe6b80..91a3f302375 100644 --- a/metricbeat/internal/metrics/cpu/metrics_test.go +++ b/metricbeat/internal/metrics/cpu/metrics_test.go @@ -23,11 +23,12 @@ import ( "github.com/stretchr/testify/assert" "github.com/elastic/beats/v7/libbeat/common" + "github.com/elastic/beats/v7/libbeat/metric/system/resolve" "github.com/elastic/beats/v7/libbeat/opt" ) func TestMonitorSample(t *testing.T) { - cpu := &Monitor{lastSample: CPUMetrics{}} + cpu := &Monitor{lastSample: CPUMetrics{}, Hostfs: resolve.NewTestResolver("")} s, err := cpu.Fetch() if err != nil { t.Fatal(err) @@ -40,10 +41,10 @@ func TestMonitorSample(t *testing.T) { func TestCoresMonitorSample(t *testing.T) { - cpuMetrics, err := Get("") + cpuMetrics, err := Get(resolve.NewTestResolver("")) assert.NoError(t, err, "error in Get()") - cores := &Monitor{lastSample: CPUMetrics{list: make([]CPU, len(cpuMetrics.list))}} + cores := &Monitor{lastSample: CPUMetrics{list: make([]CPU, len(cpuMetrics.list))}, Hostfs: resolve.NewTestResolver("")} sample, err := cores.FetchCores() if err != nil { t.Fatal(err) diff --git a/metricbeat/internal/metrics/cpu/metrics_windows.go b/metricbeat/internal/metrics/cpu/metrics_windows.go index d9e4abca19a..7e0a258aa06 100644 --- a/metricbeat/internal/metrics/cpu/metrics_windows.go +++ b/metricbeat/internal/metrics/cpu/metrics_windows.go @@ -27,12 +27,13 @@ import ( "github.com/pkg/errors" + "github.com/elastic/beats/v7/libbeat/metric/system/resolve" "github.com/elastic/beats/v7/libbeat/opt" "github.com/elastic/gosigar/sys/windows" ) // Get fetches Windows CPU system times -func Get(_ string) (CPUMetrics, error) { +func Get(_ resolve.Resolver) (CPUMetrics, error) { idle, kernel, user, err := windows.GetSystemTimes() if err != nil { return CPUMetrics{}, errors.Wrap(err, "GetSystemTimes failed") diff --git a/metricbeat/internal/metrics/memory/memory.go b/metricbeat/internal/metrics/memory/memory.go index eb00ca80202..79efbdd825e 100644 --- a/metricbeat/internal/metrics/memory/memory.go +++ b/metricbeat/internal/metrics/memory/memory.go @@ -21,6 +21,7 @@ import ( "github.com/pkg/errors" "github.com/elastic/beats/v7/libbeat/common" + "github.com/elastic/beats/v7/libbeat/metric/system/resolve" "github.com/elastic/beats/v7/libbeat/opt" ) @@ -65,7 +66,7 @@ type SwapMetrics struct { } // Get returns platform-independent memory metrics. -func Get(procfs string) (Memory, error) { +func Get(procfs resolve.Resolver) (Memory, error) { base, err := get(procfs) if err != nil { return Memory{}, errors.Wrap(err, "error getting system memory info") diff --git a/metricbeat/internal/metrics/memory/memory_aix.go b/metricbeat/internal/metrics/memory/memory_aix.go index ce31e205a92..326b01e8125 100644 --- a/metricbeat/internal/metrics/memory/memory_aix.go +++ b/metricbeat/internal/metrics/memory/memory_aix.go @@ -36,6 +36,7 @@ import ( "fmt" "os" + "github.com/elastic/beats/v7/libbeat/metric/system/resolve" "github.com/elastic/beats/v7/libbeat/opt" ) @@ -51,7 +52,7 @@ func init() { system.pagesize = uint64(os.Getpagesize()) } -func get(_ string) (Memory, error) { +func get(_ resolve.Resolver) (Memory, error) { memData := Memory{} meminfo := C.perfstat_memory_total_t{} _, err := C.perfstat_memory_total(nil, &meminfo, C.sizeof_perfstat_memory_total_t, 1) diff --git a/metricbeat/internal/metrics/memory/memory_darwin.go b/metricbeat/internal/metrics/memory/memory_darwin.go index 95c5ab4b8fe..dac04d070ea 100644 --- a/metricbeat/internal/metrics/memory/memory_darwin.go +++ b/metricbeat/internal/metrics/memory/memory_darwin.go @@ -39,6 +39,7 @@ import ( "github.com/pkg/errors" + "github.com/elastic/beats/v7/libbeat/metric/system/resolve" "github.com/elastic/beats/v7/libbeat/opt" ) @@ -47,7 +48,7 @@ type xswUsage struct { } // get is the darwin implementation for fetching Memory data -func get(_ string) (Memory, error) { +func get(_ resolve.Resolver) (Memory, error) { var vmstat C.vm_statistics_data_t mem := Memory{} diff --git a/metricbeat/internal/metrics/memory/memory_freebsd.go b/metricbeat/internal/metrics/memory/memory_freebsd.go index 7103e521ab3..007e5ef21b3 100644 --- a/metricbeat/internal/metrics/memory/memory_freebsd.go +++ b/metricbeat/internal/metrics/memory/memory_freebsd.go @@ -22,6 +22,7 @@ import ( "github.com/pkg/errors" + "github.com/elastic/beats/v7/libbeat/metric/system/resolve" "github.com/elastic/beats/v7/libbeat/opt" ) @@ -38,7 +39,7 @@ import ( */ import "C" -func get(_ string) (Memory, error) { +func get(_ resolve.Resolver) (Memory, error) { val := C.uint32_t(0) sc := C.size_t(4) diff --git a/metricbeat/internal/metrics/memory/memory_helpers.go b/metricbeat/internal/metrics/memory/memory_helpers.go index 0761e910146..c935837d88f 100644 --- a/metricbeat/internal/metrics/memory/memory_helpers.go +++ b/metricbeat/internal/metrics/memory/memory_helpers.go @@ -22,18 +22,19 @@ import ( "bytes" "io" "io/ioutil" - "path/filepath" "strconv" "strings" "github.com/pkg/errors" + + "github.com/elastic/beats/v7/libbeat/metric/system/resolve" ) // ParseMeminfo parses the contents of /proc/meminfo into a hashmap -func ParseMeminfo(rootfs string) (map[string]uint64, error) { +func ParseMeminfo(rootfs resolve.Resolver) (map[string]uint64, error) { table := map[string]uint64{} - meminfoPath := filepath.Join(rootfs, "/proc/meminfo") + meminfoPath := rootfs.ResolveHostFS("/proc/meminfo") err := readFile(meminfoPath, func(line string) bool { fields := strings.Split(line, ":") diff --git a/metricbeat/internal/metrics/memory/memory_linux.go b/metricbeat/internal/metrics/memory/memory_linux.go index e90c153e531..2aad8b36711 100644 --- a/metricbeat/internal/metrics/memory/memory_linux.go +++ b/metricbeat/internal/metrics/memory/memory_linux.go @@ -20,11 +20,12 @@ package memory import ( "github.com/pkg/errors" + "github.com/elastic/beats/v7/libbeat/metric/system/resolve" "github.com/elastic/beats/v7/libbeat/opt" ) // get is the linux implementation for fetching Memory data -func get(rootfs string) (Memory, error) { +func get(rootfs resolve.Resolver) (Memory, error) { table, err := ParseMeminfo(rootfs) if err != nil { return Memory{}, errors.Wrap(err, "error fetching meminfo") diff --git a/metricbeat/internal/metrics/memory/memory_openbsd.go b/metricbeat/internal/metrics/memory/memory_openbsd.go index 05be4800810..addc33e8875 100644 --- a/metricbeat/internal/metrics/memory/memory_openbsd.go +++ b/metricbeat/internal/metrics/memory/memory_openbsd.go @@ -35,6 +35,7 @@ import ( "github.com/pkg/errors" + "github.com/elastic/beats/v7/libbeat/metric/system/resolve" "github.com/elastic/beats/v7/libbeat/opt" ) @@ -157,7 +158,7 @@ type Swapent struct { sw_path []byte } -func get(_ string) (Memory, error) { +func get(_ resolve.Resolver) (Memory, error) { memData := Memory{} diff --git a/metricbeat/internal/metrics/memory/memory_test.go b/metricbeat/internal/metrics/memory/memory_test.go index e9e0bb63f3c..4c9c979fdce 100644 --- a/metricbeat/internal/metrics/memory/memory_test.go +++ b/metricbeat/internal/metrics/memory/memory_test.go @@ -27,11 +27,12 @@ import ( "github.com/stretchr/testify/assert" + "github.com/elastic/beats/v7/libbeat/metric/system/resolve" "github.com/elastic/beats/v7/libbeat/opt" ) func TestGetMemory(t *testing.T) { - mem, err := Get("") + mem, err := Get(resolve.NewTestResolver("")) assert.NotNil(t, mem) assert.NoError(t, err) @@ -57,7 +58,7 @@ func TestGetSwap(t *testing.T) { return //no load data on freebsd } - mem, err := Get("") + mem, err := Get(resolve.NewTestResolver("")) assert.NotNil(t, mem) assert.NoError(t, err) @@ -105,7 +106,7 @@ func TestActualMemPercentage(t *testing.T) { func TestMeminfoParse(t *testing.T) { // Make sure we're manually calculating Actual correctly on linux if runtime.GOOS == "linux" { - mem, err := Get("./oldkern") + mem, err := Get(resolve.NewTestResolver("./oldkern")) assert.NoError(t, err) assert.Equal(t, uint64(27307106304), mem.Cached.ValueOr(0)) @@ -116,7 +117,7 @@ func TestMeminfoParse(t *testing.T) { func TestMeminfoPct(t *testing.T) { if runtime.GOOS == "linux" { - memRaw, err := Get("./oldkern") + memRaw, err := Get(resolve.NewTestResolver("./oldkern")) assert.NoError(t, err) assert.Equal(t, float64(0.1606), memRaw.Actual.Used.Pct.ValueOr(0)) assert.Equal(t, float64(0.5933), memRaw.Used.Pct.ValueOr(0)) diff --git a/metricbeat/internal/metrics/memory/memory_windows.go b/metricbeat/internal/metrics/memory/memory_windows.go index 0138825c139..be0f003552e 100644 --- a/metricbeat/internal/metrics/memory/memory_windows.go +++ b/metricbeat/internal/metrics/memory/memory_windows.go @@ -20,12 +20,13 @@ package memory import ( "github.com/pkg/errors" + "github.com/elastic/beats/v7/libbeat/metric/system/resolve" "github.com/elastic/beats/v7/libbeat/opt" "github.com/elastic/go-windows" ) // get is the windows implementation of get for memory metrics -func get(_ string) (Memory, error) { +func get(_ resolve.Resolver) (Memory, error) { memData := Memory{} diff --git a/metricbeat/internal/sysinit/init.go b/metricbeat/internal/sysinit/init.go new file mode 100644 index 00000000000..203ccd4b0db --- /dev/null +++ b/metricbeat/internal/sysinit/init.go @@ -0,0 +1,112 @@ +// Licensed to Elasticsearch B.V. under one or more contributor +// license agreements. See the NOTICE file distributed with +// this work for additional information regarding copyright +// ownership. Elasticsearch B.V. licenses this file to you 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 sysinit + +import ( + "flag" + "sync" + + "github.com/elastic/beats/v7/libbeat/common/cfgwarn" + "github.com/elastic/beats/v7/libbeat/common/fleetmode" + "github.com/elastic/beats/v7/libbeat/logp" + "github.com/elastic/beats/v7/metricbeat/mb" +) + +var hostfsCLI = flag.String("system.hostfs", "", "Mount point of the host's filesystem for use in monitoring a host from within a container") + +var once sync.Once + +// A wrapper library that allows us to deal with the more complex HostFS setter logic required for legacy metricbeat code. +// This will serve as a generic init function for either the system or linux module. + +// HostFSConfig is a bare struct for unpacking the config we get from agent or metricbeat +type HostFSConfig struct { + HostFS string `config:"hostfs"` +} + +// MetricbeatHostFSConfig +type MetricbeatHostFSConfig struct { + HostFS string `config:"system.hostfs"` +} + +// Init either the system or linux module. This will produce different modules depending on if we're running under agent or not. +func InitSystemModule(base mb.BaseModule) (mb.Module, error) { + // common code for the base use case of `hostfs` being set at the module-level + logger := logp.L() + hostfs, userSet := findConfigValue(base) + if fleetmode.Enabled() { + logger.Infof("initializing HostFS values under agent: %s", hostfs) + return fleetInit(base, hostfs, userSet) + } + return metricbeatInit(base, hostfs, userSet) +} + +func fleetInit(base mb.BaseModule, modulepath string, moduleSet bool) (mb.Module, error) { + once.Do(func() { + InitModule(modulepath) + }) + + // The multiple invocations here might seem buggy, but we're dealing with a case were agent's config schemea (local, per-datastream) must mesh with the global HostFS scheme used by some libraries + // Strictly speaking, we can't guarantee that agent will send consistent HostFS config values across all datastreams, as it treats a global value as per-datastream. + if moduleSet { + InitModule(modulepath) + } + + return &Module{BaseModule: base, HostFS: modulepath, UserSetHostFS: moduleSet}, nil +} + +// Deal with the legacy configs available to metricbeat +func metricbeatInit(base mb.BaseModule, modulePath string, moduleSet bool) (mb.Module, error) { + var hostfs = modulePath + var userSet bool + // allow the CLI to override other settings + if hostfsCLI != nil && *hostfsCLI != "" { + cfgwarn.Deprecate("8.0.0", "The --system.hostfs flag will be removed in the future and replaced by a config value.") + hostfs = *hostfsCLI + userSet = true + } + + once.Do(func() { + InitModule(hostfs) + }) + return &Module{BaseModule: base, HostFS: hostfs, UserSetHostFS: userSet}, nil + +} + +// A user can supply either `system.hostfs` or `hostfs`. +// In additon, we will probably want to change Integration Config values to `hostfs` as well. +// We need to figure out which one we got, if any. +func findConfigValue(base mb.BaseModule) (string, bool) { + partialConfig := HostFSConfig{} + base.UnpackConfig(&partialConfig) + // if the newer value is set, just use that. + if partialConfig.HostFS != "" { + return partialConfig.HostFS, true + } + + legacyConfig := MetricbeatHostFSConfig{} + base.UnpackConfig(&legacyConfig) + if legacyConfig.HostFS != "" { + cfgwarn.Deprecate("8.0.0", "The system.hostfs config value will be removed, use `hostfs` from within the module config.") + // Only fallback to this if the user didn't set anything else + return legacyConfig.HostFS, true + } + + return "/", false + +} diff --git a/journalbeat/config/config.go b/metricbeat/internal/sysinit/module.go similarity index 56% rename from journalbeat/config/config.go rename to metricbeat/internal/sysinit/module.go index 1771a2a4e7c..411372064a0 100644 --- a/journalbeat/config/config.go +++ b/metricbeat/internal/sysinit/module.go @@ -15,24 +15,28 @@ // specific language governing permissions and limitations // under the License. -// Config is put into a different package to prevent cyclic imports in case -// it is needed in several locations - -package config +package sysinit import ( - "github.com/elastic/beats/v7/libbeat/common" + "path/filepath" + + "github.com/elastic/beats/v7/metricbeat/mb" ) -// Config stores the configuration of Journalbeat -type Config struct { - Inputs []*common.Config `config:"inputs"` - RegistryFile string `config:"registry_file"` +// Module represents the system/linux module +type Module struct { + mb.BaseModule + HostFS string + UserSetHostFS bool } -var ( - // DefaultConfig are the defaults of a Journalbeat instance - DefaultConfig = Config{ - RegistryFile: "registry", - } -) +// ResolveHostFS returns a full path based on a user-suppled path, and impliments the Resolver interface +// This is mostly to prevent any chance that other metricsets will develop their own way of +// using a user-suppied hostfs flag. We try to do all the logic in one place. +func (m Module) ResolveHostFS(path string) string { + return filepath.Join(m.HostFS, path) +} + +func (m Module) IsSet() bool { + return m.UserSetHostFS +} diff --git a/metricbeat/module/system/system_linux.go b/metricbeat/internal/sysinit/system_linux.go similarity index 93% rename from metricbeat/module/system/system_linux.go rename to metricbeat/internal/sysinit/system_linux.go index 2281bea3d0f..4bb992f1441 100644 --- a/metricbeat/module/system/system_linux.go +++ b/metricbeat/internal/sysinit/system_linux.go @@ -15,7 +15,7 @@ // specific language governing permissions and limitations // under the License. -package system +package sysinit import ( "os" @@ -24,16 +24,12 @@ import ( "github.com/elastic/gosigar" ) -func initModule(config string) { +func InitModule(config string) { configureHostFS(config) } func configureHostFS(config string) { dir := config - if dir == "" { - dir = "/" - } - // Set environment variables for gopsutil. os.Setenv("HOST_PROC", filepath.Join(dir, "/proc")) os.Setenv("HOST_SYS", filepath.Join(dir, "/sys")) diff --git a/metricbeat/module/system/system_other.go b/metricbeat/internal/sysinit/system_other.go similarity index 94% rename from metricbeat/module/system/system_other.go rename to metricbeat/internal/sysinit/system_other.go index 6b99c5c3fed..3ce49834b69 100644 --- a/metricbeat/module/system/system_other.go +++ b/metricbeat/internal/sysinit/system_other.go @@ -18,8 +18,8 @@ //go:build !linux && !windows // +build !linux,!windows -package system +package sysinit -func initModule(config string) { +func InitModule(config string) { // Stub method for non-linux. } diff --git a/metricbeat/module/system/system_windows.go b/metricbeat/internal/sysinit/system_windows.go similarity index 95% rename from metricbeat/module/system/system_windows.go rename to metricbeat/internal/sysinit/system_windows.go index bf6f457e24e..d043c41b496 100644 --- a/metricbeat/module/system/system_windows.go +++ b/metricbeat/internal/sysinit/system_windows.go @@ -15,14 +15,14 @@ // specific language governing permissions and limitations // under the License. -package system +package sysinit import ( "github.com/elastic/beats/v7/libbeat/logp" "github.com/elastic/beats/v7/metricbeat/helper" ) -func initModule(config string) { +func InitModule(config string) { if err := helper.CheckAndEnableSeDebugPrivilege(); err != nil { logp.Warn("%v", err) } diff --git a/metricbeat/mb/testing/modules.go b/metricbeat/mb/testing/modules.go index 605e44a4d32..c5dd3ecbcdd 100644 --- a/metricbeat/mb/testing/modules.go +++ b/metricbeat/mb/testing/modules.go @@ -344,20 +344,20 @@ func NewPushMetricSetV2WithContext(t testing.TB, config interface{}) mb.PushMetr return pushMetricSet } -// capturingPushReporterV2 stores all the events and errors from a metricset's +// CapturingPushReporterV2 stores all the events and errors from a metricset's // Run method. -type capturingPushReporterV2 struct { +type CapturingPushReporterV2 struct { context.Context eventsC chan mb.Event } -func newCapturingPushReporterV2(ctx context.Context) *capturingPushReporterV2 { - return &capturingPushReporterV2{Context: ctx, eventsC: make(chan mb.Event)} +func newCapturingPushReporterV2(ctx context.Context) *CapturingPushReporterV2 { + return &CapturingPushReporterV2{Context: ctx, eventsC: make(chan mb.Event)} } // report writes an event to the output channel and returns true. If the output // is closed it returns false. -func (r *capturingPushReporterV2) report(event mb.Event) bool { +func (r *CapturingPushReporterV2) report(event mb.Event) bool { select { case <-r.Done(): // Publisher is stopped. @@ -368,16 +368,16 @@ func (r *capturingPushReporterV2) report(event mb.Event) bool { } // Event stores the passed-in event into the events array -func (r *capturingPushReporterV2) Event(event mb.Event) bool { +func (r *CapturingPushReporterV2) Event(event mb.Event) bool { return r.report(event) } // Error stores the given error into the errors array. -func (r *capturingPushReporterV2) Error(err error) bool { +func (r *CapturingPushReporterV2) Error(err error) bool { return r.report(mb.Event{Error: err}) } -func (r *capturingPushReporterV2) capture(waitEvents int) []mb.Event { +func (r *CapturingPushReporterV2) capture(waitEvents int) []mb.Event { var events []mb.Event for { select { @@ -393,6 +393,20 @@ func (r *capturingPushReporterV2) capture(waitEvents int) []mb.Event { } } +// BlockingCapture blocks until waitEvents n of events are captured +func (r *CapturingPushReporterV2) BlockingCapture(waitEvents int) []mb.Event { + var events []mb.Event + for { + select { + case e := <-r.eventsC: + events = append(events, e) + if waitEvents > 0 && len(events) >= waitEvents { + return events + } + } + } +} + // RunPushMetricSetV2 run the given push metricset for the specific amount of // time and returns all of the events and errors that occur during that period. func RunPushMetricSetV2(timeout time.Duration, waitEvents int, metricSet mb.PushMetricSetV2) []mb.Event { @@ -405,6 +419,11 @@ func RunPushMetricSetV2(timeout time.Duration, waitEvents int, metricSet mb.Push return r.capture(waitEvents) } +// GetCapturingPushReporterV2 is a factory for a capturing push metricset +func GetCapturingPushReporterV2() mb.PushReporterV2 { + return newCapturingPushReporterV2(context.Background()) +} + // RunPushMetricSetV2WithContext run the given push metricset for the specific amount of // time and returns all of the events that occur during that period. func RunPushMetricSetV2WithContext(timeout time.Duration, waitEvents int, metricSet mb.PushMetricSetV2WithContext) []mb.Event { diff --git a/metricbeat/metricbeat.reference.yml b/metricbeat/metricbeat.reference.yml index d78e42dcf8c..2d4c51aea50 100644 --- a/metricbeat/metricbeat.reference.yml +++ b/metricbeat/metricbeat.reference.yml @@ -80,7 +80,7 @@ metricbeat.modules: processes: ['.*'] # Configure the mount point of the host’s filesystem for use in monitoring a host from within a container - #system.hostfs: "/hostfs" + #hostfs: "/hostfs" # Configure the metric types that are included by these metricsets. cpu.metrics: ["percentages","normalized_percentages"] # The other available option is ticks. @@ -500,6 +500,16 @@ metricbeat.modules: # If kube_config is not set, KUBECONFIG environment variable will be checked # and if not present it will fall back to InCluster #kube_config: ~/.kube/config + # To configure additionally node and namespace metadata, added to pod, service and container resource types, + # `add_resource_metadata` can be defined. + # By default all labels will be included while annotations are not added by default. + # add_resource_metadata: + # namespace: + # include_labels: ["namespacelabel1"] + # node: + # include_labels: ["nodelabel2"] + # include_annotations: ["nodeannotation1"] + # deployment: false # Kubernetes client QPS and burst can be configured additionally #kube_client_options: # qps: 5 @@ -534,6 +544,38 @@ metricbeat.modules: # If kube_config is not set, KUBECONFIG environment variable will be checked # and if not present it will fall back to InCluster #kube_config: ~/.kube/config + # To configure additionally node and namespace metadata, added to pod, service and container resource types, + # `add_resource_metadata` can be defined. + # By default all labels will be included while annotations are not added by default. + # add_resource_metadata: + # namespace: + # include_labels: ["namespacelabel1"] + # node: + # include_labels: ["nodelabel2"] + # include_annotations: ["nodeannotation1"] + # deployment: false + # Kubernetes client QPS and burst can be configured additionally + #kube_client_options: + # qps: 5 + # burst: 10 + +# Kubernetes Events +- module: kubernetes + enabled: true + metricsets: + - event + period: 10s + # Skip events older than Metricbeat's statup time is enabled by default. + # Setting to false the skip_older setting will stop filtering older events. + # This setting is also useful went Event's timestamps are not populated properly. + #skip_older: false + # If kube_config is not set, KUBECONFIG environment variable will be checked + # and if not present it will fall back to InCluster + #kube_config: ~/.kube/config + # Set the namespace to watch for events + #namespace: staging + # Set the sync period of the watchers + #sync_period: 10m # Kubernetes client QPS and burst can be configured additionally #kube_client_options: # qps: 5 @@ -551,8 +593,6 @@ metricbeat.modules: - /var/run/secrets/kubernetes.io/serviceaccount/ca.crt period: 30s - - # Kubernetes proxy server # (when running metricbeat locally at hosts or as a daemonset + host network) - module: kubernetes @@ -1020,66 +1060,6 @@ metricbeat.modules: # length of its retry interval each time, up to this maximum. #max_retry_interval: 30s - # The spool queue will store events in a local spool file, before - # forwarding the events to the outputs. - # Note: the spool queue is deprecated and will be removed in the future. - # Use the disk queue instead. - # - # The spool file is a circular buffer, which blocks once the file/buffer is full. - # Events are put into a write buffer and flushed once the write buffer - # is full or the flush_timeout is triggered. - # Once ACKed by the output, events are removed immediately from the queue, - # making space for new events to be persisted. - #spool: - # The file namespace configures the file path and the file creation settings. - # Once the file exists, the `size`, `page_size` and `prealloc` settings - # will have no more effect. - #file: - # Location of spool file. The default value is ${path.data}/spool.dat. - #path: "${path.data}/spool.dat" - - # Configure file permissions if file is created. The default value is 0600. - #permissions: 0600 - - # File size hint. The spool blocks, once this limit is reached. The default value is 100 MiB. - #size: 100MiB - - # The files page size. A file is split into multiple pages of the same size. The default value is 4KiB. - #page_size: 4KiB - - # If prealloc is set, the required space for the file is reserved using - # truncate. The default value is true. - #prealloc: true - - # Spool writer settings - # Events are serialized into a write buffer. The write buffer is flushed if: - # - The buffer limit has been reached. - # - The configured limit of buffered events is reached. - # - The flush timeout is triggered. - #write: - # Sets the write buffer size. - #buffer_size: 1MiB - - # Maximum duration after which events are flushed if the write buffer - # is not full yet. The default value is 1s. - #flush.timeout: 1s - - # Number of maximum buffered events. The write buffer is flushed once the - # limit is reached. - #flush.events: 16384 - - # Configure the on-disk event encoding. The encoding can be changed - # between restarts. - # Valid encodings are: json, ubjson, and cbor. - #codec: cbor - #read: - # Reader flush timeout, waiting for more events to become available, so - # to fill a complete batch as required by the outputs. - # If flush_timeout is 0, all available events are forwarded to the - # outputs immediately. - # The default value is 0s. - #flush.timeout: 0s - # Sets the maximum number of CPUs that can be executing simultaneously. The # default is the number of logical CPUs available in the system. #max_procs: @@ -1396,6 +1376,13 @@ output.elasticsearch: # The pin is a base64 encoded string of the SHA-256 fingerprint. #ssl.ca_sha256: "" + # A root CA HEX encoded fingerprint. During the SSL handshake if the + # fingerprint matches the root CA certificate, it will be added to + # the provided list of root CAs (`certificate_authorities`), if the + # list is empty or not defined, the matching certificate will be the + # only one in the list. Then the normal SSL validation happens. + #ssl.ca_trusted_fingerprint: "" + # Enable Kerberos support. Kerberos is automatically enabled if any Kerberos setting is set. #kerberos.enabled: true @@ -1528,6 +1515,13 @@ output.elasticsearch: # The pin is a base64 encoded string of the SHA-256 fingerprint. #ssl.ca_sha256: "" + # A root CA HEX encoded fingerprint. During the SSL handshake if the + # fingerprint matches the root CA certificate, it will be added to + # the provided list of root CAs (`certificate_authorities`), if the + # list is empty or not defined, the matching certificate will be the + # only one in the list. Then the normal SSL validation happens. + #ssl.ca_trusted_fingerprint: "" + # The number of times to retry publishing an event after a publishing failure. # After the specified number of retries, the events are typically dropped. # Some Beats, such as Filebeat and Winlogbeat, ignore the max_retries setting @@ -1729,6 +1723,13 @@ output.elasticsearch: # The pin is a base64 encoded string of the SHA-256 fingerprint. #ssl.ca_sha256: "" + # A root CA HEX encoded fingerprint. During the SSL handshake if the + # fingerprint matches the root CA certificate, it will be added to + # the provided list of root CAs (`certificate_authorities`), if the + # list is empty or not defined, the matching certificate will be the + # only one in the list. Then the normal SSL validation happens. + #ssl.ca_trusted_fingerprint: "" + # Enable Kerberos support. Kerberos is automatically enabled if any Kerberos setting is set. #kerberos.enabled: true @@ -1893,6 +1894,13 @@ output.elasticsearch: # The pin is a base64 encoded string of the SHA-256 fingerprint. #ssl.ca_sha256: "" + # A root CA HEX encoded fingerprint. During the SSL handshake if the + # fingerprint matches the root CA certificate, it will be added to + # the provided list of root CAs (`certificate_authorities`), if the + # list is empty or not defined, the matching certificate will be the + # only one in the list. Then the normal SSL validation happens. + #ssl.ca_trusted_fingerprint: "" + # -------------------------------- File Output --------------------------------- #output.file: @@ -1912,7 +1920,7 @@ output.elasticsearch: #path: "/tmp/metricbeat" # Name of the generated files. The default is `metricbeat` and it generates - # files: `metricbeat`, `metricbeat.1`, `metricbeat.2`, etc. + # files: `metricbeat-{datetime}.ndjson`, `metricbeat-{datetime}-1.ndjson`, etc. #filename: metricbeat # Maximum size in kilobytes of each file. When this size is reached, and on @@ -1930,6 +1938,7 @@ output.elasticsearch: # Configure automatic file rotation on every startup. The default is true. #rotate_on_startup: true + # ------------------------------- Console Output ------------------------------- #output.console: # Boolean flag to enable or disable the output module. @@ -2028,19 +2037,13 @@ output.elasticsearch: # Set to false to disable template loading. #setup.template.enabled: true -# Select the kind of index template. From Elasticsearch 7.8, it is possible to -# use component templates. Available options: legacy, component, index. -# By default metricbeat uses the legacy index templates. -#setup.template.type: legacy - # Template name. By default the template name is "metricbeat-%{[agent.version]}" # The template name and pattern has to be set in case the Elasticsearch index pattern is modified. #setup.template.name: "metricbeat-%{[agent.version]}" -# Template pattern. By default the template pattern is "-%{[agent.version]}-*" to apply to the default index settings. -# The first part is the version of the beat and then -* is used to match all daily indices. +# Template pattern. By default the template pattern is "metricbeat-%{[agent.version]}" to apply to the default index settings. # The template name and pattern has to be set in case the Elasticsearch index pattern is modified. -#setup.template.pattern: "metricbeat-%{[agent.version]}-*" +#setup.template.pattern: "metricbeat-%{[agent.version]}" # Path to fields.yml file to generate the template #setup.template.fields: "${path.config}/fields.yml" @@ -2087,17 +2090,8 @@ setup.template.settings: # output.elasticsearch.index is ignored, and the write alias is used to set the # index name. -# Enable ILM support. Valid values are true, false, and auto. When set to auto -# (the default), the Beat uses index lifecycle management when it connects to a -# cluster that supports ILM; otherwise, it creates daily indices. -#setup.ilm.enabled: auto - -# Set the prefix used in the index lifecycle write alias name. The default alias -# name is 'metricbeat-%{[agent.version]}'. -#setup.ilm.rollover_alias: 'metricbeat' - -# Set the rollover index pattern. The default is "%{now/d}-000001". -#setup.ilm.pattern: "{now/d}-000001" +# Enable ILM support. Valid values are true, false. +#setup.ilm.enabled: true # Set the lifecycle policy name. The default policy name is # 'beatname'. @@ -2195,6 +2189,13 @@ setup.kibana: # The pin is a base64 encoded string of the SHA-256 fingerprint. #ssl.ca_sha256: "" + # A root CA HEX encoded fingerprint. During the SSL handshake if the + # fingerprint matches the root CA certificate, it will be added to + # the provided list of root CAs (`certificate_authorities`), if the + # list is empty or not defined, the matching certificate will be the + # only one in the list. Then the normal SSL validation happens. + #ssl.ca_trusted_fingerprint: "" + # ================================== Logging =================================== @@ -2266,11 +2267,6 @@ logging.files: # file. Defaults to true. # rotateonstartup: true - # Rotated files are either suffixed with a number e.g. metricbeat.1 when - # renamed during rotation. Or when set to date, the date is added to - # the end of the file. On rotation a new file is created, older files are untouched. - #suffix: count - # ============================= X-Pack Monitoring ============================== # Metricbeat can export internal metrics to a central Elasticsearch monitoring # cluster. This requires xpack monitoring to be enabled in Elasticsearch. The @@ -2398,6 +2394,13 @@ logging.files: # The pin is a base64 encoded string of the SHA-256 fingerprint. #ssl.ca_sha256: "" + # A root CA HEX encoded fingerprint. During the SSL handshake if the + # fingerprint matches the root CA certificate, it will be added to + # the provided list of root CAs (`certificate_authorities`), if the + # list is empty or not defined, the matching certificate will be the + # only one in the list. Then the normal SSL validation happens. + #ssl.ca_trusted_fingerprint: "" + # Enable Kerberos support. Kerberos is automatically enabled if any Kerberos setting is set. #kerberos.enabled: true diff --git a/metricbeat/module/beat/_meta/fields.yml b/metricbeat/module/beat/_meta/fields.yml index 5f40348c572..8cb1de91166 100644 --- a/metricbeat/module/beat/_meta/fields.yml +++ b/metricbeat/module/beat/_meta/fields.yml @@ -305,19 +305,19 @@ fields: - name: host type: alias - path: beat.stats.beat.host + path: beat.stats.info.host - name: name type: alias - path: beat.stats.beat.name + path: beat.stats.info.name - name: type type: alias - path: beat.stats.beat.type + path: beat.stats.info.type - name: uuid type: alias - path: beat.stats.beat.uuid + path: beat.stats.info.uuid - name: version type: alias - path: beat.stats.beat.version + path: beat.stats.info.version - name: metrics type: group fields: @@ -634,3 +634,5 @@ type: keyword description: > Beat type. + - name: elasticsearch.cluster.id + type: keyword diff --git a/metricbeat/module/beat/fields.go b/metricbeat/module/beat/fields.go index cd59838480a..4948b3e3346 100644 --- a/metricbeat/module/beat/fields.go +++ b/metricbeat/module/beat/fields.go @@ -32,5 +32,5 @@ func init() { // AssetBeat returns asset data. // This is the base64 encoded zlib format compressed contents of module/beat. func AssetBeat() string { - return "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" + return "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" } diff --git a/metricbeat/module/beat/state/_meta/data.json b/metricbeat/module/beat/state/_meta/data.json index 6e85c8a3018..627b84f32ed 100644 --- a/metricbeat/module/beat/state/_meta/data.json +++ b/metricbeat/module/beat/state/_meta/data.json @@ -1,6 +1,11 @@ { "@timestamp": "2017-10-12T08:05:34.853Z", "beat": { + "elasticsearch": { + "cluster": { + "id": "foobar" + } + }, "state": { "beat": { "host": "2963d991095f", @@ -58,4 +63,4 @@ "address": "172.19.0.2:5066", "type": "beat" } -} \ No newline at end of file +} diff --git a/metricbeat/module/beat/state/data.go b/metricbeat/module/beat/state/data.go index 2a356407ef7..d22830e12ba 100644 --- a/metricbeat/module/beat/state/data.go +++ b/metricbeat/module/beat/state/data.go @@ -69,7 +69,8 @@ var ( func eventMapping(r mb.ReporterV2, info beat.Info, content []byte, isXpack bool) error { event := mb.Event{ - RootFields: common.MapStr{}, + RootFields: common.MapStr{}, + ModuleFields: common.MapStr{}, } var data map[string]interface{} @@ -85,6 +86,8 @@ func eventMapping(r mb.ReporterV2, info beat.Info, content []byte, isXpack bool) if isOutputES(data) { clusterUUID = getClusterUUID(data) if clusterUUID != "" { + event.ModuleFields.Put("elasticsearch.cluster.id", clusterUUID) + if event.MetricSetFields != nil { event.MetricSetFields.Put("cluster.uuid", clusterUUID) } diff --git a/metricbeat/module/beat/stats/_meta/data.json b/metricbeat/module/beat/stats/_meta/data.json index ecda8583492..361d56878f0 100644 --- a/metricbeat/module/beat/stats/_meta/data.json +++ b/metricbeat/module/beat/stats/_meta/data.json @@ -2,6 +2,11 @@ "@timestamp": "2017-10-12T08:05:34.853Z", "beat": { "id": "c4c9bc08-e990-4529-8bf5-715c00fa6615", + "elasticsearch": { + "cluster": { + "id": "foobar" + } + }, "stats": { "beat": { "host": "2963d991095f", @@ -48,7 +53,8 @@ "config": { "running": 3, "starts": 3, - "stops": 0 + "stops": 0, + "reloads": 1 }, "output": { "events": { @@ -133,4 +139,4 @@ "name": "beat", "type": "beat" } -} \ No newline at end of file +} diff --git a/metricbeat/module/beat/stats/_meta/fields.yml b/metricbeat/module/beat/stats/_meta/fields.yml index 0e5700b5fd5..539a4071b4c 100644 --- a/metricbeat/module/beat/stats/_meta/fields.yml +++ b/metricbeat/module/beat/stats/_meta/fields.yml @@ -219,6 +219,19 @@ type: long - name: unauthorized type: long + - name: info + type: group + fields: + - name: name + type: keyword + - name: host + type: keyword + - name: type + type: keyword + - name: uuid + type: keyword + - name: version + type: keyword - name: beat type: group fields: @@ -379,6 +392,8 @@ type: short - name: stops type: short + - name: reloads + type: short - name: output type: group description: > diff --git a/metricbeat/module/beat/stats/data.go b/metricbeat/module/beat/stats/data.go index 5e95f27a22e..096dc028ba7 100644 --- a/metricbeat/module/beat/stats/data.go +++ b/metricbeat/module/beat/stats/data.go @@ -88,10 +88,11 @@ var ( "total": c.Int("total"), }), }), - "config": c.Dict("config.module", s.Schema{ - "running": c.Int("running"), - "starts": c.Int("starts"), - "stops": c.Int("stops"), + "config": c.Dict("config", s.Schema{ + "running": c.Int("module.running"), + "starts": c.Int("module.starts"), + "stops": c.Int("module.stops"), + "reloads": c.Int("reloads"), }), }), "state": c.Dict("metricbeat.beat.state", s.Schema{ @@ -110,7 +111,7 @@ var ( } ) -func eventMapping(r mb.ReporterV2, info beat.Info, content []byte, isXpack bool) error { +func eventMapping(r mb.ReporterV2, info beat.Info, clusterUUID string, content []byte, isXpack bool) error { event := mb.Event{ RootFields: common.MapStr{}, ModuleFields: common.MapStr{}, @@ -118,10 +119,13 @@ func eventMapping(r mb.ReporterV2, info beat.Info, content []byte, isXpack bool) } event.RootFields.Put("service.name", beat.ModuleName) - event.ModuleFields = common.MapStr{} event.ModuleFields.Put("id", info.UUID) event.ModuleFields.Put("type", info.Beat) + if clusterUUID != "" { + event.ModuleFields.Put("elasticsearch.cluster.id", clusterUUID) + } + var data map[string]interface{} err := json.Unmarshal(content, &data) if err != nil { diff --git a/metricbeat/module/beat/stats/data_test.go b/metricbeat/module/beat/stats/data_test.go index 5a58a7c7ee1..ee4b0f38957 100644 --- a/metricbeat/module/beat/stats/data_test.go +++ b/metricbeat/module/beat/stats/data_test.go @@ -42,12 +42,14 @@ func TestEventMapping(t *testing.T) { Beat: "helloworld", } + clusterUUID := "foo" + for _, f := range files { input, err := ioutil.ReadFile(f) require.NoError(t, err) reporter := &mbtest.CapturingReporterV2{} - err = eventMapping(reporter, info, input, true) + err = eventMapping(reporter, info, clusterUUID, input, true) require.NoError(t, err, f) require.True(t, len(reporter.GetEvents()) >= 1, f) diff --git a/metricbeat/module/beat/stats/stats.go b/metricbeat/module/beat/stats/stats.go index 7058a54614b..7c260cf3e0a 100644 --- a/metricbeat/module/beat/stats/stats.go +++ b/metricbeat/module/beat/stats/stats.go @@ -18,6 +18,8 @@ package stats import ( + "github.com/pkg/errors" + "github.com/elastic/beats/v7/metricbeat/mb" "github.com/elastic/beats/v7/metricbeat/mb/parse" "github.com/elastic/beats/v7/metricbeat/module/beat" @@ -66,5 +68,36 @@ func (m *MetricSet) Fetch(r mb.ReporterV2) error { return err } - return eventMapping(r, *info, content, m.XPackEnabled) + clusterUUID, err := m.getClusterUUID() + if err != nil { + return err + } + + return eventMapping(r, *info, clusterUUID, content, m.XPackEnabled) +} + +func (m *MetricSet) getClusterUUID() (string, error) { + state, err := beat.GetState(m.MetricSet) + if err != nil { + return "", errors.Wrap(err, "could not get state information") + } + + clusterUUID := state.Monitoring.ClusterUUID + if clusterUUID != "" { + return clusterUUID, nil + } + + if state.Output.Name != "elasticsearch" { + return "", nil + } + + clusterUUID = state.Outputs.Elasticsearch.ClusterUUID + if clusterUUID == "" { + // Output is ES but cluster UUID could not be determined. No point sending monitoring + // data with empty cluster UUID since it will not be associated with the correct ES + // production cluster. Log error instead. + return "", beat.ErrClusterUUID + } + + return clusterUUID, nil } diff --git a/metricbeat/tests/system/test_beat.py b/metricbeat/module/beat/test_beat.py similarity index 100% rename from metricbeat/tests/system/test_beat.py rename to metricbeat/module/beat/test_beat.py diff --git a/metricbeat/module/elasticsearch/cluster_stats/data.go b/metricbeat/module/elasticsearch/cluster_stats/data.go index 8de27d71561..a75f58f3a44 100644 --- a/metricbeat/module/elasticsearch/cluster_stats/data.go +++ b/metricbeat/module/elasticsearch/cluster_stats/data.go @@ -303,22 +303,7 @@ func eventMapping(r mb.ReporterV2, httpClient *helper.HTTP, info elasticsearch.I metricSetFields, _ := schema.Apply(data) metricSetFields.Put("stack", stackData) - metricSetFields.Put("license", struct { - Status string `json:"status"` - Type string `json:"type"` - ExpiryDateMs int `json:"expiry_date_in_millis"` - }{ - Status: license.Status, - Type: license.Type, - ExpiryDateMs: license.ExpiryDateInMillis, - }) - - if license.ExpiryDateInMillis != 0 { - // We don't want to record a 0 expiry date as this means the license has expired - // in the Stack Monitoring UI - metricSetFields.Put("expiry_date_in_millis", license.ExpiryDateInMillis) - } - + metricSetFields.Put("license", l) metricSetFields.Put("state", clusterStateReduced) if err = elasticsearch.PassThruField("version", clusterState, event.ModuleFields); err != nil { diff --git a/metricbeat/module/elasticsearch/index_recovery/index_recovery.go b/metricbeat/module/elasticsearch/index_recovery/index_recovery.go index eb2eaf93bf6..5b5243de9f9 100644 --- a/metricbeat/module/elasticsearch/index_recovery/index_recovery.go +++ b/metricbeat/module/elasticsearch/index_recovery/index_recovery.go @@ -43,7 +43,7 @@ func New(base mb.BaseMetricSet) (mb.MetricSet, error) { config := struct { ActiveOnly bool `config:"index_recovery.active_only"` }{ - ActiveOnly: true, + ActiveOnly: false, } if err := base.Module().UnpackConfig(&config); err != nil { return nil, err diff --git a/metricbeat/module/elasticsearch/ml_job/_meta/data.json b/metricbeat/module/elasticsearch/ml_job/_meta/data.json index 0e79d5bad91..6a5e73f48f3 100644 --- a/metricbeat/module/elasticsearch/ml_job/_meta/data.json +++ b/metricbeat/module/elasticsearch/ml_job/_meta/data.json @@ -22,7 +22,8 @@ } }, "node": { - "id": "27fb1c2fd783" + "id": "27fb1c2fd783", + "name": "node-1" } }, "event": { @@ -39,4 +40,4 @@ "name": "elasticsearch", "type": "elasticsearch" } -} \ No newline at end of file +} diff --git a/metricbeat/module/elasticsearch/ml_job/data.go b/metricbeat/module/elasticsearch/ml_job/data.go index 28c296e1e5f..a23c2677f1b 100644 --- a/metricbeat/module/elasticsearch/ml_job/data.go +++ b/metricbeat/module/elasticsearch/ml_job/data.go @@ -81,7 +81,12 @@ func eventsMapping(r mb.ReporterV2, info elasticsearch.Info, content []byte, isX event.ModuleFields = common.MapStr{} event.ModuleFields.Put("cluster.name", info.ClusterName) event.ModuleFields.Put("cluster.id", info.ClusterID) - event.ModuleFields.Put("node.id", info.Name) + + if node, exists := job["node"]; exists { + nodeHash := node.(map[string]interface{}) + event.ModuleFields.Put("node.id", nodeHash["id"]) + event.ModuleFields.Put("node.name", nodeHash["name"]) + } event.MetricSetFields, _ = schema.Apply(job) diff --git a/metricbeat/module/elasticsearch/shard/_meta/data.json b/metricbeat/module/elasticsearch/shard/_meta/data.json index b6278e225f5..e56708307e7 100644 --- a/metricbeat/module/elasticsearch/shard/_meta/data.json +++ b/metricbeat/module/elasticsearch/shard/_meta/data.json @@ -6,6 +6,11 @@ "name": "docker-cluster", "state": { "id": "XNIdeSZxQwyItvGfR5fHSw" + }, + "stats": { + "state": { + "state_uuid": "XNIdeSZxQwyItvGfR5fHSw" + } } }, "index": { @@ -41,4 +46,4 @@ "address": "172.19.0.2:9200", "type": "elasticsearch" } -} \ No newline at end of file +} diff --git a/metricbeat/module/elasticsearch/shard/data.go b/metricbeat/module/elasticsearch/shard/data.go index 2dd2f93c023..575be1d7184 100644 --- a/metricbeat/module/elasticsearch/shard/data.go +++ b/metricbeat/module/elasticsearch/shard/data.go @@ -73,6 +73,7 @@ func eventsMapping(r mb.ReporterV2, content []byte, isXpack bool) error { } event.ModuleFields.Put("cluster.state.id", stateData.StateID) + event.ModuleFields.Put("cluster.stats.state.state_uuid", stateData.StateID) event.ModuleFields.Put("cluster.id", stateData.ClusterID) event.ModuleFields.Put("cluster.name", stateData.ClusterName) @@ -117,6 +118,7 @@ func eventsMapping(r mb.ReporterV2, content []byte, isXpack bool) error { errs = append(errs, errors.Wrap(err, "failure getting source node information")) continue } + event.ModuleFields.Put("node.name", sourceNode["name"]) event.MetricSetFields.Put("source_node", sourceNode) } diff --git a/metricbeat/module/elasticsearch/test_elasticsearch.py b/metricbeat/module/elasticsearch/test_elasticsearch.py index 7a48efdfb15..9726f26838d 100644 --- a/metricbeat/module/elasticsearch/test_elasticsearch.py +++ b/metricbeat/module/elasticsearch/test_elasticsearch.py @@ -140,6 +140,17 @@ def test_xpack_cluster_stats(self): proc.check_kill_and_wait() self.assert_no_logged_warnings() + docs = self.read_output_json() + for doc in docs: + t = doc["metricset"]["name"] + if t != "cluster_stats": + continue + license = doc["elasticsearch"]["cluster"]["stats"]["license"] + issue_date = license["issue_date_in_millis"] + self.assertIsNot(type(issue_date), float) + + self.assertNotIn("expiry_date_in_millis", license) + def create_ml_job(self): # Check if an ml job already exists response = self.ml_es.get_jobs() diff --git a/metricbeat/module/kibana/_meta/fields.yml b/metricbeat/module/kibana/_meta/fields.yml index 633cbadde96..05a9818f2ae 100644 --- a/metricbeat/module/kibana/_meta/fields.yml +++ b/metricbeat/module/kibana/_meta/fields.yml @@ -63,3 +63,5 @@ - name: kibana type: group fields: + - name: elasticsearch.cluster.id + type: keyword diff --git a/metricbeat/module/kibana/fields.go b/metricbeat/module/kibana/fields.go index 815dad6c853..2c728c5076d 100644 --- a/metricbeat/module/kibana/fields.go +++ b/metricbeat/module/kibana/fields.go @@ -32,5 +32,5 @@ func init() { // AssetKibana returns asset data. // This is the base64 encoded zlib format compressed contents of module/kibana. func AssetKibana() string { - return "eJzMWUtv4zYQvudXDHzZy0ZADnvxoWjRFmhRbFCkDXooCmMsjS02FKlyqCTury+oh60H9bAkd9eHIJA03/fNDDlDje7hhU5beBF7VHgHYIWVtIXNL/mFzR1ARBwakVqh1Ra+uQMAKG5CoqNM0h0Ax9rYXajVQRy3cEDJ7qohSci0haMDZrJWqCNv4c8Ns9x8hE1sbbr56w7gIEhGvM2x70FhQpWiHVu0nN8AsKfUoRmdpeWVumHd2IqE2GKSnu9U1igFcu1qijbewubbs8WmA1YoCQxxqhXTzj0aJPg+Ebs0zx3pggQJ9xE6i4znsPgBKnjNQUKJNqfgYIh2Qu32J0uziMagKsrU6JCYgyx1frvnEiGlmMXZxPLFr3qilBYTpgGLf2knRSLsEk4/YuB3OtQqzIwhlW8NRaHbQrNcHkHq8dsQi8jZMNldrnZJqsfAe4KgOZAao+Ahmbm+2tZt4E+LgD/1Az8sQ37wQFcxpFcXOal1uotI4mlJPtpYvg1h6J+M2HJgtUU5r27lCC2ADn4kuFygs9ZYxeKDuXDVKijftA63qPCVDB5pOR2+HgfKfpaJaCIHk3kVIQWlQRPo6qZZdegOed3Y/TwngupXngxyrwFVBCZT985pSMgaEXJQe7x5QKh+bXl1ia3YXCS+0OlNm/a9htBSmlBsUYUEz88//+AlcX/XIulgVSRCRfQ+l+UREwJ9KNk+MAhlySiUHtiKMNZs1/LKYfV6Zg0qTt2BEKPIEPNCVrfIyXzgM2u+rhyBl/6VDAutFpL6UM77RGHKsfZHc6+1JGzTNyj+iMnGZMDGVNHtMyEjEAx4Ri+u+QW0D4ZLkukCSyht7IOtGKUOUU7fFOd+105SZeTW65FMtwTVTvvwFdafRmUdFtkH1Xa3k8hpoc242YrmCBmqRZM09FXjdreCvo51+SXiaLDIqDVZ27OBjMMl67ct7eO0tyn2Xd655T+4rfsrdIXxheO3XmP1rNhnfG5ME+FHbYbA/8xQCNbqXF3ZX7iXjS7KSd1N+/nnVPRIsDX6qoreNX8q+tJslFSiPWiTLAZYKqSYFfSa+wIMA0GuQ/eNrrosUqvjIFT+TrsSVsYULYC6nLewG9U1wvbgWxQX6BjlYXeQGtsloonyaRWUh3kwk8drMBTrsRabJXsyrsmGUpCyUKOABCMCq/OiV3SNAB61JbAxWtgb/cZkGEJUwKQiSDJpRSoJWLh/UZHOuIFodTVDqT2cIwMykzvLWtAqpI95U7IxnXJ4Q/cZExBb3EvBMUV12MB/KC8GR5NL3kikfi3gqvP1VQfPibPE0WSed19nJDzZdGiM1gRh9yoU9azvkWAB/Oh4wPFAzgNCQTELp1CrqE3ailRM2N35Q1VhVE+VPofck8PxrpdX0J6kjZRO12bQbqHPeNQBgN8de+EASvemailyO6pc6C7CfvR60f5i6n9yup0C2J+mS+79+PD/Cf+M7wFoGQGnGFKuqBn/Rx1R8DdXTn2ckIje/TvizgS5zzm2q+i1IPfuvNZke61iCfBUlvlQZ8peVTQbp0TPlH2tQF1aXzXWL/raGxmqUVP/sa/9lWEtZcVGVx19PZmrjdzn5e+phCg+J89MVmvYPyca3xUfHs4u5XpGGketdTQ/bswR8BnfRZIlEwX0vtpdPc37LUcoQ1y7c/3g7vaDH/9h66sdkTlhfsnleCEo9tlt5hvlJg5uNefI102g3b6RMv8Gt372S/ScrCf7/ooxu3t8LuC6+wEm1KFJr0uwQpX+vmCpEfa/k4DnI/LV770TNFVd1+VKsG19B6h+U16gh3svjE8KJukFT7ert97hiMKEXnxLpQ1x/wUAAP//yfELdw==" + return "eJzMWU2P2zYQve+vGPiSS1bAHnLxoWjRFmhRJCjSBj0UhTGWxhYbilQ51O66v74gJdn6oCxZkpv4sFhI4ntvZsgZcvgIn+m0hc9ijwofAKywkraw+cU/2DwAJMSxEbkVWm3hmwcAgPIlZDopJD0AcKqN3cVaHcRxCweU7J4akoRMWzg6YCZrhTryFv7cMMvNW9ik1uabvx4ADoJkwluP/QgKM6oV7diiZf8CwJ5yh2Z0kVdPmgObg63IiC1m+flNPRqlQG48zdGmW9h8ex6x6YGVSiJDnGvFtHOfRhm+TsSuhntD+iBRxkOEbkTBc1jCADW85iijTJtTdDBEO6F2+5OlWURjUDVlbnRMzFGRO7vdd5mQUszibGOF/Fd/UUlLCfOIxb+0kyITdglnGDEKGx1rFRfGkPJLQ1HsltAsk0eQBuw2xCJxY5jszqtdEuox8AEnaI6kxiR6ymbOr+7oLvC7RcDvhoGfliE/BaBrH9Kz85zUOt8lJPG0JB5drNCCMPRPQWw5stqinJe3PEIHoIefCK4m6Kw5VrOEYC5cjQzKd83DHSp8JoNHWk6Hz8crab8oRDKRg8k8i5iiakAb6OaiSRLZipgJTZxGsSzYkokCYj7T6UWbpAdQl/jegCa7+wW2FPWv2lp4twGqBEyhHp3XICNrRMxR4/P2DqP+de1rSuw4d9imgNBKmlBsUcUEnz79/EOQxP1di6SHVZMIldDrXJYPmBHoQ8X2hkEoS0ahDMDWhKlmu5ZVDmvQMmtQce52lJgkhpgXsrpVQuYNn1n9vHIEQfpnMiy0WkgaQjmvE4U5pzrszb3WkrBL36L4IyWbkgGbUk23L4RMQDDgGb18FhbQ3VkuCaZzLKG0aQi2ZpQ6Rjl9UZwLZjdI9SA3X49k+imocVyArzD/tFLzdZFDUF1ze4Gc5tqC27VsjpBruWiShqFs3C13MFTyLr9MHA2WEbWm6Fp2JeJwifp9U/s47X2SfZ93bvqP7mv+ClVhfOKER68xe1asMyEzpokIo7ZdEP7mmgvWqlx92V+4lo1OyknVTYf552T0RLA1+qaM3h/+saxLs1FyifagTbYYYKmQstkwODzkYLji5Cb0UO+rzyK1Ol6F8ofilbAKpmQB1GW/hX2vruG2p9CkuECnKA+7g9TYTRFtlHeroDzNg5ncn4Nrvh4rsUW2J+OKbCwFKQsNCsgwIbDaJ72yakTwQVsCm6KFvdEvTIYhRgVMKoGskFbkkoCF+xcV6YJbiFbXTZjGxx4ZkJncXtaCVjG99UXJpnTy8IYeCyYgtriXglNKmrBReFNedp4mp7wRT/1awtX765s2nhObkaPBPK++Xk958tBrfbg2CLujUDIwv0ecBfCj4wHHA54HhIKymU6xVkmXtOOplLC/8q9lhVE9dfgc8kAMx6uez6ADQRtJna7MoN3C0OBRAwB+d+ylASjdSdVS4lZUNdGdh8PozaT9xdT/5HQ7BbA/TZc8eHvx/wl/j68RaJkA5xiTV9T2/wedUPQ310a9nRCIwfU7Ys4EuZ88tsvoDScPrrxOa3ytZAnwsUrzsS6UvSlptnaJgTb9Wo66lL76XqCsay9kqEFNw9u+7jXFWsrKha56+gYi1+jZz4vfxwqivI+eGazObcEcb3xX3lycTfJ6RgpHo3S0b0fmCHiPryIrsokCBo92N3fzfvMIlYsbb25v3N2/8RPebH21LTInLCy5ai9E5Tq7T3+jWsTRvfocft5E2q0bKf0l3vrRr9A92UD0wxljdvV4X8L11wNMyEOTjkuwQpb+vmRpEA6fSSBwC33zuXeCprrqulgJf0va1zHtAH299sJ4p2CSXghUu2bpve5RmFCL76m0Je6/AAAA//9Bvx66" } diff --git a/metricbeat/module/kibana/stats/_meta/data.json b/metricbeat/module/kibana/stats/_meta/data.json index dde2be30ac3..46e85773eeb 100644 --- a/metricbeat/module/kibana/stats/_meta/data.json +++ b/metricbeat/module/kibana/stats/_meta/data.json @@ -16,7 +16,7 @@ "host": { "name": "0.0.0.0" }, - "index": "b04775fa6831", + "index": ".kibana", "name": "b04775fa6831", "os": { "distro": "CentOS", @@ -88,4 +88,4 @@ "type": "kibana", "version": "7.14.0" } -} \ No newline at end of file +} diff --git a/metricbeat/module/kibana/stats/data.go b/metricbeat/module/kibana/stats/data.go index 79e6454f805..a2148f64e84 100644 --- a/metricbeat/module/kibana/stats/data.go +++ b/metricbeat/module/kibana/stats/data.go @@ -52,7 +52,7 @@ var ( "uuid": c.Str("kibana.uuid"), "name": c.Str("kibana.name"), - "index": c.Str("kibana.name"), + "index": c.Str("kibana.index"), "host": s.Object{ "name": c.Str("kibana.host"), }, diff --git a/metricbeat/module/kubernetes/_meta/config.reference.yml b/metricbeat/module/kubernetes/_meta/config.reference.yml index 09fb14662a2..3a6e22af69b 100644 --- a/metricbeat/module/kubernetes/_meta/config.reference.yml +++ b/metricbeat/module/kubernetes/_meta/config.reference.yml @@ -23,6 +23,16 @@ # If kube_config is not set, KUBECONFIG environment variable will be checked # and if not present it will fall back to InCluster #kube_config: ~/.kube/config + # To configure additionally node and namespace metadata, added to pod, service and container resource types, + # `add_resource_metadata` can be defined. + # By default all labels will be included while annotations are not added by default. + # add_resource_metadata: + # namespace: + # include_labels: ["namespacelabel1"] + # node: + # include_labels: ["nodelabel2"] + # include_annotations: ["nodeannotation1"] + # deployment: false # Kubernetes client QPS and burst can be configured additionally #kube_client_options: # qps: 5 @@ -57,6 +67,38 @@ # If kube_config is not set, KUBECONFIG environment variable will be checked # and if not present it will fall back to InCluster #kube_config: ~/.kube/config + # To configure additionally node and namespace metadata, added to pod, service and container resource types, + # `add_resource_metadata` can be defined. + # By default all labels will be included while annotations are not added by default. + # add_resource_metadata: + # namespace: + # include_labels: ["namespacelabel1"] + # node: + # include_labels: ["nodelabel2"] + # include_annotations: ["nodeannotation1"] + # deployment: false + # Kubernetes client QPS and burst can be configured additionally + #kube_client_options: + # qps: 5 + # burst: 10 + +# Kubernetes Events +- module: kubernetes + enabled: true + metricsets: + - event + period: 10s + # Skip events older than Metricbeat's statup time is enabled by default. + # Setting to false the skip_older setting will stop filtering older events. + # This setting is also useful went Event's timestamps are not populated properly. + #skip_older: false + # If kube_config is not set, KUBECONFIG environment variable will be checked + # and if not present it will fall back to InCluster + #kube_config: ~/.kube/config + # Set the namespace to watch for events + #namespace: staging + # Set the sync period of the watchers + #sync_period: 10m # Kubernetes client QPS and burst can be configured additionally #kube_client_options: # qps: 5 @@ -74,8 +116,6 @@ - /var/run/secrets/kubernetes.io/serviceaccount/ca.crt period: 30s - - # Kubernetes proxy server # (when running metricbeat locally at hosts or as a daemonset + host network) - module: kubernetes diff --git a/metricbeat/module/kubernetes/_meta/config.yml b/metricbeat/module/kubernetes/_meta/config.yml index dc9b3697ead..9e8eaee745c 100644 --- a/metricbeat/module/kubernetes/_meta/config.yml +++ b/metricbeat/module/kubernetes/_meta/config.yml @@ -22,6 +22,16 @@ #host: node_name # If kube_config is not set, KUBECONFIG environment variable will be checked # and if not present it will fall back to InCluster + # To configure additionally node and namespace metadata, added to pod, service and container resource types, + # `add_resource_metadata` can be defined. + # By default all labels will be included while annotations are not added by default. + # add_resource_metadata: + # namespace: + # include_labels: ["namespacelabel1"] + # node: + # include_labels: ["nodelabel2"] + # include_annotations: ["nodeannotation1"] + # deployment: false #kube_config: ~/.kube/config # Kubernetes client QPS and burst can be configured additionally #kube_client_options: @@ -48,7 +58,24 @@ # hosts: ["kube-state-metrics:8080"] # add_metadata: true -# Kubernetes events +# Kubernetes Events #- module: kubernetes +# enabled: true # metricsets: # - event +# period: 10s +# # Skip events older than Metricbeat's statup time is enabled by default. +# # Setting to false the skip_older setting will stop filtering older events. +# # This setting is also useful went Event's timestamps are not populated properly. +# skip_older: false +# # If kube_config is not set, KUBECONFIG environment variable will be checked +# # and if not present it will fall back to InCluster +# kube_config: ~/.kube/config +# # Set the namespace to watch for events +# namespace: staging +# # Set the sync period of the watchers +# sync_period: 10m +# # Kubernetes client QPS and burst can be configured additionally +# kube_client_options: +# qps: 5 +# burst: 10 diff --git a/metricbeat/module/kubernetes/_meta/docs.asciidoc b/metricbeat/module/kubernetes/_meta/docs.asciidoc index ac819848f33..8e8e8419523 100644 --- a/metricbeat/module/kubernetes/_meta/docs.asciidoc +++ b/metricbeat/module/kubernetes/_meta/docs.asciidoc @@ -146,7 +146,7 @@ roleRef: === Compatibility The Kubernetes module is tested with the following versions of Kubernetes: -1.14.x, 1.17.x, 1.18.x, 1.19.x, 1.20.x, 1.21.x +1.18.x, 1.19.x, 1.20.x, 1.21.x, 1.22.x, 1.23.x [float] === Dashboard diff --git a/metricbeat/module/kubernetes/_meta/kibana/7/visualization/174a6ad0-30e0-11e7-8df8-6d3604a72912-ecs.json b/metricbeat/module/kubernetes/_meta/kibana/7/visualization/174a6ad0-30e0-11e7-8df8-6d3604a72912-ecs.json index 12a7a5a03b6..530eda35e08 100644 --- a/metricbeat/module/kubernetes/_meta/kibana/7/visualization/174a6ad0-30e0-11e7-8df8-6d3604a72912-ecs.json +++ b/metricbeat/module/kubernetes/_meta/kibana/7/visualization/174a6ad0-30e0-11e7-8df8-6d3604a72912-ecs.json @@ -57,7 +57,6 @@ "type": "sum" } ], - "override_index_pattern": 1, "point_size": 1, "seperate_axis": 0, "series_interval": "10s", @@ -84,4 +83,4 @@ "type": "visualization", "updated_at": "2021-08-04T16:31:37.319Z", "version": "WzQwMjMsMV0=" -} \ No newline at end of file +} diff --git a/metricbeat/module/kubernetes/_meta/kibana/7/visualization/da1ff7c0-30ed-11e7-b9e5-2b5b07213ab3-ecs.json b/metricbeat/module/kubernetes/_meta/kibana/7/visualization/da1ff7c0-30ed-11e7-b9e5-2b5b07213ab3-ecs.json index a72257a0686..5d3875f54da 100644 --- a/metricbeat/module/kubernetes/_meta/kibana/7/visualization/da1ff7c0-30ed-11e7-b9e5-2b5b07213ab3-ecs.json +++ b/metricbeat/module/kubernetes/_meta/kibana/7/visualization/da1ff7c0-30ed-11e7-b9e5-2b5b07213ab3-ecs.json @@ -57,12 +57,9 @@ "type": "sum" } ], - "override_index_pattern": 1, "point_size": 1, "seperate_axis": 0, - "series_index_pattern": "*", "series_interval": "10s", - "series_time_field": "@timestamp", "split_color_mode": "gradient", "split_mode": "everything", "stacked": "none" @@ -86,4 +83,4 @@ "type": "visualization", "updated_at": "2021-08-04T16:31:37.319Z", "version": "WzQwMjUsMV0=" -} \ No newline at end of file +} diff --git a/metricbeat/module/kubernetes/_meta/kibana/7/visualization/e1018b90-2bfb-11e7-859b-f78b612cde28-ecs.json b/metricbeat/module/kubernetes/_meta/kibana/7/visualization/e1018b90-2bfb-11e7-859b-f78b612cde28-ecs.json index 3c3492288fb..c352ee06e79 100644 --- a/metricbeat/module/kubernetes/_meta/kibana/7/visualization/e1018b90-2bfb-11e7-859b-f78b612cde28-ecs.json +++ b/metricbeat/module/kubernetes/_meta/kibana/7/visualization/e1018b90-2bfb-11e7-859b-f78b612cde28-ecs.json @@ -57,11 +57,9 @@ "type": "sum" } ], - "override_index_pattern": 1, "point_size": 1, "seperate_axis": 0, "series_interval": "10s", - "series_time_field": "@timestamp", "split_color_mode": "gradient", "split_mode": "everything", "stacked": "none" @@ -85,4 +83,4 @@ "type": "visualization", "updated_at": "2021-08-04T16:31:37.319Z", "version": "WzQwMTYsMV0=" -} \ No newline at end of file +} diff --git a/metricbeat/module/kubernetes/container/_meta/fields.yml b/metricbeat/module/kubernetes/container/_meta/fields.yml index 8bd8bd6449a..81b99f75c0c 100644 --- a/metricbeat/module/kubernetes/container/_meta/fields.yml +++ b/metricbeat/module/kubernetes/container/_meta/fields.yml @@ -126,6 +126,11 @@ format: bytes description: > Working set memory usage + - name: limit.pct + type: scaled_float + format: percent + description: > + Working set memory usage as a percentage of the defined limit for the container (or total node allocatable memory if unlimited) - name: pagefaults type: double description: > diff --git a/metricbeat/module/kubernetes/container/container_test.go b/metricbeat/module/kubernetes/container/container_test.go index 30009846169..816464d7b9d 100644 --- a/metricbeat/module/kubernetes/container/container_test.go +++ b/metricbeat/module/kubernetes/container/container_test.go @@ -69,10 +69,11 @@ func TestEventMapping(t *testing.T) { "memory.majorpagefaults": 0, // calculated pct fields: - "cpu.usage.node.pct": 0.005631997, - "cpu.usage.limit.pct": 0.005631997, - "memory.usage.node.pct": 0.01, - "memory.usage.limit.pct": 0.1, + "cpu.usage.node.pct": 0.005631997, + "cpu.usage.limit.pct": 0.005631997, + "memory.usage.node.pct": 0.01, + "memory.usage.limit.pct": 0.1, + "memory.workingset.limit.pct": 0.09943977591036414, "name": "nginx", diff --git a/metricbeat/module/kubernetes/container/data.go b/metricbeat/module/kubernetes/container/data.go index 78c6d29b83e..ad2e1243339 100644 --- a/metricbeat/module/kubernetes/container/data.go +++ b/metricbeat/module/kubernetes/container/data.go @@ -43,9 +43,7 @@ func eventMapping(content []byte, perfMetrics *util.PerfMetricsCache) ([]common. for _, container := range pod.Containers { containerEvent := common.MapStr{ mb.ModuleDataKey: common.MapStr{ - "namespace": common.MapStr{ - "name": pod.PodRef.Namespace, - }, + "namespace": pod.PodRef.Namespace, "node": common.MapStr{ "name": node.NodeName, }, @@ -137,6 +135,7 @@ func eventMapping(content []byte, perfMetrics *util.PerfMetricsCache) ([]common. if memLimit > 0 { containerEvent.Put("memory.usage.limit.pct", float64(container.Memory.UsageBytes)/memLimit) + containerEvent.Put("memory.workingset.limit.pct", float64(container.Memory.WorkingSetBytes)/memLimit) } events = append(events, containerEvent) diff --git a/metricbeat/module/kubernetes/event/config.go b/metricbeat/module/kubernetes/event/config.go index 07e9e7da64e..be9b0c21a15 100644 --- a/metricbeat/module/kubernetes/event/config.go +++ b/metricbeat/module/kubernetes/event/config.go @@ -30,6 +30,7 @@ type kubeEventsConfig struct { SyncPeriod time.Duration `config:"sync_period"` LabelsDedot bool `config:"labels.dedot"` AnnotationsDedot bool `config:"annotations.dedot"` + SkipOlder bool `config:"skip_older"` } type Enabled struct { @@ -41,5 +42,6 @@ func defaultKubernetesEventsConfig() kubeEventsConfig { SyncPeriod: 10 * time.Minute, LabelsDedot: true, AnnotationsDedot: true, + SkipOlder: true, } } diff --git a/metricbeat/module/kubernetes/event/event.go b/metricbeat/module/kubernetes/event/event.go index 639e7d6ec15..9c844be950c 100644 --- a/metricbeat/module/kubernetes/event/event.go +++ b/metricbeat/module/kubernetes/event/event.go @@ -41,6 +41,7 @@ type MetricSet struct { watcher kubernetes.Watcher watchOptions kubernetes.WatchOptions dedotConfig dedotConfig + skipOlder bool } // dedotConfig defines LabelsDedot and AnnotationsDedot. @@ -87,6 +88,7 @@ func New(base mb.BaseMetricSet) (mb.MetricSet, error) { dedotConfig: dedotConfig, watcher: watcher, watchOptions: watchOptions, + skipOlder: config.SkipOlder, }, nil } @@ -104,10 +106,18 @@ func (m *MetricSet) Run(reporter mb.PushReporter) { DeleteFunc: nil, } m.watcher.AddEventHandler(kubernetes.FilteringResourceEventHandler{ - // skip events happened before watch FilterFunc: func(obj interface{}) bool { eve := obj.(*kubernetes.Event) - if kubernetes.Time(&eve.LastTimestamp).Before(now) { + // if fields are null they are decoded to `0001-01-01 00:00:00 +0000 UTC` + // so we need to check if they are valid first + lastTimestampValid := !kubernetes.Time(&eve.LastTimestamp).IsZero() + eventTimeValid := !kubernetes.MicroTime(&eve.EventTime).IsZero() + // if skipOlder, skip events happened before watch + if m.skipOlder && kubernetes.Time(&eve.LastTimestamp).Before(now) && lastTimestampValid { + return false + } else if m.skipOlder && kubernetes.MicroTime(&eve.EventTime).Before(now) && eventTimeValid { + // there might be cases that `LastTimestamp` is not a valid number so double check + // with `EventTime` return false } return true @@ -126,10 +136,8 @@ func generateMapStrFromEvent(eve *kubernetes.Event, dedotConfig dedotConfig) com "timestamp": common.MapStr{ "created": kubernetes.Time(&eve.ObjectMeta.CreationTimestamp).UTC(), }, - "namespace": common.MapStr{ - "name": eve.ObjectMeta.GetNamespace(), - }, "name": eve.ObjectMeta.GetName(), + "namespace": eve.ObjectMeta.GetNamespace(), "self_link": eve.ObjectMeta.GetSelfLink(), "generate_name": eve.ObjectMeta.GetGenerateName(), "uid": eve.ObjectMeta.GetUID(), diff --git a/metricbeat/module/kubernetes/fields.go b/metricbeat/module/kubernetes/fields.go index 73b71223fe1..e634e74a200 100644 --- a/metricbeat/module/kubernetes/fields.go +++ b/metricbeat/module/kubernetes/fields.go @@ -32,5 +32,5 @@ func init() { // AssetKubernetes returns asset data. // This is the base64 encoded zlib format compressed contents of module/kubernetes. func AssetKubernetes() string { - return "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" + return "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" } diff --git a/metricbeat/module/kubernetes/pod/_meta/fields.yml b/metricbeat/module/kubernetes/pod/_meta/fields.yml index 0537faab52a..0b46d290839 100644 --- a/metricbeat/module/kubernetes/pod/_meta/fields.yml +++ b/metricbeat/module/kubernetes/pod/_meta/fields.yml @@ -94,6 +94,11 @@ format: bytes description: > Total working set memory + - name: limit.pct + type: scaled_float + format: percent + description: > + Working set memory usage as a percentage of the defined limit for the pod containers (or total node allocatable memory if unlimited) - name: rss type: group fields: diff --git a/metricbeat/module/kubernetes/pod/data.go b/metricbeat/module/kubernetes/pod/data.go index 8e4ffc759eb..fdb604d4e17 100644 --- a/metricbeat/module/kubernetes/pod/data.go +++ b/metricbeat/module/kubernetes/pod/data.go @@ -59,9 +59,7 @@ func eventMapping(content []byte, perfMetrics *util.PerfMetricsCache) ([]common. podEvent := common.MapStr{ mb.ModuleDataKey: common.MapStr{ - "namespace": common.MapStr{ - "name": pod.PodRef.Namespace, - }, + "namespace": pod.PodRef.Namespace, "node": common.MapStr{ "name": node.NodeName, }, @@ -130,6 +128,8 @@ func eventMapping(content []byte, perfMetrics *util.PerfMetricsCache) ([]common. } if memLimit > 0 { podEvent.Put("memory.usage.limit.pct", float64(usageMem)/memLimit) + podEvent.Put("memory.working_set.limit.pct", float64(workingSet)/memLimit) + } } @@ -139,6 +139,7 @@ func eventMapping(content []byte, perfMetrics *util.PerfMetricsCache) ([]common. } if memLimit > 0 { podEvent.Put("memory.usage.limit.pct", float64(workingSet)/memLimit) + podEvent.Put("memory.working_set.limit.pct", float64(workingSet)/memLimit) } } diff --git a/metricbeat/module/kubernetes/pod/pod_test.go b/metricbeat/module/kubernetes/pod/pod_test.go index 41340e5dede..37486ad58e8 100644 --- a/metricbeat/module/kubernetes/pod/pod_test.go +++ b/metricbeat/module/kubernetes/pod/pod_test.go @@ -64,9 +64,10 @@ func TestEventMapping(t *testing.T) { "cpu.usage.node.pct": 0.005631997, "cpu.usage.limit.pct": 0.005631997, - "memory.usage.bytes": 1462272, - "memory.usage.node.pct": 0.01, - "memory.usage.limit.pct": 0.1, + "memory.usage.bytes": 1462272, + "memory.usage.node.pct": 0.01, + "memory.usage.limit.pct": 0.1, + "memory.working_set.limit.pct": 0.09943977591036414, } for k, v := range testCases { diff --git a/metricbeat/module/kubernetes/state_container/_meta/test/ksm.v1.3.0.expected b/metricbeat/module/kubernetes/state_container/_meta/test/ksm.v1.3.0.expected index 004b0ee9968..9bfecbe3c39 100644 --- a/metricbeat/module/kubernetes/state_container/_meta/test/ksm.v1.3.0.expected +++ b/metricbeat/module/kubernetes/state_container/_meta/test/ksm.v1.3.0.expected @@ -10,9 +10,7 @@ } }, "ModuleFields": { - "namespace": { - "name": "kube-system" - }, + "namespace": "kube-system", "node": { "name": "minikube" }, @@ -53,37 +51,30 @@ { "RootFields": { "container": { - "id": "ab382dbe8f8265f88ee9fec7de142f778da4a5fd9fe0334e3bdb6fe851124c08", + "id": "e9568dfef1dd249cabac4bf09e6bf4a239fe738ae20eba072b6516676fce4bf6", "image": { - "name": "k8s.gcr.io/kube-addon-manager:v8.6" + "name": "gcr.io/google_containers/kube-apiserver-amd64:v1.9.7" }, "runtime": "docker" } }, "ModuleFields": { - "namespace": { - "name": "kube-system" - }, + "namespace": "kube-system", "node": { "name": "minikube" }, "pod": { - "name": "kube-addon-manager-minikube" + "name": "kube-apiserver-minikube" } }, "MetricSetFields": { "cpu": { "request": { - "cores": 0.005 - } - }, - "id": "docker://ab382dbe8f8265f88ee9fec7de142f778da4a5fd9fe0334e3bdb6fe851124c08", - "memory": { - "request": { - "bytes": 52428800 + "cores": 0.25 } }, - "name": "kube-addon-manager", + "id": "docker://e9568dfef1dd249cabac4bf09e6bf4a239fe738ae20eba072b6516676fce4bf6", + "name": "kube-apiserver", "status": { "phase": "running", "ready": true, @@ -104,32 +95,25 @@ { "RootFields": { "container": { - "id": "e9568dfef1dd249cabac4bf09e6bf4a239fe738ae20eba072b6516676fce4bf6", + "id": "76c260259ddfd0267b5acb4e514465215ef1ebfa93a4057d592828772e6b39f5", "image": { - "name": "gcr.io/google_containers/kube-apiserver-amd64:v1.9.7" + "name": "gcr.io/google_containers/kube-proxy-amd64:v1.9.7" }, "runtime": "docker" } }, "ModuleFields": { - "namespace": { - "name": "kube-system" - }, + "namespace": "kube-system", "node": { "name": "minikube" }, "pod": { - "name": "kube-apiserver-minikube" + "name": "kube-proxy-znhg6" } }, "MetricSetFields": { - "cpu": { - "request": { - "cores": 0.25 - } - }, - "id": "docker://e9568dfef1dd249cabac4bf09e6bf4a239fe738ae20eba072b6516676fce4bf6", - "name": "kube-apiserver", + "id": "docker://76c260259ddfd0267b5acb4e514465215ef1ebfa93a4057d592828772e6b39f5", + "name": "kube-proxy", "status": { "phase": "running", "ready": true, @@ -150,43 +134,30 @@ { "RootFields": { "container": { - "id": "948c4ebd8ca4fdf352e7fbf7f5c5d381af7e615ced435dc42fde0c1d25851320", + "id": "4beb9aab887ca162c9cb3534c4826156636241052cd548153eaa2a170b6d102f", "image": { - "name": "k8s.gcr.io/addon-resizer:1.7" + "name": "gcr.io/google_containers/kube-controller-manager-amd64:v1.9.7" }, "runtime": "docker" } }, "ModuleFields": { - "namespace": { - "name": "kube-system" - }, + "namespace": "kube-system", "node": { "name": "minikube" }, "pod": { - "name": "kube-state-metrics-6479d88c5c-5b6cl" + "name": "kube-controller-manager-minikube" } }, "MetricSetFields": { "cpu": { - "limit": { - "cores": 0.1 - }, - "request": { - "cores": 0.1 - } - }, - "id": "docker://948c4ebd8ca4fdf352e7fbf7f5c5d381af7e615ced435dc42fde0c1d25851320", - "memory": { - "limit": { - "bytes": 31457280 - }, "request": { - "bytes": 31457280 + "cores": 0.2 } }, - "name": "addon-resizer", + "id": "docker://4beb9aab887ca162c9cb3534c4826156636241052cd548153eaa2a170b6d102f", + "name": "kube-controller-manager", "status": { "phase": "running", "ready": true, @@ -207,27 +178,41 @@ { "RootFields": { "container": { - "id": "76c260259ddfd0267b5acb4e514465215ef1ebfa93a4057d592828772e6b39f5", + "id": "948c4ebd8ca4fdf352e7fbf7f5c5d381af7e615ced435dc42fde0c1d25851320", "image": { - "name": "gcr.io/google_containers/kube-proxy-amd64:v1.9.7" + "name": "k8s.gcr.io/addon-resizer:1.7" }, "runtime": "docker" } }, "ModuleFields": { - "namespace": { - "name": "kube-system" - }, + "namespace": "kube-system", "node": { "name": "minikube" }, "pod": { - "name": "kube-proxy-znhg6" + "name": "kube-state-metrics-6479d88c5c-5b6cl" } }, "MetricSetFields": { - "id": "docker://76c260259ddfd0267b5acb4e514465215ef1ebfa93a4057d592828772e6b39f5", - "name": "kube-proxy", + "cpu": { + "limit": { + "cores": 0.1 + }, + "request": { + "cores": 0.1 + } + }, + "id": "docker://948c4ebd8ca4fdf352e7fbf7f5c5d381af7e615ced435dc42fde0c1d25851320", + "memory": { + "limit": { + "bytes": 31457280 + }, + "request": { + "bytes": 31457280 + } + }, + "name": "addon-resizer", "status": { "phase": "running", "ready": true, @@ -256,9 +241,7 @@ } }, "ModuleFields": { - "namespace": { - "name": "kube-system" - }, + "namespace": "kube-system", "node": { "name": "minikube" }, @@ -302,9 +285,7 @@ } }, "ModuleFields": { - "namespace": { - "name": "kube-system" - }, + "namespace": "kube-system", "node": { "name": "minikube" }, @@ -348,32 +329,25 @@ { "RootFields": { "container": { - "id": "4beb9aab887ca162c9cb3534c4826156636241052cd548153eaa2a170b6d102f", + "id": "6e96fd8a687409b2314dcc01f209bb0c813c2fb08b8f75ad1695e120d41e1a2a", "image": { - "name": "gcr.io/google_containers/kube-controller-manager-amd64:v1.9.7" + "name": "gcr.io/google_containers/etcd-amd64:3.1.11" }, "runtime": "docker" } }, "ModuleFields": { - "namespace": { - "name": "kube-system" - }, + "namespace": "kube-system", "node": { "name": "minikube" }, "pod": { - "name": "kube-controller-manager-minikube" + "name": "etcd-minikube" } }, "MetricSetFields": { - "cpu": { - "request": { - "cores": 0.2 - } - }, - "id": "docker://4beb9aab887ca162c9cb3534c4826156636241052cd548153eaa2a170b6d102f", - "name": "kube-controller-manager", + "id": "docker://6e96fd8a687409b2314dcc01f209bb0c813c2fb08b8f75ad1695e120d41e1a2a", + "name": "etcd", "status": { "phase": "running", "ready": true, @@ -394,43 +368,35 @@ { "RootFields": { "container": { - "id": "88951e0178ea5131fa3e2d7cafacb3a7e63700795dd6fa0d40ed2e4ac1f52f9c", + "id": "ab382dbe8f8265f88ee9fec7de142f778da4a5fd9fe0334e3bdb6fe851124c08", "image": { - "name": "quay.io/coreos/kube-state-metrics:v1.3.0" + "name": "k8s.gcr.io/kube-addon-manager:v8.6" }, "runtime": "docker" } }, "ModuleFields": { - "namespace": { - "name": "kube-system" - }, + "namespace": "kube-system", "node": { "name": "minikube" }, "pod": { - "name": "kube-state-metrics-6479d88c5c-5b6cl" + "name": "kube-addon-manager-minikube" } }, "MetricSetFields": { "cpu": { - "limit": { - "cores": 0.101 - }, "request": { - "cores": 0.101 + "cores": 0.005 } }, - "id": "docker://88951e0178ea5131fa3e2d7cafacb3a7e63700795dd6fa0d40ed2e4ac1f52f9c", + "id": "docker://ab382dbe8f8265f88ee9fec7de142f778da4a5fd9fe0334e3bdb6fe851124c08", "memory": { - "limit": { - "bytes": 106954752 - }, "request": { - "bytes": 106954752 + "bytes": 52428800 } }, - "name": "kube-state-metrics", + "name": "kube-addon-manager", "status": { "phase": "running", "ready": true, @@ -451,41 +417,44 @@ { "RootFields": { "container": { - "id": "aad0addd205dc72dc7abc8f9d02a1b429a2f2e1df3acc60431ca6b79746c093b", + "id": "88951e0178ea5131fa3e2d7cafacb3a7e63700795dd6fa0d40ed2e4ac1f52f9c", "image": { - "name": "gcr.io/google_containers/k8s-dns-sidecar-amd64:1.14.7" + "name": "quay.io/coreos/kube-state-metrics:v1.3.0" }, "runtime": "docker" } }, "ModuleFields": { - "namespace": { - "name": "kube-system" - }, + "namespace": "kube-system", "node": { "name": "minikube" }, "pod": { - "name": "kube-dns-6f4fd4bdf-wlmht" + "name": "kube-state-metrics-6479d88c5c-5b6cl" } }, "MetricSetFields": { "cpu": { + "limit": { + "cores": 0.101 + }, "request": { - "cores": 0.01 + "cores": 0.101 } }, - "id": "docker://aad0addd205dc72dc7abc8f9d02a1b429a2f2e1df3acc60431ca6b79746c093b", + "id": "docker://88951e0178ea5131fa3e2d7cafacb3a7e63700795dd6fa0d40ed2e4ac1f52f9c", "memory": { + "limit": { + "bytes": 106954752 + }, "request": { - "bytes": 20971520 + "bytes": 106954752 } }, - "name": "sidecar", + "name": "kube-state-metrics", "status": { "phase": "running", "ready": true, - "reason": "OOMKilled", "restarts": 0 } }, @@ -511,9 +480,7 @@ } }, "ModuleFields": { - "namespace": { - "name": "kube-system" - }, + "namespace": "kube-system", "node": { "name": "minikube" }, @@ -544,30 +511,39 @@ { "RootFields": { "container": { - "id": "6e96fd8a687409b2314dcc01f209bb0c813c2fb08b8f75ad1695e120d41e1a2a", + "id": "aad0addd205dc72dc7abc8f9d02a1b429a2f2e1df3acc60431ca6b79746c093b", "image": { - "name": "gcr.io/google_containers/etcd-amd64:3.1.11" + "name": "gcr.io/google_containers/k8s-dns-sidecar-amd64:1.14.7" }, "runtime": "docker" } }, "ModuleFields": { - "namespace": { - "name": "kube-system" - }, + "namespace": "kube-system", "node": { "name": "minikube" }, "pod": { - "name": "etcd-minikube" + "name": "kube-dns-6f4fd4bdf-wlmht" } }, "MetricSetFields": { - "id": "docker://6e96fd8a687409b2314dcc01f209bb0c813c2fb08b8f75ad1695e120d41e1a2a", - "name": "etcd", + "cpu": { + "request": { + "cores": 0.01 + } + }, + "id": "docker://aad0addd205dc72dc7abc8f9d02a1b429a2f2e1df3acc60431ca6b79746c093b", + "memory": { + "request": { + "bytes": 20971520 + } + }, + "name": "sidecar", "status": { "phase": "running", "ready": true, + "reason": "OOMKilled", "restarts": 0 } }, @@ -593,9 +569,7 @@ } }, "ModuleFields": { - "namespace": { - "name": "kube-system" - }, + "namespace": "kube-system", "node": { "name": "minikube" }, diff --git a/metricbeat/module/kubernetes/state_container/_meta/test/ksm.v1.8.0.expected b/metricbeat/module/kubernetes/state_container/_meta/test/ksm.v1.8.0.expected index ce83e911445..4277911c4b3 100644 --- a/metricbeat/module/kubernetes/state_container/_meta/test/ksm.v1.8.0.expected +++ b/metricbeat/module/kubernetes/state_container/_meta/test/ksm.v1.8.0.expected @@ -2,31 +2,38 @@ { "RootFields": { "container": { - "id": "30216f9823ca7d3454987075dd7256b665b14b2333c9a6762b127b6378516609", + "id": "f13c53a3ed0f3626b33b3c588d6913257320f65714eff28f25ead8f7663dc93b", "image": { - "name": "busybox:latest" + "name": "k8s.gcr.io/kube-addon-manager:v9.0.2" }, "runtime": "docker" } }, "ModuleFields": { - "namespace": { - "name": "default" - }, + "namespace": "kube-system", "node": { "name": "minikube" }, "pod": { - "name": "hello-1578512100-vr7wj" + "name": "kube-addon-manager-minikube" } }, "MetricSetFields": { - "id": "docker://30216f9823ca7d3454987075dd7256b665b14b2333c9a6762b127b6378516609", - "name": "hello", + "cpu": { + "request": { + "cores": 0.005 + } + }, + "id": "docker://f13c53a3ed0f3626b33b3c588d6913257320f65714eff28f25ead8f7663dc93b", + "memory": { + "request": { + "bytes": 52428800 + } + }, + "name": "kube-addon-manager", "status": { - "phase": "terminated", - "ready": false, - "reason": "Completed", + "phase": "running", + "ready": true, "restarts": 0 } }, @@ -52,9 +59,7 @@ } }, "ModuleFields": { - "namespace": { - "name": "kube-system" - }, + "namespace": "kube-system", "node": { "name": "minikube" }, @@ -90,40 +95,25 @@ { "RootFields": { "container": { - "id": "15ada7864628d1c8007c01420e5887a501590d3bc9c25628a4770172ad615112", + "id": "c152296116c064db311061cf6c39cff2de8d66339c954505cb68816464cf4a03", "image": { - "name": "k8s.gcr.io/coredns:1.6.2" + "name": "k8s.gcr.io/kube-proxy:v1.16.2" }, "runtime": "docker" } }, "ModuleFields": { - "namespace": { - "name": "kube-system" - }, + "namespace": "kube-system", "node": { "name": "minikube" }, "pod": { - "name": "coredns-5644d7b6d9-k6wsp" + "name": "kube-proxy-dwg6l" } }, "MetricSetFields": { - "cpu": { - "request": { - "cores": 0.1 - } - }, - "id": "docker://15ada7864628d1c8007c01420e5887a501590d3bc9c25628a4770172ad615112", - "memory": { - "limit": { - "bytes": 178257920 - }, - "request": { - "bytes": 73400320 - } - }, - "name": "coredns", + "id": "docker://c152296116c064db311061cf6c39cff2de8d66339c954505cb68816464cf4a03", + "name": "kube-proxy", "status": { "phase": "running", "ready": true, @@ -144,27 +134,30 @@ { "RootFields": { "container": { - "id": "a4cec783af3614b137f4b449eebf3ac61eaf0a8661cb2f4847741be5a24de0bf", + "id": "465ebffafd7fc238a2fa2e764255efcbff88d5513f4c68f57d70932985428d12", "image": { - "name": "k8s.gcr.io/nginx-slim:0.8" + "name": "k8s.gcr.io/kube-controller-manager:v1.16.2" }, "runtime": "docker" } }, "ModuleFields": { - "namespace": { - "name": "default" - }, + "namespace": "kube-system", "node": { "name": "minikube" }, "pod": { - "name": "web-0" + "name": "kube-controller-manager-minikube" } }, "MetricSetFields": { - "id": "docker://a4cec783af3614b137f4b449eebf3ac61eaf0a8661cb2f4847741be5a24de0bf", - "name": "nginx", + "cpu": { + "request": { + "cores": 0.2 + } + }, + "id": "docker://465ebffafd7fc238a2fa2e764255efcbff88d5513f4c68f57d70932985428d12", + "name": "kube-controller-manager", "status": { "phase": "running", "ready": true, @@ -185,30 +178,29 @@ { "RootFields": { "container": { - "id": "e0b05fcb32abf937c395942e0234b5dfc834206149bbb95afa585c51693650f3", + "id": "30216f9823ca7d3454987075dd7256b665b14b2333c9a6762b127b6378516609", "image": { - "name": "gcr.io/k8s-minikube/storage-provisioner:v1.8.1" + "name": "busybox:latest" }, "runtime": "docker" } }, "ModuleFields": { - "namespace": { - "name": "kube-system" - }, + "namespace": "default", "node": { "name": "minikube" }, "pod": { - "name": "storage-provisioner" + "name": "hello-1578512100-vr7wj" } }, "MetricSetFields": { - "id": "docker://e0b05fcb32abf937c395942e0234b5dfc834206149bbb95afa585c51693650f3", - "name": "storage-provisioner", + "id": "docker://30216f9823ca7d3454987075dd7256b665b14b2333c9a6762b127b6378516609", + "name": "hello", "status": { - "phase": "running", - "ready": true, + "phase": "terminated", + "ready": false, + "reason": "Completed", "restarts": 0 } }, @@ -226,37 +218,38 @@ { "RootFields": { "container": { - "id": "f13c53a3ed0f3626b33b3c588d6913257320f65714eff28f25ead8f7663dc93b", + "id": "f8fe5be1dbb1931d702c89235c79965730cbcced7b0ced9895f6c54c1ae8e5c3", "image": { - "name": "k8s.gcr.io/kube-addon-manager:v9.0.2" + "name": "k8s.gcr.io/coredns:1.6.2" }, "runtime": "docker" } }, "ModuleFields": { - "namespace": { - "name": "kube-system" - }, + "namespace": "kube-system", "node": { "name": "minikube" }, "pod": { - "name": "kube-addon-manager-minikube" + "name": "coredns-5644d7b6d9-fhwjd" } }, "MetricSetFields": { "cpu": { "request": { - "cores": 0.005 + "cores": 0.1 } }, - "id": "docker://f13c53a3ed0f3626b33b3c588d6913257320f65714eff28f25ead8f7663dc93b", + "id": "docker://f8fe5be1dbb1931d702c89235c79965730cbcced7b0ced9895f6c54c1ae8e5c3", "memory": { + "limit": { + "bytes": 178257920 + }, "request": { - "bytes": 52428800 + "bytes": 73400320 } }, - "name": "kube-addon-manager", + "name": "coredns", "status": { "phase": "running", "ready": true, @@ -277,27 +270,25 @@ { "RootFields": { "container": { - "id": "669cc415d86b872450deaada60c73cca387ca23a7b0f21c5b146467b95cf1f76", + "id": "e0b05fcb32abf937c395942e0234b5dfc834206149bbb95afa585c51693650f3", "image": { - "name": "k8s.gcr.io/nginx-slim:0.8" + "name": "gcr.io/k8s-minikube/storage-provisioner:v1.8.1" }, "runtime": "docker" } }, "ModuleFields": { - "namespace": { - "name": "default" - }, + "namespace": "kube-system", "node": { "name": "minikube" }, "pod": { - "name": "web-1" + "name": "storage-provisioner" } }, "MetricSetFields": { - "id": "docker://669cc415d86b872450deaada60c73cca387ca23a7b0f21c5b146467b95cf1f76", - "name": "nginx", + "id": "docker://e0b05fcb32abf937c395942e0234b5dfc834206149bbb95afa585c51693650f3", + "name": "storage-provisioner", "status": { "phase": "running", "ready": true, @@ -318,32 +309,25 @@ { "RootFields": { "container": { - "id": "cdaefb4df2f2add498f884fdc717a6ca8d2681c1636934747de600e6427e0c0d", + "id": "2e0519a3fcd62acea8f4253b994ce53356d89171c0eb0920a13fe58b637d8cdb", "image": { - "name": "k8s.gcr.io/kube-apiserver:v1.16.2" + "name": "quay.io/coreos/kube-state-metrics:v1.8.0" }, "runtime": "docker" } }, "ModuleFields": { - "namespace": { - "name": "kube-system" - }, + "namespace": "kube-system", "node": { "name": "minikube" }, "pod": { - "name": "kube-apiserver-minikube" + "name": "kube-state-metrics-898d4db8d-dqmtg" } }, "MetricSetFields": { - "cpu": { - "request": { - "cores": 0.25 - } - }, - "id": "docker://cdaefb4df2f2add498f884fdc717a6ca8d2681c1636934747de600e6427e0c0d", - "name": "kube-apiserver", + "id": "docker://2e0519a3fcd62acea8f4253b994ce53356d89171c0eb0920a13fe58b637d8cdb", + "name": "kube-state-metrics", "status": { "phase": "running", "ready": true, @@ -364,27 +348,38 @@ { "RootFields": { "container": { - "id": "c152296116c064db311061cf6c39cff2de8d66339c954505cb68816464cf4a03", + "id": "15ada7864628d1c8007c01420e5887a501590d3bc9c25628a4770172ad615112", "image": { - "name": "k8s.gcr.io/kube-proxy:v1.16.2" + "name": "k8s.gcr.io/coredns:1.6.2" }, "runtime": "docker" } }, "ModuleFields": { - "namespace": { - "name": "kube-system" - }, + "namespace": "kube-system", "node": { "name": "minikube" }, "pod": { - "name": "kube-proxy-dwg6l" + "name": "coredns-5644d7b6d9-k6wsp" } }, "MetricSetFields": { - "id": "docker://c152296116c064db311061cf6c39cff2de8d66339c954505cb68816464cf4a03", - "name": "kube-proxy", + "cpu": { + "request": { + "cores": 0.1 + } + }, + "id": "docker://15ada7864628d1c8007c01420e5887a501590d3bc9c25628a4770172ad615112", + "memory": { + "limit": { + "bytes": 178257920 + }, + "request": { + "bytes": 73400320 + } + }, + "name": "coredns", "status": { "phase": "running", "ready": true, @@ -405,40 +400,25 @@ { "RootFields": { "container": { - "id": "f8fe5be1dbb1931d702c89235c79965730cbcced7b0ced9895f6c54c1ae8e5c3", + "id": "669cc415d86b872450deaada60c73cca387ca23a7b0f21c5b146467b95cf1f76", "image": { - "name": "k8s.gcr.io/coredns:1.6.2" + "name": "k8s.gcr.io/nginx-slim:0.8" }, "runtime": "docker" } }, "ModuleFields": { - "namespace": { - "name": "kube-system" - }, + "namespace": "default", "node": { "name": "minikube" }, "pod": { - "name": "coredns-5644d7b6d9-fhwjd" + "name": "web-1" } }, "MetricSetFields": { - "cpu": { - "request": { - "cores": 0.1 - } - }, - "id": "docker://f8fe5be1dbb1931d702c89235c79965730cbcced7b0ced9895f6c54c1ae8e5c3", - "memory": { - "limit": { - "bytes": 178257920 - }, - "request": { - "bytes": 73400320 - } - }, - "name": "coredns", + "id": "docker://669cc415d86b872450deaada60c73cca387ca23a7b0f21c5b146467b95cf1f76", + "name": "nginx", "status": { "phase": "running", "ready": true, @@ -459,27 +439,30 @@ { "RootFields": { "container": { - "id": "2e0519a3fcd62acea8f4253b994ce53356d89171c0eb0920a13fe58b637d8cdb", + "id": "cdaefb4df2f2add498f884fdc717a6ca8d2681c1636934747de600e6427e0c0d", "image": { - "name": "quay.io/coreos/kube-state-metrics:v1.8.0" + "name": "k8s.gcr.io/kube-apiserver:v1.16.2" }, "runtime": "docker" } }, "ModuleFields": { - "namespace": { - "name": "kube-system" - }, + "namespace": "kube-system", "node": { "name": "minikube" }, "pod": { - "name": "kube-state-metrics-898d4db8d-dqmtg" + "name": "kube-apiserver-minikube" } }, "MetricSetFields": { - "id": "docker://2e0519a3fcd62acea8f4253b994ce53356d89171c0eb0920a13fe58b637d8cdb", - "name": "kube-state-metrics", + "cpu": { + "request": { + "cores": 0.25 + } + }, + "id": "docker://cdaefb4df2f2add498f884fdc717a6ca8d2681c1636934747de600e6427e0c0d", + "name": "kube-apiserver", "status": { "phase": "running", "ready": true, @@ -508,9 +491,7 @@ } }, "ModuleFields": { - "namespace": { - "name": "kube-system" - }, + "namespace": "kube-system", "node": { "name": "minikube" }, @@ -541,32 +522,25 @@ { "RootFields": { "container": { - "id": "465ebffafd7fc238a2fa2e764255efcbff88d5513f4c68f57d70932985428d12", + "id": "a4cec783af3614b137f4b449eebf3ac61eaf0a8661cb2f4847741be5a24de0bf", "image": { - "name": "k8s.gcr.io/kube-controller-manager:v1.16.2" + "name": "k8s.gcr.io/nginx-slim:0.8" }, "runtime": "docker" } }, "ModuleFields": { - "namespace": { - "name": "kube-system" - }, + "namespace": "default", "node": { "name": "minikube" }, "pod": { - "name": "kube-controller-manager-minikube" + "name": "web-0" } }, "MetricSetFields": { - "cpu": { - "request": { - "cores": 0.2 - } - }, - "id": "docker://465ebffafd7fc238a2fa2e764255efcbff88d5513f4c68f57d70932985428d12", - "name": "kube-controller-manager", + "id": "docker://a4cec783af3614b137f4b449eebf3ac61eaf0a8661cb2f4847741be5a24de0bf", + "name": "nginx", "status": { "phase": "running", "ready": true, diff --git a/metricbeat/module/kubernetes/state_container/_meta/test/ksm.v2.0.0.expected b/metricbeat/module/kubernetes/state_container/_meta/test/ksm.v2.0.0.expected index b1824708ae8..a8f3b293465 100644 --- a/metricbeat/module/kubernetes/state_container/_meta/test/ksm.v2.0.0.expected +++ b/metricbeat/module/kubernetes/state_container/_meta/test/ksm.v2.0.0.expected @@ -2,43 +2,38 @@ { "RootFields": { "container": { - "id": "3037e577635e9cbcefe1f273e5b06784d36807af76158e4add887e840c42e1ef", + "id": "3101d1525d6133851881f4b7cd439033663daefeb4849e5322d1428f09620628", "image": { - "name": "docker.io/kindest/kindnetd:v20210326-1e038dc5" + "name": "k8s.gcr.io/coredns:1.6.2" }, "runtime": "containerd" } }, "ModuleFields": { - "namespace": { - "name": "kube-system" - }, + "namespace": "kube-system", "node": { - "name": "kind-worker2" + "name": "kind-control-plane" }, "pod": { - "name": "kindnet-tg7tl" + "name": "coredns-5644d7b6d9-zgdsx" } }, "MetricSetFields": { "cpu": { - "limit": { - "cores": 0.1 - }, "request": { "cores": 0.1 } }, - "id": "containerd://3037e577635e9cbcefe1f273e5b06784d36807af76158e4add887e840c42e1ef", + "id": "containerd://3101d1525d6133851881f4b7cd439033663daefeb4849e5322d1428f09620628", "memory": { "limit": { - "bytes": 52428800 + "bytes": 178257920 }, "request": { - "bytes": 52428800 + "bytes": 73400320 } }, - "name": "kindnet-cni", + "name": "coredns", "status": { "phase": "running", "ready": true, @@ -59,72 +54,33 @@ { "RootFields": { "container": { - "id": "a55ee307ef431d293c02a7eb96417963d7b81b298a8ebfac2f77fe4ca58e1461", + "id": "ffdc200c097349d8ed96f5768387d276751497297730121e6335a31c2d3332a4", "image": { - "name": "k8s.gcr.io/kube-proxy:v1.16.15" + "name": "k8s.gcr.io/kube-apiserver:v1.16.15" }, "runtime": "containerd" } }, "ModuleFields": { - "namespace": { - "name": "kube-system" - }, + "namespace": "kube-system", "node": { "name": "kind-control-plane" }, "pod": { - "name": "kube-proxy-cm525" + "name": "kube-apiserver-kind-control-plane" } }, "MetricSetFields": { - "id": "containerd://a55ee307ef431d293c02a7eb96417963d7b81b298a8ebfac2f77fe4ca58e1461", - "name": "kube-proxy", + "cpu": { + "request": { + "cores": 0.25 + } + }, + "id": "containerd://ffdc200c097349d8ed96f5768387d276751497297730121e6335a31c2d3332a4", + "name": "kube-apiserver", "status": { "phase": "running", "ready": true, - "restarts": 4 - } - }, - "Index": "", - "ID": "", - "Namespace": "kubernetes.container", - "Timestamp": "0001-01-01T00:00:00Z", - "Error": null, - "Host": "", - "Service": "", - "Took": 0, - "Period": 0, - "DisableTimeSeries": false - }, - { - "RootFields": { - "container": { - "id": "a84953a247df489898d85ecfd0f893c2655ed1915ac902b309ee6e3658c7e258", - "image": { - "name": "docker.io/library/busybox:latest" - }, - "runtime": "containerd" - } - }, - "ModuleFields": { - "namespace": { - "name": "default" - }, - "node": { - "name": "kind-worker" - }, - "pod": { - "name": "hello-zf6gh" - } - }, - "MetricSetFields": { - "id": "containerd://a84953a247df489898d85ecfd0f893c2655ed1915ac902b309ee6e3658c7e258", - "name": "hello", - "status": { - "phase": "terminated", - "ready": false, - "reason": "Completed", "restarts": 0 } }, @@ -150,9 +106,7 @@ } }, "ModuleFields": { - "namespace": { - "name": "kube-system" - }, + "namespace": "kube-system", "node": { "name": "kind-worker2" }, @@ -183,32 +137,25 @@ { "RootFields": { "container": { - "id": "1c1919c3b07bf3369b5e1a4bf187762f2724b3bc7eb113239af3919f12202337", + "id": "8af6de6644ef1e5bb36b9d1f87d65e9b893096ae2c0f3e57061fad70f094d1be", "image": { - "name": "k8s.gcr.io/kube-controller-manager:v1.16.15" + "name": "k8s.gcr.io/kube-proxy:v1.16.15" }, "runtime": "containerd" } }, "ModuleFields": { - "namespace": { - "name": "kube-system" - }, + "namespace": "kube-system", "node": { - "name": "kind-control-plane" + "name": "kind-worker" }, "pod": { - "name": "kube-controller-manager-kind-control-plane" + "name": "kube-proxy-22znl" } }, "MetricSetFields": { - "cpu": { - "request": { - "cores": 0.2 - } - }, - "id": "containerd://1c1919c3b07bf3369b5e1a4bf187762f2724b3bc7eb113239af3919f12202337", - "name": "kube-controller-manager", + "id": "containerd://8af6de6644ef1e5bb36b9d1f87d65e9b893096ae2c0f3e57061fad70f094d1be", + "name": "kube-proxy", "status": { "phase": "running", "ready": true, @@ -229,31 +176,29 @@ { "RootFields": { "container": { - "id": "8af6de6644ef1e5bb36b9d1f87d65e9b893096ae2c0f3e57061fad70f094d1be", + "id": "02b0705f60dc6131a6b5d4e9a48e2510463f89a0f77e7e1bafa6b5f45cc595e8", "image": { - "name": "k8s.gcr.io/kube-proxy:v1.16.15" + "name": "docker.io/odise/busybox-python:latest" }, "runtime": "containerd" } }, "ModuleFields": { - "namespace": { - "name": "kube-system" - }, + "namespace": "default", "node": { "name": "kind-worker" }, "pod": { - "name": "kube-proxy-22znl" + "name": "hello-python-566b5479f5-ndwdl" } }, "MetricSetFields": { - "id": "containerd://8af6de6644ef1e5bb36b9d1f87d65e9b893096ae2c0f3e57061fad70f094d1be", - "name": "kube-proxy", + "id": "containerd://02b0705f60dc6131a6b5d4e9a48e2510463f89a0f77e7e1bafa6b5f45cc595e8", + "name": "hello-python", "status": { "phase": "running", "ready": true, - "restarts": 4 + "restarts": 18 } }, "Index": "", @@ -270,7 +215,7 @@ { "RootFields": { "container": { - "id": "9afadbf7fd5374d1849b008e8ad4287cdbfbbf499bab9740bf0c7a5cd6730ad9", + "id": "09603a8146bd6aacb32d55a1e52e929143f003ea30c84052f765efca129fd90a", "image": { "name": "docker.io/kindest/kindnetd:v20210326-1e038dc5" }, @@ -278,14 +223,12 @@ } }, "ModuleFields": { - "namespace": { - "name": "kube-system" - }, + "namespace": "kube-system", "node": { - "name": "kind-worker" + "name": "kind-control-plane" }, "pod": { - "name": "kindnet-9fgst" + "name": "kindnet-kch2v" } }, "MetricSetFields": { @@ -297,7 +240,7 @@ "cores": 0.1 } }, - "id": "containerd://9afadbf7fd5374d1849b008e8ad4287cdbfbbf499bab9740bf0c7a5cd6730ad9", + "id": "containerd://09603a8146bd6aacb32d55a1e52e929143f003ea30c84052f765efca129fd90a", "memory": { "limit": { "bytes": 52428800 @@ -327,39 +270,34 @@ { "RootFields": { "container": { - "id": "fae8ef6fa6ea716f5ce0a65a1b2407d1e4839b04452d6013cdb6d5be8db8ada0", + "id": "cd368e1731c278b039642fab2fe90902e2cfa470fd70a7ccfd5c2549a552cea5", "image": { - "name": "docker.io/library/redis:5.0.4" + "name": "k8s.gcr.io/kube-scheduler:v1.16.15" }, "runtime": "containerd" } }, "ModuleFields": { - "namespace": { - "name": "default" - }, + "namespace": "kube-system", "node": { - "name": "kind-worker2" + "name": "kind-control-plane" }, "pod": { - "name": "redis" + "name": "kube-scheduler-kind-control-plane" } }, "MetricSetFields": { "cpu": { - "limit": { - "cores": 0.1 - }, "request": { "cores": 0.1 } }, - "id": "containerd://fae8ef6fa6ea716f5ce0a65a1b2407d1e4839b04452d6013cdb6d5be8db8ada0", - "name": "redis", + "id": "containerd://cd368e1731c278b039642fab2fe90902e2cfa470fd70a7ccfd5c2549a552cea5", + "name": "kube-scheduler", "status": { "phase": "running", "ready": true, - "restarts": 1 + "restarts": 4 } }, "Index": "", @@ -376,36 +314,29 @@ { "RootFields": { "container": { - "id": "cd368e1731c278b039642fab2fe90902e2cfa470fd70a7ccfd5c2549a552cea5", + "id": "1a223dbb8b51a7404836789fd049701a9e4df7bb69878fb893ab10419ff4eb29", "image": { - "name": "k8s.gcr.io/kube-scheduler:v1.16.15" + "name": "docker.io/rancher/local-path-provisioner:v0.0.14" }, "runtime": "containerd" } }, "ModuleFields": { - "namespace": { - "name": "kube-system" - }, + "namespace": "local-path-storage", "node": { "name": "kind-control-plane" }, "pod": { - "name": "kube-scheduler-kind-control-plane" + "name": "local-path-provisioner-5bf465b47d-h8hjn" } }, "MetricSetFields": { - "cpu": { - "request": { - "cores": 0.1 - } - }, - "id": "containerd://cd368e1731c278b039642fab2fe90902e2cfa470fd70a7ccfd5c2549a552cea5", - "name": "kube-scheduler", + "id": "containerd://1a223dbb8b51a7404836789fd049701a9e4df7bb69878fb893ab10419ff4eb29", + "name": "local-path-provisioner", "status": { "phase": "running", "ready": true, - "restarts": 4 + "restarts": 8 } }, "Index": "", @@ -422,7 +353,7 @@ { "RootFields": { "container": { - "id": "90560da422742a41de53c281969942c25f24d7b6bf73af6e4f226ee62338f640", + "id": "d66f649ad0f6c1822039f1c4ea27b6f792f6a86029bf862e77afa2966042a1ce", "image": { "name": "docker.elastic.co/beats/metricbeat:7.15.0-SNAPSHOT" }, @@ -430,14 +361,12 @@ } }, "ModuleFields": { - "namespace": { - "name": "kube-system" - }, + "namespace": "kube-system", "node": { - "name": "kind-worker" + "name": "kind-worker2" }, "pod": { - "name": "metricbeat-bvr2v" + "name": "metricbeat-55fp7" } }, "MetricSetFields": { @@ -446,7 +375,7 @@ "cores": 0.1 } }, - "id": "containerd://90560da422742a41de53c281969942c25f24d7b6bf73af6e4f226ee62338f640", + "id": "containerd://d66f649ad0f6c1822039f1c4ea27b6f792f6a86029bf862e77afa2966042a1ce", "memory": { "limit": { "bytes": 209715200 @@ -484,9 +413,7 @@ } }, "ModuleFields": { - "namespace": { - "name": "kube-system" - }, + "namespace": "kube-system", "node": { "name": "kind-control-plane" }, @@ -530,31 +457,37 @@ { "RootFields": { "container": { - "id": "3f9250f160ca15f681b8c7da78fdf34cd8be8a86fde3910b682ad413b940a8c5", + "id": "fae8ef6fa6ea716f5ce0a65a1b2407d1e4839b04452d6013cdb6d5be8db8ada0", "image": { - "name": "k8s.gcr.io/etcd:3.3.15-0" + "name": "docker.io/library/redis:5.0.4" }, "runtime": "containerd" } }, "ModuleFields": { - "namespace": { - "name": "kube-system" - }, + "namespace": "default", "node": { - "name": "kind-control-plane" + "name": "kind-worker2" }, "pod": { - "name": "etcd-kind-control-plane" + "name": "redis" } }, "MetricSetFields": { - "id": "containerd://3f9250f160ca15f681b8c7da78fdf34cd8be8a86fde3910b682ad413b940a8c5", - "name": "etcd", + "cpu": { + "limit": { + "cores": 0.1 + }, + "request": { + "cores": 0.1 + } + }, + "id": "containerd://fae8ef6fa6ea716f5ce0a65a1b2407d1e4839b04452d6013cdb6d5be8db8ada0", + "name": "redis", "status": { "phase": "running", "ready": true, - "restarts": 0 + "restarts": 1 } }, "Index": "", @@ -571,36 +504,45 @@ { "RootFields": { "container": { - "id": "ffdc200c097349d8ed96f5768387d276751497297730121e6335a31c2d3332a4", + "id": "9afadbf7fd5374d1849b008e8ad4287cdbfbbf499bab9740bf0c7a5cd6730ad9", "image": { - "name": "k8s.gcr.io/kube-apiserver:v1.16.15" + "name": "docker.io/kindest/kindnetd:v20210326-1e038dc5" }, "runtime": "containerd" } }, "ModuleFields": { - "namespace": { - "name": "kube-system" - }, + "namespace": "kube-system", "node": { - "name": "kind-control-plane" + "name": "kind-worker" }, "pod": { - "name": "kube-apiserver-kind-control-plane" + "name": "kindnet-9fgst" } }, "MetricSetFields": { "cpu": { + "limit": { + "cores": 0.1 + }, "request": { - "cores": 0.25 + "cores": 0.1 } }, - "id": "containerd://ffdc200c097349d8ed96f5768387d276751497297730121e6335a31c2d3332a4", - "name": "kube-apiserver", + "id": "containerd://9afadbf7fd5374d1849b008e8ad4287cdbfbbf499bab9740bf0c7a5cd6730ad9", + "memory": { + "limit": { + "bytes": 52428800 + }, + "request": { + "bytes": 52428800 + } + }, + "name": "kindnet-cni", "status": { "phase": "running", "ready": true, - "restarts": 0 + "restarts": 4 } }, "Index": "", @@ -617,44 +559,29 @@ { "RootFields": { "container": { - "id": "3101d1525d6133851881f4b7cd439033663daefeb4849e5322d1428f09620628", + "id": "ae513b826459c9382984bea986eb3546aa45fd0e650051cb9591ab7a8efed6ea", "image": { - "name": "k8s.gcr.io/coredns:1.6.2" + "name": "k8s.gcr.io/kube-state-metrics/kube-state-metrics:v2.1.0" }, "runtime": "containerd" } }, "ModuleFields": { - "namespace": { - "name": "kube-system" - }, + "namespace": "kube-system", "node": { - "name": "kind-control-plane" + "name": "kind-worker" }, "pod": { - "name": "coredns-5644d7b6d9-zgdsx" + "name": "kube-state-metrics-f655d484d-hj69w" } }, "MetricSetFields": { - "cpu": { - "request": { - "cores": 0.1 - } - }, - "id": "containerd://3101d1525d6133851881f4b7cd439033663daefeb4849e5322d1428f09620628", - "memory": { - "limit": { - "bytes": 178257920 - }, - "request": { - "bytes": 73400320 - } - }, - "name": "coredns", + "id": "containerd://ae513b826459c9382984bea986eb3546aa45fd0e650051cb9591ab7a8efed6ea", + "name": "kube-state-metrics", "status": { "phase": "running", "ready": true, - "restarts": 4 + "restarts": 2 } }, "Index": "", @@ -671,7 +598,7 @@ { "RootFields": { "container": { - "id": "d66f649ad0f6c1822039f1c4ea27b6f792f6a86029bf862e77afa2966042a1ce", + "id": "90560da422742a41de53c281969942c25f24d7b6bf73af6e4f226ee62338f640", "image": { "name": "docker.elastic.co/beats/metricbeat:7.15.0-SNAPSHOT" }, @@ -679,14 +606,12 @@ } }, "ModuleFields": { - "namespace": { - "name": "kube-system" - }, + "namespace": "kube-system", "node": { - "name": "kind-worker2" + "name": "kind-worker" }, "pod": { - "name": "metricbeat-55fp7" + "name": "metricbeat-bvr2v" } }, "MetricSetFields": { @@ -695,7 +620,7 @@ "cores": 0.1 } }, - "id": "containerd://d66f649ad0f6c1822039f1c4ea27b6f792f6a86029bf862e77afa2966042a1ce", + "id": "containerd://90560da422742a41de53c281969942c25f24d7b6bf73af6e4f226ee62338f640", "memory": { "limit": { "bytes": 209715200 @@ -725,31 +650,30 @@ { "RootFields": { "container": { - "id": "ae513b826459c9382984bea986eb3546aa45fd0e650051cb9591ab7a8efed6ea", + "id": "a84953a247df489898d85ecfd0f893c2655ed1915ac902b309ee6e3658c7e258", "image": { - "name": "k8s.gcr.io/kube-state-metrics/kube-state-metrics:v2.1.0" + "name": "docker.io/library/busybox:latest" }, "runtime": "containerd" } }, "ModuleFields": { - "namespace": { - "name": "kube-system" - }, + "namespace": "default", "node": { "name": "kind-worker" }, "pod": { - "name": "kube-state-metrics-f655d484d-hj69w" + "name": "hello-zf6gh" } }, "MetricSetFields": { - "id": "containerd://ae513b826459c9382984bea986eb3546aa45fd0e650051cb9591ab7a8efed6ea", - "name": "kube-state-metrics", + "id": "containerd://a84953a247df489898d85ecfd0f893c2655ed1915ac902b309ee6e3658c7e258", + "name": "hello", "status": { - "phase": "running", - "ready": true, - "restarts": 2 + "phase": "terminated", + "ready": false, + "reason": "Completed", + "restarts": 0 } }, "Index": "", @@ -766,43 +690,25 @@ { "RootFields": { "container": { - "id": "09603a8146bd6aacb32d55a1e52e929143f003ea30c84052f765efca129fd90a", + "id": "a55ee307ef431d293c02a7eb96417963d7b81b298a8ebfac2f77fe4ca58e1461", "image": { - "name": "docker.io/kindest/kindnetd:v20210326-1e038dc5" + "name": "k8s.gcr.io/kube-proxy:v1.16.15" }, "runtime": "containerd" } }, "ModuleFields": { - "namespace": { - "name": "kube-system" - }, + "namespace": "kube-system", "node": { "name": "kind-control-plane" }, "pod": { - "name": "kindnet-kch2v" + "name": "kube-proxy-cm525" } }, "MetricSetFields": { - "cpu": { - "limit": { - "cores": 0.1 - }, - "request": { - "cores": 0.1 - } - }, - "id": "containerd://09603a8146bd6aacb32d55a1e52e929143f003ea30c84052f765efca129fd90a", - "memory": { - "limit": { - "bytes": 52428800 - }, - "request": { - "bytes": 52428800 - } - }, - "name": "kindnet-cni", + "id": "containerd://a55ee307ef431d293c02a7eb96417963d7b81b298a8ebfac2f77fe4ca58e1461", + "name": "kube-proxy", "status": { "phase": "running", "ready": true, @@ -823,31 +729,29 @@ { "RootFields": { "container": { - "id": "02b0705f60dc6131a6b5d4e9a48e2510463f89a0f77e7e1bafa6b5f45cc595e8", + "id": "3f9250f160ca15f681b8c7da78fdf34cd8be8a86fde3910b682ad413b940a8c5", "image": { - "name": "docker.io/odise/busybox-python:latest" + "name": "k8s.gcr.io/etcd:3.3.15-0" }, "runtime": "containerd" } }, "ModuleFields": { - "namespace": { - "name": "default" - }, + "namespace": "kube-system", "node": { - "name": "kind-worker" + "name": "kind-control-plane" }, "pod": { - "name": "hello-python-566b5479f5-ndwdl" + "name": "etcd-kind-control-plane" } }, "MetricSetFields": { - "id": "containerd://02b0705f60dc6131a6b5d4e9a48e2510463f89a0f77e7e1bafa6b5f45cc595e8", - "name": "hello-python", + "id": "containerd://3f9250f160ca15f681b8c7da78fdf34cd8be8a86fde3910b682ad413b940a8c5", + "name": "etcd", "status": { "phase": "running", "ready": true, - "restarts": 18 + "restarts": 0 } }, "Index": "", @@ -864,31 +768,89 @@ { "RootFields": { "container": { - "id": "1a223dbb8b51a7404836789fd049701a9e4df7bb69878fb893ab10419ff4eb29", + "id": "3037e577635e9cbcefe1f273e5b06784d36807af76158e4add887e840c42e1ef", "image": { - "name": "docker.io/rancher/local-path-provisioner:v0.0.14" + "name": "docker.io/kindest/kindnetd:v20210326-1e038dc5" }, "runtime": "containerd" } }, "ModuleFields": { - "namespace": { - "name": "local-path-storage" + "namespace": "kube-system", + "node": { + "name": "kind-worker2" + }, + "pod": { + "name": "kindnet-tg7tl" + } + }, + "MetricSetFields": { + "cpu": { + "limit": { + "cores": 0.1 + }, + "request": { + "cores": 0.1 + } }, + "id": "containerd://3037e577635e9cbcefe1f273e5b06784d36807af76158e4add887e840c42e1ef", + "memory": { + "limit": { + "bytes": 52428800 + }, + "request": { + "bytes": 52428800 + } + }, + "name": "kindnet-cni", + "status": { + "phase": "running", + "ready": true, + "restarts": 4 + } + }, + "Index": "", + "ID": "", + "Namespace": "kubernetes.container", + "Timestamp": "0001-01-01T00:00:00Z", + "Error": null, + "Host": "", + "Service": "", + "Took": 0, + "Period": 0, + "DisableTimeSeries": false + }, + { + "RootFields": { + "container": { + "id": "1c1919c3b07bf3369b5e1a4bf187762f2724b3bc7eb113239af3919f12202337", + "image": { + "name": "k8s.gcr.io/kube-controller-manager:v1.16.15" + }, + "runtime": "containerd" + } + }, + "ModuleFields": { + "namespace": "kube-system", "node": { "name": "kind-control-plane" }, "pod": { - "name": "local-path-provisioner-5bf465b47d-h8hjn" + "name": "kube-controller-manager-kind-control-plane" } }, "MetricSetFields": { - "id": "containerd://1a223dbb8b51a7404836789fd049701a9e4df7bb69878fb893ab10419ff4eb29", - "name": "local-path-provisioner", + "cpu": { + "request": { + "cores": 0.2 + } + }, + "id": "containerd://1c1919c3b07bf3369b5e1a4bf187762f2724b3bc7eb113239af3919f12202337", + "name": "kube-controller-manager", "status": { "phase": "running", "ready": true, - "restarts": 8 + "restarts": 4 } }, "Index": "", diff --git a/metricbeat/module/kubernetes/state_container/_meta/testdata/ksm-v1_3_0.plain-expected.json b/metricbeat/module/kubernetes/state_container/_meta/testdata/ksm-v1_3_0.plain-expected.json index a38d8487d34..91d3176317d 100644 --- a/metricbeat/module/kubernetes/state_container/_meta/testdata/ksm-v1_3_0.plain-expected.json +++ b/metricbeat/module/kubernetes/state_container/_meta/testdata/ksm-v1_3_0.plain-expected.json @@ -1,9 +1,9 @@ [ { "container": { - "id": "52fa55e051dc5b68e44c027588685b7edd85aaa03b07f7216d399249ff4fc821", + "id": "469f5d2b7854eb52e5d13dc0cd3e664c1b682b157aabaf596ffe4984f1516902", "image": { - "name": "gcr.io/google_containers/exechealthz-amd64:1.2" + "name": "gcr.io/kubernetes-helm/tiller:v2.3.1" }, "runtime": "docker" }, @@ -14,35 +14,20 @@ }, "kubernetes": { "container": { - "cpu": { - "request": { - "cores": 0.01 - } - }, - "id": "docker://52fa55e051dc5b68e44c027588685b7edd85aaa03b07f7216d399249ff4fc821", - "memory": { - "limit": { - "bytes": 52428800 - }, - "request": { - "bytes": 52428800 - } - }, - "name": "healthz", + "id": "docker://469f5d2b7854eb52e5d13dc0cd3e664c1b682b157aabaf596ffe4984f1516902", + "name": "tiller", "status": { "phase": "running", "ready": true, - "restarts": 2 + "restarts": 1 } }, - "namespace": { - "name": "kube-system" - }, + "namespace": "kube-system", "node": { "name": "minikube" }, "pod": { - "name": "kube-dns-v20-5g5cb" + "name": "tiller-deploy-3067024529-9lpmb" } }, "metricset": { @@ -56,9 +41,9 @@ }, { "container": { - "id": "fa3d83f648de42492b38fa3e8501d109376f391c50f2bd210c895c8477ae4b62", + "id": "3aaee8bdd311c015240e99fa2a5a5f2f26b11b51236a683b39d8c1902e423978", "image": { - "name": "gcr.io/google_containers/kubedns-amd64:1.9" + "name": "gcr.io/google_containers/kubernetes-dashboard-amd64:v1.5.1" }, "runtime": "docker" }, @@ -69,35 +54,20 @@ }, "kubernetes": { "container": { - "cpu": { - "request": { - "cores": 0.1 - } - }, - "id": "docker://fa3d83f648de42492b38fa3e8501d109376f391c50f2bd210c895c8477ae4b62", - "memory": { - "limit": { - "bytes": 178257920 - }, - "request": { - "bytes": 73400320 - } - }, - "name": "kubedns", + "id": "docker://3aaee8bdd311c015240e99fa2a5a5f2f26b11b51236a683b39d8c1902e423978", + "name": "kubernetes-dashboard", "status": { "phase": "running", "ready": true, "restarts": 2 } }, - "namespace": { - "name": "kube-system" - }, + "namespace": "kube-system", "node": { "name": "minikube" }, "pod": { - "name": "kube-dns-v20-5g5cb" + "name": "kubernetes-dashboard-vw0l6" } }, "metricset": { @@ -110,13 +80,6 @@ } }, { - "container": { - "id": "91fdd43f6b1b4c3dd133cfca53e0b1210bc557c2ae56006026b5ccdb5f52826f", - "image": { - "name": "gcr.io/google-containers/kube-addon-manager:v6.3" - }, - "runtime": "docker" - }, "event": { "dataset": "kubernetes.container", "duration": 115000, @@ -125,31 +88,26 @@ "kubernetes": { "container": { "cpu": { + "limit": { + "cores": 0.2 + }, "request": { - "cores": 0.005 + "cores": 0.1 } }, - "id": "docker://91fdd43f6b1b4c3dd133cfca53e0b1210bc557c2ae56006026b5ccdb5f52826f", "memory": { - "request": { + "limit": { "bytes": 52428800 + }, + "request": { + "bytes": 31457280 } }, - "name": "kube-addon-manager", - "status": { - "phase": "running", - "ready": true, - "restarts": 2 - } - }, - "namespace": { - "name": "kube-system" - }, - "node": { - "name": "minikube" + "name": "kube-state-metrics" }, + "namespace": "kube-system", "pod": { - "name": "kube-addon-manager-minikube" + "name": "kube-state-metrics-1303537707-mnzbp" } }, "metricset": { @@ -163,9 +121,9 @@ }, { "container": { - "id": "3aaee8bdd311c015240e99fa2a5a5f2f26b11b51236a683b39d8c1902e423978", + "id": "973cbe45982c5126a5caf8c58d964c0ab1d5bb2c165ccc59715fcc1ebd58ab3d", "image": { - "name": "gcr.io/google_containers/kubernetes-dashboard-amd64:v1.5.1" + "name": "gcr.io/google_containers/kube-state-metrics:v0.4.1" }, "runtime": "docker" }, @@ -176,22 +134,36 @@ }, "kubernetes": { "container": { - "id": "docker://3aaee8bdd311c015240e99fa2a5a5f2f26b11b51236a683b39d8c1902e423978", - "name": "kubernetes-dashboard", + "cpu": { + "limit": { + "cores": 0.2 + }, + "request": { + "cores": 0.1 + } + }, + "id": "docker://973cbe45982c5126a5caf8c58d964c0ab1d5bb2c165ccc59715fcc1ebd58ab3d", + "memory": { + "limit": { + "bytes": 52428800 + }, + "request": { + "bytes": 31457280 + } + }, + "name": "kube-state-metrics", "status": { "phase": "running", "ready": true, - "restarts": 2 + "restarts": 1 } }, - "namespace": { - "name": "kube-system" - }, + "namespace": "kube-system", "node": { "name": "minikube" }, "pod": { - "name": "kubernetes-dashboard-vw0l6" + "name": "kube-state-metrics-1303537707-7ncd1" } }, "metricset": { @@ -205,9 +177,9 @@ }, { "container": { - "id": "fa3d83f648de42492b38fa3e8501d109376f391c50f2bd210c895c8477ae4b62-test", + "id": "e2ee1c2c7b8d4e5fd8c834b83cba8377d6b0e39da18157688ccc1a06b7c53117", "image": { - "name": "gcr.io/google_containers/kubedns-amd64:1.9-test" + "name": "jenkinsci/jenkins:2.46.1" }, "runtime": "docker" }, @@ -223,30 +195,25 @@ "cores": 0.2 } }, - "id": "docker://fa3d83f648de42492b38fa3e8501d109376f391c50f2bd210c895c8477ae4b62-test", + "id": "docker://e2ee1c2c7b8d4e5fd8c834b83cba8377d6b0e39da18157688ccc1a06b7c53117", "memory": { - "limit": { - "bytes": 278257920 - }, "request": { - "bytes": 83400320 + "bytes": 268435456 } }, - "name": "kubedns", + "name": "wise-lynx-jenkins", "status": { - "phase": "terminated", - "ready": false, - "restarts": 3 + "phase": "running", + "ready": true, + "restarts": 1 } }, - "namespace": { - "name": "test" - }, + "namespace": "jenkins", "node": { - "name": "minikube-test" + "name": "minikube" }, "pod": { - "name": "kube-dns-v20-5g5cb-test" + "name": "wise-lynx-jenkins-1616735317-svn6k" } }, "metricset": { @@ -260,9 +227,9 @@ }, { "container": { - "id": "e2ee1c2c7b8d4e5fd8c834b83cba8377d6b0e39da18157688ccc1a06b7c53117", + "id": "fa3d83f648de42492b38fa3e8501d109376f391c50f2bd210c895c8477ae4b62", "image": { - "name": "jenkinsci/jenkins:2.46.1" + "name": "gcr.io/google_containers/kubedns-amd64:1.9" }, "runtime": "docker" }, @@ -275,30 +242,31 @@ "container": { "cpu": { "request": { - "cores": 0.2 + "cores": 0.1 } }, - "id": "docker://e2ee1c2c7b8d4e5fd8c834b83cba8377d6b0e39da18157688ccc1a06b7c53117", + "id": "docker://fa3d83f648de42492b38fa3e8501d109376f391c50f2bd210c895c8477ae4b62", "memory": { + "limit": { + "bytes": 178257920 + }, "request": { - "bytes": 268435456 + "bytes": 73400320 } }, - "name": "wise-lynx-jenkins", + "name": "kubedns", "status": { "phase": "running", "ready": true, - "restarts": 1 + "restarts": 2 } }, - "namespace": { - "name": "jenkins" - }, + "namespace": "kube-system", "node": { "name": "minikube" }, "pod": { - "name": "wise-lynx-jenkins-1616735317-svn6k" + "name": "kube-dns-v20-5g5cb" } }, "metricset": { @@ -311,6 +279,13 @@ } }, { + "container": { + "id": "4fa227874ee68536bf902394fb662f07b99099798ca9cd5c1506b79075acc065", + "image": { + "name": "bitnami/redis:3.2.8-r2" + }, + "runtime": "docker" + }, "event": { "dataset": "kubernetes.container", "duration": 115000, @@ -319,28 +294,29 @@ "kubernetes": { "container": { "cpu": { - "limit": { - "cores": 0.2 - }, "request": { "cores": 0.1 } }, + "id": "docker://4fa227874ee68536bf902394fb662f07b99099798ca9cd5c1506b79075acc065", "memory": { - "limit": { - "bytes": 52428800 - }, "request": { - "bytes": 31457280 + "bytes": 268435456 } }, - "name": "kube-state-metrics" + "name": "jumpy-owl-redis", + "status": { + "phase": "waiting", + "ready": false, + "restarts": 270 + } }, - "namespace": { - "name": "kube-system" + "namespace": "default", + "node": { + "name": "minikube" }, "pod": { - "name": "kube-state-metrics-1303537707-mnzbp" + "name": "jumpy-owl-redis-3481028193-s78x9" } }, "metricset": { @@ -354,9 +330,9 @@ }, { "container": { - "id": "9a4c9462cd078d7be4f0a9b94bcfeb69d5fdd76bff67142df3f58367ac7e8d61", + "id": "fa3d83f648de42492b38fa3e8501d109376f391c50f2bd210c895c8477ae4b62-test", "image": { - "name": "gcr.io/google_containers/kube-dnsmasq-amd64:1.4" + "name": "gcr.io/google_containers/kubedns-amd64:1.9-test" }, "runtime": "docker" }, @@ -367,22 +343,33 @@ }, "kubernetes": { "container": { - "id": "docker://9a4c9462cd078d7be4f0a9b94bcfeb69d5fdd76bff67142df3f58367ac7e8d61", - "name": "dnsmasq", + "cpu": { + "request": { + "cores": 0.2 + } + }, + "id": "docker://fa3d83f648de42492b38fa3e8501d109376f391c50f2bd210c895c8477ae4b62-test", + "memory": { + "limit": { + "bytes": 278257920 + }, + "request": { + "bytes": 83400320 + } + }, + "name": "kubedns", "status": { - "phase": "running", - "ready": true, - "restarts": 2 + "phase": "terminated", + "ready": false, + "restarts": 3 } }, - "namespace": { - "name": "kube-system" - }, + "namespace": "test", "node": { - "name": "minikube" + "name": "minikube-test" }, "pod": { - "name": "kube-dns-v20-5g5cb" + "name": "kube-dns-v20-5g5cb-test" } }, "metricset": { @@ -396,9 +383,9 @@ }, { "container": { - "id": "973cbe45982c5126a5caf8c58d964c0ab1d5bb2c165ccc59715fcc1ebd58ab3d", + "id": "91fdd43f6b1b4c3dd133cfca53e0b1210bc557c2ae56006026b5ccdb5f52826f", "image": { - "name": "gcr.io/google_containers/kube-state-metrics:v0.4.1" + "name": "gcr.io/google-containers/kube-addon-manager:v6.3" }, "runtime": "docker" }, @@ -410,37 +397,29 @@ "kubernetes": { "container": { "cpu": { - "limit": { - "cores": 0.2 - }, "request": { - "cores": 0.1 + "cores": 0.005 } }, - "id": "docker://973cbe45982c5126a5caf8c58d964c0ab1d5bb2c165ccc59715fcc1ebd58ab3d", + "id": "docker://91fdd43f6b1b4c3dd133cfca53e0b1210bc557c2ae56006026b5ccdb5f52826f", "memory": { - "limit": { - "bytes": 52428800 - }, "request": { - "bytes": 31457280 + "bytes": 52428800 } }, - "name": "kube-state-metrics", + "name": "kube-addon-manager", "status": { "phase": "running", "ready": true, - "restarts": 1 + "restarts": 2 } }, - "namespace": { - "name": "kube-system" - }, + "namespace": "kube-system", "node": { "name": "minikube" }, "pod": { - "name": "kube-state-metrics-1303537707-7ncd1" + "name": "kube-addon-manager-minikube" } }, "metricset": { @@ -454,9 +433,9 @@ }, { "container": { - "id": "4fa227874ee68536bf902394fb662f07b99099798ca9cd5c1506b79075acc065", + "id": "52fa55e051dc5b68e44c027588685b7edd85aaa03b07f7216d399249ff4fc821", "image": { - "name": "bitnami/redis:3.2.8-r2" + "name": "gcr.io/google_containers/exechealthz-amd64:1.2" }, "runtime": "docker" }, @@ -469,30 +448,31 @@ "container": { "cpu": { "request": { - "cores": 0.1 + "cores": 0.01 } }, - "id": "docker://4fa227874ee68536bf902394fb662f07b99099798ca9cd5c1506b79075acc065", + "id": "docker://52fa55e051dc5b68e44c027588685b7edd85aaa03b07f7216d399249ff4fc821", "memory": { + "limit": { + "bytes": 52428800 + }, "request": { - "bytes": 268435456 + "bytes": 52428800 } }, - "name": "jumpy-owl-redis", + "name": "healthz", "status": { - "phase": "waiting", - "ready": false, - "restarts": 270 + "phase": "running", + "ready": true, + "restarts": 2 } }, - "namespace": { - "name": "default" - }, + "namespace": "kube-system", "node": { "name": "minikube" }, "pod": { - "name": "jumpy-owl-redis-3481028193-s78x9" + "name": "kube-dns-v20-5g5cb" } }, "metricset": { @@ -506,9 +486,9 @@ }, { "container": { - "id": "469f5d2b7854eb52e5d13dc0cd3e664c1b682b157aabaf596ffe4984f1516902", + "id": "9a4c9462cd078d7be4f0a9b94bcfeb69d5fdd76bff67142df3f58367ac7e8d61", "image": { - "name": "gcr.io/kubernetes-helm/tiller:v2.3.1" + "name": "gcr.io/google_containers/kube-dnsmasq-amd64:1.4" }, "runtime": "docker" }, @@ -519,22 +499,20 @@ }, "kubernetes": { "container": { - "id": "docker://469f5d2b7854eb52e5d13dc0cd3e664c1b682b157aabaf596ffe4984f1516902", - "name": "tiller", + "id": "docker://9a4c9462cd078d7be4f0a9b94bcfeb69d5fdd76bff67142df3f58367ac7e8d61", + "name": "dnsmasq", "status": { "phase": "running", "ready": true, - "restarts": 1 + "restarts": 2 } }, - "namespace": { - "name": "kube-system" - }, + "namespace": "kube-system", "node": { "name": "minikube" }, "pod": { - "name": "tiller-deploy-3067024529-9lpmb" + "name": "kube-dns-v20-5g5cb" } }, "metricset": { diff --git a/metricbeat/module/kubernetes/state_container/state_container.go b/metricbeat/module/kubernetes/state_container/state_container.go index 56ab2d8adac..23c34bf040f 100644 --- a/metricbeat/module/kubernetes/state_container/state_container.go +++ b/metricbeat/module/kubernetes/state_container/state_container.go @@ -78,7 +78,7 @@ var ( Labels: map[string]p.LabelMap{ "pod": p.KeyLabel(mb.ModuleDataKey + ".pod.name"), "container": p.KeyLabel("name"), - "namespace": p.KeyLabel(mb.ModuleDataKey + ".namespace.name"), + "namespace": p.KeyLabel(mb.ModuleDataKey + ".namespace"), "node": p.Label(mb.ModuleDataKey + ".node.name"), "container_id": p.Label("id"), diff --git a/metricbeat/module/kubernetes/state_cronjob/_meta/docs.asciidoc b/metricbeat/module/kubernetes/state_cronjob/_meta/docs.asciidoc index 1558a5f00e5..d994fe5dced 100644 --- a/metricbeat/module/kubernetes/state_cronjob/_meta/docs.asciidoc +++ b/metricbeat/module/kubernetes/state_cronjob/_meta/docs.asciidoc @@ -1 +1,6 @@ This is the `state_cronjob` metricset of the Kubernetes module. + +This metricset does not add metadata by default and hence in order to +add metadata for this one need to configure the metricset with `add_metadata: true` +and uncomment the proper `apiGroup` in the `ClusterRole`. Metadata are only available +for versions of k8s >= v1.21. diff --git a/metricbeat/module/kubernetes/state_cronjob/_meta/test/ksm.v1.8.0.expected b/metricbeat/module/kubernetes/state_cronjob/_meta/test/ksm.v1.8.0.expected index 35dea56dcff..926f896d112 100644 --- a/metricbeat/module/kubernetes/state_cronjob/_meta/test/ksm.v1.8.0.expected +++ b/metricbeat/module/kubernetes/state_cronjob/_meta/test/ksm.v1.8.0.expected @@ -2,9 +2,7 @@ { "RootFields": null, "ModuleFields": { - "namespace": { - "name": "default" - } + "namespace": "default" }, "MetricSetFields": { "active": { diff --git a/metricbeat/module/kubernetes/state_cronjob/_meta/test/ksm.v2.0.0.expected b/metricbeat/module/kubernetes/state_cronjob/_meta/test/ksm.v2.0.0.expected index aedf4d80e84..0702ef4cfe2 100644 --- a/metricbeat/module/kubernetes/state_cronjob/_meta/test/ksm.v2.0.0.expected +++ b/metricbeat/module/kubernetes/state_cronjob/_meta/test/ksm.v2.0.0.expected @@ -2,9 +2,7 @@ { "RootFields": null, "ModuleFields": { - "namespace": { - "name": "default" - } + "namespace": "default" }, "MetricSetFields": { "active": { diff --git a/metricbeat/module/kubernetes/state_cronjob/state_cronjob.go b/metricbeat/module/kubernetes/state_cronjob/state_cronjob.go index ffed1e92b67..013f2afe965 100644 --- a/metricbeat/module/kubernetes/state_cronjob/state_cronjob.go +++ b/metricbeat/module/kubernetes/state_cronjob/state_cronjob.go @@ -20,9 +20,9 @@ package state_cronjob import ( "fmt" - "github.com/pkg/errors" + "github.com/elastic/beats/v7/libbeat/common/kubernetes" + "github.com/elastic/beats/v7/metricbeat/module/kubernetes/util" - "github.com/elastic/beats/v7/libbeat/common" p "github.com/elastic/beats/v7/metricbeat/helper/prometheus" "github.com/elastic/beats/v7/metricbeat/mb" k8smod "github.com/elastic/beats/v7/metricbeat/module/kubernetes" @@ -44,6 +44,7 @@ type CronJobMetricSet struct { prometheus p.Prometheus mapping *p.MetricsMapping mod k8smod.Module + enricher util.Enricher } // NewCronJobMetricSet returns a prometheus based metricset for CronJobs @@ -58,7 +59,12 @@ func NewCronJobMetricSet(base mb.BaseMetricSet) (mb.MetricSet, error) { return nil, fmt.Errorf("must be child of kubernetes module") } - return &CronJobMetricSet{ + config := util.GetDefaultDisabledMetaConfig() + if err := base.Module().UnpackConfig(&config); err != nil { + return nil, fmt.Errorf("error loading config of kubernetes module") + } + + ms := CronJobMetricSet{ BaseMetricSet: base, prometheus: prometheus, mod: mod, @@ -74,47 +80,63 @@ func NewCronJobMetricSet(base mb.BaseMetricSet) (mb.MetricSet, error) { }, Labels: map[string]p.LabelMap{ "cronjob": p.KeyLabel("name"), - "namespace": p.KeyLabel(mb.ModuleDataKey + ".namespace.name"), + "namespace": p.KeyLabel(mb.ModuleDataKey + ".namespace"), "schedule": p.KeyLabel("schedule"), "concurrency_policy": p.KeyLabel("concurrency"), }, }, - }, nil + } + if config.AddMetadata { + ms.enricher = util.NewResourceMetadataEnricher( + base, &kubernetes.CronJob{}, false) + } + return &ms, nil } // Fetch prometheus metrics and treats those prefixed by mb.ModuleDataKey as // module rooted fields at the event that gets reported // // Copied from other kube state metrics. -func (m *CronJobMetricSet) Fetch(reporter mb.ReporterV2) error { +func (m *CronJobMetricSet) Fetch(reporter mb.ReporterV2) { + if m.enricher != nil { + m.enricher.Start() + } + families, err := m.mod.GetStateMetricsFamilies(m.prometheus) if err != nil { - return errors.Wrap(err, "error getting family metrics") + m.Logger().Error(err) + reporter.Error(err) + return } events, err := m.prometheus.ProcessMetrics(families, m.mapping) if err != nil { - return errors.Wrap(err, "error getting metrics") + m.Logger().Error(err) + reporter.Error(err) + return } + if m.enricher != nil { + m.enricher.Enrich(events) + } for _, event := range events { - var moduleFieldsMapStr common.MapStr - moduleFields, ok := event[mb.ModuleDataKey] - if ok { - moduleFieldsMapStr, ok = moduleFields.(common.MapStr) - if !ok { - m.Logger().Errorf("error trying to convert '%s' from event to common.MapStr", mb.ModuleDataKey) - } + e, err := util.CreateEvent(event, "kubernetes.cronjob") + if err != nil { + m.Logger().Error(err) } - delete(event, mb.ModuleDataKey) - - if reported := reporter.Event(mb.Event{ - MetricSetFields: event, - ModuleFields: moduleFieldsMapStr, - Namespace: "kubernetes.cronjob", - }); !reported { - return nil + + if reported := reporter.Event(e); !reported { + m.Logger().Debug("error trying to emit event") + return } } + return +} + +// Close stops this metricset +func (m *CronJobMetricSet) Close() error { + if m.enricher != nil { + m.enricher.Stop() + } return nil } diff --git a/metricbeat/module/kubernetes/state_cronjob/state_cronjob_integration_test.go b/metricbeat/module/kubernetes/state_cronjob/state_cronjob_integration_test.go index 68e567b8bea..aa3b003f06a 100644 --- a/metricbeat/module/kubernetes/state_cronjob/state_cronjob_integration_test.go +++ b/metricbeat/module/kubernetes/state_cronjob/state_cronjob_integration_test.go @@ -30,7 +30,7 @@ import ( ) func TestFetchMetricset(t *testing.T) { - config := test.GetKubeStateMetricsConfig(t, "state_cronjob") + config := test.GetKubeStateMetricsConfigWithMetaDisabled(t, "state_cronjob") metricSet := mbtest.NewFetcher(t, config) events, errs := metricSet.FetchEvents() if len(errs) > 0 { diff --git a/metricbeat/module/kubernetes/state_daemonset/_meta/data.json b/metricbeat/module/kubernetes/state_daemonset/_meta/data.json index 158d2a34eeb..5856069d568 100644 --- a/metricbeat/module/kubernetes/state_daemonset/_meta/data.json +++ b/metricbeat/module/kubernetes/state_daemonset/_meta/data.json @@ -7,7 +7,7 @@ }, "kubernetes": { "daemonset": { - "name": "kindnet", + "name": "kube-proxy", "replicas": { "available": 1, "desired": 1, @@ -15,9 +15,7 @@ "unavailable": 0 } }, - "namespace": { - "name": "kube-system" - } + "namespace": "kube-system" }, "metricset": { "name": "state_daemonset", diff --git a/metricbeat/module/kubernetes/state_daemonset/_meta/test/ksm.v1.3.0.expected b/metricbeat/module/kubernetes/state_daemonset/_meta/test/ksm.v1.3.0.expected index 73dfd269be2..93e2d068788 100644 --- a/metricbeat/module/kubernetes/state_daemonset/_meta/test/ksm.v1.3.0.expected +++ b/metricbeat/module/kubernetes/state_daemonset/_meta/test/ksm.v1.3.0.expected @@ -2,9 +2,7 @@ { "RootFields": null, "ModuleFields": { - "namespace": { - "name": "kube-system" - } + "namespace": "kube-system" }, "MetricSetFields": { "name": "kube-proxy", diff --git a/metricbeat/module/kubernetes/state_daemonset/_meta/test/ksm.v1.8.0.expected b/metricbeat/module/kubernetes/state_daemonset/_meta/test/ksm.v1.8.0.expected index 73dfd269be2..93e2d068788 100644 --- a/metricbeat/module/kubernetes/state_daemonset/_meta/test/ksm.v1.8.0.expected +++ b/metricbeat/module/kubernetes/state_daemonset/_meta/test/ksm.v1.8.0.expected @@ -2,9 +2,7 @@ { "RootFields": null, "ModuleFields": { - "namespace": { - "name": "kube-system" - } + "namespace": "kube-system" }, "MetricSetFields": { "name": "kube-proxy", diff --git a/metricbeat/module/kubernetes/state_daemonset/_meta/test/ksm.v2.0.0.expected b/metricbeat/module/kubernetes/state_daemonset/_meta/test/ksm.v2.0.0.expected index ff94aebc50a..fbb6670ecd7 100644 --- a/metricbeat/module/kubernetes/state_daemonset/_meta/test/ksm.v2.0.0.expected +++ b/metricbeat/module/kubernetes/state_daemonset/_meta/test/ksm.v2.0.0.expected @@ -2,12 +2,10 @@ { "RootFields": null, "ModuleFields": { - "namespace": { - "name": "kube-system" - } + "namespace": "kube-system" }, "MetricSetFields": { - "name": "kindnet", + "name": "kube-proxy", "replicas": { "available": 3, "desired": 3, @@ -29,16 +27,14 @@ { "RootFields": null, "ModuleFields": { - "namespace": { - "name": "kube-system" - } + "namespace": "kube-system" }, "MetricSetFields": { - "name": "kube-proxy", + "name": "metricbeat", "replicas": { - "available": 3, - "desired": 3, - "ready": 3, + "available": 2, + "desired": 2, + "ready": 2, "unavailable": 0 } }, @@ -56,16 +52,14 @@ { "RootFields": null, "ModuleFields": { - "namespace": { - "name": "kube-system" - } + "namespace": "kube-system" }, "MetricSetFields": { - "name": "metricbeat", + "name": "kindnet", "replicas": { - "available": 2, - "desired": 2, - "ready": 2, + "available": 3, + "desired": 3, + "ready": 3, "unavailable": 0 } }, diff --git a/metricbeat/module/kubernetes/state_daemonset/_meta/testdata/docs.plain-expected.json b/metricbeat/module/kubernetes/state_daemonset/_meta/testdata/docs.plain-expected.json index a95bd894fb0..9768d8d3928 100644 --- a/metricbeat/module/kubernetes/state_daemonset/_meta/testdata/docs.plain-expected.json +++ b/metricbeat/module/kubernetes/state_daemonset/_meta/testdata/docs.plain-expected.json @@ -7,7 +7,7 @@ }, "kubernetes": { "daemonset": { - "name": "kindnet", + "name": "kube-proxy", "replicas": { "available": 1, "desired": 1, @@ -15,9 +15,7 @@ "unavailable": 0 } }, - "namespace": { - "name": "kube-system" - } + "namespace": "kube-system" }, "metricset": { "name": "state_daemonset", @@ -36,7 +34,7 @@ }, "kubernetes": { "daemonset": { - "name": "kube-proxy", + "name": "kindnet", "replicas": { "available": 1, "desired": 1, @@ -44,9 +42,7 @@ "unavailable": 0 } }, - "namespace": { - "name": "kube-system" - } + "namespace": "kube-system" }, "metricset": { "name": "state_daemonset", diff --git a/metricbeat/module/kubernetes/state_daemonset/state_daemonset.go b/metricbeat/module/kubernetes/state_daemonset/state_daemonset.go index 95e580744b1..1066afa2195 100644 --- a/metricbeat/module/kubernetes/state_daemonset/state_daemonset.go +++ b/metricbeat/module/kubernetes/state_daemonset/state_daemonset.go @@ -50,7 +50,7 @@ var ( Labels: map[string]p.LabelMap{ "daemonset": p.KeyLabel("name"), - "namespace": p.KeyLabel(mb.ModuleDataKey + ".namespace.name"), + "namespace": p.KeyLabel(mb.ModuleDataKey + ".namespace"), }, } ) diff --git a/metricbeat/module/kubernetes/state_deployment/_meta/test/ksm.v1.3.0.expected b/metricbeat/module/kubernetes/state_deployment/_meta/test/ksm.v1.3.0.expected index fa3dbf2df80..b2dce007146 100644 --- a/metricbeat/module/kubernetes/state_deployment/_meta/test/ksm.v1.3.0.expected +++ b/metricbeat/module/kubernetes/state_deployment/_meta/test/ksm.v1.3.0.expected @@ -2,12 +2,10 @@ { "RootFields": null, "ModuleFields": { - "namespace": { - "name": "kube-system" - } + "namespace": "kube-system" }, "MetricSetFields": { - "name": "kube-dns", + "name": "kube-state-metrics", "paused": false, "replicas": { "available": 1, @@ -30,9 +28,7 @@ { "RootFields": null, "ModuleFields": { - "namespace": { - "name": "kube-system" - } + "namespace": "kube-system" }, "MetricSetFields": { "name": "kubernetes-dashboard", @@ -58,12 +54,10 @@ { "RootFields": null, "ModuleFields": { - "namespace": { - "name": "kube-system" - } + "namespace": "kube-system" }, "MetricSetFields": { - "name": "kube-state-metrics", + "name": "kube-dns", "paused": false, "replicas": { "available": 1, diff --git a/metricbeat/module/kubernetes/state_deployment/_meta/test/ksm.v1.8.0.expected b/metricbeat/module/kubernetes/state_deployment/_meta/test/ksm.v1.8.0.expected index b83cb15d7fd..3f1255e36c6 100644 --- a/metricbeat/module/kubernetes/state_deployment/_meta/test/ksm.v1.8.0.expected +++ b/metricbeat/module/kubernetes/state_deployment/_meta/test/ksm.v1.8.0.expected @@ -2,18 +2,16 @@ { "RootFields": null, "ModuleFields": { - "namespace": { - "name": "kube-system" - } + "namespace": "kube-system" }, "MetricSetFields": { - "name": "coredns", + "name": "kube-state-metrics", "paused": false, "replicas": { - "available": 2, - "desired": 2, + "available": 1, + "desired": 1, "unavailable": 0, - "updated": 2 + "updated": 1 } }, "Index": "", @@ -30,18 +28,16 @@ { "RootFields": null, "ModuleFields": { - "namespace": { - "name": "kube-system" - } + "namespace": "kube-system" }, "MetricSetFields": { - "name": "kube-state-metrics", + "name": "coredns", "paused": false, "replicas": { - "available": 1, - "desired": 1, + "available": 2, + "desired": 2, "unavailable": 0, - "updated": 1 + "updated": 2 } }, "Index": "", diff --git a/metricbeat/module/kubernetes/state_deployment/_meta/test/ksm.v2.0.0.expected b/metricbeat/module/kubernetes/state_deployment/_meta/test/ksm.v2.0.0.expected index 5f0b8c20689..de439f14386 100644 --- a/metricbeat/module/kubernetes/state_deployment/_meta/test/ksm.v2.0.0.expected +++ b/metricbeat/module/kubernetes/state_deployment/_meta/test/ksm.v2.0.0.expected @@ -2,18 +2,16 @@ { "RootFields": null, "ModuleFields": { - "namespace": { - "name": "kube-system" - } + "namespace": "kube-system" }, "MetricSetFields": { - "name": "coredns", + "name": "kube-state-metrics", "paused": false, "replicas": { - "available": 2, - "desired": 2, + "available": 1, + "desired": 1, "unavailable": 0, - "updated": 2 + "updated": 1 } }, "Index": "", @@ -30,9 +28,7 @@ { "RootFields": null, "ModuleFields": { - "namespace": { - "name": "local-path-storage" - } + "namespace": "local-path-storage" }, "MetricSetFields": { "name": "local-path-provisioner", @@ -58,12 +54,10 @@ { "RootFields": null, "ModuleFields": { - "namespace": { - "name": "kube-system" - } + "namespace": "default" }, "MetricSetFields": { - "name": "kube-state-metrics", + "name": "hello-python", "paused": false, "replicas": { "available": 1, @@ -86,18 +80,16 @@ { "RootFields": null, "ModuleFields": { - "namespace": { - "name": "default" - } + "namespace": "kube-system" }, "MetricSetFields": { - "name": "hello-python", + "name": "coredns", "paused": false, "replicas": { - "available": 1, - "desired": 1, + "available": 2, + "desired": 2, "unavailable": 0, - "updated": 1 + "updated": 2 } }, "Index": "", diff --git a/metricbeat/module/kubernetes/state_deployment/_meta/testdata/ksm-v1.3.0.plain-expected.json b/metricbeat/module/kubernetes/state_deployment/_meta/testdata/ksm-v1.3.0.plain-expected.json index fabdb0fabb0..19faf98a4ce 100644 --- a/metricbeat/module/kubernetes/state_deployment/_meta/testdata/ksm-v1.3.0.plain-expected.json +++ b/metricbeat/module/kubernetes/state_deployment/_meta/testdata/ksm-v1.3.0.plain-expected.json @@ -7,18 +7,16 @@ }, "kubernetes": { "deployment": { - "name": "jumpy-owl-redis", - "paused": true, + "name": "tiller-deploy", + "paused": false, "replicas": { - "available": 6, - "desired": 2, - "unavailable": 7, - "updated": 8 + "available": 1, + "desired": 1, + "unavailable": 0, + "updated": 1 } }, - "namespace": { - "name": "test" - } + "namespace": "kube-system" }, "metricset": { "name": "state_deployment", @@ -37,18 +35,16 @@ }, "kubernetes": { "deployment": { - "name": "kube-state-metrics", + "name": "wise-lynx-jenkins", "paused": false, "replicas": { "available": 1, - "desired": 2, - "unavailable": 1, - "updated": 2 + "desired": 1, + "unavailable": 0, + "updated": 1 } }, - "namespace": { - "name": "kube-system" - } + "namespace": "jenkins" }, "metricset": { "name": "state_deployment", @@ -68,17 +64,15 @@ "kubernetes": { "deployment": { "name": "jumpy-owl-redis", - "paused": false, + "paused": true, "replicas": { - "available": 0, - "desired": 1, - "unavailable": 1, - "updated": 1 + "available": 6, + "desired": 2, + "unavailable": 7, + "updated": 8 } }, - "namespace": { - "name": "default" - } + "namespace": "test" }, "metricset": { "name": "state_deployment", @@ -97,18 +91,16 @@ }, "kubernetes": { "deployment": { - "name": "tiller-deploy", + "name": "jumpy-owl-redis", "paused": false, "replicas": { - "available": 1, + "available": 0, "desired": 1, - "unavailable": 0, + "unavailable": 1, "updated": 1 } }, - "namespace": { - "name": "kube-system" - } + "namespace": "default" }, "metricset": { "name": "state_deployment", @@ -127,18 +119,16 @@ }, "kubernetes": { "deployment": { - "name": "wise-lynx-jenkins", + "name": "kube-state-metrics", "paused": false, "replicas": { "available": 1, - "desired": 1, - "unavailable": 0, - "updated": 1 + "desired": 2, + "unavailable": 1, + "updated": 2 } }, - "namespace": { - "name": "jenkins" - } + "namespace": "kube-system" }, "metricset": { "name": "state_deployment", diff --git a/metricbeat/module/kubernetes/state_deployment/_meta/testdata/ksm-v1.8.0.plain-expected.json b/metricbeat/module/kubernetes/state_deployment/_meta/testdata/ksm-v1.8.0.plain-expected.json index bfc922814ee..b766e4068f4 100644 --- a/metricbeat/module/kubernetes/state_deployment/_meta/testdata/ksm-v1.8.0.plain-expected.json +++ b/metricbeat/module/kubernetes/state_deployment/_meta/testdata/ksm-v1.8.0.plain-expected.json @@ -7,7 +7,7 @@ }, "kubernetes": { "deployment": { - "name": "springboot-cr-applier", + "name": "metricbeat", "paused": false, "replicas": { "available": 1, @@ -16,9 +16,7 @@ "updated": 1 } }, - "namespace": { - "name": "telenet-cluster-ops" - } + "namespace": "openshift-logging" }, "metricset": { "name": "state_deployment", @@ -37,7 +35,7 @@ }, "kubernetes": { "deployment": { - "name": "namespace-operator", + "name": "springboot-operator", "paused": false, "replicas": { "available": 1, @@ -46,9 +44,7 @@ "updated": 1 } }, - "namespace": { - "name": "telenet-operators" - } + "namespace": "bi" }, "metricset": { "name": "state_deployment", @@ -67,7 +63,7 @@ }, "kubernetes": { "deployment": { - "name": "jenkins-operator", + "name": "tiller", "paused": false, "replicas": { "available": 1, @@ -76,9 +72,7 @@ "updated": 1 } }, - "namespace": { - "name": "devops-playground" - } + "namespace": "tiller" }, "metricset": { "name": "state_deployment", @@ -97,18 +91,16 @@ }, "kubernetes": { "deployment": { - "name": "kube-state-metrics", + "name": "jenkins-operator", "paused": false, "replicas": { - "available": 1, - "desired": 1, + "available": 0, + "desired": 0, "unavailable": 0, - "updated": 1 + "updated": 0 } }, - "namespace": { - "name": "openshift-monitoring" - } + "namespace": "adc-vault" }, "metricset": { "name": "state_deployment", @@ -127,18 +119,16 @@ }, "kubernetes": { "deployment": { - "name": "webconsole", + "name": "jenkins-operator", "paused": false, "replicas": { - "available": 3, - "desired": 3, + "available": 1, + "desired": 1, "unavailable": 0, - "updated": 3 + "updated": 1 } }, - "namespace": { - "name": "openshift-web-console" - } + "namespace": "paas-demo" }, "metricset": { "name": "state_deployment", @@ -157,7 +147,7 @@ }, "kubernetes": { "deployment": { - "name": "springboot-operator", + "name": "springboot-cr-applier", "paused": false, "replicas": { "available": 1, @@ -166,9 +156,7 @@ "updated": 1 } }, - "namespace": { - "name": "gdpr" - } + "namespace": "telenet-cluster-ops" }, "metricset": { "name": "state_deployment", @@ -196,9 +184,7 @@ "updated": 1 } }, - "namespace": { - "name": "edev-communication" - } + "namespace": "paas-demo" }, "metricset": { "name": "state_deployment", @@ -217,7 +203,7 @@ }, "kubernetes": { "deployment": { - "name": "jenkins-operator", + "name": "springboot-operator", "paused": false, "replicas": { "available": 1, @@ -226,9 +212,7 @@ "updated": 1 } }, - "namespace": { - "name": "telenet-baseimages" - } + "namespace": "edev-communication" }, "metricset": { "name": "state_deployment", @@ -247,7 +231,7 @@ }, "kubernetes": { "deployment": { - "name": "jenkins-operator", + "name": "kube-state-metrics", "paused": false, "replicas": { "available": 1, @@ -256,9 +240,7 @@ "updated": 1 } }, - "namespace": { - "name": "bi" - } + "namespace": "openshift-logging" }, "metricset": { "name": "state_deployment", @@ -277,7 +259,7 @@ }, "kubernetes": { "deployment": { - "name": "dynatrace-oneagent-operator", + "name": "jenkins-operator", "paused": false, "replicas": { "available": 1, @@ -286,9 +268,7 @@ "updated": 1 } }, - "namespace": { - "name": "dynatrace" - } + "namespace": "devops-playground" }, "metricset": { "name": "state_deployment", @@ -316,9 +296,7 @@ "updated": 1 } }, - "namespace": { - "name": "darwin-integrations" - } + "namespace": "edev-tools" }, "metricset": { "name": "state_deployment", @@ -346,9 +324,7 @@ "updated": 1 } }, - "namespace": { - "name": "paas-demo" - } + "namespace": "devops-playground" }, "metricset": { "name": "state_deployment", @@ -376,9 +352,7 @@ "updated": 1 } }, - "namespace": { - "name": "openshift-monitoring" - } + "namespace": "openshift-monitoring" }, "metricset": { "name": "state_deployment", @@ -397,18 +371,16 @@ }, "kubernetes": { "deployment": { - "name": "jenkins-cr-applier", + "name": "tiller-deploy", "paused": false, "replicas": { - "available": 1, + "available": 0, "desired": 1, - "unavailable": 0, + "unavailable": 1, "updated": 1 } }, - "namespace": { - "name": "telenet-cluster-ops" - } + "namespace": "tiller" }, "metricset": { "name": "state_deployment", @@ -427,18 +399,16 @@ }, "kubernetes": { "deployment": { - "name": "tiller-deploy", + "name": "jenkins-operator", "paused": false, "replicas": { - "available": 0, + "available": 1, "desired": 1, - "unavailable": 1, + "unavailable": 0, "updated": 1 } }, - "namespace": { - "name": "tiller" - } + "namespace": "darwin-integrations" }, "metricset": { "name": "state_deployment", @@ -457,18 +427,16 @@ }, "kubernetes": { "deployment": { - "name": "elasticsearch", + "name": "jenkins-operator", "paused": false, "replicas": { - "available": 0, + "available": 1, "desired": 1, - "unavailable": 1, + "unavailable": 0, "updated": 1 } }, - "namespace": { - "name": "test-config" - } + "namespace": "edev-communication" }, "metricset": { "name": "state_deployment", @@ -487,18 +455,16 @@ }, "kubernetes": { "deployment": { - "name": "jenkins-operator", + "name": "webconsole", "paused": false, "replicas": { - "available": 0, - "desired": 0, + "available": 3, + "desired": 3, "unavailable": 0, - "updated": 0 + "updated": 3 } }, - "namespace": { - "name": "adc-vault" - } + "namespace": "openshift-web-console" }, "metricset": { "name": "state_deployment", @@ -517,7 +483,7 @@ }, "kubernetes": { "deployment": { - "name": "springboot-operator", + "name": "console", "paused": false, "replicas": { "available": 1, @@ -526,9 +492,7 @@ "updated": 1 } }, - "namespace": { - "name": "edev-tools" - } + "namespace": "openshift-console" }, "metricset": { "name": "state_deployment", @@ -547,7 +511,7 @@ }, "kubernetes": { "deployment": { - "name": "springboot-operator", + "name": "jenkins-operator", "paused": false, "replicas": { "available": 1, @@ -556,9 +520,7 @@ "updated": 1 } }, - "namespace": { - "name": "devops-playground" - } + "namespace": "gdpr" }, "metricset": { "name": "state_deployment", @@ -577,7 +539,7 @@ }, "kubernetes": { "deployment": { - "name": "cluster-monitoring-operator", + "name": "jenkins-cr-applier", "paused": false, "replicas": { "available": 1, @@ -586,9 +548,7 @@ "updated": 1 } }, - "namespace": { - "name": "openshift-monitoring" - } + "namespace": "telenet-cluster-ops" }, "metricset": { "name": "state_deployment", @@ -607,7 +567,7 @@ }, "kubernetes": { "deployment": { - "name": "jenkins-operator", + "name": "namespace-operator", "paused": false, "replicas": { "available": 1, @@ -616,9 +576,7 @@ "updated": 1 } }, - "namespace": { - "name": "paas-demo" - } + "namespace": "telenet-operators" }, "metricset": { "name": "state_deployment", @@ -637,7 +595,7 @@ }, "kubernetes": { "deployment": { - "name": "springboot-operator", + "name": "jenkins-operator", "paused": false, "replicas": { "available": 1, @@ -646,9 +604,7 @@ "updated": 1 } }, - "namespace": { - "name": "bi" - } + "namespace": "telenet-baseimages" }, "metricset": { "name": "state_deployment", @@ -667,7 +623,7 @@ }, "kubernetes": { "deployment": { - "name": "console", + "name": "cluster-monitoring-operator", "paused": false, "replicas": { "available": 1, @@ -676,9 +632,7 @@ "updated": 1 } }, - "namespace": { - "name": "openshift-console" - } + "namespace": "openshift-monitoring" }, "metricset": { "name": "state_deployment", @@ -697,18 +651,16 @@ }, "kubernetes": { "deployment": { - "name": "kibana-kibana", + "name": "springboot-operator", "paused": false, "replicas": { - "available": 0, - "desired": 0, + "available": 1, + "desired": 1, "unavailable": 0, - "updated": 0 + "updated": 1 } }, - "namespace": { - "name": "kibana-tst" - } + "namespace": "darwin-integrations" }, "metricset": { "name": "state_deployment", @@ -727,7 +679,7 @@ }, "kubernetes": { "deployment": { - "name": "jenkins-operator", + "name": "kibana", "paused": false, "replicas": { "available": 1, @@ -736,9 +688,7 @@ "updated": 1 } }, - "namespace": { - "name": "edev-tools" - } + "namespace": "test-config" }, "metricset": { "name": "state_deployment", @@ -757,7 +707,7 @@ }, "kubernetes": { "deployment": { - "name": "jenkins-operator", + "name": "dynatrace-oneagent-operator", "paused": false, "replicas": { "available": 1, @@ -766,9 +716,7 @@ "updated": 1 } }, - "namespace": { - "name": "edev-communication" - } + "namespace": "dynatrace" }, "metricset": { "name": "state_deployment", @@ -787,7 +735,7 @@ }, "kubernetes": { "deployment": { - "name": "kube-state-metrics", + "name": "springboot-operator", "paused": false, "replicas": { "available": 1, @@ -796,9 +744,7 @@ "updated": 1 } }, - "namespace": { - "name": "openshift-logging" - } + "namespace": "edev-tools" }, "metricset": { "name": "state_deployment", @@ -817,7 +763,7 @@ }, "kubernetes": { "deployment": { - "name": "grafana", + "name": "sonarqube-operator", "paused": false, "replicas": { "available": 1, @@ -826,9 +772,7 @@ "updated": 1 } }, - "namespace": { - "name": "openshift-monitoring" - } + "namespace": "devops-playground" }, "metricset": { "name": "state_deployment", @@ -847,7 +791,7 @@ }, "kubernetes": { "deployment": { - "name": "weblogic-operator", + "name": "grafana", "paused": false, "replicas": { "available": 1, @@ -856,9 +800,7 @@ "updated": 1 } }, - "namespace": { - "name": "weblogic-poc" - } + "namespace": "openshift-monitoring" }, "metricset": { "name": "state_deployment", @@ -877,18 +819,16 @@ }, "kubernetes": { "deployment": { - "name": "jenkins-operator", + "name": "kibana-kibana", "paused": false, "replicas": { - "available": 1, - "desired": 1, + "available": 0, + "desired": 0, "unavailable": 0, - "updated": 1 + "updated": 0 } }, - "namespace": { - "name": "gdpr" - } + "namespace": "kibana-tst" }, "metricset": { "name": "state_deployment", @@ -907,7 +847,7 @@ }, "kubernetes": { "deployment": { - "name": "sonarqube-operator", + "name": "kube-state-metrics", "paused": false, "replicas": { "available": 1, @@ -916,9 +856,7 @@ "updated": 1 } }, - "namespace": { - "name": "devops-playground" - } + "namespace": "openshift-monitoring" }, "metricset": { "name": "state_deployment", @@ -937,18 +875,16 @@ }, "kubernetes": { "deployment": { - "name": "kibana", + "name": "elasticsearch", "paused": false, "replicas": { - "available": 1, + "available": 0, "desired": 1, - "unavailable": 0, + "unavailable": 1, "updated": 1 } }, - "namespace": { - "name": "test-config" - } + "namespace": "test-config" }, "metricset": { "name": "state_deployment", @@ -976,9 +912,7 @@ "updated": 1 } }, - "namespace": { - "name": "darwin-integrations" - } + "namespace": "gdpr" }, "metricset": { "name": "state_deployment", @@ -997,7 +931,7 @@ }, "kubernetes": { "deployment": { - "name": "tiller", + "name": "jenkins-operator", "paused": false, "replicas": { "available": 1, @@ -1006,9 +940,7 @@ "updated": 1 } }, - "namespace": { - "name": "tiller" - } + "namespace": "bi" }, "metricset": { "name": "state_deployment", @@ -1027,7 +959,7 @@ }, "kubernetes": { "deployment": { - "name": "metricbeat", + "name": "weblogic-operator", "paused": false, "replicas": { "available": 1, @@ -1036,9 +968,7 @@ "updated": 1 } }, - "namespace": { - "name": "openshift-logging" - } + "namespace": "weblogic-poc" }, "metricset": { "name": "state_deployment", diff --git a/metricbeat/module/kubernetes/state_deployment/state_deployment.go b/metricbeat/module/kubernetes/state_deployment/state_deployment.go index 6b440baa2b9..02448afdc9a 100644 --- a/metricbeat/module/kubernetes/state_deployment/state_deployment.go +++ b/metricbeat/module/kubernetes/state_deployment/state_deployment.go @@ -51,7 +51,7 @@ var ( Labels: map[string]p.LabelMap{ "deployment": p.KeyLabel("name"), - "namespace": p.KeyLabel(mb.ModuleDataKey + ".namespace.name"), + "namespace": p.KeyLabel(mb.ModuleDataKey + ".namespace"), }, } ) diff --git a/metricbeat/module/kubernetes/state_job/_meta/test/ksm.v1.8.0.expected b/metricbeat/module/kubernetes/state_job/_meta/test/ksm.v1.8.0.expected index 5b40b8ece05..8822378f36d 100644 --- a/metricbeat/module/kubernetes/state_job/_meta/test/ksm.v1.8.0.expected +++ b/metricbeat/module/kubernetes/state_job/_meta/test/ksm.v1.8.0.expected @@ -2,9 +2,7 @@ { "RootFields": null, "ModuleFields": { - "namespace": { - "name": "default" - } + "namespace": "default" }, "MetricSetFields": { "completions": { diff --git a/metricbeat/module/kubernetes/state_job/_meta/test/ksm.v2.0.0.expected b/metricbeat/module/kubernetes/state_job/_meta/test/ksm.v2.0.0.expected index 484d805c3a0..c9110a37ed0 100644 --- a/metricbeat/module/kubernetes/state_job/_meta/test/ksm.v2.0.0.expected +++ b/metricbeat/module/kubernetes/state_job/_meta/test/ksm.v2.0.0.expected @@ -2,9 +2,7 @@ { "RootFields": null, "ModuleFields": { - "namespace": { - "name": "default" - } + "namespace": "default" }, "MetricSetFields": { "completions": { diff --git a/metricbeat/module/kubernetes/state_job/_meta/testdata/kube-state-metrics-v1.8.0.plain-expected.json b/metricbeat/module/kubernetes/state_job/_meta/testdata/kube-state-metrics-v1.8.0.plain-expected.json index 926fc60faaa..afa859bc418 100644 --- a/metricbeat/module/kubernetes/state_job/_meta/testdata/kube-state-metrics-v1.8.0.plain-expected.json +++ b/metricbeat/module/kubernetes/state_job/_meta/testdata/kube-state-metrics-v1.8.0.plain-expected.json @@ -10,7 +10,7 @@ "completions": { "desired": 1 }, - "name": "sleep-30-ok-cron-27075628", + "name": "sleep-30-ok-cron-27075645", "owner": { "is_controller": "true", "kind": "CronJob", @@ -25,12 +25,10 @@ "succeeded": 0 }, "time": { - "created": "2021-06-24T12:28:00.000Z" + "created": "2021-06-24T12:45:00.000Z" } }, - "namespace": { - "name": "default" - } + "namespace": "default" }, "metricset": { "name": "state_job", @@ -50,33 +48,27 @@ "kubernetes": { "job": { "completions": { - "desired": 1 + "desired": 20 }, - "name": "sleep-30-ok-cron-27075625", + "name": "sleep-5-parallel-cron-27075617", "owner": { "is_controller": "true", "kind": "CronJob", - "name": "sleep-30-ok-cron" + "name": "sleep-5-parallel-cron" }, "parallelism": { - "desired": 1 + "desired": 5 }, "pods": { - "active": 0, + "active": 5, "failed": 0, - "succeeded": 1 - }, - "status": { - "complete": "true" + "succeeded": 0 }, "time": { - "completed": "2021-06-24T12:37:03.000Z", - "created": "2021-06-24T12:25:00.000Z" + "created": "2021-06-24T12:17:00.000Z" } }, - "namespace": { - "name": "default" - } + "namespace": "parallel-ns" }, "metricset": { "name": "state_job", @@ -96,29 +88,27 @@ "kubernetes": { "job": { "completions": { - "desired": 20 + "desired": 1 }, - "name": "sleep-5-parallel-cron-27075641", + "name": "sleep-30-fail-cron-27075644", "owner": { "is_controller": "true", "kind": "CronJob", - "name": "sleep-5-parallel-cron" + "name": "sleep-30-fail-cron" }, "parallelism": { - "desired": 5 + "desired": 1 }, "pods": { - "active": 5, + "active": 1, "failed": 0, "succeeded": 0 }, "time": { - "created": "2021-06-24T12:41:00.000Z" + "created": "2021-06-24T12:44:00.000Z" } }, - "namespace": { - "name": "parallel-ns" - } + "namespace": "default" }, "metricset": { "name": "state_job", @@ -140,7 +130,7 @@ "completions": { "desired": 1 }, - "name": "sleep-30-fail-cron-27075644", + "name": "sleep-30-fail-cron-27075549", "owner": { "is_controller": "true", "kind": "CronJob", @@ -155,12 +145,10 @@ "succeeded": 0 }, "time": { - "created": "2021-06-24T12:44:00.000Z" + "created": "2021-06-24T11:09:00.000Z" } }, - "namespace": { - "name": "default" - } + "namespace": "default" }, "metricset": { "name": "state_job", @@ -182,11 +170,11 @@ "completions": { "desired": 1 }, - "name": "sleep-30-fail-cron-27075618", + "name": "sleep-30-ok-cron-27075638", "owner": { "is_controller": "true", "kind": "CronJob", - "name": "sleep-30-fail-cron" + "name": "sleep-30-ok-cron" }, "parallelism": { "desired": 1 @@ -197,12 +185,10 @@ "succeeded": 0 }, "time": { - "created": "2021-06-24T12:18:00.000Z" + "created": "2021-06-24T12:38:00.000Z" } }, - "namespace": { - "name": "default" - } + "namespace": "default" }, "metricset": { "name": "state_job", @@ -222,29 +208,27 @@ "kubernetes": { "job": { "completions": { - "desired": 1 + "desired": 20 }, - "name": "sleep-30-ok-cron-27075618", + "name": "sleep-5-parallel-cron-27075639", "owner": { "is_controller": "true", "kind": "CronJob", - "name": "sleep-30-ok-cron" + "name": "sleep-5-parallel-cron" }, "parallelism": { - "desired": 1 + "desired": 5 }, "pods": { - "active": 1, + "active": 5, "failed": 0, "succeeded": 0 }, "time": { - "created": "2021-06-24T12:18:00.000Z" + "created": "2021-06-24T12:39:00.000Z" } }, - "namespace": { - "name": "default" - } + "namespace": "parallel-ns" }, "metricset": { "name": "state_job", @@ -266,7 +250,7 @@ "completions": { "desired": 1 }, - "name": "sleep-30-fail-cron-27075622", + "name": "sleep-30-fail-cron-27075535", "owner": { "is_controller": "true", "kind": "CronJob", @@ -281,12 +265,10 @@ "succeeded": 0 }, "time": { - "created": "2021-06-24T12:22:00.000Z" + "created": "2021-06-24T10:55:00.000Z" } }, - "namespace": { - "name": "default" - } + "namespace": "default" }, "metricset": { "name": "state_job", @@ -306,29 +288,27 @@ "kubernetes": { "job": { "completions": { - "desired": 1 + "desired": 20 }, - "name": "sleep-30-ok-cron-27075617", + "name": "sleep-5-parallel-cron-27075551", "owner": { "is_controller": "true", "kind": "CronJob", - "name": "sleep-30-ok-cron" + "name": "sleep-5-parallel-cron" }, "parallelism": { - "desired": 1 + "desired": 5 }, "pods": { - "active": 1, + "active": 2, "failed": 0, - "succeeded": 0 + "succeeded": 18 }, "time": { - "created": "2021-06-24T12:17:00.000Z" + "created": "2021-06-24T11:11:00.000Z" } }, - "namespace": { - "name": "default" - } + "namespace": "parallel-ns" }, "metricset": { "name": "state_job", @@ -350,7 +330,7 @@ "completions": { "desired": 20 }, - "name": "sleep-5-parallel-cron-27075639", + "name": "sleep-5-parallel-cron-27075623", "owner": { "is_controller": "true", "kind": "CronJob", @@ -360,17 +340,15 @@ "desired": 5 }, "pods": { - "active": 5, + "active": 1, "failed": 0, - "succeeded": 0 + "succeeded": 19 }, "time": { - "created": "2021-06-24T12:39:00.000Z" + "created": "2021-06-24T12:23:00.000Z" } }, - "namespace": { - "name": "parallel-ns" - } + "namespace": "parallel-ns" }, "metricset": { "name": "state_job", @@ -392,7 +370,7 @@ "completions": { "desired": 1 }, - "name": "sleep-30-ok-cron-27075590", + "name": "sleep-30-ok-cron-27075592", "owner": { "is_controller": "true", "kind": "CronJob", @@ -407,12 +385,10 @@ "succeeded": 0 }, "time": { - "created": "2021-06-24T11:50:00.000Z" + "created": "2021-06-24T11:52:00.000Z" } }, - "namespace": { - "name": "default" - } + "namespace": "default" }, "metricset": { "name": "state_job", @@ -432,29 +408,27 @@ "kubernetes": { "job": { "completions": { - "desired": 20 + "desired": 1 }, - "name": "sleep-5-parallel-cron-27075622", + "name": "sleep-30-fail-cron-27075584", "owner": { "is_controller": "true", "kind": "CronJob", - "name": "sleep-5-parallel-cron" + "name": "sleep-30-fail-cron" }, "parallelism": { - "desired": 5 + "desired": 1 }, "pods": { - "active": 5, + "active": 1, "failed": 0, - "succeeded": 2 + "succeeded": 0 }, "time": { - "created": "2021-06-24T12:22:00.000Z" + "created": "2021-06-24T11:44:00.000Z" } }, - "namespace": { - "name": "parallel-ns" - } + "namespace": "default" }, "metricset": { "name": "state_job", @@ -476,7 +450,7 @@ "completions": { "desired": 1 }, - "name": "sleep-30-ok-cron-27075627", + "name": "sleep-30-ok-cron-27075642", "owner": { "is_controller": "true", "kind": "CronJob", @@ -486,21 +460,15 @@ "desired": 1 }, "pods": { - "active": 0, + "active": 1, "failed": 0, - "succeeded": 1 - }, - "status": { - "complete": "true" + "succeeded": 0 }, "time": { - "completed": "2021-06-24T12:32:20.000Z", - "created": "2021-06-24T12:27:00.000Z" + "created": "2021-06-24T12:42:00.000Z" } }, - "namespace": { - "name": "default" - } + "namespace": "default" }, "metricset": { "name": "state_job", @@ -520,19 +488,19 @@ "kubernetes": { "job": { "completions": { - "desired": 1 + "desired": 20 }, - "name": "sleep-30-ok-cron-27075643", + "name": "sleep-5-parallel-cron-27075643", "owner": { "is_controller": "true", "kind": "CronJob", - "name": "sleep-30-ok-cron" + "name": "sleep-5-parallel-cron" }, "parallelism": { - "desired": 1 + "desired": 5 }, "pods": { - "active": 1, + "active": 5, "failed": 0, "succeeded": 0 }, @@ -540,9 +508,7 @@ "created": "2021-06-24T12:43:00.000Z" } }, - "namespace": { - "name": "default" - } + "namespace": "parallel-ns" }, "metricset": { "name": "state_job", @@ -564,7 +530,7 @@ "completions": { "desired": 1 }, - "name": "sleep-30-fail-cron-27075625", + "name": "sleep-30-fail-cron-27075536", "owner": { "is_controller": "true", "kind": "CronJob", @@ -579,12 +545,10 @@ "succeeded": 0 }, "time": { - "created": "2021-06-24T12:25:00.000Z" + "created": "2021-06-24T10:56:00.000Z" } }, - "namespace": { - "name": "default" - } + "namespace": "default" }, "metricset": { "name": "state_job", @@ -606,7 +570,7 @@ "completions": { "desired": 20 }, - "name": "sleep-5-parallel-cron-27075644", + "name": "sleep-5-parallel-cron-27075630", "owner": { "is_controller": "true", "kind": "CronJob", @@ -621,12 +585,10 @@ "succeeded": 0 }, "time": { - "created": "2021-06-24T12:44:00.000Z" + "created": "2021-06-24T12:30:00.000Z" } }, - "namespace": { - "name": "parallel-ns" - } + "namespace": "parallel-ns" }, "metricset": { "name": "state_job", @@ -646,29 +608,27 @@ "kubernetes": { "job": { "completions": { - "desired": 1 + "desired": 20 }, - "name": "sleep-30-ok-cron-27075610", + "name": "sleep-5-parallel-cron-27075626", "owner": { "is_controller": "true", "kind": "CronJob", - "name": "sleep-30-ok-cron" + "name": "sleep-5-parallel-cron" }, "parallelism": { - "desired": 1 + "desired": 5 }, "pods": { - "active": 1, + "active": 5, "failed": 0, - "succeeded": 0 + "succeeded": 2 }, "time": { - "created": "2021-06-24T12:10:00.000Z" + "created": "2021-06-24T12:26:00.000Z" } }, - "namespace": { - "name": "default" - } + "namespace": "parallel-ns" }, "metricset": { "name": "state_job", @@ -688,29 +648,27 @@ "kubernetes": { "job": { "completions": { - "desired": 20 + "desired": 1 }, - "name": "sleep-5-parallel-cron-27075628", + "name": "sleep-30-fail-cron-27075610", "owner": { "is_controller": "true", "kind": "CronJob", - "name": "sleep-5-parallel-cron" + "name": "sleep-30-fail-cron" }, "parallelism": { - "desired": 5 + "desired": 1 }, "pods": { - "active": 5, + "active": 1, "failed": 0, "succeeded": 0 }, "time": { - "created": "2021-06-24T12:28:00.000Z" + "created": "2021-06-24T12:10:00.000Z" } }, - "namespace": { - "name": "parallel-ns" - } + "namespace": "default" }, "metricset": { "name": "state_job", @@ -732,11 +690,11 @@ "completions": { "desired": 1 }, - "name": "sleep-30-fail-cron-27075632", + "name": "sleep-30-ok-cron-27075618", "owner": { "is_controller": "true", "kind": "CronJob", - "name": "sleep-30-fail-cron" + "name": "sleep-30-ok-cron" }, "parallelism": { "desired": 1 @@ -747,12 +705,10 @@ "succeeded": 0 }, "time": { - "created": "2021-06-24T12:32:00.000Z" + "created": "2021-06-24T12:18:00.000Z" } }, - "namespace": { - "name": "default" - } + "namespace": "default" }, "metricset": { "name": "state_job", @@ -772,29 +728,27 @@ "kubernetes": { "job": { "completions": { - "desired": 1 + "desired": 20 }, - "name": "sleep-30-fail-cron-27075612", + "name": "sleep-5-parallel-cron-27075608", "owner": { "is_controller": "true", "kind": "CronJob", - "name": "sleep-30-fail-cron" + "name": "sleep-5-parallel-cron" }, "parallelism": { - "desired": 1 + "desired": 5 }, "pods": { "active": 1, "failed": 0, - "succeeded": 0 + "succeeded": 19 }, "time": { - "created": "2021-06-24T12:12:00.000Z" + "created": "2021-06-24T12:08:00.000Z" } }, - "namespace": { - "name": "default" - } + "namespace": "parallel-ns" }, "metricset": { "name": "state_job", @@ -814,29 +768,27 @@ "kubernetes": { "job": { "completions": { - "desired": 1 + "desired": 20 }, - "name": "sleep-30-ok-cron-27075633", + "name": "sleep-5-parallel-cron-27075622", "owner": { "is_controller": "true", "kind": "CronJob", - "name": "sleep-30-ok-cron" + "name": "sleep-5-parallel-cron" }, "parallelism": { - "desired": 1 + "desired": 5 }, "pods": { - "active": 1, + "active": 5, "failed": 0, - "succeeded": 0 + "succeeded": 2 }, "time": { - "created": "2021-06-24T12:33:00.000Z" + "created": "2021-06-24T12:22:00.000Z" } }, - "namespace": { - "name": "default" - } + "namespace": "parallel-ns" }, "metricset": { "name": "state_job", @@ -858,7 +810,7 @@ "completions": { "desired": 1 }, - "name": "sleep-30-fail-cron-27075615", + "name": "sleep-30-fail-cron-27075591", "owner": { "is_controller": "true", "kind": "CronJob", @@ -873,12 +825,10 @@ "succeeded": 0 }, "time": { - "created": "2021-06-24T12:15:00.000Z" + "created": "2021-06-24T11:51:00.000Z" } }, - "namespace": { - "name": "default" - } + "namespace": "default" }, "metricset": { "name": "state_job", @@ -900,11 +850,11 @@ "completions": { "desired": 1 }, - "name": "sleep-30-ok-cron-27075621", + "name": "sleep-30-fail-cron-27075598", "owner": { "is_controller": "true", "kind": "CronJob", - "name": "sleep-30-ok-cron" + "name": "sleep-30-fail-cron" }, "parallelism": { "desired": 1 @@ -915,12 +865,10 @@ "succeeded": 0 }, "time": { - "created": "2021-06-24T12:21:00.000Z" + "created": "2021-06-24T11:58:00.000Z" } }, - "namespace": { - "name": "default" - } + "namespace": "default" }, "metricset": { "name": "state_job", @@ -940,29 +888,27 @@ "kubernetes": { "job": { "completions": { - "desired": 1 + "desired": 20 }, - "name": "sleep-30-fail-cron-27075591", + "name": "sleep-5-parallel-cron-27075636", "owner": { "is_controller": "true", "kind": "CronJob", - "name": "sleep-30-fail-cron" + "name": "sleep-5-parallel-cron" }, "parallelism": { - "desired": 1 + "desired": 5 }, "pods": { - "active": 1, + "active": 5, "failed": 0, - "succeeded": 0 + "succeeded": 4 }, "time": { - "created": "2021-06-24T11:51:00.000Z" + "created": "2021-06-24T12:36:00.000Z" } }, - "namespace": { - "name": "default" - } + "namespace": "parallel-ns" }, "metricset": { "name": "state_job", @@ -984,11 +930,11 @@ "completions": { "desired": 1 }, - "name": "sleep-30-ok-cron-27075639", + "name": "sleep-30-fail-cron-27075645", "owner": { "is_controller": "true", "kind": "CronJob", - "name": "sleep-30-ok-cron" + "name": "sleep-30-fail-cron" }, "parallelism": { "desired": 1 @@ -999,12 +945,10 @@ "succeeded": 0 }, "time": { - "created": "2021-06-24T12:39:00.000Z" + "created": "2021-06-24T12:45:00.000Z" } }, - "namespace": { - "name": "default" - } + "namespace": "default" }, "metricset": { "name": "state_job", @@ -1026,27 +970,29 @@ "completions": { "desired": 1 }, - "name": "sleep-30-fail-cron-27075638", + "name": "sleep-30-ok-cron-27075629", "owner": { "is_controller": "true", "kind": "CronJob", - "name": "sleep-30-fail-cron" + "name": "sleep-30-ok-cron" }, "parallelism": { "desired": 1 }, "pods": { - "active": 1, + "active": 0, "failed": 0, - "succeeded": 0 + "succeeded": 1 + }, + "status": { + "complete": "true" }, "time": { - "created": "2021-06-24T12:38:00.000Z" + "completed": "2021-06-24T12:42:50.000Z", + "created": "2021-06-24T12:29:00.000Z" } }, - "namespace": { - "name": "default" - } + "namespace": "default" }, "metricset": { "name": "state_job", @@ -1066,29 +1012,27 @@ "kubernetes": { "job": { "completions": { - "desired": 1 + "desired": 20 }, - "name": "sleep-30-ok-cron-27075641", + "name": "sleep-5-parallel-cron-27075604", "owner": { "is_controller": "true", "kind": "CronJob", - "name": "sleep-30-ok-cron" + "name": "sleep-5-parallel-cron" }, "parallelism": { - "desired": 1 + "desired": 5 }, "pods": { "active": 1, "failed": 0, - "succeeded": 0 + "succeeded": 19 }, "time": { - "created": "2021-06-24T12:41:00.000Z" + "created": "2021-06-24T12:04:00.000Z" } }, - "namespace": { - "name": "default" - } + "namespace": "parallel-ns" }, "metricset": { "name": "state_job", @@ -1108,29 +1052,27 @@ "kubernetes": { "job": { "completions": { - "desired": 1 + "desired": 20 }, - "name": "sleep-30-ok-cron-27075636", + "name": "sleep-5-parallel-cron-27075591", "owner": { "is_controller": "true", "kind": "CronJob", - "name": "sleep-30-ok-cron" + "name": "sleep-5-parallel-cron" }, "parallelism": { - "desired": 1 + "desired": 5 }, "pods": { "active": 1, "failed": 0, - "succeeded": 0 + "succeeded": 19 }, "time": { - "created": "2021-06-24T12:36:00.000Z" + "created": "2021-06-24T11:51:00.000Z" } }, - "namespace": { - "name": "default" - } + "namespace": "parallel-ns" }, "metricset": { "name": "state_job", @@ -1150,29 +1092,27 @@ "kubernetes": { "job": { "completions": { - "desired": 1 + "desired": 20 }, - "name": "sleep-30-fail-cron-27075605", + "name": "sleep-5-parallel-cron-27075645", "owner": { "is_controller": "true", "kind": "CronJob", - "name": "sleep-30-fail-cron" + "name": "sleep-5-parallel-cron" }, "parallelism": { - "desired": 1 + "desired": 5 }, "pods": { - "active": 1, + "active": 5, "failed": 0, "succeeded": 0 }, "time": { - "created": "2021-06-24T12:05:00.000Z" + "created": "2021-06-24T12:45:00.000Z" } }, - "namespace": { - "name": "default" - } + "namespace": "parallel-ns" }, "metricset": { "name": "state_job", @@ -1194,11 +1134,11 @@ "completions": { "desired": 1 }, - "name": "sleep-30-ok-cron-27075634", + "name": "sleep-30-fail-cron-27075625", "owner": { "is_controller": "true", "kind": "CronJob", - "name": "sleep-30-ok-cron" + "name": "sleep-30-fail-cron" }, "parallelism": { "desired": 1 @@ -1209,12 +1149,10 @@ "succeeded": 0 }, "time": { - "created": "2021-06-24T12:34:00.000Z" + "created": "2021-06-24T12:25:00.000Z" } }, - "namespace": { - "name": "default" - } + "namespace": "default" }, "metricset": { "name": "state_job", @@ -1236,7 +1174,7 @@ "completions": { "desired": 1 }, - "name": "sleep-30-fail-cron-27075547", + "name": "sleep-30-fail-cron-27075639", "owner": { "is_controller": "true", "kind": "CronJob", @@ -1251,12 +1189,10 @@ "succeeded": 0 }, "time": { - "created": "2021-06-24T11:07:00.000Z" + "created": "2021-06-24T12:39:00.000Z" } }, - "namespace": { - "name": "default" - } + "namespace": "default" }, "metricset": { "name": "state_job", @@ -1278,11 +1214,11 @@ "completions": { "desired": 1 }, - "name": "sleep-30-ok-cron-27075592", + "name": "sleep-30-fail-cron-27075636", "owner": { "is_controller": "true", "kind": "CronJob", - "name": "sleep-30-ok-cron" + "name": "sleep-30-fail-cron" }, "parallelism": { "desired": 1 @@ -1293,12 +1229,10 @@ "succeeded": 0 }, "time": { - "created": "2021-06-24T11:52:00.000Z" + "created": "2021-06-24T12:36:00.000Z" } }, - "namespace": { - "name": "default" - } + "namespace": "default" }, "metricset": { "name": "state_job", @@ -1318,29 +1252,27 @@ "kubernetes": { "job": { "completions": { - "desired": 20 + "desired": 1 }, - "name": "sleep-5-parallel-cron-27075601", + "name": "sleep-30-fail-cron-27075615", "owner": { "is_controller": "true", "kind": "CronJob", - "name": "sleep-5-parallel-cron" + "name": "sleep-30-fail-cron" }, "parallelism": { - "desired": 5 + "desired": 1 }, "pods": { - "active": 3, + "active": 1, "failed": 0, - "succeeded": 17 + "succeeded": 0 }, "time": { - "created": "2021-06-24T12:01:00.000Z" + "created": "2021-06-24T12:15:00.000Z" } }, - "namespace": { - "name": "parallel-ns" - } + "namespace": "default" }, "metricset": { "name": "state_job", @@ -1362,7 +1294,7 @@ "completions": { "desired": 20 }, - "name": "sleep-5-parallel-cron-27075603", + "name": "sleep-5-parallel-cron-27075641", "owner": { "is_controller": "true", "kind": "CronJob", @@ -1372,17 +1304,15 @@ "desired": 5 }, "pods": { - "active": 1, + "active": 5, "failed": 0, - "succeeded": 19 + "succeeded": 0 }, "time": { - "created": "2021-06-24T12:03:00.000Z" + "created": "2021-06-24T12:41:00.000Z" } }, - "namespace": { - "name": "parallel-ns" - } + "namespace": "parallel-ns" }, "metricset": { "name": "state_job", @@ -1402,33 +1332,27 @@ "kubernetes": { "job": { "completions": { - "desired": 20 + "desired": 1 }, - "name": "sleep-5-parallel-cron-27075613", + "name": "sleep-30-ok-cron-27075621", "owner": { "is_controller": "true", "kind": "CronJob", - "name": "sleep-5-parallel-cron" + "name": "sleep-30-ok-cron" }, "parallelism": { - "desired": 5 + "desired": 1 }, "pods": { - "active": 0, + "active": 1, "failed": 0, - "succeeded": 20 - }, - "status": { - "complete": "true" + "succeeded": 0 }, "time": { - "completed": "2021-06-24T12:28:39.000Z", - "created": "2021-06-24T12:13:00.000Z" + "created": "2021-06-24T12:21:00.000Z" } }, - "namespace": { - "name": "parallel-ns" - } + "namespace": "default" }, "metricset": { "name": "state_job", @@ -1448,29 +1372,27 @@ "kubernetes": { "job": { "completions": { - "desired": 20 + "desired": 1 }, - "name": "sleep-5-parallel-cron-27075626", + "name": "sleep-30-ok-cron-27075623", "owner": { "is_controller": "true", "kind": "CronJob", - "name": "sleep-5-parallel-cron" + "name": "sleep-30-ok-cron" }, "parallelism": { - "desired": 5 + "desired": 1 }, "pods": { - "active": 5, + "active": 1, "failed": 0, - "succeeded": 2 + "succeeded": 0 }, "time": { - "created": "2021-06-24T12:26:00.000Z" + "created": "2021-06-24T12:23:00.000Z" } }, - "namespace": { - "name": "parallel-ns" - } + "namespace": "default" }, "metricset": { "name": "state_job", @@ -1490,29 +1412,27 @@ "kubernetes": { "job": { "completions": { - "desired": 1 + "desired": 20 }, - "name": "sleep-30-fail-cron-27075576", + "name": "sleep-5-parallel-cron-27075563", "owner": { "is_controller": "true", "kind": "CronJob", - "name": "sleep-30-fail-cron" + "name": "sleep-5-parallel-cron" }, "parallelism": { - "desired": 1 + "desired": 5 }, "pods": { - "active": 1, + "active": 2, "failed": 0, - "succeeded": 0 + "succeeded": 18 }, "time": { - "created": "2021-06-24T11:36:00.000Z" + "created": "2021-06-24T11:23:00.000Z" } }, - "namespace": { - "name": "default" - } + "namespace": "parallel-ns" }, "metricset": { "name": "state_job", @@ -1534,11 +1454,11 @@ "completions": { "desired": 1 }, - "name": "sleep-30-ok-cron-27075547", + "name": "sleep-30-fail-cron-27075612", "owner": { "is_controller": "true", "kind": "CronJob", - "name": "sleep-30-ok-cron" + "name": "sleep-30-fail-cron" }, "parallelism": { "desired": 1 @@ -1549,12 +1469,10 @@ "succeeded": 0 }, "time": { - "created": "2021-06-24T11:07:00.000Z" + "created": "2021-06-24T12:12:00.000Z" } }, - "namespace": { - "name": "default" - } + "namespace": "default" }, "metricset": { "name": "state_job", @@ -1576,7 +1494,7 @@ "completions": { "desired": 20 }, - "name": "sleep-5-parallel-cron-27075615", + "name": "sleep-5-parallel-cron-27075634", "owner": { "is_controller": "true", "kind": "CronJob", @@ -1586,21 +1504,15 @@ "desired": 5 }, "pods": { - "active": 0, + "active": 5, "failed": 0, - "succeeded": 20 - }, - "status": { - "complete": "true" + "succeeded": 1 }, "time": { - "completed": "2021-06-24T12:33:19.000Z", - "created": "2021-06-24T12:15:00.000Z" + "created": "2021-06-24T12:34:00.000Z" } }, - "namespace": { - "name": "parallel-ns" - } + "namespace": "parallel-ns" }, "metricset": { "name": "state_job", @@ -1620,29 +1532,27 @@ "kubernetes": { "job": { "completions": { - "desired": 1 + "desired": 20 }, - "name": "sleep-30-fail-cron-27075628", + "name": "sleep-5-parallel-cron-27075590", "owner": { "is_controller": "true", "kind": "CronJob", - "name": "sleep-30-fail-cron" + "name": "sleep-5-parallel-cron" }, "parallelism": { - "desired": 1 + "desired": 5 }, "pods": { "active": 1, "failed": 0, - "succeeded": 0 + "succeeded": 19 }, "time": { - "created": "2021-06-24T12:28:00.000Z" + "created": "2021-06-24T11:50:00.000Z" } }, - "namespace": { - "name": "default" - } + "namespace": "parallel-ns" }, "metricset": { "name": "state_job", @@ -1664,11 +1574,11 @@ "completions": { "desired": 1 }, - "name": "sleep-30-ok-cron-27075640", + "name": "sleep-30-fail-cron-27075621", "owner": { "is_controller": "true", "kind": "CronJob", - "name": "sleep-30-ok-cron" + "name": "sleep-30-fail-cron" }, "parallelism": { "desired": 1 @@ -1679,12 +1589,10 @@ "succeeded": 0 }, "time": { - "created": "2021-06-24T12:40:00.000Z" + "created": "2021-06-24T12:21:00.000Z" } }, - "namespace": { - "name": "default" - } + "namespace": "default" }, "metricset": { "name": "state_job", @@ -1706,7 +1614,7 @@ "completions": { "desired": 1 }, - "name": "sleep-30-ok-cron-27075642", + "name": "sleep-30-ok-cron-27075639", "owner": { "is_controller": "true", "kind": "CronJob", @@ -1721,12 +1629,10 @@ "succeeded": 0 }, "time": { - "created": "2021-06-24T12:42:00.000Z" + "created": "2021-06-24T12:39:00.000Z" } }, - "namespace": { - "name": "default" - } + "namespace": "default" }, "metricset": { "name": "state_job", @@ -1746,29 +1652,27 @@ "kubernetes": { "job": { "completions": { - "desired": 20 + "desired": 1 }, - "name": "sleep-5-parallel-cron-27075630", + "name": "sleep-30-fail-cron-27075594", "owner": { "is_controller": "true", "kind": "CronJob", - "name": "sleep-5-parallel-cron" + "name": "sleep-30-fail-cron" }, "parallelism": { - "desired": 5 + "desired": 1 }, "pods": { - "active": 5, + "active": 1, "failed": 0, "succeeded": 0 }, "time": { - "created": "2021-06-24T12:30:00.000Z" + "created": "2021-06-24T11:54:00.000Z" } }, - "namespace": { - "name": "parallel-ns" - } + "namespace": "default" }, "metricset": { "name": "state_job", @@ -1790,7 +1694,7 @@ "completions": { "desired": 20 }, - "name": "sleep-5-parallel-cron-27075635", + "name": "sleep-5-parallel-cron-27075631", "owner": { "is_controller": "true", "kind": "CronJob", @@ -1802,15 +1706,13 @@ "pods": { "active": 5, "failed": 0, - "succeeded": 0 + "succeeded": 3 }, "time": { - "created": "2021-06-24T12:35:00.000Z" + "created": "2021-06-24T12:31:00.000Z" } }, - "namespace": { - "name": "parallel-ns" - } + "namespace": "parallel-ns" }, "metricset": { "name": "state_job", @@ -1830,29 +1732,27 @@ "kubernetes": { "job": { "completions": { - "desired": 20 + "desired": 1 }, - "name": "sleep-5-parallel-cron-27075621", + "name": "sleep-30-ok-cron-27075535", "owner": { "is_controller": "true", "kind": "CronJob", - "name": "sleep-5-parallel-cron" + "name": "sleep-30-ok-cron" }, "parallelism": { - "desired": 5 + "desired": 1 }, "pods": { - "active": 5, + "active": 1, "failed": 0, - "succeeded": 1 + "succeeded": 0 }, "time": { - "created": "2021-06-24T12:21:00.000Z" + "created": "2021-06-24T10:55:00.000Z" } }, - "namespace": { - "name": "parallel-ns" - } + "namespace": "default" }, "metricset": { "name": "state_job", @@ -1874,11 +1774,11 @@ "completions": { "desired": 1 }, - "name": "sleep-30-ok-cron-27075646", + "name": "sleep-30-fail-cron-27075631", "owner": { "is_controller": "true", "kind": "CronJob", - "name": "sleep-30-ok-cron" + "name": "sleep-30-fail-cron" }, "parallelism": { "desired": 1 @@ -1889,12 +1789,10 @@ "succeeded": 0 }, "time": { - "created": "2021-06-24T12:46:00.000Z" + "created": "2021-06-24T12:31:00.000Z" } }, - "namespace": { - "name": "default" - } + "namespace": "default" }, "metricset": { "name": "state_job", @@ -1916,7 +1814,7 @@ "completions": { "desired": 20 }, - "name": "sleep-5-parallel-cron-27075584", + "name": "sleep-5-parallel-cron-27075629", "owner": { "is_controller": "true", "kind": "CronJob", @@ -1926,17 +1824,15 @@ "desired": 5 }, "pods": { - "active": 2, + "active": 5, "failed": 0, - "succeeded": 18 + "succeeded": 6 }, "time": { - "created": "2021-06-24T11:44:00.000Z" + "created": "2021-06-24T12:29:00.000Z" } }, - "namespace": { - "name": "parallel-ns" - } + "namespace": "parallel-ns" }, "metricset": { "name": "state_job", @@ -1958,7 +1854,7 @@ "completions": { "desired": 20 }, - "name": "sleep-5-parallel-cron-27075604", + "name": "sleep-5-parallel-cron-27075633", "owner": { "is_controller": "true", "kind": "CronJob", @@ -1968,17 +1864,15 @@ "desired": 5 }, "pods": { - "active": 1, + "active": 5, "failed": 0, - "succeeded": 19 + "succeeded": 0 }, "time": { - "created": "2021-06-24T12:04:00.000Z" + "created": "2021-06-24T12:33:00.000Z" } }, - "namespace": { - "name": "parallel-ns" - } + "namespace": "parallel-ns" }, "metricset": { "name": "state_job", @@ -2000,7 +1894,7 @@ "completions": { "desired": 20 }, - "name": "sleep-5-parallel-cron-27075585", + "name": "sleep-5-parallel-cron-27075616", "owner": { "is_controller": "true", "kind": "CronJob", @@ -2010,17 +1904,15 @@ "desired": 5 }, "pods": { - "active": 5, + "active": 1, "failed": 0, - "succeeded": 10 + "succeeded": 19 }, "time": { - "created": "2021-06-24T11:45:00.000Z" + "created": "2021-06-24T12:16:00.000Z" } }, - "namespace": { - "name": "parallel-ns" - } + "namespace": "parallel-ns" }, "metricset": { "name": "state_job", @@ -2042,11 +1934,11 @@ "completions": { "desired": 1 }, - "name": "sleep-30-fail-cron-27075603", + "name": "sleep-30-ok-cron-27075637", "owner": { "is_controller": "true", "kind": "CronJob", - "name": "sleep-30-fail-cron" + "name": "sleep-30-ok-cron" }, "parallelism": { "desired": 1 @@ -2057,12 +1949,10 @@ "succeeded": 0 }, "time": { - "created": "2021-06-24T12:03:00.000Z" + "created": "2021-06-24T12:37:00.000Z" } }, - "namespace": { - "name": "default" - } + "namespace": "default" }, "metricset": { "name": "state_job", @@ -2084,7 +1974,7 @@ "completions": { "desired": 1 }, - "name": "sleep-30-fail-cron-27075619", + "name": "sleep-30-fail-cron-27075616", "owner": { "is_controller": "true", "kind": "CronJob", @@ -2099,12 +1989,10 @@ "succeeded": 0 }, "time": { - "created": "2021-06-24T12:19:00.000Z" + "created": "2021-06-24T12:16:00.000Z" } }, - "namespace": { - "name": "default" - } + "namespace": "default" }, "metricset": { "name": "state_job", @@ -2126,7 +2014,7 @@ "completions": { "desired": 20 }, - "name": "sleep-5-parallel-cron-27075620", + "name": "sleep-5-parallel-cron-27075615", "owner": { "is_controller": "true", "kind": "CronJob", @@ -2144,13 +2032,11 @@ "complete": "true" }, "time": { - "completed": "2021-06-24T12:37:24.000Z", - "created": "2021-06-24T12:20:00.000Z" + "completed": "2021-06-24T12:33:19.000Z", + "created": "2021-06-24T12:15:00.000Z" } }, - "namespace": { - "name": "parallel-ns" - } + "namespace": "parallel-ns" }, "metricset": { "name": "state_job", @@ -2172,7 +2058,7 @@ "completions": { "desired": 1 }, - "name": "sleep-30-ok-cron-27075630", + "name": "sleep-30-ok-cron-27075627", "owner": { "is_controller": "true", "kind": "CronJob", @@ -2182,17 +2068,19 @@ "desired": 1 }, "pods": { - "active": 1, + "active": 0, "failed": 0, - "succeeded": 0 + "succeeded": 1 + }, + "status": { + "complete": "true" }, "time": { - "created": "2021-06-24T12:30:00.000Z" + "completed": "2021-06-24T12:32:20.000Z", + "created": "2021-06-24T12:27:00.000Z" } }, - "namespace": { - "name": "default" - } + "namespace": "default" }, "metricset": { "name": "state_job", @@ -2214,7 +2102,7 @@ "completions": { "desired": 1 }, - "name": "sleep-30-fail-cron-27075634", + "name": "sleep-30-fail-cron-27075611", "owner": { "is_controller": "true", "kind": "CronJob", @@ -2229,12 +2117,10 @@ "succeeded": 0 }, "time": { - "created": "2021-06-24T12:34:00.000Z" + "created": "2021-06-24T12:11:00.000Z" } }, - "namespace": { - "name": "default" - } + "namespace": "default" }, "metricset": { "name": "state_job", @@ -2256,31 +2142,25 @@ "completions": { "desired": 1 }, - "name": "sleep-30-ok-cron-27075629", + "name": "sleep-30-fail-cron-27075593", "owner": { "is_controller": "true", "kind": "CronJob", - "name": "sleep-30-ok-cron" + "name": "sleep-30-fail-cron" }, "parallelism": { "desired": 1 }, "pods": { - "active": 0, + "active": 1, "failed": 0, - "succeeded": 1 - }, - "status": { - "complete": "true" + "succeeded": 0 }, "time": { - "completed": "2021-06-24T12:42:50.000Z", - "created": "2021-06-24T12:29:00.000Z" + "created": "2021-06-24T11:53:00.000Z" } }, - "namespace": { - "name": "default" - } + "namespace": "default" }, "metricset": { "name": "state_job", @@ -2302,11 +2182,11 @@ "completions": { "desired": 1 }, - "name": "sleep-30-ok-cron-27075594", + "name": "sleep-30-fail-cron-27075641", "owner": { "is_controller": "true", "kind": "CronJob", - "name": "sleep-30-ok-cron" + "name": "sleep-30-fail-cron" }, "parallelism": { "desired": 1 @@ -2317,12 +2197,10 @@ "succeeded": 0 }, "time": { - "created": "2021-06-24T11:54:00.000Z" + "created": "2021-06-24T12:41:00.000Z" } }, - "namespace": { - "name": "default" - } + "namespace": "default" }, "metricset": { "name": "state_job", @@ -2342,29 +2220,27 @@ "kubernetes": { "job": { "completions": { - "desired": 20 + "desired": 1 }, - "name": "sleep-5-parallel-cron-27075532", + "name": "sleep-30-fail-cron-27075628", "owner": { "is_controller": "true", "kind": "CronJob", - "name": "sleep-5-parallel-cron" + "name": "sleep-30-fail-cron" }, "parallelism": { - "desired": 5 + "desired": 1 }, "pods": { - "active": 2, + "active": 1, "failed": 0, - "succeeded": 18 + "succeeded": 0 }, "time": { - "created": "2021-06-24T10:52:00.000Z" + "created": "2021-06-24T12:28:00.000Z" } }, - "namespace": { - "name": "parallel-ns" - } + "namespace": "default" }, "metricset": { "name": "state_job", @@ -2384,29 +2260,31 @@ "kubernetes": { "job": { "completions": { - "desired": 20 + "desired": 1 }, - "name": "sleep-5-parallel-cron-27075612", + "name": "sleep-30-ok-cron-27075625", "owner": { "is_controller": "true", "kind": "CronJob", - "name": "sleep-5-parallel-cron" + "name": "sleep-30-ok-cron" }, "parallelism": { - "desired": 5 + "desired": 1 }, "pods": { - "active": 5, + "active": 0, "failed": 0, "succeeded": 1 }, + "status": { + "complete": "true" + }, "time": { - "created": "2021-06-24T12:12:00.000Z" + "completed": "2021-06-24T12:37:03.000Z", + "created": "2021-06-24T12:25:00.000Z" } }, - "namespace": { - "name": "parallel-ns" - } + "namespace": "default" }, "metricset": { "name": "state_job", @@ -2428,7 +2306,7 @@ "completions": { "desired": 20 }, - "name": "sleep-5-parallel-cron-27075610", + "name": "sleep-5-parallel-cron-27075585", "owner": { "is_controller": "true", "kind": "CronJob", @@ -2438,17 +2316,15 @@ "desired": 5 }, "pods": { - "active": 3, + "active": 5, "failed": 0, - "succeeded": 17 + "succeeded": 10 }, "time": { - "created": "2021-06-24T12:10:00.000Z" + "created": "2021-06-24T11:45:00.000Z" } }, - "namespace": { - "name": "parallel-ns" - } + "namespace": "parallel-ns" }, "metricset": { "name": "state_job", @@ -2470,11 +2346,11 @@ "completions": { "desired": 1 }, - "name": "sleep-30-ok-cron-27075536", + "name": "sleep-30-fail-cron-27075601", "owner": { "is_controller": "true", "kind": "CronJob", - "name": "sleep-30-ok-cron" + "name": "sleep-30-fail-cron" }, "parallelism": { "desired": 1 @@ -2485,12 +2361,10 @@ "succeeded": 0 }, "time": { - "created": "2021-06-24T10:56:00.000Z" + "created": "2021-06-24T12:01:00.000Z" } }, - "namespace": { - "name": "default" - } + "namespace": "default" }, "metricset": { "name": "state_job", @@ -2512,7 +2386,7 @@ "completions": { "desired": 1 }, - "name": "sleep-30-fail-cron-27075636", + "name": "sleep-30-fail-cron-27075614", "owner": { "is_controller": "true", "kind": "CronJob", @@ -2527,12 +2401,10 @@ "succeeded": 0 }, "time": { - "created": "2021-06-24T12:36:00.000Z" + "created": "2021-06-24T12:14:00.000Z" } }, - "namespace": { - "name": "default" - } + "namespace": "default" }, "metricset": { "name": "state_job", @@ -2552,29 +2424,27 @@ "kubernetes": { "job": { "completions": { - "desired": 1 + "desired": 20 }, - "name": "sleep-30-fail-cron-27075549", + "name": "sleep-5-parallel-cron-27075644", "owner": { "is_controller": "true", "kind": "CronJob", - "name": "sleep-30-fail-cron" + "name": "sleep-5-parallel-cron" }, "parallelism": { - "desired": 1 + "desired": 5 }, "pods": { - "active": 1, + "active": 5, "failed": 0, "succeeded": 0 }, "time": { - "created": "2021-06-24T11:09:00.000Z" + "created": "2021-06-24T12:44:00.000Z" } }, - "namespace": { - "name": "default" - } + "namespace": "parallel-ns" }, "metricset": { "name": "state_job", @@ -2596,7 +2466,7 @@ "completions": { "desired": 1 }, - "name": "sleep-30-fail-cron-27075640", + "name": "sleep-30-fail-cron-27075617", "owner": { "is_controller": "true", "kind": "CronJob", @@ -2611,12 +2481,10 @@ "succeeded": 0 }, "time": { - "created": "2021-06-24T12:40:00.000Z" + "created": "2021-06-24T12:17:00.000Z" } }, - "namespace": { - "name": "default" - } + "namespace": "default" }, "metricset": { "name": "state_job", @@ -2636,29 +2504,27 @@ "kubernetes": { "job": { "completions": { - "desired": 20 + "desired": 1 }, - "name": "sleep-5-parallel-cron-27075592", + "name": "sleep-30-ok-cron-27075601", "owner": { "is_controller": "true", "kind": "CronJob", - "name": "sleep-5-parallel-cron" + "name": "sleep-30-ok-cron" }, "parallelism": { - "desired": 5 + "desired": 1 }, "pods": { "active": 1, "failed": 0, - "succeeded": 19 + "succeeded": 0 }, "time": { - "created": "2021-06-24T11:52:00.000Z" + "created": "2021-06-24T12:01:00.000Z" } }, - "namespace": { - "name": "parallel-ns" - } + "namespace": "default" }, "metricset": { "name": "state_job", @@ -2678,29 +2544,27 @@ "kubernetes": { "job": { "completions": { - "desired": 1 + "desired": 20 }, - "name": "sleep-30-fail-cron-27075598", + "name": "sleep-5-parallel-cron-27075628", "owner": { "is_controller": "true", "kind": "CronJob", - "name": "sleep-30-fail-cron" + "name": "sleep-5-parallel-cron" }, "parallelism": { - "desired": 1 + "desired": 5 }, "pods": { - "active": 1, + "active": 5, "failed": 0, "succeeded": 0 }, "time": { - "created": "2021-06-24T11:58:00.000Z" + "created": "2021-06-24T12:28:00.000Z" } }, - "namespace": { - "name": "default" - } + "namespace": "parallel-ns" }, "metricset": { "name": "state_job", @@ -2722,11 +2586,11 @@ "completions": { "desired": 1 }, - "name": "sleep-30-ok-cron-27075631", + "name": "sleep-30-fail-cron-27075605", "owner": { "is_controller": "true", "kind": "CronJob", - "name": "sleep-30-ok-cron" + "name": "sleep-30-fail-cron" }, "parallelism": { "desired": 1 @@ -2737,12 +2601,10 @@ "succeeded": 0 }, "time": { - "created": "2021-06-24T12:31:00.000Z" + "created": "2021-06-24T12:05:00.000Z" } }, - "namespace": { - "name": "default" - } + "namespace": "default" }, "metricset": { "name": "state_job", @@ -2764,11 +2626,11 @@ "completions": { "desired": 1 }, - "name": "sleep-30-fail-cron-27075609", + "name": "sleep-30-ok-cron-27075646", "owner": { "is_controller": "true", "kind": "CronJob", - "name": "sleep-30-fail-cron" + "name": "sleep-30-ok-cron" }, "parallelism": { "desired": 1 @@ -2779,12 +2641,10 @@ "succeeded": 0 }, "time": { - "created": "2021-06-24T12:09:00.000Z" + "created": "2021-06-24T12:46:00.000Z" } }, - "namespace": { - "name": "default" - } + "namespace": "default" }, "metricset": { "name": "state_job", @@ -2804,29 +2664,27 @@ "kubernetes": { "job": { "completions": { - "desired": 20 + "desired": 1 }, - "name": "sleep-5-parallel-cron-27075646", + "name": "sleep-30-fail-cron-27075607", "owner": { "is_controller": "true", "kind": "CronJob", - "name": "sleep-5-parallel-cron" + "name": "sleep-30-fail-cron" }, "parallelism": { - "desired": 5 + "desired": 1 }, "pods": { - "active": 5, + "active": 1, "failed": 0, "succeeded": 0 }, "time": { - "created": "2021-06-24T12:46:00.000Z" + "created": "2021-06-24T12:07:00.000Z" } }, - "namespace": { - "name": "parallel-ns" - } + "namespace": "default" }, "metricset": { "name": "state_job", @@ -2846,29 +2704,27 @@ "kubernetes": { "job": { "completions": { - "desired": 1 + "desired": 20 }, - "name": "sleep-30-fail-cron-27075630", + "name": "sleep-5-parallel-cron-27075627", "owner": { "is_controller": "true", "kind": "CronJob", - "name": "sleep-30-fail-cron" + "name": "sleep-5-parallel-cron" }, "parallelism": { - "desired": 1 + "desired": 5 }, "pods": { - "active": 1, + "active": 5, "failed": 0, - "succeeded": 0 + "succeeded": 15 }, "time": { - "created": "2021-06-24T12:30:00.000Z" + "created": "2021-06-24T12:27:00.000Z" } }, - "namespace": { - "name": "default" - } + "namespace": "parallel-ns" }, "metricset": { "name": "state_job", @@ -2890,7 +2746,7 @@ "completions": { "desired": 20 }, - "name": "sleep-5-parallel-cron-27075634", + "name": "sleep-5-parallel-cron-27075620", "owner": { "is_controller": "true", "kind": "CronJob", @@ -2900,17 +2756,19 @@ "desired": 5 }, "pods": { - "active": 5, + "active": 0, "failed": 0, - "succeeded": 1 + "succeeded": 20 + }, + "status": { + "complete": "true" }, "time": { - "created": "2021-06-24T12:34:00.000Z" + "completed": "2021-06-24T12:37:24.000Z", + "created": "2021-06-24T12:20:00.000Z" } }, - "namespace": { - "name": "parallel-ns" - } + "namespace": "parallel-ns" }, "metricset": { "name": "state_job", @@ -2930,29 +2788,30 @@ "kubernetes": { "job": { "completions": { - "desired": 20 + "desired": 1 }, - "name": "sleep-5-parallel-cron-27075632", + "name": "sleep-30-fail-cron-27075600", "owner": { "is_controller": "true", "kind": "CronJob", - "name": "sleep-5-parallel-cron" + "name": "sleep-30-fail-cron" }, "parallelism": { - "desired": 5 + "desired": 1 }, "pods": { - "active": 5, - "failed": 0, - "succeeded": 1 + "active": 0, + "failed": 1, + "succeeded": 0 + }, + "status": { + "failed": "true" }, "time": { - "created": "2021-06-24T12:32:00.000Z" + "created": "2021-06-24T12:00:00.000Z" } }, - "namespace": { - "name": "parallel-ns" - } + "namespace": "default" }, "metricset": { "name": "state_job", @@ -2972,29 +2831,27 @@ "kubernetes": { "job": { "completions": { - "desired": 1 + "desired": 20 }, - "name": "sleep-30-fail-cron-27075563", + "name": "sleep-5-parallel-cron-27075607", "owner": { "is_controller": "true", "kind": "CronJob", - "name": "sleep-30-fail-cron" + "name": "sleep-5-parallel-cron" }, "parallelism": { - "desired": 1 + "desired": 5 }, "pods": { - "active": 1, + "active": 3, "failed": 0, - "succeeded": 0 + "succeeded": 17 }, "time": { - "created": "2021-06-24T11:23:00.000Z" + "created": "2021-06-24T12:07:00.000Z" } }, - "namespace": { - "name": "default" - } + "namespace": "parallel-ns" }, "metricset": { "name": "state_job", @@ -3014,29 +2871,27 @@ "kubernetes": { "job": { "completions": { - "desired": 20 + "desired": 1 }, - "name": "sleep-5-parallel-cron-27075535", + "name": "sleep-30-fail-cron-27075590", "owner": { "is_controller": "true", "kind": "CronJob", - "name": "sleep-5-parallel-cron" + "name": "sleep-30-fail-cron" }, "parallelism": { - "desired": 5 + "desired": 1 }, "pods": { "active": 1, "failed": 0, - "succeeded": 19 + "succeeded": 0 }, "time": { - "created": "2021-06-24T10:55:00.000Z" + "created": "2021-06-24T11:50:00.000Z" } }, - "namespace": { - "name": "parallel-ns" - } + "namespace": "default" }, "metricset": { "name": "state_job", @@ -3056,29 +2911,27 @@ "kubernetes": { "job": { "completions": { - "desired": 20 + "desired": 1 }, - "name": "sleep-5-parallel-cron-27075643", + "name": "sleep-30-ok-cron-27075617", "owner": { "is_controller": "true", "kind": "CronJob", - "name": "sleep-5-parallel-cron" + "name": "sleep-30-ok-cron" }, "parallelism": { - "desired": 5 + "desired": 1 }, "pods": { - "active": 5, + "active": 1, "failed": 0, "succeeded": 0 }, "time": { - "created": "2021-06-24T12:43:00.000Z" + "created": "2021-06-24T12:17:00.000Z" } }, - "namespace": { - "name": "parallel-ns" - } + "namespace": "default" }, "metricset": { "name": "state_job", @@ -3098,29 +2951,27 @@ "kubernetes": { "job": { "completions": { - "desired": 1 + "desired": 20 }, - "name": "sleep-30-fail-cron-27075641", + "name": "sleep-5-parallel-cron-27075610", "owner": { "is_controller": "true", "kind": "CronJob", - "name": "sleep-30-fail-cron" + "name": "sleep-5-parallel-cron" }, "parallelism": { - "desired": 1 + "desired": 5 }, "pods": { - "active": 1, + "active": 3, "failed": 0, - "succeeded": 0 + "succeeded": 17 }, "time": { - "created": "2021-06-24T12:41:00.000Z" + "created": "2021-06-24T12:10:00.000Z" } }, - "namespace": { - "name": "default" - } + "namespace": "parallel-ns" }, "metricset": { "name": "state_job", @@ -3140,29 +2991,27 @@ "kubernetes": { "job": { "completions": { - "desired": 1 + "desired": 20 }, - "name": "sleep-30-fail-cron-27075633", + "name": "sleep-5-parallel-cron-27075572", "owner": { "is_controller": "true", "kind": "CronJob", - "name": "sleep-30-fail-cron" + "name": "sleep-5-parallel-cron" }, "parallelism": { - "desired": 1 + "desired": 5 }, "pods": { - "active": 1, + "active": 2, "failed": 0, - "succeeded": 0 + "succeeded": 18 }, "time": { - "created": "2021-06-24T12:33:00.000Z" + "created": "2021-06-24T11:32:00.000Z" } }, - "namespace": { - "name": "default" - } + "namespace": "parallel-ns" }, "metricset": { "name": "state_job", @@ -3184,11 +3033,11 @@ "completions": { "desired": 1 }, - "name": "sleep-30-fail-cron-27075614", + "name": "sleep-30-ok-cron-27075641", "owner": { "is_controller": "true", "kind": "CronJob", - "name": "sleep-30-fail-cron" + "name": "sleep-30-ok-cron" }, "parallelism": { "desired": 1 @@ -3199,12 +3048,10 @@ "succeeded": 0 }, "time": { - "created": "2021-06-24T12:14:00.000Z" + "created": "2021-06-24T12:41:00.000Z" } }, - "namespace": { - "name": "default" - } + "namespace": "default" }, "metricset": { "name": "state_job", @@ -3226,7 +3073,7 @@ "completions": { "desired": 1 }, - "name": "sleep-30-fail-cron-27075604", + "name": "sleep-30-fail-cron-27075547", "owner": { "is_controller": "true", "kind": "CronJob", @@ -3241,12 +3088,10 @@ "succeeded": 0 }, "time": { - "created": "2021-06-24T12:04:00.000Z" + "created": "2021-06-24T11:07:00.000Z" } }, - "namespace": { - "name": "default" - } + "namespace": "default" }, "metricset": { "name": "state_job", @@ -3268,11 +3113,11 @@ "completions": { "desired": 1 }, - "name": "sleep-30-fail-cron-27075643", + "name": "sleep-30-ok-cron-27075630", "owner": { "is_controller": "true", "kind": "CronJob", - "name": "sleep-30-fail-cron" + "name": "sleep-30-ok-cron" }, "parallelism": { "desired": 1 @@ -3283,12 +3128,10 @@ "succeeded": 0 }, "time": { - "created": "2021-06-24T12:43:00.000Z" + "created": "2021-06-24T12:30:00.000Z" } }, - "namespace": { - "name": "default" - } + "namespace": "default" }, "metricset": { "name": "state_job", @@ -3310,7 +3153,7 @@ "completions": { "desired": 20 }, - "name": "sleep-5-parallel-cron-27075642", + "name": "sleep-5-parallel-cron-27075621", "owner": { "is_controller": "true", "kind": "CronJob", @@ -3322,15 +3165,13 @@ "pods": { "active": 5, "failed": 0, - "succeeded": 0 + "succeeded": 1 }, "time": { - "created": "2021-06-24T12:42:00.000Z" + "created": "2021-06-24T12:21:00.000Z" } }, - "namespace": { - "name": "parallel-ns" - } + "namespace": "parallel-ns" }, "metricset": { "name": "state_job", @@ -3350,29 +3191,27 @@ "kubernetes": { "job": { "completions": { - "desired": 20 + "desired": 1 }, - "name": "sleep-5-parallel-cron-27075551", + "name": "sleep-30-fail-cron-27075624", "owner": { "is_controller": "true", "kind": "CronJob", - "name": "sleep-5-parallel-cron" + "name": "sleep-30-fail-cron" }, "parallelism": { - "desired": 5 + "desired": 1 }, "pods": { - "active": 2, + "active": 1, "failed": 0, - "succeeded": 18 + "succeeded": 0 }, "time": { - "created": "2021-06-24T11:11:00.000Z" + "created": "2021-06-24T12:24:00.000Z" } }, - "namespace": { - "name": "parallel-ns" - } + "namespace": "default" }, "metricset": { "name": "state_job", @@ -3392,29 +3231,27 @@ "kubernetes": { "job": { "completions": { - "desired": 20 + "desired": 1 }, - "name": "sleep-5-parallel-cron-27075614", + "name": "sleep-30-fail-cron-27075619", "owner": { "is_controller": "true", "kind": "CronJob", - "name": "sleep-5-parallel-cron" + "name": "sleep-30-fail-cron" }, "parallelism": { - "desired": 5 + "desired": 1 }, "pods": { - "active": 5, + "active": 1, "failed": 0, - "succeeded": 15 + "succeeded": 0 }, "time": { - "created": "2021-06-24T12:14:00.000Z" + "created": "2021-06-24T12:19:00.000Z" } }, - "namespace": { - "name": "parallel-ns" - } + "namespace": "default" }, "metricset": { "name": "state_job", @@ -3434,29 +3271,27 @@ "kubernetes": { "job": { "completions": { - "desired": 1 + "desired": 20 }, - "name": "sleep-30-fail-cron-27075607", + "name": "sleep-5-parallel-cron-27075601", "owner": { "is_controller": "true", "kind": "CronJob", - "name": "sleep-30-fail-cron" + "name": "sleep-5-parallel-cron" }, "parallelism": { - "desired": 1 + "desired": 5 }, "pods": { - "active": 1, + "active": 3, "failed": 0, - "succeeded": 0 + "succeeded": 17 }, "time": { - "created": "2021-06-24T12:07:00.000Z" + "created": "2021-06-24T12:01:00.000Z" } }, - "namespace": { - "name": "default" - } + "namespace": "parallel-ns" }, "metricset": { "name": "state_job", @@ -3478,7 +3313,7 @@ "completions": { "desired": 1 }, - "name": "sleep-30-fail-cron-27075588", + "name": "sleep-30-fail-cron-27075643", "owner": { "is_controller": "true", "kind": "CronJob", @@ -3493,12 +3328,10 @@ "succeeded": 0 }, "time": { - "created": "2021-06-24T11:48:00.000Z" + "created": "2021-06-24T12:43:00.000Z" } }, - "namespace": { - "name": "default" - } + "namespace": "default" }, "metricset": { "name": "state_job", @@ -3520,11 +3353,11 @@ "completions": { "desired": 1 }, - "name": "sleep-30-fail-cron-27075590", + "name": "sleep-30-ok-cron-27075635", "owner": { "is_controller": "true", "kind": "CronJob", - "name": "sleep-30-fail-cron" + "name": "sleep-30-ok-cron" }, "parallelism": { "desired": 1 @@ -3535,12 +3368,10 @@ "succeeded": 0 }, "time": { - "created": "2021-06-24T11:50:00.000Z" + "created": "2021-06-24T12:35:00.000Z" } }, - "namespace": { - "name": "default" - } + "namespace": "default" }, "metricset": { "name": "state_job", @@ -3562,7 +3393,7 @@ "completions": { "desired": 1 }, - "name": "sleep-30-ok-cron-27075612", + "name": "sleep-30-ok-cron-27075547", "owner": { "is_controller": "true", "kind": "CronJob", @@ -3577,12 +3408,10 @@ "succeeded": 0 }, "time": { - "created": "2021-06-24T12:12:00.000Z" + "created": "2021-06-24T11:07:00.000Z" } }, - "namespace": { - "name": "default" - } + "namespace": "default" }, "metricset": { "name": "state_job", @@ -3604,11 +3433,11 @@ "completions": { "desired": 1 }, - "name": "sleep-30-ok-cron-27075535", + "name": "sleep-30-fail-cron-27075588", "owner": { "is_controller": "true", "kind": "CronJob", - "name": "sleep-30-ok-cron" + "name": "sleep-30-fail-cron" }, "parallelism": { "desired": 1 @@ -3619,12 +3448,10 @@ "succeeded": 0 }, "time": { - "created": "2021-06-24T10:55:00.000Z" + "created": "2021-06-24T11:48:00.000Z" } }, - "namespace": { - "name": "default" - } + "namespace": "default" }, "metricset": { "name": "state_job", @@ -3646,7 +3473,7 @@ "completions": { "desired": 1 }, - "name": "sleep-30-ok-cron-27075637", + "name": "sleep-30-ok-cron-27075612", "owner": { "is_controller": "true", "kind": "CronJob", @@ -3661,12 +3488,10 @@ "succeeded": 0 }, "time": { - "created": "2021-06-24T12:37:00.000Z" + "created": "2021-06-24T12:12:00.000Z" } }, - "namespace": { - "name": "default" - } + "namespace": "default" }, "metricset": { "name": "state_job", @@ -3686,29 +3511,27 @@ "kubernetes": { "job": { "completions": { - "desired": 1 + "desired": 20 }, - "name": "sleep-30-fail-cron-27075620", + "name": "sleep-5-parallel-cron-27075646", "owner": { "is_controller": "true", "kind": "CronJob", - "name": "sleep-30-fail-cron" + "name": "sleep-5-parallel-cron" }, "parallelism": { - "desired": 1 + "desired": 5 }, "pods": { - "active": 1, + "active": 5, "failed": 0, "succeeded": 0 }, "time": { - "created": "2021-06-24T12:20:00.000Z" + "created": "2021-06-24T12:46:00.000Z" } }, - "namespace": { - "name": "default" - } + "namespace": "parallel-ns" }, "metricset": { "name": "state_job", @@ -3730,11 +3553,11 @@ "completions": { "desired": 1 }, - "name": "sleep-30-ok-cron-27075638", + "name": "sleep-30-fail-cron-27075604", "owner": { "is_controller": "true", "kind": "CronJob", - "name": "sleep-30-ok-cron" + "name": "sleep-30-fail-cron" }, "parallelism": { "desired": 1 @@ -3745,12 +3568,10 @@ "succeeded": 0 }, "time": { - "created": "2021-06-24T12:38:00.000Z" + "created": "2021-06-24T12:04:00.000Z" } }, - "namespace": { - "name": "default" - } + "namespace": "default" }, "metricset": { "name": "state_job", @@ -3772,7 +3593,7 @@ "completions": { "desired": 1 }, - "name": "sleep-30-fail-cron-27075592", + "name": "sleep-30-fail-cron-27075640", "owner": { "is_controller": "true", "kind": "CronJob", @@ -3787,12 +3608,10 @@ "succeeded": 0 }, "time": { - "created": "2021-06-24T11:52:00.000Z" + "created": "2021-06-24T12:40:00.000Z" } }, - "namespace": { - "name": "default" - } + "namespace": "default" }, "metricset": { "name": "state_job", @@ -3814,11 +3633,11 @@ "completions": { "desired": 1 }, - "name": "sleep-30-fail-cron-27075629", + "name": "sleep-30-ok-cron-27075631", "owner": { "is_controller": "true", "kind": "CronJob", - "name": "sleep-30-fail-cron" + "name": "sleep-30-ok-cron" }, "parallelism": { "desired": 1 @@ -3829,12 +3648,10 @@ "succeeded": 0 }, "time": { - "created": "2021-06-24T12:29:00.000Z" + "created": "2021-06-24T12:31:00.000Z" } }, - "namespace": { - "name": "default" - } + "namespace": "default" }, "metricset": { "name": "state_job", @@ -3856,7 +3673,7 @@ "completions": { "desired": 1 }, - "name": "sleep-30-fail-cron-27075554", + "name": "sleep-30-fail-cron-27075635", "owner": { "is_controller": "true", "kind": "CronJob", @@ -3871,12 +3688,10 @@ "succeeded": 0 }, "time": { - "created": "2021-06-24T11:14:00.000Z" + "created": "2021-06-24T12:35:00.000Z" } }, - "namespace": { - "name": "default" - } + "namespace": "default" }, "metricset": { "name": "state_job", @@ -3896,29 +3711,27 @@ "kubernetes": { "job": { "completions": { - "desired": 20 + "desired": 1 }, - "name": "sleep-5-parallel-cron-27075591", + "name": "sleep-30-ok-cron-27075634", "owner": { "is_controller": "true", "kind": "CronJob", - "name": "sleep-5-parallel-cron" + "name": "sleep-30-ok-cron" }, "parallelism": { - "desired": 5 + "desired": 1 }, "pods": { "active": 1, "failed": 0, - "succeeded": 19 + "succeeded": 0 }, "time": { - "created": "2021-06-24T11:51:00.000Z" + "created": "2021-06-24T12:34:00.000Z" } }, - "namespace": { - "name": "parallel-ns" - } + "namespace": "default" }, "metricset": { "name": "state_job", @@ -3938,32 +3751,27 @@ "kubernetes": { "job": { "completions": { - "desired": 1 + "desired": 20 }, - "name": "sleep-30-fail-cron-27075600", + "name": "sleep-5-parallel-cron-27075592", "owner": { "is_controller": "true", "kind": "CronJob", - "name": "sleep-30-fail-cron" + "name": "sleep-5-parallel-cron" }, "parallelism": { - "desired": 1 + "desired": 5 }, "pods": { - "active": 0, - "failed": 1, - "succeeded": 0 - }, - "status": { - "failed": "true" + "active": 1, + "failed": 0, + "succeeded": 19 }, "time": { - "created": "2021-06-24T12:00:00.000Z" + "created": "2021-06-24T11:52:00.000Z" } }, - "namespace": { - "name": "default" - } + "namespace": "parallel-ns" }, "metricset": { "name": "state_job", @@ -3983,29 +3791,27 @@ "kubernetes": { "job": { "completions": { - "desired": 20 + "desired": 1 }, - "name": "sleep-5-parallel-cron-27075618", + "name": "sleep-30-fail-cron-27075618", "owner": { "is_controller": "true", "kind": "CronJob", - "name": "sleep-5-parallel-cron" + "name": "sleep-30-fail-cron" }, "parallelism": { - "desired": 5 + "desired": 1 }, "pods": { - "active": 2, + "active": 1, "failed": 0, - "succeeded": 18 + "succeeded": 0 }, "time": { "created": "2021-06-24T12:18:00.000Z" } }, - "namespace": { - "name": "parallel-ns" - } + "namespace": "default" }, "metricset": { "name": "state_job", @@ -4027,7 +3833,7 @@ "completions": { "desired": 1 }, - "name": "sleep-30-fail-cron-27075645", + "name": "sleep-30-fail-cron-27075642", "owner": { "is_controller": "true", "kind": "CronJob", @@ -4042,12 +3848,10 @@ "succeeded": 0 }, "time": { - "created": "2021-06-24T12:45:00.000Z" + "created": "2021-06-24T12:42:00.000Z" } }, - "namespace": { - "name": "default" - } + "namespace": "default" }, "metricset": { "name": "state_job", @@ -4069,7 +3873,7 @@ "completions": { "desired": 20 }, - "name": "sleep-5-parallel-cron-27075636", + "name": "sleep-5-parallel-cron-27075535", "owner": { "is_controller": "true", "kind": "CronJob", @@ -4079,17 +3883,15 @@ "desired": 5 }, "pods": { - "active": 5, + "active": 1, "failed": 0, - "succeeded": 4 + "succeeded": 19 }, "time": { - "created": "2021-06-24T12:36:00.000Z" + "created": "2021-06-24T10:55:00.000Z" } }, - "namespace": { - "name": "parallel-ns" - } + "namespace": "parallel-ns" }, "metricset": { "name": "state_job", @@ -4111,7 +3913,7 @@ "completions": { "desired": 20 }, - "name": "sleep-5-parallel-cron-27075548", + "name": "sleep-5-parallel-cron-27075566", "owner": { "is_controller": "true", "kind": "CronJob", @@ -4126,12 +3928,10 @@ "succeeded": 19 }, "time": { - "created": "2021-06-24T11:08:00.000Z" + "created": "2021-06-24T11:26:00.000Z" } }, - "namespace": { - "name": "parallel-ns" - } + "namespace": "parallel-ns" }, "metricset": { "name": "state_job", @@ -4151,29 +3951,27 @@ "kubernetes": { "job": { "completions": { - "desired": 20 + "desired": 1 }, - "name": "sleep-5-parallel-cron-27075607", + "name": "sleep-30-fail-cron-27075634", "owner": { "is_controller": "true", "kind": "CronJob", - "name": "sleep-5-parallel-cron" + "name": "sleep-30-fail-cron" }, "parallelism": { - "desired": 5 + "desired": 1 }, "pods": { - "active": 3, + "active": 1, "failed": 0, - "succeeded": 17 + "succeeded": 0 }, "time": { - "created": "2021-06-24T12:07:00.000Z" + "created": "2021-06-24T12:34:00.000Z" } }, - "namespace": { - "name": "parallel-ns" - } + "namespace": "default" }, "metricset": { "name": "state_job", @@ -4195,7 +3993,7 @@ "completions": { "desired": 1 }, - "name": "sleep-30-fail-cron-27075606", + "name": "sleep-30-fail-cron-27075602", "owner": { "is_controller": "true", "kind": "CronJob", @@ -4210,12 +4008,10 @@ "succeeded": 0 }, "time": { - "created": "2021-06-24T12:06:00.000Z" + "created": "2021-06-24T12:02:00.000Z" } }, - "namespace": { - "name": "default" - } + "namespace": "default" }, "metricset": { "name": "state_job", @@ -4235,29 +4031,27 @@ "kubernetes": { "job": { "completions": { - "desired": 1 + "desired": 20 }, - "name": "sleep-30-fail-cron-27075536", + "name": "sleep-5-parallel-cron-27075640", "owner": { "is_controller": "true", "kind": "CronJob", - "name": "sleep-30-fail-cron" + "name": "sleep-5-parallel-cron" }, "parallelism": { - "desired": 1 + "desired": 5 }, "pods": { - "active": 1, + "active": 5, "failed": 0, - "succeeded": 0 + "succeeded": 1 }, "time": { - "created": "2021-06-24T10:56:00.000Z" + "created": "2021-06-24T12:40:00.000Z" } }, - "namespace": { - "name": "default" - } + "namespace": "parallel-ns" }, "metricset": { "name": "state_job", @@ -4277,29 +4071,31 @@ "kubernetes": { "job": { "completions": { - "desired": 1 + "desired": 20 }, - "name": "sleep-30-fail-cron-27075642", + "name": "sleep-5-parallel-cron-27075613", "owner": { "is_controller": "true", "kind": "CronJob", - "name": "sleep-30-fail-cron" + "name": "sleep-5-parallel-cron" }, "parallelism": { - "desired": 1 + "desired": 5 }, "pods": { - "active": 1, + "active": 0, "failed": 0, - "succeeded": 0 + "succeeded": 20 + }, + "status": { + "complete": "true" }, "time": { - "created": "2021-06-24T12:42:00.000Z" + "completed": "2021-06-24T12:28:39.000Z", + "created": "2021-06-24T12:13:00.000Z" } }, - "namespace": { - "name": "default" - } + "namespace": "parallel-ns" }, "metricset": { "name": "state_job", @@ -4321,7 +4117,7 @@ "completions": { "desired": 20 }, - "name": "sleep-5-parallel-cron-27075645", + "name": "sleep-5-parallel-cron-27075624", "owner": { "is_controller": "true", "kind": "CronJob", @@ -4333,15 +4129,13 @@ "pods": { "active": 5, "failed": 0, - "succeeded": 0 + "succeeded": 7 }, "time": { - "created": "2021-06-24T12:45:00.000Z" + "created": "2021-06-24T12:24:00.000Z" } }, - "namespace": { - "name": "parallel-ns" - } + "namespace": "parallel-ns" }, "metricset": { "name": "state_job", @@ -4361,29 +4155,27 @@ "kubernetes": { "job": { "completions": { - "desired": 20 + "desired": 1 }, - "name": "sleep-5-parallel-cron-27075637", + "name": "sleep-30-fail-cron-27075637", "owner": { "is_controller": "true", "kind": "CronJob", - "name": "sleep-5-parallel-cron" + "name": "sleep-30-fail-cron" }, "parallelism": { - "desired": 5 + "desired": 1 }, "pods": { - "active": 5, + "active": 1, "failed": 0, - "succeeded": 2 + "succeeded": 0 }, "time": { "created": "2021-06-24T12:37:00.000Z" } }, - "namespace": { - "name": "parallel-ns" - } + "namespace": "default" }, "metricset": { "name": "state_job", @@ -4405,7 +4197,7 @@ "completions": { "desired": 1 }, - "name": "sleep-30-fail-cron-27075646", + "name": "sleep-30-fail-cron-27075606", "owner": { "is_controller": "true", "kind": "CronJob", @@ -4420,12 +4212,10 @@ "succeeded": 0 }, "time": { - "created": "2021-06-24T12:46:00.000Z" + "created": "2021-06-24T12:06:00.000Z" } }, - "namespace": { - "name": "default" - } + "namespace": "default" }, "metricset": { "name": "state_job", @@ -4445,29 +4235,27 @@ "kubernetes": { "job": { "completions": { - "desired": 20 + "desired": 1 }, - "name": "sleep-5-parallel-cron-27075594", + "name": "sleep-30-ok-cron-27075632", "owner": { "is_controller": "true", "kind": "CronJob", - "name": "sleep-5-parallel-cron" + "name": "sleep-30-ok-cron" }, "parallelism": { - "desired": 5 + "desired": 1 }, "pods": { - "active": 5, + "active": 1, "failed": 0, - "succeeded": 9 + "succeeded": 0 }, "time": { - "created": "2021-06-24T11:54:00.000Z" + "created": "2021-06-24T12:32:00.000Z" } }, - "namespace": { - "name": "parallel-ns" - } + "namespace": "default" }, "metricset": { "name": "state_job", @@ -4487,29 +4275,27 @@ "kubernetes": { "job": { "completions": { - "desired": 20 + "desired": 1 }, - "name": "sleep-5-parallel-cron-27075631", + "name": "sleep-30-fail-cron-27075627", "owner": { "is_controller": "true", "kind": "CronJob", - "name": "sleep-5-parallel-cron" + "name": "sleep-30-fail-cron" }, "parallelism": { - "desired": 5 + "desired": 1 }, "pods": { - "active": 5, + "active": 1, "failed": 0, - "succeeded": 3 + "succeeded": 0 }, "time": { - "created": "2021-06-24T12:31:00.000Z" + "created": "2021-06-24T12:27:00.000Z" } }, - "namespace": { - "name": "parallel-ns" - } + "namespace": "default" }, "metricset": { "name": "state_job", @@ -4531,7 +4317,7 @@ "completions": { "desired": 20 }, - "name": "sleep-5-parallel-cron-27075572", + "name": "sleep-5-parallel-cron-27075571", "owner": { "is_controller": "true", "kind": "CronJob", @@ -4546,12 +4332,10 @@ "succeeded": 18 }, "time": { - "created": "2021-06-24T11:32:00.000Z" + "created": "2021-06-24T11:31:00.000Z" } }, - "namespace": { - "name": "parallel-ns" - } + "namespace": "parallel-ns" }, "metricset": { "name": "state_job", @@ -4571,29 +4355,27 @@ "kubernetes": { "job": { "completions": { - "desired": 1 + "desired": 20 }, - "name": "sleep-30-fail-cron-27075610", + "name": "sleep-5-parallel-cron-27075564", "owner": { "is_controller": "true", "kind": "CronJob", - "name": "sleep-30-fail-cron" + "name": "sleep-5-parallel-cron" }, "parallelism": { - "desired": 1 + "desired": 5 }, "pods": { - "active": 1, + "active": 2, "failed": 0, - "succeeded": 0 + "succeeded": 18 }, "time": { - "created": "2021-06-24T12:10:00.000Z" + "created": "2021-06-24T11:24:00.000Z" } }, - "namespace": { - "name": "default" - } + "namespace": "parallel-ns" }, "metricset": { "name": "state_job", @@ -4613,29 +4395,27 @@ "kubernetes": { "job": { "completions": { - "desired": 20 + "desired": 1 }, - "name": "sleep-5-parallel-cron-27075566", + "name": "sleep-30-fail-cron-27075622", "owner": { "is_controller": "true", "kind": "CronJob", - "name": "sleep-5-parallel-cron" + "name": "sleep-30-fail-cron" }, "parallelism": { - "desired": 5 + "desired": 1 }, "pods": { "active": 1, "failed": 0, - "succeeded": 19 + "succeeded": 0 }, "time": { - "created": "2021-06-24T11:26:00.000Z" + "created": "2021-06-24T12:22:00.000Z" } }, - "namespace": { - "name": "parallel-ns" - } + "namespace": "default" }, "metricset": { "name": "state_job", @@ -4655,29 +4435,27 @@ "kubernetes": { "job": { "completions": { - "desired": 20 + "desired": 1 }, - "name": "sleep-5-parallel-cron-27075623", + "name": "sleep-30-ok-cron-27075536", "owner": { "is_controller": "true", "kind": "CronJob", - "name": "sleep-5-parallel-cron" + "name": "sleep-30-ok-cron" }, "parallelism": { - "desired": 5 + "desired": 1 }, "pods": { "active": 1, "failed": 0, - "succeeded": 19 + "succeeded": 0 }, "time": { - "created": "2021-06-24T12:23:00.000Z" + "created": "2021-06-24T10:56:00.000Z" } }, - "namespace": { - "name": "parallel-ns" - } + "namespace": "default" }, "metricset": { "name": "state_job", @@ -4697,29 +4475,27 @@ "kubernetes": { "job": { "completions": { - "desired": 1 + "desired": 20 }, - "name": "sleep-30-fail-cron-27075608", + "name": "sleep-5-parallel-cron-27075612", "owner": { "is_controller": "true", "kind": "CronJob", - "name": "sleep-30-fail-cron" + "name": "sleep-5-parallel-cron" }, "parallelism": { - "desired": 1 + "desired": 5 }, "pods": { - "active": 1, + "active": 5, "failed": 0, - "succeeded": 0 + "succeeded": 1 }, "time": { - "created": "2021-06-24T12:08:00.000Z" + "created": "2021-06-24T12:12:00.000Z" } }, - "namespace": { - "name": "default" - } + "namespace": "parallel-ns" }, "metricset": { "name": "state_job", @@ -4741,7 +4517,7 @@ "completions": { "desired": 20 }, - "name": "sleep-5-parallel-cron-27075625", + "name": "sleep-5-parallel-cron-27075619", "owner": { "is_controller": "true", "kind": "CronJob", @@ -4751,17 +4527,15 @@ "desired": 5 }, "pods": { - "active": 5, + "active": 4, "failed": 0, - "succeeded": 11 + "succeeded": 16 }, "time": { - "created": "2021-06-24T12:25:00.000Z" + "created": "2021-06-24T12:19:00.000Z" } }, - "namespace": { - "name": "parallel-ns" - } + "namespace": "parallel-ns" }, "metricset": { "name": "state_job", @@ -4781,29 +4555,27 @@ "kubernetes": { "job": { "completions": { - "desired": 1 + "desired": 20 }, - "name": "sleep-30-ok-cron-27075645", + "name": "sleep-5-parallel-cron-27075638", "owner": { "is_controller": "true", "kind": "CronJob", - "name": "sleep-30-ok-cron" + "name": "sleep-5-parallel-cron" }, "parallelism": { - "desired": 1 + "desired": 5 }, "pods": { - "active": 1, + "active": 5, "failed": 0, "succeeded": 0 }, "time": { - "created": "2021-06-24T12:45:00.000Z" + "created": "2021-06-24T12:38:00.000Z" } }, - "namespace": { - "name": "default" - } + "namespace": "parallel-ns" }, "metricset": { "name": "state_job", @@ -4825,11 +4597,11 @@ "completions": { "desired": 1 }, - "name": "sleep-30-fail-cron-27075602", + "name": "sleep-30-ok-cron-27075590", "owner": { "is_controller": "true", "kind": "CronJob", - "name": "sleep-30-fail-cron" + "name": "sleep-30-ok-cron" }, "parallelism": { "desired": 1 @@ -4840,12 +4612,10 @@ "succeeded": 0 }, "time": { - "created": "2021-06-24T12:02:00.000Z" + "created": "2021-06-24T11:50:00.000Z" } }, - "namespace": { - "name": "default" - } + "namespace": "default" }, "metricset": { "name": "state_job", @@ -4867,11 +4637,11 @@ "completions": { "desired": 1 }, - "name": "sleep-30-fail-cron-27075593", + "name": "sleep-30-ok-cron-27075626", "owner": { "is_controller": "true", "kind": "CronJob", - "name": "sleep-30-fail-cron" + "name": "sleep-30-ok-cron" }, "parallelism": { "desired": 1 @@ -4882,12 +4652,10 @@ "succeeded": 0 }, "time": { - "created": "2021-06-24T11:53:00.000Z" + "created": "2021-06-24T12:26:00.000Z" } }, - "namespace": { - "name": "default" - } + "namespace": "default" }, "metricset": { "name": "state_job", @@ -4907,29 +4675,27 @@ "kubernetes": { "job": { "completions": { - "desired": 1 + "desired": 20 }, - "name": "sleep-30-fail-cron-27075586", + "name": "sleep-5-parallel-cron-27075625", "owner": { "is_controller": "true", "kind": "CronJob", - "name": "sleep-30-fail-cron" + "name": "sleep-5-parallel-cron" }, "parallelism": { - "desired": 1 + "desired": 5 }, "pods": { - "active": 1, + "active": 5, "failed": 0, - "succeeded": 0 + "succeeded": 11 }, "time": { - "created": "2021-06-24T11:46:00.000Z" + "created": "2021-06-24T12:25:00.000Z" } }, - "namespace": { - "name": "default" - } + "namespace": "parallel-ns" }, "metricset": { "name": "state_job", @@ -4951,7 +4717,7 @@ "completions": { "desired": 20 }, - "name": "sleep-5-parallel-cron-27075616", + "name": "sleep-5-parallel-cron-27075603", "owner": { "is_controller": "true", "kind": "CronJob", @@ -4966,12 +4732,10 @@ "succeeded": 19 }, "time": { - "created": "2021-06-24T12:16:00.000Z" + "created": "2021-06-24T12:03:00.000Z" } }, - "namespace": { - "name": "parallel-ns" - } + "namespace": "parallel-ns" }, "metricset": { "name": "state_job", @@ -4993,11 +4757,11 @@ "completions": { "desired": 1 }, - "name": "sleep-30-fail-cron-27075613", + "name": "sleep-30-ok-cron-27075643", "owner": { "is_controller": "true", "kind": "CronJob", - "name": "sleep-30-fail-cron" + "name": "sleep-30-ok-cron" }, "parallelism": { "desired": 1 @@ -5008,12 +4772,10 @@ "succeeded": 0 }, "time": { - "created": "2021-06-24T12:13:00.000Z" + "created": "2021-06-24T12:43:00.000Z" } }, - "namespace": { - "name": "default" - } + "namespace": "default" }, "metricset": { "name": "state_job", @@ -5033,29 +4795,27 @@ "kubernetes": { "job": { "completions": { - "desired": 1 + "desired": 20 }, - "name": "sleep-30-fail-cron-27075594", + "name": "sleep-5-parallel-cron-27075548", "owner": { "is_controller": "true", "kind": "CronJob", - "name": "sleep-30-fail-cron" + "name": "sleep-5-parallel-cron" }, "parallelism": { - "desired": 1 + "desired": 5 }, "pods": { "active": 1, "failed": 0, - "succeeded": 0 + "succeeded": 19 }, "time": { - "created": "2021-06-24T11:54:00.000Z" + "created": "2021-06-24T11:08:00.000Z" } }, - "namespace": { - "name": "default" - } + "namespace": "parallel-ns" }, "metricset": { "name": "state_job", @@ -5075,29 +4835,27 @@ "kubernetes": { "job": { "completions": { - "desired": 1 + "desired": 20 }, - "name": "sleep-30-fail-cron-27075584", + "name": "sleep-5-parallel-cron-27075632", "owner": { "is_controller": "true", "kind": "CronJob", - "name": "sleep-30-fail-cron" + "name": "sleep-5-parallel-cron" }, "parallelism": { - "desired": 1 + "desired": 5 }, "pods": { - "active": 1, + "active": 5, "failed": 0, - "succeeded": 0 + "succeeded": 1 }, "time": { - "created": "2021-06-24T11:44:00.000Z" + "created": "2021-06-24T12:32:00.000Z" } }, - "namespace": { - "name": "default" - } + "namespace": "parallel-ns" }, "metricset": { "name": "state_job", @@ -5119,7 +4877,7 @@ "completions": { "desired": 20 }, - "name": "sleep-5-parallel-cron-27075627", + "name": "sleep-5-parallel-cron-27075637", "owner": { "is_controller": "true", "kind": "CronJob", @@ -5131,15 +4889,13 @@ "pods": { "active": 5, "failed": 0, - "succeeded": 15 + "succeeded": 2 }, "time": { - "created": "2021-06-24T12:27:00.000Z" + "created": "2021-06-24T12:37:00.000Z" } }, - "namespace": { - "name": "parallel-ns" - } + "namespace": "parallel-ns" }, "metricset": { "name": "state_job", @@ -5161,7 +4917,7 @@ "completions": { "desired": 1 }, - "name": "sleep-30-ok-cron-27075626", + "name": "sleep-30-ok-cron-27075628", "owner": { "is_controller": "true", "kind": "CronJob", @@ -5176,12 +4932,10 @@ "succeeded": 0 }, "time": { - "created": "2021-06-24T12:26:00.000Z" + "created": "2021-06-24T12:28:00.000Z" } }, - "namespace": { - "name": "default" - } + "namespace": "default" }, "metricset": { "name": "state_job", @@ -5203,11 +4957,11 @@ "completions": { "desired": 1 }, - "name": "sleep-30-ok-cron-27075632", + "name": "sleep-30-fail-cron-27075620", "owner": { "is_controller": "true", "kind": "CronJob", - "name": "sleep-30-ok-cron" + "name": "sleep-30-fail-cron" }, "parallelism": { "desired": 1 @@ -5218,12 +4972,10 @@ "succeeded": 0 }, "time": { - "created": "2021-06-24T12:32:00.000Z" + "created": "2021-06-24T12:20:00.000Z" } }, - "namespace": { - "name": "default" - } + "namespace": "default" }, "metricset": { "name": "state_job", @@ -5243,29 +4995,27 @@ "kubernetes": { "job": { "completions": { - "desired": 20 + "desired": 1 }, - "name": "sleep-5-parallel-cron-27075589", + "name": "sleep-30-fail-cron-27075633", "owner": { "is_controller": "true", "kind": "CronJob", - "name": "sleep-5-parallel-cron" + "name": "sleep-30-fail-cron" }, "parallelism": { - "desired": 5 + "desired": 1 }, "pods": { "active": 1, "failed": 0, - "succeeded": 19 + "succeeded": 0 }, "time": { - "created": "2021-06-24T11:49:00.000Z" + "created": "2021-06-24T12:33:00.000Z" } }, - "namespace": { - "name": "parallel-ns" - } + "namespace": "default" }, "metricset": { "name": "state_job", @@ -5287,11 +5037,11 @@ "completions": { "desired": 1 }, - "name": "sleep-30-fail-cron-27075611", + "name": "sleep-30-ok-cron-27075640", "owner": { "is_controller": "true", "kind": "CronJob", - "name": "sleep-30-fail-cron" + "name": "sleep-30-ok-cron" }, "parallelism": { "desired": 1 @@ -5302,12 +5052,10 @@ "succeeded": 0 }, "time": { - "created": "2021-06-24T12:11:00.000Z" + "created": "2021-06-24T12:40:00.000Z" } }, - "namespace": { - "name": "default" - } + "namespace": "default" }, "metricset": { "name": "state_job", @@ -5329,7 +5077,7 @@ "completions": { "desired": 20 }, - "name": "sleep-5-parallel-cron-27075608", + "name": "sleep-5-parallel-cron-27075593", "owner": { "is_controller": "true", "kind": "CronJob", @@ -5344,12 +5092,10 @@ "succeeded": 19 }, "time": { - "created": "2021-06-24T12:08:00.000Z" + "created": "2021-06-24T11:53:00.000Z" } }, - "namespace": { - "name": "parallel-ns" - } + "namespace": "parallel-ns" }, "metricset": { "name": "state_job", @@ -5371,7 +5117,7 @@ "completions": { "desired": 20 }, - "name": "sleep-5-parallel-cron-27075640", + "name": "sleep-5-parallel-cron-27075635", "owner": { "is_controller": "true", "kind": "CronJob", @@ -5383,15 +5129,13 @@ "pods": { "active": 5, "failed": 0, - "succeeded": 1 + "succeeded": 0 }, "time": { - "created": "2021-06-24T12:40:00.000Z" + "created": "2021-06-24T12:35:00.000Z" } }, - "namespace": { - "name": "parallel-ns" - } + "namespace": "parallel-ns" }, "metricset": { "name": "state_job", @@ -5411,29 +5155,27 @@ "kubernetes": { "job": { "completions": { - "desired": 20 + "desired": 1 }, - "name": "sleep-5-parallel-cron-27075624", + "name": "sleep-30-fail-cron-27075554", "owner": { "is_controller": "true", "kind": "CronJob", - "name": "sleep-5-parallel-cron" + "name": "sleep-30-fail-cron" }, "parallelism": { - "desired": 5 + "desired": 1 }, "pods": { - "active": 5, + "active": 1, "failed": 0, - "succeeded": 7 + "succeeded": 0 }, "time": { - "created": "2021-06-24T12:24:00.000Z" + "created": "2021-06-24T11:14:00.000Z" } }, - "namespace": { - "name": "parallel-ns" - } + "namespace": "default" }, "metricset": { "name": "state_job", @@ -5455,11 +5197,11 @@ "completions": { "desired": 1 }, - "name": "sleep-30-ok-cron-27075623", + "name": "sleep-30-fail-cron-27075609", "owner": { "is_controller": "true", "kind": "CronJob", - "name": "sleep-30-ok-cron" + "name": "sleep-30-fail-cron" }, "parallelism": { "desired": 1 @@ -5470,12 +5212,10 @@ "succeeded": 0 }, "time": { - "created": "2021-06-24T12:23:00.000Z" + "created": "2021-06-24T12:09:00.000Z" } }, - "namespace": { - "name": "default" - } + "namespace": "default" }, "metricset": { "name": "state_job", @@ -5497,11 +5237,11 @@ "completions": { "desired": 1 }, - "name": "sleep-30-fail-cron-27075535", + "name": "sleep-30-ok-cron-27075633", "owner": { "is_controller": "true", "kind": "CronJob", - "name": "sleep-30-fail-cron" + "name": "sleep-30-ok-cron" }, "parallelism": { "desired": 1 @@ -5512,12 +5252,10 @@ "succeeded": 0 }, "time": { - "created": "2021-06-24T10:55:00.000Z" + "created": "2021-06-24T12:33:00.000Z" } }, - "namespace": { - "name": "default" - } + "namespace": "default" }, "metricset": { "name": "state_job", @@ -5539,7 +5277,7 @@ "completions": { "desired": 20 }, - "name": "sleep-5-parallel-cron-27075593", + "name": "sleep-5-parallel-cron-27075557", "owner": { "is_controller": "true", "kind": "CronJob", @@ -5554,12 +5292,10 @@ "succeeded": 19 }, "time": { - "created": "2021-06-24T11:53:00.000Z" + "created": "2021-06-24T11:17:00.000Z" } }, - "namespace": { - "name": "parallel-ns" - } + "namespace": "parallel-ns" }, "metricset": { "name": "state_job", @@ -5581,7 +5317,7 @@ "completions": { "desired": 1 }, - "name": "sleep-30-fail-cron-27075616", + "name": "sleep-30-fail-cron-27075608", "owner": { "is_controller": "true", "kind": "CronJob", @@ -5596,12 +5332,10 @@ "succeeded": 0 }, "time": { - "created": "2021-06-24T12:16:00.000Z" + "created": "2021-06-24T12:08:00.000Z" } }, - "namespace": { - "name": "default" - } + "namespace": "default" }, "metricset": { "name": "state_job", @@ -5621,29 +5355,27 @@ "kubernetes": { "job": { "completions": { - "desired": 20 + "desired": 1 }, - "name": "sleep-5-parallel-cron-27075557", + "name": "sleep-30-ok-cron-27075636", "owner": { "is_controller": "true", "kind": "CronJob", - "name": "sleep-5-parallel-cron" + "name": "sleep-30-ok-cron" }, "parallelism": { - "desired": 5 + "desired": 1 }, "pods": { "active": 1, "failed": 0, - "succeeded": 19 + "succeeded": 0 }, "time": { - "created": "2021-06-24T11:17:00.000Z" + "created": "2021-06-24T12:36:00.000Z" } }, - "namespace": { - "name": "parallel-ns" - } + "namespace": "default" }, "metricset": { "name": "state_job", @@ -5663,29 +5395,27 @@ "kubernetes": { "job": { "completions": { - "desired": 20 + "desired": 1 }, - "name": "sleep-5-parallel-cron-27075571", + "name": "sleep-30-ok-cron-27075610", "owner": { "is_controller": "true", "kind": "CronJob", - "name": "sleep-5-parallel-cron" + "name": "sleep-30-ok-cron" }, "parallelism": { - "desired": 5 + "desired": 1 }, "pods": { - "active": 2, + "active": 1, "failed": 0, - "succeeded": 18 + "succeeded": 0 }, "time": { - "created": "2021-06-24T11:31:00.000Z" + "created": "2021-06-24T12:10:00.000Z" } }, - "namespace": { - "name": "parallel-ns" - } + "namespace": "default" }, "metricset": { "name": "state_job", @@ -5707,7 +5437,7 @@ "completions": { "desired": 1 }, - "name": "sleep-30-fail-cron-27075631", + "name": "sleep-30-fail-cron-27075632", "owner": { "is_controller": "true", "kind": "CronJob", @@ -5722,12 +5452,10 @@ "succeeded": 0 }, "time": { - "created": "2021-06-24T12:31:00.000Z" + "created": "2021-06-24T12:32:00.000Z" } }, - "namespace": { - "name": "default" - } + "namespace": "default" }, "metricset": { "name": "state_job", @@ -5747,29 +5475,27 @@ "kubernetes": { "job": { "completions": { - "desired": 1 + "desired": 20 }, - "name": "sleep-30-fail-cron-27075635", + "name": "sleep-5-parallel-cron-27075594", "owner": { "is_controller": "true", "kind": "CronJob", - "name": "sleep-30-fail-cron" + "name": "sleep-5-parallel-cron" }, "parallelism": { - "desired": 1 + "desired": 5 }, "pods": { - "active": 1, + "active": 5, "failed": 0, - "succeeded": 0 + "succeeded": 9 }, "time": { - "created": "2021-06-24T12:35:00.000Z" + "created": "2021-06-24T11:54:00.000Z" } }, - "namespace": { - "name": "default" - } + "namespace": "parallel-ns" }, "metricset": { "name": "state_job", @@ -5789,29 +5515,27 @@ "kubernetes": { "job": { "completions": { - "desired": 1 + "desired": 20 }, - "name": "sleep-30-fail-cron-27075601", + "name": "sleep-5-parallel-cron-27075584", "owner": { "is_controller": "true", "kind": "CronJob", - "name": "sleep-30-fail-cron" + "name": "sleep-5-parallel-cron" }, "parallelism": { - "desired": 1 + "desired": 5 }, "pods": { - "active": 1, + "active": 2, "failed": 0, - "succeeded": 0 + "succeeded": 18 }, "time": { - "created": "2021-06-24T12:01:00.000Z" + "created": "2021-06-24T11:44:00.000Z" } }, - "namespace": { - "name": "default" - } + "namespace": "parallel-ns" }, "metricset": { "name": "state_job", @@ -5831,29 +5555,27 @@ "kubernetes": { "job": { "completions": { - "desired": 1 + "desired": 20 }, - "name": "sleep-30-fail-cron-27075627", + "name": "sleep-5-parallel-cron-27075614", "owner": { "is_controller": "true", "kind": "CronJob", - "name": "sleep-30-fail-cron" + "name": "sleep-5-parallel-cron" }, "parallelism": { - "desired": 1 + "desired": 5 }, "pods": { - "active": 1, + "active": 5, "failed": 0, - "succeeded": 0 + "succeeded": 15 }, "time": { - "created": "2021-06-24T12:27:00.000Z" + "created": "2021-06-24T12:14:00.000Z" } }, - "namespace": { - "name": "default" - } + "namespace": "parallel-ns" }, "metricset": { "name": "state_job", @@ -5873,29 +5595,27 @@ "kubernetes": { "job": { "completions": { - "desired": 20 + "desired": 1 }, - "name": "sleep-5-parallel-cron-27075617", + "name": "sleep-30-fail-cron-27075638", "owner": { "is_controller": "true", "kind": "CronJob", - "name": "sleep-5-parallel-cron" + "name": "sleep-30-fail-cron" }, "parallelism": { - "desired": 5 + "desired": 1 }, "pods": { - "active": 5, + "active": 1, "failed": 0, "succeeded": 0 }, "time": { - "created": "2021-06-24T12:17:00.000Z" + "created": "2021-06-24T12:38:00.000Z" } }, - "namespace": { - "name": "parallel-ns" - } + "namespace": "default" }, "metricset": { "name": "state_job", @@ -5915,29 +5635,27 @@ "kubernetes": { "job": { "completions": { - "desired": 20 + "desired": 1 }, - "name": "sleep-5-parallel-cron-27075599", + "name": "sleep-30-fail-cron-27075576", "owner": { "is_controller": "true", "kind": "CronJob", - "name": "sleep-5-parallel-cron" + "name": "sleep-30-fail-cron" }, "parallelism": { - "desired": 5 + "desired": 1 }, "pods": { - "active": 5, + "active": 1, "failed": 0, - "succeeded": 2 + "succeeded": 0 }, "time": { - "created": "2021-06-24T11:59:00.000Z" + "created": "2021-06-24T11:36:00.000Z" } }, - "namespace": { - "name": "parallel-ns" - } + "namespace": "default" }, "metricset": { "name": "state_job", @@ -5959,7 +5677,7 @@ "completions": { "desired": 1 }, - "name": "sleep-30-fail-cron-27075624", + "name": "sleep-30-fail-cron-27075626", "owner": { "is_controller": "true", "kind": "CronJob", @@ -5974,12 +5692,10 @@ "succeeded": 0 }, "time": { - "created": "2021-06-24T12:24:00.000Z" + "created": "2021-06-24T12:26:00.000Z" } }, - "namespace": { - "name": "default" - } + "namespace": "default" }, "metricset": { "name": "state_job", @@ -6001,11 +5717,11 @@ "completions": { "desired": 1 }, - "name": "sleep-30-ok-cron-27075635", + "name": "sleep-30-fail-cron-27075563", "owner": { "is_controller": "true", "kind": "CronJob", - "name": "sleep-30-ok-cron" + "name": "sleep-30-fail-cron" }, "parallelism": { "desired": 1 @@ -6016,12 +5732,10 @@ "succeeded": 0 }, "time": { - "created": "2021-06-24T12:35:00.000Z" + "created": "2021-06-24T11:23:00.000Z" } }, - "namespace": { - "name": "default" - } + "namespace": "default" }, "metricset": { "name": "state_job", @@ -6043,11 +5757,11 @@ "completions": { "desired": 1 }, - "name": "sleep-30-ok-cron-27075601", + "name": "sleep-30-fail-cron-27075646", "owner": { "is_controller": "true", "kind": "CronJob", - "name": "sleep-30-ok-cron" + "name": "sleep-30-fail-cron" }, "parallelism": { "desired": 1 @@ -6058,12 +5772,10 @@ "succeeded": 0 }, "time": { - "created": "2021-06-24T12:01:00.000Z" + "created": "2021-06-24T12:46:00.000Z" } }, - "namespace": { - "name": "default" - } + "namespace": "default" }, "metricset": { "name": "state_job", @@ -6085,7 +5797,7 @@ "completions": { "desired": 20 }, - "name": "sleep-5-parallel-cron-27075629", + "name": "sleep-5-parallel-cron-27075532", "owner": { "is_controller": "true", "kind": "CronJob", @@ -6095,17 +5807,15 @@ "desired": 5 }, "pods": { - "active": 5, + "active": 2, "failed": 0, - "succeeded": 6 + "succeeded": 18 }, "time": { - "created": "2021-06-24T12:29:00.000Z" + "created": "2021-06-24T10:52:00.000Z" } }, - "namespace": { - "name": "parallel-ns" - } + "namespace": "parallel-ns" }, "metricset": { "name": "state_job", @@ -6125,29 +5835,27 @@ "kubernetes": { "job": { "completions": { - "desired": 20 + "desired": 1 }, - "name": "sleep-5-parallel-cron-27075563", + "name": "sleep-30-fail-cron-27075613", "owner": { "is_controller": "true", "kind": "CronJob", - "name": "sleep-5-parallel-cron" + "name": "sleep-30-fail-cron" }, "parallelism": { - "desired": 5 + "desired": 1 }, "pods": { - "active": 2, + "active": 1, "failed": 0, - "succeeded": 18 + "succeeded": 0 }, "time": { - "created": "2021-06-24T11:23:00.000Z" + "created": "2021-06-24T12:13:00.000Z" } }, - "namespace": { - "name": "parallel-ns" - } + "namespace": "default" }, "metricset": { "name": "state_job", @@ -6167,29 +5875,27 @@ "kubernetes": { "job": { "completions": { - "desired": 1 + "desired": 20 }, - "name": "sleep-30-fail-cron-27075626", + "name": "sleep-5-parallel-cron-27075599", "owner": { "is_controller": "true", "kind": "CronJob", - "name": "sleep-30-fail-cron" + "name": "sleep-5-parallel-cron" }, "parallelism": { - "desired": 1 + "desired": 5 }, "pods": { - "active": 1, + "active": 5, "failed": 0, - "succeeded": 0 + "succeeded": 2 }, "time": { - "created": "2021-06-24T12:26:00.000Z" + "created": "2021-06-24T11:59:00.000Z" } }, - "namespace": { - "name": "default" - } + "namespace": "parallel-ns" }, "metricset": { "name": "state_job", @@ -6209,29 +5915,27 @@ "kubernetes": { "job": { "completions": { - "desired": 1 + "desired": 20 }, - "name": "sleep-30-ok-cron-27075644", + "name": "sleep-5-parallel-cron-27075589", "owner": { "is_controller": "true", "kind": "CronJob", - "name": "sleep-30-ok-cron" + "name": "sleep-5-parallel-cron" }, "parallelism": { - "desired": 1 + "desired": 5 }, "pods": { "active": 1, "failed": 0, - "succeeded": 0 + "succeeded": 19 }, "time": { - "created": "2021-06-24T12:44:00.000Z" + "created": "2021-06-24T11:49:00.000Z" } }, - "namespace": { - "name": "default" - } + "namespace": "parallel-ns" }, "metricset": { "name": "state_job", @@ -6251,29 +5955,27 @@ "kubernetes": { "job": { "completions": { - "desired": 20 + "desired": 1 }, - "name": "sleep-5-parallel-cron-27075590", + "name": "sleep-30-ok-cron-27075644", "owner": { "is_controller": "true", "kind": "CronJob", - "name": "sleep-5-parallel-cron" + "name": "sleep-30-ok-cron" }, "parallelism": { - "desired": 5 + "desired": 1 }, "pods": { "active": 1, "failed": 0, - "succeeded": 19 + "succeeded": 0 }, "time": { - "created": "2021-06-24T11:50:00.000Z" + "created": "2021-06-24T12:44:00.000Z" } }, - "namespace": { - "name": "parallel-ns" - } + "namespace": "default" }, "metricset": { "name": "state_job", @@ -6295,11 +5997,11 @@ "completions": { "desired": 1 }, - "name": "sleep-30-fail-cron-27075621", + "name": "sleep-30-ok-cron-27075594", "owner": { "is_controller": "true", "kind": "CronJob", - "name": "sleep-30-fail-cron" + "name": "sleep-30-ok-cron" }, "parallelism": { "desired": 1 @@ -6310,12 +6012,10 @@ "succeeded": 0 }, "time": { - "created": "2021-06-24T12:21:00.000Z" + "created": "2021-06-24T11:54:00.000Z" } }, - "namespace": { - "name": "default" - } + "namespace": "default" }, "metricset": { "name": "state_job", @@ -6335,29 +6035,27 @@ "kubernetes": { "job": { "completions": { - "desired": 20 + "desired": 1 }, - "name": "sleep-5-parallel-cron-27075619", + "name": "sleep-30-fail-cron-27075629", "owner": { "is_controller": "true", "kind": "CronJob", - "name": "sleep-5-parallel-cron" + "name": "sleep-30-fail-cron" }, "parallelism": { - "desired": 5 + "desired": 1 }, "pods": { - "active": 4, + "active": 1, "failed": 0, - "succeeded": 16 + "succeeded": 0 }, "time": { - "created": "2021-06-24T12:19:00.000Z" + "created": "2021-06-24T12:29:00.000Z" } }, - "namespace": { - "name": "parallel-ns" - } + "namespace": "default" }, "metricset": { "name": "state_job", @@ -6377,29 +6075,27 @@ "kubernetes": { "job": { "completions": { - "desired": 1 + "desired": 20 }, - "name": "sleep-30-fail-cron-27075617", + "name": "sleep-5-parallel-cron-27075642", "owner": { "is_controller": "true", "kind": "CronJob", - "name": "sleep-30-fail-cron" + "name": "sleep-5-parallel-cron" }, "parallelism": { - "desired": 1 + "desired": 5 }, "pods": { - "active": 1, + "active": 5, "failed": 0, "succeeded": 0 }, "time": { - "created": "2021-06-24T12:17:00.000Z" + "created": "2021-06-24T12:42:00.000Z" } }, - "namespace": { - "name": "default" - } + "namespace": "parallel-ns" }, "metricset": { "name": "state_job", @@ -6421,7 +6117,7 @@ "completions": { "desired": 1 }, - "name": "sleep-30-fail-cron-27075639", + "name": "sleep-30-fail-cron-27075603", "owner": { "is_controller": "true", "kind": "CronJob", @@ -6436,12 +6132,10 @@ "succeeded": 0 }, "time": { - "created": "2021-06-24T12:39:00.000Z" + "created": "2021-06-24T12:03:00.000Z" } }, - "namespace": { - "name": "default" - } + "namespace": "default" }, "metricset": { "name": "state_job", @@ -6463,7 +6157,7 @@ "completions": { "desired": 1 }, - "name": "sleep-30-fail-cron-27075637", + "name": "sleep-30-fail-cron-27075623", "owner": { "is_controller": "true", "kind": "CronJob", @@ -6478,12 +6172,10 @@ "succeeded": 0 }, "time": { - "created": "2021-06-24T12:37:00.000Z" + "created": "2021-06-24T12:23:00.000Z" } }, - "namespace": { - "name": "default" - } + "namespace": "default" }, "metricset": { "name": "state_job", @@ -6505,7 +6197,7 @@ "completions": { "desired": 1 }, - "name": "sleep-30-fail-cron-27075623", + "name": "sleep-30-fail-cron-27075586", "owner": { "is_controller": "true", "kind": "CronJob", @@ -6520,12 +6212,10 @@ "succeeded": 0 }, "time": { - "created": "2021-06-24T12:23:00.000Z" + "created": "2021-06-24T11:46:00.000Z" } }, - "namespace": { - "name": "default" - } + "namespace": "default" }, "metricset": { "name": "state_job", @@ -6545,29 +6235,27 @@ "kubernetes": { "job": { "completions": { - "desired": 20 + "desired": 1 }, - "name": "sleep-5-parallel-cron-27075638", + "name": "sleep-30-fail-cron-27075630", "owner": { "is_controller": "true", "kind": "CronJob", - "name": "sleep-5-parallel-cron" + "name": "sleep-30-fail-cron" }, "parallelism": { - "desired": 5 + "desired": 1 }, "pods": { - "active": 5, + "active": 1, "failed": 0, "succeeded": 0 }, "time": { - "created": "2021-06-24T12:38:00.000Z" + "created": "2021-06-24T12:30:00.000Z" } }, - "namespace": { - "name": "parallel-ns" - } + "namespace": "default" }, "metricset": { "name": "state_job", @@ -6589,7 +6277,7 @@ "completions": { "desired": 20 }, - "name": "sleep-5-parallel-cron-27075633", + "name": "sleep-5-parallel-cron-27075618", "owner": { "is_controller": "true", "kind": "CronJob", @@ -6599,17 +6287,15 @@ "desired": 5 }, "pods": { - "active": 5, + "active": 2, "failed": 0, - "succeeded": 0 + "succeeded": 18 }, "time": { - "created": "2021-06-24T12:33:00.000Z" + "created": "2021-06-24T12:18:00.000Z" } }, - "namespace": { - "name": "parallel-ns" - } + "namespace": "parallel-ns" }, "metricset": { "name": "state_job", @@ -6629,29 +6315,27 @@ "kubernetes": { "job": { "completions": { - "desired": 20 + "desired": 1 }, - "name": "sleep-5-parallel-cron-27075564", + "name": "sleep-30-fail-cron-27075592", "owner": { "is_controller": "true", "kind": "CronJob", - "name": "sleep-5-parallel-cron" + "name": "sleep-30-fail-cron" }, "parallelism": { - "desired": 5 + "desired": 1 }, "pods": { - "active": 2, + "active": 1, "failed": 0, - "succeeded": 18 + "succeeded": 0 }, "time": { - "created": "2021-06-24T11:24:00.000Z" + "created": "2021-06-24T11:52:00.000Z" } }, - "namespace": { - "name": "parallel-ns" - } + "namespace": "default" }, "metricset": { "name": "state_job", diff --git a/metricbeat/module/kubernetes/state_job/state_job.go b/metricbeat/module/kubernetes/state_job/state_job.go index bfad2bcba8b..1b072eae742 100644 --- a/metricbeat/module/kubernetes/state_job/state_job.go +++ b/metricbeat/module/kubernetes/state_job/state_job.go @@ -65,7 +65,7 @@ var ( Labels: map[string]p.LabelMap{ // Jobs are uniquely identified by the combination of name and namespace. "job_name": p.KeyLabel("name"), - "namespace": p.KeyLabel(mb.ModuleDataKey + ".namespace.name"), + "namespace": p.KeyLabel(mb.ModuleDataKey + ".namespace"), // Add owner information provided by the "kube_job_owner" InfoMetric. "owner_kind": p.Label("owner.kind"), "owner_name": p.Label("owner.name"), diff --git a/metricbeat/module/kubernetes/state_persistentvolumeclaim/_meta/test/ksm.unit.v1.8.0.expected b/metricbeat/module/kubernetes/state_persistentvolumeclaim/_meta/test/ksm.unit.v1.8.0.expected index fbc1e75a94e..1bafc31a84c 100644 --- a/metricbeat/module/kubernetes/state_persistentvolumeclaim/_meta/test/ksm.unit.v1.8.0.expected +++ b/metricbeat/module/kubernetes/state_persistentvolumeclaim/_meta/test/ksm.unit.v1.8.0.expected @@ -5,9 +5,7 @@ "labels": { "app": "mysql-server" }, - "namespace": { - "name": "default" - } + "namespace": "default" }, "MetricSetFields": { "access_mode": "ReadWriteOnce", @@ -32,12 +30,15 @@ }, { "RootFields": {}, - "ModuleFields": null, + "ModuleFields": { + "namespace": "default" + }, "MetricSetFields": { "access_mode": "ReadWriteOnce", - "name": "mongo-data", - "phase": "Lost", - "storage_class": "\u003cnone\u003e" + "name": "prometheus-data", + "phase": "Pending", + "storage_class": "rbd", + "volume_name": "pvc-prometheus-data" }, "Index": "", "ID": "", @@ -52,17 +53,12 @@ }, { "RootFields": {}, - "ModuleFields": { - "namespace": { - "name": "default" - } - }, + "ModuleFields": null, "MetricSetFields": { "access_mode": "ReadWriteOnce", - "name": "prometheus-data", - "phase": "Pending", - "storage_class": "rbd", - "volume_name": "pvc-prometheus-data" + "name": "mongo-data", + "phase": "Lost", + "storage_class": "\u003cnone\u003e" }, "Index": "", "ID": "", diff --git a/metricbeat/module/kubernetes/state_persistentvolumeclaim/_meta/test/ksm.v1.8.0.expected b/metricbeat/module/kubernetes/state_persistentvolumeclaim/_meta/test/ksm.v1.8.0.expected index 925b651362e..e5c4c21bd2f 100644 --- a/metricbeat/module/kubernetes/state_persistentvolumeclaim/_meta/test/ksm.v1.8.0.expected +++ b/metricbeat/module/kubernetes/state_persistentvolumeclaim/_meta/test/ksm.v1.8.0.expected @@ -5,19 +5,17 @@ "labels": { "app": "nginx" }, - "namespace": { - "name": "default" - } + "namespace": "default" }, "MetricSetFields": { "access_mode": "ReadWriteOnce", - "name": "www-web-1", + "name": "www-web-0", "phase": "Bound", "request_storage": { "bytes": 1073741824 }, "storage_class": "standard", - "volume_name": "pvc-539a19cf-ea44-43a4-84c5-4acca3f9b583" + "volume_name": "pvc-c87e31f9-f853-4b20-b5db-fc41466c8b56" }, "Index": "", "ID": "", @@ -36,19 +34,17 @@ "labels": { "app": "nginx" }, - "namespace": { - "name": "default" - } + "namespace": "default" }, "MetricSetFields": { "access_mode": "ReadWriteOnce", - "name": "www-web-0", + "name": "www-web-1", "phase": "Bound", "request_storage": { "bytes": 1073741824 }, "storage_class": "standard", - "volume_name": "pvc-c87e31f9-f853-4b20-b5db-fc41466c8b56" + "volume_name": "pvc-539a19cf-ea44-43a4-84c5-4acca3f9b583" }, "Index": "", "ID": "", diff --git a/metricbeat/module/kubernetes/state_persistentvolumeclaim/_meta/test/ksm.v2.0.0.expected b/metricbeat/module/kubernetes/state_persistentvolumeclaim/_meta/test/ksm.v2.0.0.expected index dc1ada939b5..09a2c61e789 100644 --- a/metricbeat/module/kubernetes/state_persistentvolumeclaim/_meta/test/ksm.v2.0.0.expected +++ b/metricbeat/module/kubernetes/state_persistentvolumeclaim/_meta/test/ksm.v2.0.0.expected @@ -2,9 +2,7 @@ { "RootFields": {}, "ModuleFields": { - "namespace": { - "name": "default" - } + "namespace": "default" }, "MetricSetFields": { "access_mode": "ReadWriteOnce", diff --git a/metricbeat/module/kubernetes/state_persistentvolumeclaim/state_persistentvolumeclaim.go b/metricbeat/module/kubernetes/state_persistentvolumeclaim/state_persistentvolumeclaim.go index 15072c5710c..3cf414c498a 100644 --- a/metricbeat/module/kubernetes/state_persistentvolumeclaim/state_persistentvolumeclaim.go +++ b/metricbeat/module/kubernetes/state_persistentvolumeclaim/state_persistentvolumeclaim.go @@ -69,7 +69,7 @@ func NewpersistentvolumeclaimMetricSet(base mb.BaseMetricSet) (mb.MetricSet, err "kube_persistentvolumeclaim_status_phase": p.LabelMetric("phase", "phase"), }, Labels: map[string]p.LabelMap{ - "namespace": p.KeyLabel(mb.ModuleDataKey + ".namespace.name"), + "namespace": p.KeyLabel(mb.ModuleDataKey + ".namespace"), "persistentvolumeclaim": p.KeyLabel("name"), "storageclass": p.Label("storage_class"), "volumename": p.Label("volume_name"), diff --git a/metricbeat/module/kubernetes/state_pod/_meta/data.json b/metricbeat/module/kubernetes/state_pod/_meta/data.json index 2a002a1470e..474341cacd3 100644 --- a/metricbeat/module/kubernetes/state_pod/_meta/data.json +++ b/metricbeat/module/kubernetes/state_pod/_meta/data.json @@ -6,16 +6,14 @@ "module": "kubernetes" }, "kubernetes": { - "namespace": { - "name": "jenkins" - }, + "namespace": "kube-system", "node": { "name": "minikube" }, "pod": { "host_ip": "192.168.99.100", - "ip": "172.17.0.7", - "name": "wise-lynx-jenkins-1616735317-svn6k", + "ip": "172.17.0.2", + "name": "tiller-deploy-3067024529-9lpmb", "status": { "phase": "running", "ready": "true", diff --git a/metricbeat/module/kubernetes/state_pod/_meta/test/ksm.v1.3.0.expected b/metricbeat/module/kubernetes/state_pod/_meta/test/ksm.v1.3.0.expected index b8ffd59a24b..b47439bb83e 100644 --- a/metricbeat/module/kubernetes/state_pod/_meta/test/ksm.v1.3.0.expected +++ b/metricbeat/module/kubernetes/state_pod/_meta/test/ksm.v1.3.0.expected @@ -2,17 +2,15 @@ { "RootFields": null, "ModuleFields": { - "namespace": { - "name": "kube-system" - }, + "namespace": "kube-system", "node": { "name": "minikube" } }, "MetricSetFields": { "host_ip": "10.0.2.15", - "ip": "172.17.0.5", - "name": "kube-state-metrics-6479d88c5c-5b6cl", + "ip": "10.0.2.15", + "name": "kube-scheduler-minikube", "status": { "phase": "running", "ready": "true", @@ -33,9 +31,7 @@ { "RootFields": null, "ModuleFields": { - "namespace": { - "name": "kube-system" - }, + "namespace": "kube-system", "node": { "name": "minikube" } @@ -43,7 +39,7 @@ "MetricSetFields": { "host_ip": "10.0.2.15", "ip": "10.0.2.15", - "name": "kube-proxy-znhg6", + "name": "kube-apiserver-minikube", "status": { "phase": "running", "ready": "true", @@ -64,9 +60,7 @@ { "RootFields": null, "ModuleFields": { - "namespace": { - "name": "kube-system" - }, + "namespace": "kube-system", "node": { "name": "minikube" } @@ -74,7 +68,7 @@ "MetricSetFields": { "host_ip": "10.0.2.15", "ip": "10.0.2.15", - "name": "kube-controller-manager-minikube", + "name": "kube-addon-manager-minikube", "status": { "phase": "running", "ready": "true", @@ -95,17 +89,15 @@ { "RootFields": null, "ModuleFields": { - "namespace": { - "name": "kube-system" - }, + "namespace": "kube-system", "node": { "name": "minikube" } }, "MetricSetFields": { "host_ip": "10.0.2.15", - "ip": "10.0.2.15", - "name": "storage-provisioner", + "ip": "172.17.0.3", + "name": "kubernetes-dashboard-77d8b98585-vqtzm", "status": { "phase": "running", "ready": "true", @@ -126,17 +118,15 @@ { "RootFields": null, "ModuleFields": { - "namespace": { - "name": "kube-system" - }, + "namespace": "kube-system", "node": { "name": "minikube" } }, "MetricSetFields": { "host_ip": "10.0.2.15", - "ip": "10.0.2.15", - "name": "etcd-minikube", + "ip": "172.17.0.2", + "name": "kube-dns-6f4fd4bdf-wlmht", "status": { "phase": "running", "ready": "true", @@ -157,17 +147,15 @@ { "RootFields": null, "ModuleFields": { - "namespace": { - "name": "kube-system" - }, + "namespace": "kube-system", "node": { "name": "minikube" } }, "MetricSetFields": { "host_ip": "10.0.2.15", - "ip": "172.17.0.2", - "name": "kube-dns-6f4fd4bdf-wlmht", + "ip": "10.0.2.15", + "name": "kube-controller-manager-minikube", "status": { "phase": "running", "ready": "true", @@ -188,17 +176,15 @@ { "RootFields": null, "ModuleFields": { - "namespace": { - "name": "kube-system" - }, + "namespace": "kube-system", "node": { "name": "minikube" } }, "MetricSetFields": { "host_ip": "10.0.2.15", - "ip": "172.17.0.3", - "name": "kubernetes-dashboard-77d8b98585-vqtzm", + "ip": "10.0.2.15", + "name": "storage-provisioner", "status": { "phase": "running", "ready": "true", @@ -219,9 +205,7 @@ { "RootFields": null, "ModuleFields": { - "namespace": { - "name": "kube-system" - }, + "namespace": "kube-system", "node": { "name": "minikube" } @@ -229,7 +213,7 @@ "MetricSetFields": { "host_ip": "10.0.2.15", "ip": "10.0.2.15", - "name": "kube-scheduler-minikube", + "name": "etcd-minikube", "status": { "phase": "running", "ready": "true", @@ -250,17 +234,15 @@ { "RootFields": null, "ModuleFields": { - "namespace": { - "name": "kube-system" - }, + "namespace": "kube-system", "node": { "name": "minikube" } }, "MetricSetFields": { "host_ip": "10.0.2.15", - "ip": "10.0.2.15", - "name": "kube-addon-manager-minikube", + "ip": "172.17.0.5", + "name": "kube-state-metrics-6479d88c5c-5b6cl", "status": { "phase": "running", "ready": "true", @@ -281,9 +263,7 @@ { "RootFields": null, "ModuleFields": { - "namespace": { - "name": "kube-system" - }, + "namespace": "kube-system", "node": { "name": "minikube" } @@ -291,7 +271,7 @@ "MetricSetFields": { "host_ip": "10.0.2.15", "ip": "10.0.2.15", - "name": "kube-apiserver-minikube", + "name": "kube-proxy-znhg6", "status": { "phase": "running", "ready": "true", diff --git a/metricbeat/module/kubernetes/state_pod/_meta/test/ksm.v1.8.0.expected b/metricbeat/module/kubernetes/state_pod/_meta/test/ksm.v1.8.0.expected index 8e4e7e97417..3048bed3e48 100644 --- a/metricbeat/module/kubernetes/state_pod/_meta/test/ksm.v1.8.0.expected +++ b/metricbeat/module/kubernetes/state_pod/_meta/test/ksm.v1.8.0.expected @@ -2,20 +2,18 @@ { "RootFields": null, "ModuleFields": { - "namespace": { - "name": "kube-system" - }, + "namespace": "default", "node": { "name": "minikube" } }, "MetricSetFields": { "host_ip": "192.168.64.6", - "ip": "192.168.64.6", - "name": "kube-scheduler-minikube", + "ip": "172.17.0.7", + "name": "hello-1578512100-vr7wj", "status": { - "phase": "running", - "ready": "true", + "phase": "succeeded", + "ready": "false", "scheduled": "true" } }, @@ -33,17 +31,15 @@ { "RootFields": null, "ModuleFields": { - "namespace": { - "name": "default" - }, + "namespace": "kube-system", "node": { "name": "minikube" } }, "MetricSetFields": { "host_ip": "192.168.64.6", - "ip": "172.17.0.6", - "name": "web-1", + "ip": "192.168.64.6", + "name": "etcd-minikube", "status": { "phase": "running", "ready": "true", @@ -64,17 +60,15 @@ { "RootFields": null, "ModuleFields": { - "namespace": { - "name": "kube-system" - }, + "namespace": "default", "node": { "name": "minikube" } }, "MetricSetFields": { "host_ip": "192.168.64.6", - "ip": "192.168.64.6", - "name": "kube-addon-manager-minikube", + "ip": "172.17.0.6", + "name": "web-1", "status": { "phase": "running", "ready": "true", @@ -95,17 +89,15 @@ { "RootFields": null, "ModuleFields": { - "namespace": { - "name": "kube-system" - }, + "namespace": "kube-system", "node": { "name": "minikube" } }, "MetricSetFields": { "host_ip": "192.168.64.6", - "ip": "172.17.0.3", - "name": "coredns-5644d7b6d9-k6wsp", + "ip": "172.17.0.2", + "name": "coredns-5644d7b6d9-fhwjd", "status": { "phase": "running", "ready": "true", @@ -126,17 +118,15 @@ { "RootFields": null, "ModuleFields": { - "namespace": { - "name": "kube-system" - }, + "namespace": "default", "node": { "name": "minikube" } }, "MetricSetFields": { "host_ip": "192.168.64.6", - "ip": "192.168.64.6", - "name": "storage-provisioner", + "ip": "172.17.0.5", + "name": "web-0", "status": { "phase": "running", "ready": "true", @@ -157,9 +147,7 @@ { "RootFields": null, "ModuleFields": { - "namespace": { - "name": "kube-system" - }, + "namespace": "kube-system", "node": { "name": "minikube" } @@ -167,7 +155,7 @@ "MetricSetFields": { "host_ip": "192.168.64.6", "ip": "192.168.64.6", - "name": "kube-controller-manager-minikube", + "name": "kube-proxy-dwg6l", "status": { "phase": "running", "ready": "true", @@ -188,9 +176,7 @@ { "RootFields": null, "ModuleFields": { - "namespace": { - "name": "kube-system" - }, + "namespace": "kube-system", "node": { "name": "minikube" } @@ -198,7 +184,7 @@ "MetricSetFields": { "host_ip": "192.168.64.6", "ip": "192.168.64.6", - "name": "kube-apiserver-minikube", + "name": "kube-scheduler-minikube", "status": { "phase": "running", "ready": "true", @@ -219,17 +205,15 @@ { "RootFields": null, "ModuleFields": { - "namespace": { - "name": "kube-system" - }, + "namespace": "kube-system", "node": { "name": "minikube" } }, "MetricSetFields": { "host_ip": "192.168.64.6", - "ip": "172.17.0.4", - "name": "kube-state-metrics-898d4db8d-dqmtg", + "ip": "192.168.64.6", + "name": "kube-addon-manager-minikube", "status": { "phase": "running", "ready": "true", @@ -250,17 +234,15 @@ { "RootFields": null, "ModuleFields": { - "namespace": { - "name": "default" - }, + "namespace": "kube-system", "node": { "name": "minikube" } }, "MetricSetFields": { "host_ip": "192.168.64.6", - "ip": "172.17.0.5", - "name": "web-0", + "ip": "172.17.0.3", + "name": "coredns-5644d7b6d9-k6wsp", "status": { "phase": "running", "ready": "true", @@ -281,9 +263,7 @@ { "RootFields": null, "ModuleFields": { - "namespace": { - "name": "kube-system" - }, + "namespace": "kube-system", "node": { "name": "minikube" } @@ -291,7 +271,7 @@ "MetricSetFields": { "host_ip": "192.168.64.6", "ip": "192.168.64.6", - "name": "kube-proxy-dwg6l", + "name": "storage-provisioner", "status": { "phase": "running", "ready": "true", @@ -312,20 +292,18 @@ { "RootFields": null, "ModuleFields": { - "namespace": { - "name": "default" - }, + "namespace": "kube-system", "node": { "name": "minikube" } }, "MetricSetFields": { "host_ip": "192.168.64.6", - "ip": "172.17.0.7", - "name": "hello-1578512100-vr7wj", + "ip": "192.168.64.6", + "name": "kube-controller-manager-minikube", "status": { - "phase": "succeeded", - "ready": "false", + "phase": "running", + "ready": "true", "scheduled": "true" } }, @@ -343,17 +321,15 @@ { "RootFields": null, "ModuleFields": { - "namespace": { - "name": "kube-system" - }, + "namespace": "kube-system", "node": { "name": "minikube" } }, "MetricSetFields": { "host_ip": "192.168.64.6", - "ip": "172.17.0.2", - "name": "coredns-5644d7b6d9-fhwjd", + "ip": "192.168.64.6", + "name": "kube-apiserver-minikube", "status": { "phase": "running", "ready": "true", @@ -374,17 +350,15 @@ { "RootFields": null, "ModuleFields": { - "namespace": { - "name": "kube-system" - }, + "namespace": "kube-system", "node": { "name": "minikube" } }, "MetricSetFields": { "host_ip": "192.168.64.6", - "ip": "192.168.64.6", - "name": "etcd-minikube", + "ip": "172.17.0.4", + "name": "kube-state-metrics-898d4db8d-dqmtg", "status": { "phase": "running", "ready": "true", diff --git a/metricbeat/module/kubernetes/state_pod/_meta/test/ksm.v2.0.0.expected b/metricbeat/module/kubernetes/state_pod/_meta/test/ksm.v2.0.0.expected index 865ffcf6449..9ee91db17f4 100644 --- a/metricbeat/module/kubernetes/state_pod/_meta/test/ksm.v2.0.0.expected +++ b/metricbeat/module/kubernetes/state_pod/_meta/test/ksm.v2.0.0.expected @@ -2,9 +2,7 @@ { "RootFields": null, "ModuleFields": { - "namespace": { - "name": "kube-system" - }, + "namespace": "kube-system", "node": { "name": "kind-worker" } @@ -12,7 +10,7 @@ "MetricSetFields": { "host_ip": "172.20.0.4", "ip": "172.20.0.4", - "name": "metricbeat-bvr2v", + "name": "kube-proxy-22znl", "status": { "phase": "running", "ready": "true", @@ -33,17 +31,15 @@ { "RootFields": null, "ModuleFields": { - "namespace": { - "name": "default" - }, + "namespace": "default", "node": { - "name": "kind-worker" + "name": "kind-worker2" } }, "MetricSetFields": { - "host_ip": "172.20.0.4", - "ip": "10.244.2.3", - "name": "hello-python-566b5479f5-ndwdl", + "host_ip": "172.20.0.3", + "ip": "10.244.1.2", + "name": "redis", "status": { "phase": "running", "ready": "true", @@ -64,17 +60,15 @@ { "RootFields": null, "ModuleFields": { - "namespace": { - "name": "kube-system" - }, + "namespace": "kube-system", "node": { "name": "kind-control-plane" } }, "MetricSetFields": { "host_ip": "172.20.0.2", - "ip": "172.20.0.2", - "name": "kube-proxy-cm525", + "ip": "10.244.0.3", + "name": "coredns-5644d7b6d9-zgdsx", "status": { "phase": "running", "ready": "true", @@ -95,17 +89,15 @@ { "RootFields": null, "ModuleFields": { - "namespace": { - "name": "kube-system" - }, + "namespace": "kube-system", "node": { "name": "kind-control-plane" } }, "MetricSetFields": { "host_ip": "172.20.0.2", - "ip": "172.20.0.2", - "name": "kube-scheduler-kind-control-plane", + "ip": "10.244.0.2", + "name": "coredns-5644d7b6d9-nnwmb", "status": { "phase": "running", "ready": "true", @@ -126,17 +118,15 @@ { "RootFields": null, "ModuleFields": { - "namespace": { - "name": "kube-system" - }, + "namespace": "kube-system", "node": { - "name": "kind-worker2" + "name": "kind-worker" } }, "MetricSetFields": { - "host_ip": "172.20.0.3", - "ip": "172.20.0.3", - "name": "metricbeat-55fp7", + "host_ip": "172.20.0.4", + "ip": "172.20.0.4", + "name": "kindnet-9fgst", "status": { "phase": "running", "ready": "true", @@ -157,17 +147,15 @@ { "RootFields": null, "ModuleFields": { - "namespace": { - "name": "default" - }, + "namespace": "kube-system", "node": { "name": "kind-worker2" } }, "MetricSetFields": { "host_ip": "172.20.0.3", - "ip": "10.244.1.2", - "name": "redis", + "ip": "172.20.0.3", + "name": "kube-proxy-lf6md", "status": { "phase": "running", "ready": "true", @@ -188,17 +176,15 @@ { "RootFields": null, "ModuleFields": { - "namespace": { - "name": "kube-system" - }, + "namespace": "kube-system", "node": { - "name": "kind-worker" + "name": "kind-control-plane" } }, "MetricSetFields": { - "host_ip": "172.20.0.4", - "ip": "10.244.2.2", - "name": "kube-state-metrics-f655d484d-hj69w", + "host_ip": "172.20.0.2", + "ip": "172.20.0.2", + "name": "kube-controller-manager-kind-control-plane", "status": { "phase": "running", "ready": "true", @@ -219,9 +205,7 @@ { "RootFields": null, "ModuleFields": { - "namespace": { - "name": "kube-system" - }, + "namespace": "kube-system", "node": { "name": "kind-control-plane" } @@ -229,7 +213,7 @@ "MetricSetFields": { "host_ip": "172.20.0.2", "ip": "172.20.0.2", - "name": "kindnet-kch2v", + "name": "kube-apiserver-kind-control-plane", "status": { "phase": "running", "ready": "true", @@ -250,17 +234,15 @@ { "RootFields": null, "ModuleFields": { - "namespace": { - "name": "kube-system" - }, + "namespace": "kube-system", "node": { - "name": "kind-worker2" + "name": "kind-control-plane" } }, "MetricSetFields": { - "host_ip": "172.20.0.3", - "ip": "172.20.0.3", - "name": "kindnet-tg7tl", + "host_ip": "172.20.0.2", + "ip": "172.20.0.2", + "name": "etcd-kind-control-plane", "status": { "phase": "running", "ready": "true", @@ -281,17 +263,15 @@ { "RootFields": null, "ModuleFields": { - "namespace": { - "name": "kube-system" - }, + "namespace": "default", "node": { "name": "kind-worker" } }, "MetricSetFields": { "host_ip": "172.20.0.4", - "ip": "172.20.0.4", - "name": "kindnet-9fgst", + "ip": "10.244.2.3", + "name": "hello-python-566b5479f5-ndwdl", "status": { "phase": "running", "ready": "true", @@ -312,9 +292,7 @@ { "RootFields": null, "ModuleFields": { - "namespace": { - "name": "kube-system" - }, + "namespace": "kube-system", "node": { "name": "kind-control-plane" } @@ -322,7 +300,7 @@ "MetricSetFields": { "host_ip": "172.20.0.2", "ip": "172.20.0.2", - "name": "kube-controller-manager-kind-control-plane", + "name": "kube-proxy-cm525", "status": { "phase": "running", "ready": "true", @@ -343,17 +321,15 @@ { "RootFields": null, "ModuleFields": { - "namespace": { - "name": "kube-system" - }, + "namespace": "local-path-storage", "node": { "name": "kind-control-plane" } }, "MetricSetFields": { "host_ip": "172.20.0.2", - "ip": "172.20.0.2", - "name": "kube-apiserver-kind-control-plane", + "ip": "10.244.0.4", + "name": "local-path-provisioner-5bf465b47d-h8hjn", "status": { "phase": "running", "ready": "true", @@ -374,17 +350,15 @@ { "RootFields": null, "ModuleFields": { - "namespace": { - "name": "kube-system" - }, + "namespace": "kube-system", "node": { - "name": "kind-control-plane" + "name": "kind-worker" } }, "MetricSetFields": { - "host_ip": "172.20.0.2", - "ip": "172.20.0.2", - "name": "etcd-kind-control-plane", + "host_ip": "172.20.0.4", + "ip": "10.244.2.2", + "name": "kube-state-metrics-f655d484d-hj69w", "status": { "phase": "running", "ready": "true", @@ -405,20 +379,18 @@ { "RootFields": null, "ModuleFields": { - "namespace": { - "name": "default" - }, + "namespace": "kube-system", "node": { - "name": "kind-worker" + "name": "kind-control-plane" } }, "MetricSetFields": { - "host_ip": "172.20.0.3", - "ip": "10.244.2.2", - "name": "hello-zf6gh", + "host_ip": "172.20.0.2", + "ip": "172.20.0.2", + "name": "kube-scheduler-kind-control-plane", "status": { - "phase": "succeeded", - "ready": "false", + "phase": "running", + "ready": "true", "scheduled": "true" } }, @@ -436,20 +408,18 @@ { "RootFields": null, "ModuleFields": { - "namespace": { - "name": "kube-system" - }, + "namespace": "default", "node": { "name": "kind-worker" } }, "MetricSetFields": { - "host_ip": "172.20.0.4", - "ip": "172.20.0.4", - "name": "kube-proxy-22znl", + "host_ip": "172.20.0.3", + "ip": "10.244.2.2", + "name": "hello-zf6gh", "status": { - "phase": "running", - "ready": "true", + "phase": "succeeded", + "ready": "false", "scheduled": "true" } }, @@ -467,17 +437,15 @@ { "RootFields": null, "ModuleFields": { - "namespace": { - "name": "kube-system" - }, + "namespace": "kube-system", "node": { - "name": "kind-worker2" + "name": "kind-control-plane" } }, "MetricSetFields": { - "host_ip": "172.20.0.3", - "ip": "172.20.0.3", - "name": "kube-proxy-lf6md", + "host_ip": "172.20.0.2", + "ip": "172.20.0.2", + "name": "kindnet-kch2v", "status": { "phase": "running", "ready": "true", @@ -498,17 +466,15 @@ { "RootFields": null, "ModuleFields": { - "namespace": { - "name": "local-path-storage" - }, + "namespace": "kube-system", "node": { - "name": "kind-control-plane" + "name": "kind-worker2" } }, "MetricSetFields": { - "host_ip": "172.20.0.2", - "ip": "10.244.0.4", - "name": "local-path-provisioner-5bf465b47d-h8hjn", + "host_ip": "172.20.0.3", + "ip": "172.20.0.3", + "name": "metricbeat-55fp7", "status": { "phase": "running", "ready": "true", @@ -529,17 +495,15 @@ { "RootFields": null, "ModuleFields": { - "namespace": { - "name": "kube-system" - }, + "namespace": "kube-system", "node": { - "name": "kind-control-plane" + "name": "kind-worker" } }, "MetricSetFields": { - "host_ip": "172.20.0.2", - "ip": "10.244.0.3", - "name": "coredns-5644d7b6d9-zgdsx", + "host_ip": "172.20.0.4", + "ip": "172.20.0.4", + "name": "metricbeat-bvr2v", "status": { "phase": "running", "ready": "true", @@ -560,17 +524,15 @@ { "RootFields": null, "ModuleFields": { - "namespace": { - "name": "kube-system" - }, + "namespace": "kube-system", "node": { - "name": "kind-control-plane" + "name": "kind-worker2" } }, "MetricSetFields": { - "host_ip": "172.20.0.2", - "ip": "10.244.0.2", - "name": "coredns-5644d7b6d9-nnwmb", + "host_ip": "172.20.0.3", + "ip": "172.20.0.3", + "name": "kindnet-tg7tl", "status": { "phase": "running", "ready": "true", diff --git a/metricbeat/module/kubernetes/state_pod/_meta/testdata/docs.plain-expected.json b/metricbeat/module/kubernetes/state_pod/_meta/testdata/docs.plain-expected.json index 7816dfea70f..09de4a43609 100644 --- a/metricbeat/module/kubernetes/state_pod/_meta/testdata/docs.plain-expected.json +++ b/metricbeat/module/kubernetes/state_pod/_meta/testdata/docs.plain-expected.json @@ -6,16 +6,14 @@ "module": "kubernetes" }, "kubernetes": { - "namespace": { - "name": "jenkins" - }, + "namespace": "kube-system", "node": { "name": "minikube" }, "pod": { "host_ip": "192.168.99.100", - "ip": "172.17.0.7", - "name": "wise-lynx-jenkins-1616735317-svn6k", + "ip": "172.17.0.2", + "name": "tiller-deploy-3067024529-9lpmb", "status": { "phase": "running", "ready": "true", @@ -39,16 +37,14 @@ "module": "kubernetes" }, "kubernetes": { - "namespace": { - "name": "kube-system" - }, + "namespace": "kube-system", "node": { "name": "minikube" }, "pod": { "host_ip": "192.168.99.100", - "ip": "172.17.0.6", - "name": "kube-dns-v20-5g5cb", + "ip": "172.17.0.3", + "name": "kube-state-metrics-1303537707-7ncd1", "status": { "phase": "running", "ready": "true", @@ -72,9 +68,7 @@ "module": "kubernetes" }, "kubernetes": { - "namespace": { - "name": "default" - }, + "namespace": "default", "node": { "name": "minikube" }, @@ -105,20 +99,18 @@ "module": "kubernetes" }, "kubernetes": { - "namespace": { - "name": "kube-system" - }, + "namespace": "test", "node": { - "name": "minikube" + "name": "minikube-test" }, "pod": { - "host_ip": "192.168.99.100", - "ip": "172.17.0.3", - "name": "kube-state-metrics-1303537707-7ncd1", + "host_ip": "192.168.99.200", + "ip": "172.17.0.5", + "name": "jumpy-owl-redis-3481028193-s78x9", "status": { "phase": "running", "ready": "true", - "scheduled": "true" + "scheduled": "false" } } }, @@ -138,14 +130,18 @@ "module": "kubernetes" }, "kubernetes": { - "namespace": { - "name": "kube-system" + "namespace": "jenkins", + "node": { + "name": "minikube" }, "pod": { - "name": "kube-state-metrics-1303537707-mnzbp", + "host_ip": "192.168.99.100", + "ip": "172.17.0.7", + "name": "wise-lynx-jenkins-1616735317-svn6k", "status": { - "phase": "pending", - "scheduled": "false" + "phase": "running", + "ready": "true", + "scheduled": "true" } } }, @@ -165,20 +161,12 @@ "module": "kubernetes" }, "kubernetes": { - "namespace": { - "name": "kube-system" - }, - "node": { - "name": "minikube" - }, + "namespace": "kube-system", "pod": { - "host_ip": "192.168.99.100", - "ip": "172.17.0.5", - "name": "kubernetes-dashboard-vw0l6", + "name": "kube-state-metrics-1303537707-mnzbp", "status": { - "phase": "running", - "ready": "true", - "scheduled": "true" + "phase": "pending", + "scheduled": "false" } } }, @@ -198,20 +186,18 @@ "module": "kubernetes" }, "kubernetes": { - "namespace": { - "name": "test" - }, + "namespace": "kube-system", "node": { - "name": "minikube-test" + "name": "minikube" }, "pod": { - "host_ip": "192.168.99.200", - "ip": "172.17.0.5", - "name": "jumpy-owl-redis-3481028193-s78x9", + "host_ip": "192.168.99.100", + "ip": "172.17.0.6", + "name": "kube-dns-v20-5g5cb", "status": { "phase": "running", "ready": "true", - "scheduled": "false" + "scheduled": "true" } } }, @@ -231,16 +217,14 @@ "module": "kubernetes" }, "kubernetes": { - "namespace": { - "name": "kube-system" - }, + "namespace": "kube-system", "node": { "name": "minikube" }, "pod": { "host_ip": "192.168.99.100", - "ip": "172.17.0.2", - "name": "tiller-deploy-3067024529-9lpmb", + "ip": "172.17.0.5", + "name": "kubernetes-dashboard-vw0l6", "status": { "phase": "running", "ready": "true", @@ -264,9 +248,7 @@ "module": "kubernetes" }, "kubernetes": { - "namespace": { - "name": "kube-system" - }, + "namespace": "kube-system", "node": { "name": "minikube" }, diff --git a/metricbeat/module/kubernetes/state_pod/state_pod.go b/metricbeat/module/kubernetes/state_pod/state_pod.go index e4bd290850b..ea742ab26bd 100644 --- a/metricbeat/module/kubernetes/state_pod/state_pod.go +++ b/metricbeat/module/kubernetes/state_pod/state_pod.go @@ -49,7 +49,7 @@ var ( Labels: map[string]p.LabelMap{ "pod": p.KeyLabel("name"), - "namespace": p.KeyLabel(mb.ModuleDataKey + ".namespace.name"), + "namespace": p.KeyLabel(mb.ModuleDataKey + ".namespace"), "node": p.Label(mb.ModuleDataKey + ".node.name"), "pod_ip": p.Label("ip"), diff --git a/metricbeat/module/kubernetes/state_replicaset/_meta/data.json b/metricbeat/module/kubernetes/state_replicaset/_meta/data.json index 0c1091c8ad5..f4441104d6b 100644 --- a/metricbeat/module/kubernetes/state_replicaset/_meta/data.json +++ b/metricbeat/module/kubernetes/state_replicaset/_meta/data.json @@ -6,17 +6,15 @@ "module": "kubernetes" }, "kubernetes": { - "namespace": { - "name": "jenkins" - }, + "namespace": "default", "replicaset": { - "name": "wise-lynx-jenkins-1616735317", + "name": "jumpy-owl-redis-3481028193", "replicas": { "available": 1, "desired": 1, "labeled": 1, "observed": 1, - "ready": 1 + "ready": 0 } } }, diff --git a/metricbeat/module/kubernetes/state_replicaset/_meta/test/ksm.v1.3.0.expected b/metricbeat/module/kubernetes/state_replicaset/_meta/test/ksm.v1.3.0.expected index c8a26911c7b..1705a5a87dc 100644 --- a/metricbeat/module/kubernetes/state_replicaset/_meta/test/ksm.v1.3.0.expected +++ b/metricbeat/module/kubernetes/state_replicaset/_meta/test/ksm.v1.3.0.expected @@ -2,12 +2,10 @@ { "RootFields": null, "ModuleFields": { - "namespace": { - "name": "kube-system" - } + "namespace": "kube-system" }, "MetricSetFields": { - "name": "kube-state-metrics-6479d88c5c", + "name": "kubernetes-dashboard-77d8b98585", "replicas": { "available": 1, "desired": 1, @@ -30,18 +28,16 @@ { "RootFields": null, "ModuleFields": { - "namespace": { - "name": "kube-system" - } + "namespace": "kube-system" }, "MetricSetFields": { - "name": "kube-state-metrics-86dd856df7", + "name": "kube-state-metrics-6479d88c5c", "replicas": { - "available": 0, - "desired": 0, - "labeled": 0, - "observed": 2, - "ready": 0 + "available": 1, + "desired": 1, + "labeled": 1, + "observed": 1, + "ready": 1 } }, "Index": "", @@ -58,9 +54,7 @@ { "RootFields": null, "ModuleFields": { - "namespace": { - "name": "kube-system" - } + "namespace": "kube-system" }, "MetricSetFields": { "name": "kube-dns-6f4fd4bdf", @@ -86,18 +80,16 @@ { "RootFields": null, "ModuleFields": { - "namespace": { - "name": "kube-system" - } + "namespace": "kube-system" }, "MetricSetFields": { - "name": "kubernetes-dashboard-77d8b98585", + "name": "kube-state-metrics-86dd856df7", "replicas": { - "available": 1, - "desired": 1, - "labeled": 1, - "observed": 1, - "ready": 1 + "available": 0, + "desired": 0, + "labeled": 0, + "observed": 2, + "ready": 0 } }, "Index": "", diff --git a/metricbeat/module/kubernetes/state_replicaset/_meta/test/ksm.v1.8.0.expected b/metricbeat/module/kubernetes/state_replicaset/_meta/test/ksm.v1.8.0.expected index 9cc72c20d21..d292785f458 100644 --- a/metricbeat/module/kubernetes/state_replicaset/_meta/test/ksm.v1.8.0.expected +++ b/metricbeat/module/kubernetes/state_replicaset/_meta/test/ksm.v1.8.0.expected @@ -2,18 +2,16 @@ { "RootFields": null, "ModuleFields": { - "namespace": { - "name": "kube-system" - } + "namespace": "kube-system" }, "MetricSetFields": { - "name": "kube-state-metrics-898d4db8d", + "name": "coredns-5644d7b6d9", "replicas": { - "available": 1, - "desired": 1, - "labeled": 1, + "available": 2, + "desired": 2, + "labeled": 2, "observed": 1, - "ready": 1 + "ready": 2 } }, "Index": "", @@ -30,18 +28,16 @@ { "RootFields": null, "ModuleFields": { - "namespace": { - "name": "kube-system" - } + "namespace": "kube-system" }, "MetricSetFields": { - "name": "coredns-5644d7b6d9", + "name": "kube-state-metrics-898d4db8d", "replicas": { - "available": 2, - "desired": 2, - "labeled": 2, + "available": 1, + "desired": 1, + "labeled": 1, "observed": 1, - "ready": 2 + "ready": 1 } }, "Index": "", diff --git a/metricbeat/module/kubernetes/state_replicaset/_meta/test/ksm.v2.0.0.expected b/metricbeat/module/kubernetes/state_replicaset/_meta/test/ksm.v2.0.0.expected index 229e8e3f5db..fb06db2106b 100644 --- a/metricbeat/module/kubernetes/state_replicaset/_meta/test/ksm.v2.0.0.expected +++ b/metricbeat/module/kubernetes/state_replicaset/_meta/test/ksm.v2.0.0.expected @@ -2,12 +2,10 @@ { "RootFields": null, "ModuleFields": { - "namespace": { - "name": "default" - } + "namespace": "kube-system" }, "MetricSetFields": { - "name": "hello-python-566b5479f5", + "name": "kube-state-metrics-f655d484d", "replicas": { "available": 1, "desired": 1, @@ -30,18 +28,16 @@ { "RootFields": null, "ModuleFields": { - "namespace": { - "name": "kube-system" - } + "namespace": "default" }, "MetricSetFields": { - "name": "coredns-5644d7b6d9", + "name": "hello-python-566b5479f5", "replicas": { - "available": 2, - "desired": 2, - "labeled": 2, + "available": 1, + "desired": 1, + "labeled": 1, "observed": 1, - "ready": 2 + "ready": 1 } }, "Index": "", @@ -58,18 +54,16 @@ { "RootFields": null, "ModuleFields": { - "namespace": { - "name": "local-path-storage" - } + "namespace": "kube-system" }, "MetricSetFields": { - "name": "local-path-provisioner-5bf465b47d", + "name": "coredns-5644d7b6d9", "replicas": { - "available": 1, - "desired": 1, - "labeled": 1, + "available": 2, + "desired": 2, + "labeled": 2, "observed": 1, - "ready": 1 + "ready": 2 } }, "Index": "", @@ -86,12 +80,10 @@ { "RootFields": null, "ModuleFields": { - "namespace": { - "name": "kube-system" - } + "namespace": "local-path-storage" }, "MetricSetFields": { - "name": "kube-state-metrics-f655d484d", + "name": "local-path-provisioner-5bf465b47d", "replicas": { "available": 1, "desired": 1, diff --git a/metricbeat/module/kubernetes/state_replicaset/_meta/testdata/docs.plain-expected.json b/metricbeat/module/kubernetes/state_replicaset/_meta/testdata/docs.plain-expected.json index 72df48f77e8..cfdafbd4cc3 100644 --- a/metricbeat/module/kubernetes/state_replicaset/_meta/testdata/docs.plain-expected.json +++ b/metricbeat/module/kubernetes/state_replicaset/_meta/testdata/docs.plain-expected.json @@ -6,17 +6,15 @@ "module": "kubernetes" }, "kubernetes": { - "namespace": { - "name": "jenkins" - }, + "namespace": "default", "replicaset": { - "name": "wise-lynx-jenkins-1616735317", + "name": "jumpy-owl-redis-3481028193", "replicas": { "available": 1, "desired": 1, "labeled": 1, "observed": 1, - "ready": 1 + "ready": 0 } } }, @@ -36,17 +34,15 @@ "module": "kubernetes" }, "kubernetes": { - "namespace": { - "name": "kube-system" - }, + "namespace": "test", "replicaset": { - "name": "tiller-deploy-3067024529", + "name": "kube-state-metrics-1303537707", "replicas": { - "available": 1, - "desired": 1, - "labeled": 1, - "observed": 1, - "ready": 1 + "available": 7, + "desired": 3, + "labeled": 4, + "observed": 5, + "ready": 6 } } }, @@ -66,17 +62,15 @@ "module": "kubernetes" }, "kubernetes": { - "namespace": { - "name": "test" - }, + "namespace": "kube-system", "replicaset": { "name": "kube-state-metrics-1303537707", "replicas": { - "available": 7, - "desired": 3, - "labeled": 4, - "observed": 5, - "ready": 6 + "available": 2, + "desired": 2, + "labeled": 2, + "observed": 1, + "ready": 1 } } }, @@ -96,17 +90,15 @@ "module": "kubernetes" }, "kubernetes": { - "namespace": { - "name": "default" - }, + "namespace": "jenkins", "replicaset": { - "name": "jumpy-owl-redis-3481028193", + "name": "wise-lynx-jenkins-1616735317", "replicas": { "available": 1, "desired": 1, "labeled": 1, "observed": 1, - "ready": 0 + "ready": 1 } } }, @@ -126,15 +118,13 @@ "module": "kubernetes" }, "kubernetes": { - "namespace": { - "name": "kube-system" - }, + "namespace": "kube-system", "replicaset": { - "name": "kube-state-metrics-1303537707", + "name": "tiller-deploy-3067024529", "replicas": { - "available": 2, - "desired": 2, - "labeled": 2, + "available": 1, + "desired": 1, + "labeled": 1, "observed": 1, "ready": 1 } diff --git a/metricbeat/module/kubernetes/state_replicaset/state_replicaset.go b/metricbeat/module/kubernetes/state_replicaset/state_replicaset.go index 5a28a237a77..7ee8e62864a 100644 --- a/metricbeat/module/kubernetes/state_replicaset/state_replicaset.go +++ b/metricbeat/module/kubernetes/state_replicaset/state_replicaset.go @@ -51,7 +51,7 @@ var ( Labels: map[string]p.LabelMap{ "replicaset": p.KeyLabel("name"), - "namespace": p.KeyLabel(mb.ModuleDataKey + ".namespace.name"), + "namespace": p.KeyLabel(mb.ModuleDataKey + ".namespace"), }, } ) diff --git a/metricbeat/module/kubernetes/state_resourcequota/_meta/test/ksm.v1.8.0.expected b/metricbeat/module/kubernetes/state_resourcequota/_meta/test/ksm.v1.8.0.expected index 5946cf6c8cb..071423392dc 100644 --- a/metricbeat/module/kubernetes/state_resourcequota/_meta/test/ksm.v1.8.0.expected +++ b/metricbeat/module/kubernetes/state_resourcequota/_meta/test/ksm.v1.8.0.expected @@ -2,14 +2,12 @@ { "RootFields": {}, "ModuleFields": { - "namespace": { - "name": "myspace" - } + "namespace": "myspace" }, "MetricSetFields": { "name": "object-counts", - "quota": 20, - "resource": "replicationcontrollers", + "quota": 10, + "resource": "services", "type": "hard" }, "Index": "", @@ -26,15 +24,13 @@ { "RootFields": {}, "ModuleFields": { - "namespace": { - "name": "myspace" - } + "namespace": "myspace" }, "MetricSetFields": { "name": "object-counts", - "quota": 4, - "resource": "pods", - "type": "hard" + "quota": 0, + "resource": "replicationcontrollers", + "type": "used" }, "Index": "", "ID": "", @@ -50,15 +46,13 @@ { "RootFields": {}, "ModuleFields": { - "namespace": { - "name": "myspace" - } + "namespace": "myspace" }, "MetricSetFields": { - "name": "object-counts", - "quota": 10, - "resource": "configmaps", - "type": "hard" + "name": "compute-resources", + "quota": 0, + "resource": "requests.memory", + "type": "used" }, "Index": "", "ID": "", @@ -74,15 +68,13 @@ { "RootFields": {}, "ModuleFields": { - "namespace": { - "name": "myspace" - } + "namespace": "myspace" }, "MetricSetFields": { - "name": "object-counts", - "quota": 4, - "resource": "persistentvolumeclaims", - "type": "hard" + "created": { + "sec": 1578507202 + }, + "name": "compute-resources" }, "Index": "", "ID": "", @@ -98,14 +90,12 @@ { "RootFields": {}, "ModuleFields": { - "namespace": { - "name": "myspace" - } + "namespace": "myspace" }, "MetricSetFields": { "name": "compute-resources", - "quota": 1073741824, - "resource": "requests.memory", + "quota": 2147483648, + "resource": "limits.memory", "type": "hard" }, "Index": "", @@ -122,15 +112,13 @@ { "RootFields": {}, "ModuleFields": { - "namespace": { - "name": "myspace" - } + "namespace": "myspace" }, "MetricSetFields": { "name": "object-counts", - "quota": 0, + "quota": 4, "resource": "persistentvolumeclaims", - "type": "used" + "type": "hard" }, "Index": "", "ID": "", @@ -146,15 +134,13 @@ { "RootFields": {}, "ModuleFields": { - "namespace": { - "name": "myspace" - } + "namespace": "myspace" }, "MetricSetFields": { "name": "compute-resources", - "quota": 0, - "resource": "limits.memory", - "type": "used" + "quota": 1073741824, + "resource": "requests.memory", + "type": "hard" }, "Index": "", "ID": "", @@ -170,15 +156,13 @@ { "RootFields": {}, "ModuleFields": { - "namespace": { - "name": "myspace" - } + "namespace": "myspace" }, "MetricSetFields": { "name": "object-counts", - "quota": 10, - "resource": "services", - "type": "hard" + "quota": 0, + "resource": "persistentvolumeclaims", + "type": "used" }, "Index": "", "ID": "", @@ -194,15 +178,13 @@ { "RootFields": {}, "ModuleFields": { - "namespace": { - "name": "myspace" - } + "namespace": "myspace" }, "MetricSetFields": { - "name": "compute-resources", - "quota": 0, - "resource": "requests.memory", - "type": "used" + "name": "object-counts", + "quota": 4, + "resource": "pods", + "type": "hard" }, "Index": "", "ID": "", @@ -218,15 +200,13 @@ { "RootFields": {}, "ModuleFields": { - "namespace": { - "name": "myspace" - } + "namespace": "myspace" }, "MetricSetFields": { "name": "object-counts", - "quota": 0, + "quota": 20, "resource": "replicationcontrollers", - "type": "used" + "type": "hard" }, "Index": "", "ID": "", @@ -242,14 +222,12 @@ { "RootFields": {}, "ModuleFields": { - "namespace": { - "name": "myspace" - } + "namespace": "myspace" }, "MetricSetFields": { - "name": "compute-resources", - "quota": 2147483648, - "resource": "limits.memory", + "name": "object-counts", + "quota": 10, + "resource": "configmaps", "type": "hard" }, "Index": "", @@ -266,15 +244,13 @@ { "RootFields": {}, "ModuleFields": { - "namespace": { - "name": "myspace" - } + "namespace": "myspace" }, "MetricSetFields": { - "created": { - "sec": 1578507202 - }, - "name": "compute-resources" + "name": "compute-resources", + "quota": 0, + "resource": "limits.memory", + "type": "used" }, "Index": "", "ID": "", @@ -290,15 +266,13 @@ { "RootFields": {}, "ModuleFields": { - "namespace": { - "name": "myspace" - } + "namespace": "myspace" }, "MetricSetFields": { - "created": { - "sec": 1578507217 - }, - "name": "object-counts" + "name": "object-counts", + "quota": 10, + "resource": "secrets", + "type": "hard" }, "Index": "", "ID": "", @@ -314,14 +288,12 @@ { "RootFields": {}, "ModuleFields": { - "namespace": { - "name": "myspace" - } + "namespace": "myspace" }, "MetricSetFields": { - "name": "compute-resources", + "name": "object-counts", "quota": 0, - "resource": "requests.nvidia.com/gpu", + "resource": "services", "type": "used" }, "Index": "", @@ -338,15 +310,13 @@ { "RootFields": {}, "ModuleFields": { - "namespace": { - "name": "myspace" - } + "namespace": "myspace" }, "MetricSetFields": { "name": "object-counts", - "quota": 1, - "resource": "secrets", - "type": "used" + "quota": 2, + "resource": "services.loadbalancers", + "type": "hard" }, "Index": "", "ID": "", @@ -362,14 +332,12 @@ { "RootFields": {}, "ModuleFields": { - "namespace": { - "name": "myspace" - } + "namespace": "myspace" }, "MetricSetFields": { - "name": "object-counts", + "name": "compute-resources", "quota": 0, - "resource": "pods", + "resource": "limits.cpu", "type": "used" }, "Index": "", @@ -386,15 +354,13 @@ { "RootFields": {}, "ModuleFields": { - "namespace": { - "name": "myspace" - } + "namespace": "myspace" }, "MetricSetFields": { - "name": "compute-resources", - "quota": 1, - "resource": "requests.cpu", - "type": "hard" + "name": "object-counts", + "quota": 0, + "resource": "configmaps", + "type": "used" }, "Index": "", "ID": "", @@ -410,15 +376,13 @@ { "RootFields": {}, "ModuleFields": { - "namespace": { - "name": "myspace" - } + "namespace": "myspace" }, "MetricSetFields": { - "name": "compute-resources", - "quota": 4, - "resource": "requests.nvidia.com/gpu", - "type": "hard" + "name": "object-counts", + "quota": 1, + "resource": "secrets", + "type": "used" }, "Index": "", "ID": "", @@ -434,15 +398,13 @@ { "RootFields": {}, "ModuleFields": { - "namespace": { - "name": "myspace" - } + "namespace": "myspace" }, "MetricSetFields": { - "name": "compute-resources", - "quota": 2, - "resource": "limits.cpu", - "type": "hard" + "name": "object-counts", + "quota": 0, + "resource": "pods", + "type": "used" }, "Index": "", "ID": "", @@ -458,14 +420,12 @@ { "RootFields": {}, "ModuleFields": { - "namespace": { - "name": "myspace" - } + "namespace": "myspace" }, "MetricSetFields": { - "name": "object-counts", + "name": "compute-resources", "quota": 0, - "resource": "services.loadbalancers", + "resource": "requests.nvidia.com/gpu", "type": "used" }, "Index": "", @@ -482,15 +442,13 @@ { "RootFields": {}, "ModuleFields": { - "namespace": { - "name": "myspace" - } + "namespace": "myspace" }, "MetricSetFields": { - "name": "compute-resources", - "quota": 0, - "resource": "requests.cpu", - "type": "used" + "created": { + "sec": 1578507217 + }, + "name": "object-counts" }, "Index": "", "ID": "", @@ -506,15 +464,13 @@ { "RootFields": {}, "ModuleFields": { - "namespace": { - "name": "myspace" - } + "namespace": "myspace" }, "MetricSetFields": { "name": "object-counts", - "quota": 10, - "resource": "secrets", - "type": "hard" + "quota": 0, + "resource": "services.loadbalancers", + "type": "used" }, "Index": "", "ID": "", @@ -530,15 +486,13 @@ { "RootFields": {}, "ModuleFields": { - "namespace": { - "name": "myspace" - } + "namespace": "myspace" }, "MetricSetFields": { - "name": "object-counts", - "quota": 0, - "resource": "services", - "type": "used" + "name": "compute-resources", + "quota": 2, + "resource": "limits.cpu", + "type": "hard" }, "Index": "", "ID": "", @@ -554,15 +508,13 @@ { "RootFields": {}, "ModuleFields": { - "namespace": { - "name": "myspace" - } + "namespace": "myspace" }, "MetricSetFields": { - "name": "object-counts", - "quota": 2, - "resource": "services.loadbalancers", - "type": "hard" + "name": "compute-resources", + "quota": 0, + "resource": "requests.cpu", + "type": "used" }, "Index": "", "ID": "", @@ -578,15 +530,13 @@ { "RootFields": {}, "ModuleFields": { - "namespace": { - "name": "myspace" - } + "namespace": "myspace" }, "MetricSetFields": { - "name": "object-counts", - "quota": 0, - "resource": "configmaps", - "type": "used" + "name": "compute-resources", + "quota": 1, + "resource": "requests.cpu", + "type": "hard" }, "Index": "", "ID": "", @@ -602,15 +552,13 @@ { "RootFields": {}, "ModuleFields": { - "namespace": { - "name": "myspace" - } + "namespace": "myspace" }, "MetricSetFields": { "name": "compute-resources", - "quota": 0, - "resource": "limits.cpu", - "type": "used" + "quota": 4, + "resource": "requests.nvidia.com/gpu", + "type": "hard" }, "Index": "", "ID": "", diff --git a/metricbeat/module/kubernetes/state_resourcequota/state_resourcequota.go b/metricbeat/module/kubernetes/state_resourcequota/state_resourcequota.go index 5fb72e5b577..eb8bc6ddf35 100644 --- a/metricbeat/module/kubernetes/state_resourcequota/state_resourcequota.go +++ b/metricbeat/module/kubernetes/state_resourcequota/state_resourcequota.go @@ -63,7 +63,7 @@ func NewResourceQuotaMetricSet(base mb.BaseMetricSet) (mb.MetricSet, error) { "kube_resourcequota": p.Metric("quota"), }, Labels: map[string]p.LabelMap{ - "namespace": p.KeyLabel(mb.ModuleDataKey + ".namespace.name"), + "namespace": p.KeyLabel(mb.ModuleDataKey + ".namespace"), "resourcequota": p.KeyLabel("name"), "resource": p.KeyLabel("resource"), diff --git a/metricbeat/module/kubernetes/state_service/_meta/test/ksm.unit.v1.8.0.expected b/metricbeat/module/kubernetes/state_service/_meta/test/ksm.unit.v1.8.0.expected index 8f34da5871b..d0c0c46a4ad 100644 --- a/metricbeat/module/kubernetes/state_service/_meta/test/ksm.unit.v1.8.0.expected +++ b/metricbeat/module/kubernetes/state_service/_meta/test/ksm.unit.v1.8.0.expected @@ -3,17 +3,15 @@ "RootFields": null, "ModuleFields": { "labels": { - "app": "example4" + "app": "example2" }, - "namespace": { - "name": "default" - } + "namespace": "default" }, "MetricSetFields": { + "cluster_ip": "1.2.3.5", "created": "2017-07-14T02:40:00.000Z", - "external_name": "www.example.com", - "name": "test-service4", - "type": "ExternalName" + "name": "test-service2", + "type": "NodePort" }, "Index": "", "ID": "", @@ -30,17 +28,16 @@ "RootFields": null, "ModuleFields": { "labels": { - "app": "example2" + "app": "example3" }, - "namespace": { - "name": "default" - } + "namespace": "default" }, "MetricSetFields": { - "cluster_ip": "1.2.3.5", + "cluster_ip": "1.2.3.6", "created": "2017-07-14T02:40:00.000Z", - "name": "test-service2", - "type": "NodePort" + "load_balancer_ip": "1.2.3.7", + "name": "test-service3", + "type": "LoadBalancer" }, "Index": "", "ID": "", @@ -57,17 +54,15 @@ "RootFields": null, "ModuleFields": { "labels": { - "app": "example3" + "app": "example5" }, - "namespace": { - "name": "default" - } + "namespace": "default" }, "MetricSetFields": { - "cluster_ip": "1.2.3.6", "created": "2017-07-14T02:40:00.000Z", - "load_balancer_ip": "1.2.3.7", - "name": "test-service3", + "ingress_hostname": "www.example.com", + "ingress_ip": "1.2.3.8", + "name": "test-service5", "type": "LoadBalancer" }, "Index": "", @@ -85,18 +80,15 @@ "RootFields": null, "ModuleFields": { "labels": { - "app": "example5" + "app": "example4" }, - "namespace": { - "name": "default" - } + "namespace": "default" }, "MetricSetFields": { "created": "2017-07-14T02:40:00.000Z", - "ingress_hostname": "www.example.com", - "ingress_ip": "1.2.3.8", - "name": "test-service5", - "type": "LoadBalancer" + "external_name": "www.example.com", + "name": "test-service4", + "type": "ExternalName" }, "Index": "", "ID": "", @@ -115,9 +107,7 @@ "labels": { "app": "example6" }, - "namespace": { - "name": "default" - } + "namespace": "default" }, "MetricSetFields": { "created": "2017-07-14T02:40:00.000Z", @@ -142,9 +132,7 @@ "labels": { "app": "example1" }, - "namespace": { - "name": "default" - } + "namespace": "default" }, "MetricSetFields": { "cluster_ip": "1.2.3.4", diff --git a/metricbeat/module/kubernetes/state_service/_meta/test/ksm.v1.3.0.expected b/metricbeat/module/kubernetes/state_service/_meta/test/ksm.v1.3.0.expected index 8921833ee55..5717193d8a2 100644 --- a/metricbeat/module/kubernetes/state_service/_meta/test/ksm.v1.3.0.expected +++ b/metricbeat/module/kubernetes/state_service/_meta/test/ksm.v1.3.0.expected @@ -3,19 +3,18 @@ "RootFields": null, "ModuleFields": { "labels": { - "k8s_app": "kube-dns", - "kubernetes_io_cluster_service": "true", - "kubernetes_io_name": "KubeDNS" + "addonmanager_kubernetes_io_mode": "Reconcile", + "app": "kubernetes-dashboard", + "kubernetes_io_minikube_addons": "dashboard", + "kubernetes_io_minikube_addons_endpoint": "dashboard" }, - "namespace": { - "name": "kube-system" - } + "namespace": "kube-system" }, "MetricSetFields": { - "cluster_ip": "10.96.0.10", - "created": "2018-05-30T16:24:36.000Z", - "name": "kube-dns", - "type": "ClusterIP" + "cluster_ip": "10.109.175.127", + "created": "2018-05-30T16:24:44.000Z", + "name": "kubernetes-dashboard", + "type": "NodePort" }, "Index": "", "ID": "", @@ -32,17 +31,16 @@ "RootFields": null, "ModuleFields": { "labels": { - "component": "apiserver", - "provider": "kubernetes" + "k8s_app": "kube-dns", + "kubernetes_io_cluster_service": "true", + "kubernetes_io_name": "KubeDNS" }, - "namespace": { - "name": "default" - } + "namespace": "kube-system" }, "MetricSetFields": { - "cluster_ip": "10.96.0.1", - "created": "2018-05-30T16:24:29.000Z", - "name": "kubernetes", + "cluster_ip": "10.96.0.10", + "created": "2018-05-30T16:24:36.000Z", + "name": "kube-dns", "type": "ClusterIP" }, "Index": "", @@ -60,20 +58,16 @@ "RootFields": null, "ModuleFields": { "labels": { - "addonmanager_kubernetes_io_mode": "Reconcile", - "app": "kubernetes-dashboard", - "kubernetes_io_minikube_addons": "dashboard", - "kubernetes_io_minikube_addons_endpoint": "dashboard" + "component": "apiserver", + "provider": "kubernetes" }, - "namespace": { - "name": "kube-system" - } + "namespace": "default" }, "MetricSetFields": { - "cluster_ip": "10.109.175.127", - "created": "2018-05-30T16:24:44.000Z", - "name": "kubernetes-dashboard", - "type": "NodePort" + "cluster_ip": "10.96.0.1", + "created": "2018-05-30T16:24:29.000Z", + "name": "kubernetes", + "type": "ClusterIP" }, "Index": "", "ID": "", @@ -92,9 +86,7 @@ "labels": { "k8s_app": "kube-state-metrics" }, - "namespace": { - "name": "kube-system" - } + "namespace": "kube-system" }, "MetricSetFields": { "cluster_ip": "10.108.182.194", diff --git a/metricbeat/module/kubernetes/state_service/_meta/test/ksm.v1.8.0.expected b/metricbeat/module/kubernetes/state_service/_meta/test/ksm.v1.8.0.expected index d56cabf40b5..9e7b4c7cd3b 100644 --- a/metricbeat/module/kubernetes/state_service/_meta/test/ksm.v1.8.0.expected +++ b/metricbeat/module/kubernetes/state_service/_meta/test/ksm.v1.8.0.expected @@ -5,9 +5,7 @@ "labels": { "k8s_app": "kube-state-metrics" }, - "namespace": { - "name": "kube-system" - } + "namespace": "kube-system" }, "MetricSetFields": { "cluster_ip": "10.101.63.187", @@ -34,9 +32,7 @@ "kubernetes_io_cluster_service": "true", "kubernetes_io_name": "KubeDNS" }, - "namespace": { - "name": "kube-system" - } + "namespace": "kube-system" }, "MetricSetFields": { "cluster_ip": "10.96.0.10", @@ -59,17 +55,14 @@ "RootFields": null, "ModuleFields": { "labels": { - "component": "apiserver", - "provider": "kubernetes" + "app": "nginx" }, - "namespace": { - "name": "default" - } + "namespace": "default" }, "MetricSetFields": { - "cluster_ip": "10.96.0.1", - "created": "2020-01-07T16:11:02.000Z", - "name": "kubernetes", + "cluster_ip": "None", + "created": "2020-01-08T18:15:25.000Z", + "name": "nginx", "type": "ClusterIP" }, "Index": "", @@ -87,16 +80,15 @@ "RootFields": null, "ModuleFields": { "labels": { - "app": "nginx" + "component": "apiserver", + "provider": "kubernetes" }, - "namespace": { - "name": "default" - } + "namespace": "default" }, "MetricSetFields": { - "cluster_ip": "None", - "created": "2020-01-08T18:15:25.000Z", - "name": "nginx", + "cluster_ip": "10.96.0.1", + "created": "2020-01-07T16:11:02.000Z", + "name": "kubernetes", "type": "ClusterIP" }, "Index": "", diff --git a/metricbeat/module/kubernetes/state_service/_meta/test/ksm.v2.0.0.expected b/metricbeat/module/kubernetes/state_service/_meta/test/ksm.v2.0.0.expected index 58c5637cf15..096ec78662d 100644 --- a/metricbeat/module/kubernetes/state_service/_meta/test/ksm.v2.0.0.expected +++ b/metricbeat/module/kubernetes/state_service/_meta/test/ksm.v2.0.0.expected @@ -2,14 +2,12 @@ { "RootFields": null, "ModuleFields": { - "namespace": { - "name": "kube-system" - } + "namespace": "kube-system" }, "MetricSetFields": { - "cluster_ip": "None", - "created": "2021-08-23T13:04:03.000Z", - "name": "kube-state-metrics", + "cluster_ip": "10.96.0.10", + "created": "2021-08-12T14:24:46.000Z", + "name": "kube-dns", "type": "ClusterIP" }, "Index": "", @@ -26,14 +24,12 @@ { "RootFields": null, "ModuleFields": { - "namespace": { - "name": "kube-system" - } + "namespace": "kube-system" }, "MetricSetFields": { - "cluster_ip": "10.96.0.10", - "created": "2021-08-12T14:24:46.000Z", - "name": "kube-dns", + "cluster_ip": "None", + "created": "2021-08-23T13:04:03.000Z", + "name": "kube-state-metrics", "type": "ClusterIP" }, "Index": "", @@ -50,9 +46,7 @@ { "RootFields": null, "ModuleFields": { - "namespace": { - "name": "default" - } + "namespace": "default" }, "MetricSetFields": { "cluster_ip": "10.96.0.1", diff --git a/metricbeat/module/kubernetes/state_service/state_service.go b/metricbeat/module/kubernetes/state_service/state_service.go index e46ab08623a..6794c36c44f 100644 --- a/metricbeat/module/kubernetes/state_service/state_service.go +++ b/metricbeat/module/kubernetes/state_service/state_service.go @@ -75,7 +75,7 @@ func NewServiceMetricSet(base mb.BaseMetricSet) (mb.MetricSet, error) { "kube_service_status_load_balancer_ingress": p.InfoMetric(), }, Labels: map[string]p.LabelMap{ - "namespace": p.KeyLabel(mb.ModuleDataKey + ".namespace.name"), + "namespace": p.KeyLabel(mb.ModuleDataKey + ".namespace"), "service": p.KeyLabel("name"), "cluster_ip": p.Label("cluster_ip"), "external_name": p.Label("external_name"), diff --git a/metricbeat/module/kubernetes/state_statefulset/_meta/data.json b/metricbeat/module/kubernetes/state_statefulset/_meta/data.json index 96a17077792..776b4a48d93 100644 --- a/metricbeat/module/kubernetes/state_statefulset/_meta/data.json +++ b/metricbeat/module/kubernetes/state_statefulset/_meta/data.json @@ -6,20 +6,18 @@ "module": "kubernetes" }, "kubernetes": { - "namespace": { - "name": "default" - }, + "namespace": "default", "statefulset": { - "created": 1511973651, + "created": 1511989697, "generation": { - "desired": 3, - "observed": 1 + "desired": 4, + "observed": 2 }, - "name": "elasticsearch", + "name": "mysql", "replicas": { - "desired": 4, - "observed": 1, - "ready": 1 + "desired": 5, + "observed": 2, + "ready": 2 } } }, diff --git a/metricbeat/module/kubernetes/state_statefulset/_meta/test/ksm.unit.v2.0.0.expected b/metricbeat/module/kubernetes/state_statefulset/_meta/test/ksm.unit.v2.0.0.expected index d2fe830a9f1..d55d49a0b85 100644 --- a/metricbeat/module/kubernetes/state_statefulset/_meta/test/ksm.unit.v2.0.0.expected +++ b/metricbeat/module/kubernetes/state_statefulset/_meta/test/ksm.unit.v2.0.0.expected @@ -2,9 +2,7 @@ { "RootFields": null, "ModuleFields": { - "namespace": { - "name": "default" - } + "namespace": "default" }, "MetricSetFields": { "created": 1629966737, diff --git a/metricbeat/module/kubernetes/state_statefulset/_meta/test/ksm.v1.8.0.expected b/metricbeat/module/kubernetes/state_statefulset/_meta/test/ksm.v1.8.0.expected index ae8659926a3..a5c1c584229 100644 --- a/metricbeat/module/kubernetes/state_statefulset/_meta/test/ksm.v1.8.0.expected +++ b/metricbeat/module/kubernetes/state_statefulset/_meta/test/ksm.v1.8.0.expected @@ -2,9 +2,7 @@ { "RootFields": null, "ModuleFields": { - "namespace": { - "name": "default" - } + "namespace": "default" }, "MetricSetFields": { "created": 1578507325, diff --git a/metricbeat/module/kubernetes/state_statefulset/_meta/testdata/docs.plain-expected.json b/metricbeat/module/kubernetes/state_statefulset/_meta/testdata/docs.plain-expected.json index ef3ba87ef22..8ab015da061 100644 --- a/metricbeat/module/kubernetes/state_statefulset/_meta/testdata/docs.plain-expected.json +++ b/metricbeat/module/kubernetes/state_statefulset/_meta/testdata/docs.plain-expected.json @@ -6,20 +6,18 @@ "module": "kubernetes" }, "kubernetes": { - "namespace": { - "name": "default" - }, + "namespace": "default", "statefulset": { - "created": 1511973651, + "created": 1511989697, "generation": { - "desired": 3, - "observed": 1 + "desired": 4, + "observed": 2 }, - "name": "elasticsearch", + "name": "mysql", "replicas": { - "desired": 4, - "observed": 1, - "ready": 1 + "desired": 5, + "observed": 2, + "ready": 2 } } }, @@ -39,9 +37,7 @@ "module": "kubernetes" }, "kubernetes": { - "namespace": { - "name": "custom" - }, + "namespace": "custom", "statefulset": { "created": 1511999697, "generation": { @@ -72,20 +68,18 @@ "module": "kubernetes" }, "kubernetes": { - "namespace": { - "name": "default" - }, + "namespace": "default", "statefulset": { - "created": 1511989697, + "created": 1511973651, "generation": { - "desired": 4, - "observed": 2 + "desired": 3, + "observed": 1 }, - "name": "mysql", + "name": "elasticsearch", "replicas": { - "desired": 5, - "observed": 2, - "ready": 2 + "desired": 4, + "observed": 1, + "ready": 1 } } }, diff --git a/metricbeat/module/kubernetes/state_statefulset/state_statefulset.go b/metricbeat/module/kubernetes/state_statefulset/state_statefulset.go index 59de9bfeff1..c2c02195206 100644 --- a/metricbeat/module/kubernetes/state_statefulset/state_statefulset.go +++ b/metricbeat/module/kubernetes/state_statefulset/state_statefulset.go @@ -51,7 +51,7 @@ var ( Labels: map[string]p.LabelMap{ "statefulset": p.KeyLabel("name"), - "namespace": p.KeyLabel(mb.ModuleDataKey + ".namespace.name"), + "namespace": p.KeyLabel(mb.ModuleDataKey + ".namespace"), }, } ) diff --git a/metricbeat/module/kubernetes/test/integration.go b/metricbeat/module/kubernetes/test/integration.go index 6966e82406c..ba7a7c0256b 100644 --- a/metricbeat/module/kubernetes/test/integration.go +++ b/metricbeat/module/kubernetes/test/integration.go @@ -49,6 +49,18 @@ func GetKubeStateMetricsConfig(t *testing.T, metricSetName string) map[string]in } } +// GetKubeStateMetricsConfigWithMetaDisabled function returns configuration for talking to kube-state-metrics. +func GetKubeStateMetricsConfigWithMetaDisabled(t *testing.T, metricSetName string) map[string]interface{} { + t.Helper() + return map[string]interface{}{ + "module": "kubernetes", + "metricsets": []string{metricSetName}, + "host": "${NODE_NAME}", + "hosts": []string{"kube-state-metrics:8080"}, + "add_metadata": false, + } +} + // GetKubeletConfig function returns configuration for talking to Kubelet API. func GetKubeletConfig(t *testing.T, metricSetName string) map[string]interface{} { t.Helper() @@ -79,10 +91,12 @@ func GetKubeProxyConfig(t *testing.T, metricSetName string) map[string]interface func GetSchedulerConfig(t *testing.T, metricSetName string) map[string]interface{} { t.Helper() return map[string]interface{}{ - "module": "kubernetes", - "metricsets": []string{metricSetName}, - "host": "${NODE_NAME}", - "hosts": []string{"localhost:10251"}, + "module": "kubernetes", + "metricsets": []string{metricSetName}, + "host": "${NODE_NAME}", + "hosts": []string{"https://0.0.0.0:10259"}, + "bearer_token_file": "/var/run/secrets/kubernetes.io/serviceaccount/token", + "ssl.verification_mode": "none", } } @@ -90,9 +104,11 @@ func GetSchedulerConfig(t *testing.T, metricSetName string) map[string]interface func GetControllerManagerConfig(t *testing.T, metricSetName string) map[string]interface{} { t.Helper() return map[string]interface{}{ - "module": "kubernetes", - "metricsets": []string{metricSetName}, - "host": "${NODE_NAME}", - "hosts": []string{"localhost:10252"}, + "module": "kubernetes", + "metricsets": []string{metricSetName}, + "host": "${NODE_NAME}", + "hosts": []string{"https://0.0.0.0:10257"}, + "bearer_token_file": "/var/run/secrets/kubernetes.io/serviceaccount/token", + "ssl.verification_mode": "none", } } diff --git a/metricbeat/module/kubernetes/util/kubernetes.go b/metricbeat/module/kubernetes/util/kubernetes.go index 41e0a2bac16..6518a258e26 100644 --- a/metricbeat/module/kubernetes/util/kubernetes.go +++ b/metricbeat/module/kubernetes/util/kubernetes.go @@ -48,105 +48,63 @@ type Enricher interface { } type kubernetesConfig struct { - // AddMetadata enables enriching metricset events with metadata from the API server - AddMetadata bool `config:"add_metadata"` KubeConfig string `config:"kube_config"` - Host string `config:"host"` - SyncPeriod time.Duration `config:"sync_period"` KubeClientOptions kubernetes.KubeClientOptions `config:"kube_client_options"` + + Host string `config:"host"` + SyncPeriod time.Duration `config:"sync_period"` + + // AddMetadata enables enriching metricset events with metadata from the API server + AddMetadata bool `config:"add_metadata"` + AddResourceMetadata *metadata.AddResourceMetadataConfig `config:"add_resource_metadata"` } type enricher struct { sync.RWMutex - metadata map[string]common.MapStr - index func(common.MapStr) string - watcher kubernetes.Watcher - watcherStarted bool - watcherStartedLock sync.Mutex - isPod bool + metadata map[string]common.MapStr + index func(common.MapStr) string + watcher kubernetes.Watcher + watchersStarted bool + watchersStartedLock sync.Mutex + namespaceWatcher kubernetes.Watcher + nodeWatcher kubernetes.Watcher + isPod bool } const selector = "kubernetes" -// GetWatcher initializes a kubernetes watcher with the given -// scope (node or cluster), and resource type -func GetWatcher(base mb.BaseMetricSet, resource kubernetes.Resource, nodeScope bool) (kubernetes.Watcher, error) { - return GetNamedWatcher("", base, resource, nodeScope) -} - -func GetNamedWatcher(name string, base mb.BaseMetricSet, resource kubernetes.Resource, nodeScope bool) (kubernetes.Watcher, error) { - config := kubernetesConfig{ - AddMetadata: true, - SyncPeriod: time.Minute * 10, - } - if err := base.Module().UnpackConfig(&config); err != nil { - return nil, err - } - - // Return nil if metadata enriching is disabled: - if !config.AddMetadata { - return nil, nil - } - - client, err := kubernetes.GetKubernetesClient(config.KubeConfig, config.KubeClientOptions) - if err != nil { - return nil, err - } - - options := kubernetes.WatchOptions{ - SyncTimeout: config.SyncPeriod, - } - - log := logp.NewLogger(selector) - - // Watch objects in the node only - if nodeScope { - nd := &kubernetes.DiscoverKubernetesNodeParams{ - ConfigHost: config.Host, - Client: client, - IsInCluster: kubernetes.IsInCluster(config.KubeConfig), - HostUtils: &kubernetes.DefaultDiscoveryUtils{}, - } - options.Node, err = kubernetes.DiscoverKubernetesNode(log, nd) - if err != nil { - return nil, fmt.Errorf("couldn't discover kubernetes node: %w", err) - } - } - - log.Debugf("Initializing a new Kubernetes watcher using host: %v", config.Host) - - return kubernetes.NewNamedWatcher(name, client, resource, options, nil) -} - // NewResourceMetadataEnricher returns an Enricher configured for kubernetes resource events func NewResourceMetadataEnricher( base mb.BaseMetricSet, res kubernetes.Resource, nodeScope bool) Enricher { - watcher, err := GetNamedWatcher("resource_metadata_enricher", base, res, nodeScope) - if err != nil { - logp.Err("Error initializing Kubernetes metadata enricher: %s", err) + config := validatedConfig(base) + if config == nil { + logp.Info("Kubernetes metricset enriching is disabled") return &nilEnricher{} } + watcher, nodeWatcher, namespaceWatcher := getResourceMetadataWatchers(config, res, nodeScope) + if watcher == nil { - logp.Info("Kubernetes metricset enriching is disabled") return &nilEnricher{} } - metaConfig := metadata.Config{} - if err := base.Module().UnpackConfig(&metaConfig); err != nil { + // GetPodMetaGen requires cfg of type Config + commonMetaConfig := metadata.Config{} + if err := base.Module().UnpackConfig(&commonMetaConfig); err != nil { logp.Err("Error initializing Kubernetes metadata enricher: %s", err) return &nilEnricher{} } - - cfg, _ := common.NewConfigFrom(&metaConfig) + cfg, _ := common.NewConfigFrom(&commonMetaConfig) metaGen := metadata.NewResourceMetadataGenerator(cfg, watcher.Client()) - podMetaGen := metadata.NewPodMetadataGenerator(cfg, nil, watcher.Client(), nil, nil, true) - serviceMetaGen := metadata.NewServiceMetadataGenerator(cfg, nil, nil, watcher.Client()) - enricher := buildMetadataEnricher(watcher, + podMetaGen := metadata.GetPodMetaGen(cfg, watcher, nodeWatcher, namespaceWatcher, config.AddResourceMetadata) + + namespaceMeta := metadata.NewNamespaceMetadataGenerator(config.AddResourceMetadata.Namespace, namespaceWatcher.Store(), watcher.Client()) + serviceMetaGen := metadata.NewServiceMetadataGenerator(cfg, watcher.Store(), namespaceMeta, watcher.Client()) + enricher := buildMetadataEnricher(watcher, nodeWatcher, namespaceWatcher, // update func(m map[string]common.MapStr, r kubernetes.Resource) { accessor, _ := meta.Accessor(r) @@ -176,6 +134,8 @@ func NewResourceMetadataEnricher( m[id] = metaGen.Generate("deployment", r) case *kubernetes.Job: m[id] = metaGen.Generate("job", r) + case *kubernetes.CronJob: + m[id] = metaGen.Generate("cronjob", r) case *kubernetes.Service: m[id] = serviceMetaGen.Generate(r) case *kubernetes.StatefulSet: @@ -196,7 +156,7 @@ func NewResourceMetadataEnricher( }, // index func(e common.MapStr) string { - return join(getString(e, mb.ModuleDataKey+".namespace.name"), getString(e, "name")) + return join(getString(e, mb.ModuleDataKey+".namespace"), getString(e, "name")) }, ) @@ -214,32 +174,40 @@ func NewContainerMetadataEnricher( base mb.BaseMetricSet, nodeScope bool) Enricher { - watcher, err := GetNamedWatcher("container_metadata_enricher", base, &kubernetes.Pod{}, nodeScope) - if err != nil { - logp.Err("Error initializing Kubernetes metadata enricher: %s", err) + config := validatedConfig(base) + if config == nil { + logp.Info("Kubernetes metricset enriching is disabled") return &nilEnricher{} } + watcher, nodeWatcher, namespaceWatcher := getResourceMetadataWatchers(config, &kubernetes.Pod{}, nodeScope) if watcher == nil { - logp.Info("Kubernetes metricset enriching is disabled") return &nilEnricher{} } - metaConfig := metadata.Config{} - if err := base.Module().UnpackConfig(&metaConfig); err != nil { + commonMetaConfig := metadata.Config{} + if err := base.Module().UnpackConfig(&commonMetaConfig); err != nil { logp.Err("Error initializing Kubernetes metadata enricher: %s", err) return &nilEnricher{} } + cfg, _ := common.NewConfigFrom(&commonMetaConfig) - cfg, _ := common.NewConfigFrom(&metaConfig) + metaGen := metadata.GetPodMetaGen(cfg, watcher, nodeWatcher, namespaceWatcher, config.AddResourceMetadata) - metaGen := metadata.NewPodMetadataGenerator(cfg, nil, watcher.Client(), nil, nil, true) - enricher := buildMetadataEnricher(watcher, + enricher := buildMetadataEnricher(watcher, nodeWatcher, namespaceWatcher, // update func(m map[string]common.MapStr, r kubernetes.Resource) { pod := r.(*kubernetes.Pod) meta := metaGen.Generate(pod) + statuses := make(map[string]*kubernetes.PodContainerStatus) + mapStatuses := func(s []kubernetes.PodContainerStatus) { + for i := range s { + statuses[s[i].Name] = &s[i] + } + } + mapStatuses(pod.Status.ContainerStatuses) + mapStatuses(pod.Status.InitContainerStatuses) for _, container := range append(pod.Spec.Containers, pod.Spec.InitContainers...) { cuid := ContainerUID(pod.GetObjectMeta().GetNamespace(), pod.GetObjectMeta().GetName(), container.Name) @@ -255,6 +223,15 @@ func NewContainerMetadataEnricher( } } + if s, ok := statuses[container.Name]; ok { + // Extracting id and runtime ECS fields from ContainerID + // which is in the form of :// + split := strings.Index(s.ContainerID, "://") + if split != -1 { + meta.Put("container.id", s.ContainerID[split+3:]) + meta.Put("container.runtime", s.ContainerID[:split]) + } + } id := join(pod.GetObjectMeta().GetNamespace(), pod.GetObjectMeta().GetName(), container.Name) m[id] = meta } @@ -276,6 +253,82 @@ func NewContainerMetadataEnricher( return enricher } +func getResourceMetadataWatchers(config *kubernetesConfig, resource kubernetes.Resource, nodeScope bool) (kubernetes.Watcher, kubernetes.Watcher, kubernetes.Watcher) { + client, err := kubernetes.GetKubernetesClient(config.KubeConfig, config.KubeClientOptions) + if err != nil { + logp.Err("Error creating Kubernetes client: %s", err) + return nil, nil, nil + } + + options := kubernetes.WatchOptions{ + SyncTimeout: config.SyncPeriod, + } + + log := logp.NewLogger(selector) + + // Watch objects in the node only + if nodeScope { + nd := &kubernetes.DiscoverKubernetesNodeParams{ + ConfigHost: config.Host, + Client: client, + IsInCluster: kubernetes.IsInCluster(config.KubeConfig), + HostUtils: &kubernetes.DefaultDiscoveryUtils{}, + } + options.Node, err = kubernetes.DiscoverKubernetesNode(log, nd) + if err != nil { + logp.Err("Couldn't discover kubernetes node: %s", err) + return nil, nil, nil + } + } + + log.Debugf("Initializing a new Kubernetes watcher using host: %v", config.Host) + + watcher, err := kubernetes.NewNamedWatcher("resource_metadata_enricher", client, resource, options, nil) + if err != nil { + logp.Err("Error initializing Kubernetes watcher: %s", err) + return nil, nil, nil + } + + nodeWatcher, err := kubernetes.NewNamedWatcher("resource_metadata_enricher_node", client, &kubernetes.Node{}, options, nil) + if err != nil { + logp.Err("Error creating watcher for %T due to error %+v", &kubernetes.Node{}, err) + return watcher, nil, nil + } + + namespaceWatcher, err := kubernetes.NewNamedWatcher("resource_metadata_enricher_namespace", client, &kubernetes.Namespace{}, kubernetes.WatchOptions{ + SyncTimeout: config.SyncPeriod, + }, nil) + if err != nil { + logp.Err("Error creating watcher for %T due to error %+v", &kubernetes.Namespace{}, err) + return watcher, nodeWatcher, nil + } + + return watcher, nodeWatcher, namespaceWatcher +} + +func GetDefaultDisabledMetaConfig() *kubernetesConfig { + return &kubernetesConfig{ + AddMetadata: false, + } +} + +func validatedConfig(base mb.BaseMetricSet) *kubernetesConfig { + config := kubernetesConfig{ + AddMetadata: true, + SyncPeriod: time.Minute * 10, + AddResourceMetadata: metadata.GetDefaultResourceMetadataConfig(), + } + if err := base.Module().UnpackConfig(&config); err != nil { + return nil + } + + // Return nil if metadata enriching is disabled: + if !config.AddMetadata { + return nil + } + return &config +} + func getString(m common.MapStr, key string) string { val, err := m.GetValue(key) if err != nil { @@ -292,14 +345,18 @@ func join(fields ...string) string { func buildMetadataEnricher( watcher kubernetes.Watcher, + nodeWatcher kubernetes.Watcher, + namespaceWatcher kubernetes.Watcher, update func(map[string]common.MapStr, kubernetes.Resource), delete func(map[string]common.MapStr, kubernetes.Resource), index func(e common.MapStr) string) *enricher { enricher := enricher{ - metadata: map[string]common.MapStr{}, - index: index, - watcher: watcher, + metadata: map[string]common.MapStr{}, + index: index, + watcher: watcher, + nodeWatcher: nodeWatcher, + namespaceWatcher: namespaceWatcher, } watcher.AddEventHandler(kubernetes.ResourceEventHandlerFuncs{ @@ -324,23 +381,44 @@ func buildMetadataEnricher( } func (m *enricher) Start() { - m.watcherStartedLock.Lock() - defer m.watcherStartedLock.Unlock() - if !m.watcherStarted { + m.watchersStartedLock.Lock() + defer m.watchersStartedLock.Unlock() + if !m.watchersStarted { + if m.nodeWatcher != nil { + if err := m.nodeWatcher.Start(); err != nil { + logp.Warn("Error starting node watcher: %s", err) + } + } + + if m.namespaceWatcher != nil { + if err := m.namespaceWatcher.Start(); err != nil { + logp.Warn("Error starting namespace watcher: %s", err) + } + } + err := m.watcher.Start() if err != nil { logp.Warn("Error starting Kubernetes watcher: %s", err) } - m.watcherStarted = true + m.watchersStarted = true } } func (m *enricher) Stop() { - m.watcherStartedLock.Lock() - defer m.watcherStartedLock.Unlock() - if m.watcherStarted { + m.watchersStartedLock.Lock() + defer m.watchersStartedLock.Unlock() + if m.watchersStarted { m.watcher.Stop() - m.watcherStarted = false + + if m.namespaceWatcher != nil { + m.namespaceWatcher.Stop() + } + + if m.nodeWatcher != nil { + m.nodeWatcher.Stop() + } + + m.watchersStarted = false } } diff --git a/metricbeat/module/kubernetes/util/kubernetes_test.go b/metricbeat/module/kubernetes/util/kubernetes_test.go index 4ab9acc9d5d..83bbd3dd1f7 100644 --- a/metricbeat/module/kubernetes/util/kubernetes_test.go +++ b/metricbeat/module/kubernetes/util/kubernetes_test.go @@ -36,6 +36,8 @@ import ( func TestBuildMetadataEnricher(t *testing.T) { watcher := mockWatcher{} + nodeWatcher := mockWatcher{} + namespaceWatcher := mockWatcher{} funcs := mockFuncs{} resource := &v1.Pod{ ObjectMeta: metav1.ObjectMeta{ @@ -48,7 +50,7 @@ func TestBuildMetadataEnricher(t *testing.T) { }, } - enricher := buildMetadataEnricher(&watcher, funcs.update, funcs.delete, funcs.index) + enricher := buildMetadataEnricher(&watcher, &nodeWatcher, &namespaceWatcher, funcs.update, funcs.delete, funcs.index) assert.NotNil(t, watcher.handler) enricher.Start() diff --git a/metricbeat/module/kubernetes/volume/data.go b/metricbeat/module/kubernetes/volume/data.go index 03508a37155..6170bbadbcc 100644 --- a/metricbeat/module/kubernetes/volume/data.go +++ b/metricbeat/module/kubernetes/volume/data.go @@ -40,9 +40,7 @@ func eventMapping(content []byte) ([]common.MapStr, error) { for _, volume := range pod.Volume { volumeEvent := common.MapStr{ mb.ModuleDataKey: common.MapStr{ - "namespace": common.MapStr{ - "name": pod.PodRef.Namespace, - }, + "namespace": pod.PodRef.Namespace, "node": common.MapStr{ "name": node.NodeName, }, diff --git a/metricbeat/module/linux/conntrack/conntrack.go b/metricbeat/module/linux/conntrack/conntrack.go index c8d9122de09..4d896a20928 100644 --- a/metricbeat/module/linux/conntrack/conntrack.go +++ b/metricbeat/module/linux/conntrack/conntrack.go @@ -18,15 +18,13 @@ package conntrack import ( - "path/filepath" - "github.com/pkg/errors" "github.com/prometheus/procfs" "github.com/elastic/beats/v7/libbeat/common" "github.com/elastic/beats/v7/libbeat/common/cfgwarn" + "github.com/elastic/beats/v7/libbeat/metric/system/resolve" "github.com/elastic/beats/v7/metricbeat/mb" - "github.com/elastic/beats/v7/metricbeat/module/linux" ) // init registers the MetricSet with the central registry as soon as the program @@ -43,7 +41,7 @@ func init() { // interface methods except for Fetch. type MetricSet struct { mb.BaseMetricSet - fs procfs.FS + mod resolve.Resolver } // New creates a new instance of the MetricSet. New is responsible for unpacking @@ -51,18 +49,11 @@ type MetricSet struct { func New(base mb.BaseMetricSet) (mb.MetricSet, error) { cfgwarn.Beta("The linux conntrack metricset is beta.") - sys := base.Module().(linux.LinuxModule) - hostfs := sys.GetHostFS() - - path := filepath.Join(hostfs, "proc") - newFS, err := procfs.NewFS(path) - if err != nil { - return nil, errors.Wrapf(err, "error creating new Host FS at %s", path) - } + sys := base.Module().(resolve.Resolver) return &MetricSet{ BaseMetricSet: base, - fs: newFS, + mod: sys, }, nil } @@ -70,7 +61,11 @@ func New(base mb.BaseMetricSet) (mb.MetricSet, error) { // format. It publishes the event which is then forwarded to the output. In case // of an error set the Error field of mb.Event or simply call report.Error(). func (m *MetricSet) Fetch(report mb.ReporterV2) error { - conntrackStats, err := m.fs.ConntrackStat() + newFS, err := procfs.NewFS(m.mod.ResolveHostFS("/proc")) + if err != nil { + return errors.Wrapf(err, "error creating new Host FS at %s", m.mod.ResolveHostFS("/proc")) + } + conntrackStats, err := newFS.ConntrackStat() if err != nil { return errors.Wrap(err, "error fetching conntrack stats") } diff --git a/metricbeat/module/linux/conntrack/conntrack_test.go b/metricbeat/module/linux/conntrack/conntrack_test.go index 32232249597..e09d9439cc1 100644 --- a/metricbeat/module/linux/conntrack/conntrack_test.go +++ b/metricbeat/module/linux/conntrack/conntrack_test.go @@ -24,6 +24,7 @@ import ( "github.com/elastic/beats/v7/libbeat/common" mbtest "github.com/elastic/beats/v7/metricbeat/mb/testing" + _ "github.com/elastic/beats/v7/metricbeat/module/linux" ) func TestData(t *testing.T) { diff --git a/metricbeat/module/linux/iostat/iostat.go b/metricbeat/module/linux/iostat/iostat.go index 9f40b260cbe..389424ff2fe 100644 --- a/metricbeat/module/linux/iostat/iostat.go +++ b/metricbeat/module/linux/iostat/iostat.go @@ -70,7 +70,6 @@ func New(base mb.BaseMetricSet) (mb.MetricSet, error) { // format. It publishes the event which is then forwarded to the output. In case // of an error set the Error field of mb.Event or simply call report.Error(). func (m *MetricSet) Fetch(report mb.ReporterV2) error { - IOstats, err := diskio.IOCounters(m.includeDevices...) if err != nil { return errors.Wrap(err, "disk io counters") diff --git a/metricbeat/module/linux/iostat/iostat_test.go b/metricbeat/module/linux/iostat/iostat_test.go index be955e5fec4..7cdbb9f8326 100644 --- a/metricbeat/module/linux/iostat/iostat_test.go +++ b/metricbeat/module/linux/iostat/iostat_test.go @@ -26,6 +26,7 @@ import ( "github.com/stretchr/testify/assert" mbtest "github.com/elastic/beats/v7/metricbeat/mb/testing" + _ "github.com/elastic/beats/v7/metricbeat/module/linux" ) func TestFetch(t *testing.T) { diff --git a/metricbeat/module/linux/ksm/ksm.go b/metricbeat/module/linux/ksm/ksm.go index 67ec072f6bf..204b9364f54 100644 --- a/metricbeat/module/linux/ksm/ksm.go +++ b/metricbeat/module/linux/ksm/ksm.go @@ -18,15 +18,13 @@ package ksm import ( - "path/filepath" - "github.com/elastic/beats/v7/libbeat/common" "github.com/pkg/errors" "github.com/elastic/beats/v7/libbeat/common/cfgwarn" + "github.com/elastic/beats/v7/libbeat/metric/system/resolve" "github.com/elastic/beats/v7/metricbeat/mb" - "github.com/elastic/beats/v7/metricbeat/module/linux" ) // init registers the MetricSet with the central registry as soon as the program @@ -43,7 +41,7 @@ func init() { // interface methods except for Fetch. type MetricSet struct { mb.BaseMetricSet - fs string + mod resolve.Resolver } // New creates a new instance of the MetricSet. New is responsible for unpacking @@ -51,12 +49,11 @@ type MetricSet struct { func New(base mb.BaseMetricSet) (mb.MetricSet, error) { cfgwarn.Beta("The linux pageinfo metricset is beta.") - sys := base.Module().(linux.LinuxModule) - hostfs := sys.GetHostFS() + sys := base.Module().(resolve.Resolver) return &MetricSet{ BaseMetricSet: base, - fs: filepath.Join(hostfs, "/sys/kernel/mm/ksm"), + mod: sys, }, nil } @@ -64,7 +61,7 @@ func New(base mb.BaseMetricSet) (mb.MetricSet, error) { // format. It publishes the event which is then forwarded to the output. In case // of an error set the Error field of mb.Event or simply call report.Error(). func (m *MetricSet) Fetch(report mb.ReporterV2) error { - ksmData, err := fetchKSMStats(m.fs) + ksmData, err := fetchKSMStats(m.mod.ResolveHostFS("/sys/kernel/mm/ksm")) if err != nil { return errors.Wrap(err, "error fetching KSM stats") } diff --git a/metricbeat/module/linux/ksm/ksm_test.go b/metricbeat/module/linux/ksm/ksm_test.go index f6e4ee50eca..f4ee324d3d8 100644 --- a/metricbeat/module/linux/ksm/ksm_test.go +++ b/metricbeat/module/linux/ksm/ksm_test.go @@ -24,6 +24,7 @@ import ( "github.com/elastic/beats/v7/libbeat/common" mbtest "github.com/elastic/beats/v7/metricbeat/mb/testing" + _ "github.com/elastic/beats/v7/metricbeat/module/linux" ) func TestData(t *testing.T) { diff --git a/metricbeat/module/linux/linux.go b/metricbeat/module/linux/linux.go index 25a29f15d01..a86b41f3c8f 100644 --- a/metricbeat/module/linux/linux.go +++ b/metricbeat/module/linux/linux.go @@ -18,56 +18,13 @@ package linux import ( - "time" - - "github.com/elastic/beats/v7/libbeat/paths" + "github.com/elastic/beats/v7/metricbeat/internal/sysinit" "github.com/elastic/beats/v7/metricbeat/mb" ) func init() { // Register the ModuleFactory function for the "system" module. - if err := mb.Registry.AddModule("linux", NewModule); err != nil { + if err := mb.Registry.AddModule("linux", sysinit.InitSystemModule); err != nil { panic(err) } } - -type LinuxModule interface { - GetHostFS() string -} - -// Module defines the base module config used in `linux` -type Module struct { - mb.BaseModule - HostFS string `config:"hostfs"` - Period time.Duration -} - -// NewModule initializes a new module -func NewModule(base mb.BaseModule) (mb.Module, error) { - // This only needs to be configured once for all system modules. - - config := struct { - Hostfs string `config:"hostfs"` - Period time.Duration `config:"period"` - }{} - - if err := base.UnpackConfig(&config); err != nil { - return nil, err - } - - dir := config.Hostfs - if dir == "" { - dir = "/" - } - - // Steer towards system.hostfs, since the two behave fundamentally the same, and system.hostfs has a CLI flag that many users may default to. - if len(paths.Paths.Hostfs) > 2 { - dir = paths.Paths.Hostfs - } - - return &Module{BaseModule: base, HostFS: dir, Period: config.Period}, nil -} - -func (m Module) GetHostFS() string { - return m.HostFS -} diff --git a/metricbeat/module/linux/memory/data.go b/metricbeat/module/linux/memory/data.go index ddf2cfc0797..1f3740a7093 100644 --- a/metricbeat/module/linux/memory/data.go +++ b/metricbeat/module/linux/memory/data.go @@ -21,13 +21,14 @@ import ( "github.com/pkg/errors" "github.com/elastic/beats/v7/libbeat/common" + "github.com/elastic/beats/v7/libbeat/metric/system/resolve" "github.com/elastic/beats/v7/metricbeat/internal/metrics/memory" sysinfo "github.com/elastic/go-sysinfo" sysinfotypes "github.com/elastic/go-sysinfo/types" ) // FetchLinuxMemStats gets page_stat and huge pages data for linux -func FetchLinuxMemStats(baseMap common.MapStr) error { +func FetchLinuxMemStats(baseMap common.MapStr, hostfs resolve.Resolver) error { vmstat, err := GetVMStat() if err != nil { @@ -66,7 +67,7 @@ func FetchLinuxMemStats(baseMap common.MapStr) error { } baseMap["page_stats"] = pageStats - thp, err := getHugePages() + thp, err := getHugePages(hostfs) if err != nil { return errors.Wrap(err, "error getting huge pages") } @@ -82,9 +83,9 @@ func FetchLinuxMemStats(baseMap common.MapStr) error { return nil } -func getHugePages() (common.MapStr, error) { +func getHugePages(hostfs resolve.Resolver) (common.MapStr, error) { // see https://www.kernel.org/doc/Documentation/vm/hugetlbpage.txt - table, err := memory.ParseMeminfo("") + table, err := memory.ParseMeminfo(hostfs) if err != nil { return nil, errors.Wrap(err, "error parsing meminfo") } diff --git a/metricbeat/module/linux/memory/memory.go b/metricbeat/module/linux/memory/memory.go index 35cd407b9b3..bd71cadc690 100644 --- a/metricbeat/module/linux/memory/memory.go +++ b/metricbeat/module/linux/memory/memory.go @@ -22,6 +22,7 @@ import ( "github.com/elastic/beats/v7/libbeat/common" "github.com/elastic/beats/v7/libbeat/common/cfgwarn" + "github.com/elastic/beats/v7/libbeat/metric/system/resolve" "github.com/elastic/beats/v7/metricbeat/mb" ) @@ -39,15 +40,17 @@ func init() { // interface methods except for Fetch. type MetricSet struct { mb.BaseMetricSet + mod resolve.Resolver } // New creates a new instance of the MetricSet. New is responsible for unpacking // any MetricSet specific configuration options if there are any. func New(base mb.BaseMetricSet) (mb.MetricSet, error) { cfgwarn.Beta("The linux memory metricset is beta.") - + sys := base.Module().(resolve.Resolver) return &MetricSet{ BaseMetricSet: base, + mod: sys, }, nil } @@ -56,7 +59,7 @@ func New(base mb.BaseMetricSet) (mb.MetricSet, error) { // of an error set the Error field of mb.Event or simply call report.Error(). func (m *MetricSet) Fetch(report mb.ReporterV2) error { rootEvent := common.MapStr{} - err := FetchLinuxMemStats(rootEvent) + err := FetchLinuxMemStats(rootEvent, m.mod) if err != nil { return errors.Wrap(err, "error fetching memory stats") } diff --git a/metricbeat/module/linux/memory/memory_linux_test.go b/metricbeat/module/linux/memory/memory_linux_test.go index bddecc8f8a7..da9ce77ca93 100644 --- a/metricbeat/module/linux/memory/memory_linux_test.go +++ b/metricbeat/module/linux/memory/memory_linux_test.go @@ -23,6 +23,7 @@ import ( "github.com/stretchr/testify/assert" mbtest "github.com/elastic/beats/v7/metricbeat/mb/testing" + _ "github.com/elastic/beats/v7/metricbeat/module/linux" ) func TestFetch(t *testing.T) { diff --git a/metricbeat/module/linux/pageinfo/pageinfo.go b/metricbeat/module/linux/pageinfo/pageinfo.go index e4d700be7db..2ffad602d99 100644 --- a/metricbeat/module/linux/pageinfo/pageinfo.go +++ b/metricbeat/module/linux/pageinfo/pageinfo.go @@ -20,14 +20,13 @@ package pageinfo import ( "bufio" "os" - "path/filepath" "github.com/pkg/errors" "github.com/elastic/beats/v7/libbeat/common" "github.com/elastic/beats/v7/libbeat/common/cfgwarn" + "github.com/elastic/beats/v7/libbeat/metric/system/resolve" "github.com/elastic/beats/v7/metricbeat/mb" - "github.com/elastic/beats/v7/metricbeat/module/linux" ) // init registers the MetricSet with the central registry as soon as the program @@ -44,7 +43,7 @@ func init() { // interface methods except for Fetch. type MetricSet struct { mb.BaseMetricSet - fs string + mod resolve.Resolver } // New creates a new instance of the MetricSet. New is responsible for unpacking @@ -52,12 +51,11 @@ type MetricSet struct { func New(base mb.BaseMetricSet) (mb.MetricSet, error) { cfgwarn.Beta("The linux pageinfo metricset is beta.") - sys := base.Module().(linux.LinuxModule) - hostfs := sys.GetHostFS() + sys := base.Module().(resolve.Resolver) return &MetricSet{ BaseMetricSet: base, - fs: hostfs, + mod: sys, }, nil } @@ -65,7 +63,7 @@ func New(base mb.BaseMetricSet) (mb.MetricSet, error) { // format. It publishes the event which is then forwarded to the output. In case // of an error set the Error field of mb.Event or simply call report.Error(). func (m *MetricSet) Fetch(report mb.ReporterV2) error { - pagePath := filepath.Join(m.fs, "/proc/pagetypeinfo") + pagePath := m.mod.ResolveHostFS("/proc/pagetypeinfo") fd, err := os.Open(pagePath) if err != nil { diff --git a/metricbeat/module/linux/pageinfo/pageinfo_test.go b/metricbeat/module/linux/pageinfo/pageinfo_test.go index e16c38fc601..272e79cb0a7 100644 --- a/metricbeat/module/linux/pageinfo/pageinfo_test.go +++ b/metricbeat/module/linux/pageinfo/pageinfo_test.go @@ -24,6 +24,7 @@ import ( "github.com/elastic/beats/v7/libbeat/common" mbtest "github.com/elastic/beats/v7/metricbeat/mb/testing" + _ "github.com/elastic/beats/v7/metricbeat/module/linux" ) func TestData(t *testing.T) { diff --git a/metricbeat/module/linux/pressure/pressure.go b/metricbeat/module/linux/pressure/pressure.go index 9a0e90c1839..f352cc04843 100644 --- a/metricbeat/module/linux/pressure/pressure.go +++ b/metricbeat/module/linux/pressure/pressure.go @@ -19,7 +19,6 @@ package pressure import ( "fmt" - "path/filepath" "runtime" "github.com/pkg/errors" @@ -27,8 +26,8 @@ import ( "github.com/elastic/beats/v7/libbeat/common" "github.com/elastic/beats/v7/libbeat/common/cfgwarn" + "github.com/elastic/beats/v7/libbeat/metric/system/resolve" "github.com/elastic/beats/v7/metricbeat/mb" - "github.com/elastic/beats/v7/metricbeat/module/linux" ) const ( @@ -50,8 +49,7 @@ func init() { // interface methods except for Fetch. type MetricSet struct { mb.BaseMetricSet - fs string - procfs procfs.FS + mod resolve.Resolver } // New creates a new instance of the MetricSet. New is responsible for unpacking @@ -63,19 +61,11 @@ func New(base mb.BaseMetricSet) (mb.MetricSet, error) { return nil, fmt.Errorf("the %v/%v metricset is only supported on Linux", moduleName, metricsetName) } - sys := base.Module().(linux.LinuxModule) - hostfs := sys.GetHostFS() - - path := filepath.Join(hostfs, "proc") - procfs, err := procfs.NewFS(path) - if err != nil { - return nil, errors.Wrapf(err, "error creating new Host FS at %s", path) - } + sys := base.Module().(resolve.Resolver) return &MetricSet{ BaseMetricSet: base, - fs: hostfs, - procfs: procfs, + mod: sys, }, nil } @@ -100,8 +90,13 @@ func fetchLinuxPSIStats(m *MetricSet) ([]common.MapStr, error) { resources := []string{"cpu", "memory", "io"} events := []common.MapStr{} + procfs, err := procfs.NewFS(m.mod.ResolveHostFS("/proc")) + if err != nil { + return nil, errors.Wrapf(err, "error creating new Host FS at %s", m.mod.ResolveHostFS("/proc")) + } + for _, resource := range resources { - psiMetric, err := m.procfs.PSIStatsForResource(resource) + psiMetric, err := procfs.PSIStatsForResource(resource) if err != nil { return nil, errors.Wrap(err, "check that /proc/pressure is available, and/or enabled") } diff --git a/metricbeat/module/linux/pressure/pressure_test.go b/metricbeat/module/linux/pressure/pressure_test.go index 098b9fcbe76..d6b737dc1ef 100644 --- a/metricbeat/module/linux/pressure/pressure_test.go +++ b/metricbeat/module/linux/pressure/pressure_test.go @@ -28,6 +28,7 @@ import ( "github.com/elastic/beats/v7/libbeat/common" mbtest "github.com/elastic/beats/v7/metricbeat/mb/testing" + _ "github.com/elastic/beats/v7/metricbeat/module/linux" ) func TestFetch(t *testing.T) { diff --git a/metricbeat/module/linux/rapl/rapl.go b/metricbeat/module/linux/rapl/rapl.go index f7d3cacf93c..40a627f53f8 100644 --- a/metricbeat/module/linux/rapl/rapl.go +++ b/metricbeat/module/linux/rapl/rapl.go @@ -37,8 +37,8 @@ import ( "github.com/elastic/beats/v7/libbeat/common" "github.com/elastic/beats/v7/libbeat/common/cfgwarn" "github.com/elastic/beats/v7/libbeat/logp" + "github.com/elastic/beats/v7/libbeat/metric/system/resolve" "github.com/elastic/beats/v7/metricbeat/mb" - "github.com/elastic/beats/v7/metricbeat/module/linux" ) // init registers the MetricSet with the central registry as soon as the program @@ -83,16 +83,15 @@ func New(base mb.BaseMetricSet) (mb.MetricSet, error) { return nil, err } - sys := base.Module().(linux.LinuxModule) - hostfs := sys.GetHostFS() - CPUList, err := getMSRCPUs(hostfs) + sys := base.Module().(resolve.Resolver) + CPUList, err := getMSRCPUs(sys) if err != nil { return nil, errors.Wrap(err, "error getting list of CPUs to query") } // check to see if msr-safe is installed if config.UseMSRSafe { - queryPath := filepath.Join(hostfs, "/dev/cpu/", fmt.Sprint(CPUList[0]), "msr_safe") + queryPath := sys.ResolveHostFS(filepath.Join("/dev/cpu/", fmt.Sprint(CPUList[0]), "msr_safe")) _, err := os.Stat(queryPath) if errors.Is(err, os.ErrNotExist) { return nil, errors.New("no msr_safe device found. Is the kernel module loaded?") @@ -112,7 +111,7 @@ func New(base mb.BaseMetricSet) (mb.MetricSet, error) { handlers := map[int]rapl.RAPLHandler{} for _, cpu := range CPUList { - formatPath := filepath.Join(hostfs, "/dev/cpu/%d") + formatPath := sys.ResolveHostFS("/dev/cpu/%d") if config.UseMSRSafe { formatPath = filepath.Join(formatPath, "/msr_safe") } else { @@ -205,7 +204,7 @@ func (m *MetricSet) updatePower() map[int]map[rapl.RAPLDomain]energyUsage { // getMSRCPUs forms a list of CPU cores to query // For multi-processor systems, this will be more than 1. -func getMSRCPUs(hostfs string) ([]int, error) { +func getMSRCPUs(hostfs resolve.Resolver) ([]int, error) { CPUs, err := topoPkgCPUMap(hostfs) if err != nil { return nil, errors.Wrap(err, "error fetching CPU topology") @@ -227,12 +226,12 @@ func getMSRCPUs(hostfs string) ([]int, error) { //it is, however, the simplest way to do this. The intel power gadget iterates through each CPU using affinity masks, and runs `cpuid` in a loop to //figure things out //This uses /sys/devices/system/cpu/cpu*/topology/physical_package_id, which is what lscpu does. I *think* geopm does something similar to this. -func topoPkgCPUMap(hostfs string) (map[int][]int, error) { +func topoPkgCPUMap(hostfs resolve.Resolver) (map[int][]int, error) { sysdir := "/sys/devices/system/cpu/" cpuMap := make(map[int][]int) - files, err := ioutil.ReadDir(filepath.Join(hostfs, sysdir)) + files, err := ioutil.ReadDir(hostfs.ResolveHostFS(sysdir)) if err != nil { return nil, err } @@ -242,7 +241,7 @@ func topoPkgCPUMap(hostfs string) (map[int][]int, error) { for _, file := range files { if file.IsDir() && re.MatchString(file.Name()) { - fullPkg := filepath.Join(hostfs, sysdir, file.Name(), "/topology/physical_package_id") + fullPkg := hostfs.ResolveHostFS(filepath.Join(sysdir, file.Name(), "/topology/physical_package_id")) dat, err := ioutil.ReadFile(fullPkg) if err != nil { return nil, errors.Wrapf(err, "error reading file %s", fullPkg) diff --git a/metricbeat/module/linux/rapl/rapl_test.go b/metricbeat/module/linux/rapl/rapl_test.go index d51fbedb105..43568a5031a 100644 --- a/metricbeat/module/linux/rapl/rapl_test.go +++ b/metricbeat/module/linux/rapl/rapl_test.go @@ -24,6 +24,8 @@ import ( "testing" "github.com/stretchr/testify/assert" + + "github.com/elastic/beats/v7/libbeat/metric/system/resolve" ) // func TestData(t *testing.T) { @@ -47,8 +49,7 @@ import ( // } func TestTopo(t *testing.T) { - hostfs := "./testdata/" - + hostfs := resolve.NewTestResolver("./testdata") cpus, err := topoPkgCPUMap(hostfs) assert.NoError(t, err) good := map[int][]int{ diff --git a/metricbeat/module/logstash/_meta/fields.yml b/metricbeat/module/logstash/_meta/fields.yml index caa5d152974..850e5b0ba0d 100644 --- a/metricbeat/module/logstash/_meta/fields.yml +++ b/metricbeat/module/logstash/_meta/fields.yml @@ -104,3 +104,5 @@ - name: logstash type: group fields: + - name: elasticsearch.cluster.id + type: keyword diff --git a/metricbeat/module/logstash/fields.go b/metricbeat/module/logstash/fields.go index c2a1e208929..0f9ed630565 100644 --- a/metricbeat/module/logstash/fields.go +++ b/metricbeat/module/logstash/fields.go @@ -32,5 +32,5 @@ func init() { // AssetLogstash returns asset data. // This is the base64 encoded zlib format compressed contents of module/logstash. func AssetLogstash() string { - return "eJy8Wc2Oq0YT3fspSl5/F+lbZONFlEUSZaJEyepuogj1QBn3vUB3+sfJ5OkjsMFA/xWGGRazaFznnKouqqtrPsFXfDtBLSptmL4cAAw3NZ7g+Mt96XgAKFEXikvDRXuCbw8AAMNraERpazwAKKyRaTxBxQ4AGo3hbaVP8MdR6/r4PzhejJHHP7t3F6FMXoj2zKsTnFmtO/szx7rUpx79E7SswYeuXBtmdP8KwLzJjkUJK+8rU9OpueENasMaOb4ZrFnNmZ6sSmYuJzh+N1ocHbAv18aBmYrwCZnaN9jM1kMYIZwp1gWZzK3GMudt/vpmUDs/DXk693gIcNaKErM+ytmXa5M12GQEkpmehv3z7nKCHIMSK7st7H7T8LrmS6qwiLiAIOzAi1dsjd6UILzdQexNR7bAGiiENftxLMEGktIq1pWKXTfhzhnBXtaMTXthLS93UD2uOXgD0RWV5mKPnR/XlpADleQSa96im6UtaoOlYyC25XMh7W4Fr3MxWFN8gDHQKXBrm1dUuTjnWDPZFTuJiovSV6MgWcUgukNCZ0WvNSuk7deydfTTcy03FyWMqbHMW9aKD9JLZnbj2x+tD9uPjm+K/lE+WJmzKypW4btk3P+/WfYBe/kubTZVn4WYRiUfJiSu48MCsiAaC5VvO5+vVYW0rChMZjWrMPiJPNsOzZI8yDPWfCUK1LdQSFQFtobYC/u4Y2gD418WLd6P67wQdhNhAMx7PcDV14PhQMxmZ/M6jZj5UByGi68heYJjxAl0O3TnO/Tk8e65+A3Pwn5++xue9yS/3QmhQaN4obPVWmDRXjyivFslcHrIB9xXfPtbqPAxtEiYtPFoKPTaHr8zybo/HcLiFw2vbh33CYyyy7eRLeqen4Q24IBua301qisv0Olyd5A7zjQ+e7D9YwCI5keC7+fPv8JLexYrs8rvOSRTK6mne3yuw6yihXM6fpgNh4cfIb5xRPG/3yjg5fvgV+6/iz7zcbuJEMeLYQJ9gjEnqkVbRdHcqRNNaUotrJ1GEXU7uImpEgE2OKKZ24YiQci7H3pkb34Bcded4Q/BMbK+7nlpC9HwtrqHAfpuClUWVeXOi/aW9Zs1lVgr68xrgypxh9yu7cc7zSptyekXQWVklDW33lRn3BHXHDx8jlDOojSOd8y0n3/u+ImGncIH+rCATkghBdIQYc4ZrbNAmQU8ibdVX/RuPsfYYyNpd3aidiBlIc0BihOQHpSuJ6USw4ZhqqsqmV/w3Bh0I9PaKSaRjjalmQOVwr7WbrGJDfnnAIth/+MhtSnbj4zAzXYdSD8YeveqEJhi+QlJ5aD7aRIpFgBYBiHX/F/cufHueu5dwZMtOOy6b+G2laAVnmnmCLiTlsnwIhjN/aKwp3hwv4rgjWUl3FCxcpQXbFCxOg9WGSB/I4smfx3JwtPN6bQQQ4BN1lt4NhIEt2+fvrT6kj+RQ+daRFuQmZp1VKT/MczV9PvyXwAAAP//XRLRjg==" + return "eJy8Wb2OrEYTzfcpShN/F+kLnExgObAtr2XLjm5iWagXaqDvbeh2/4y9fnoLZmCB/qEY2CWYAKhzTlcV1dU1n+Arvp5ByMpYZuonAMutwDOcfrnfOj0BlGgKzZXlsj3Dt08AAMNjaGTpBD4BaBTIDJ6hYk8ABq3lbWXO8MfJGHH6H5xqa9Xpz+5ZLbXNC9leeHWGCxOms79wFKU59+ifoGUNvunKjWXW9I8A7KvqWLR06n5najo1t7xBY1mjxieDNROcmcldxWx9htN3o8XJA/tybTyYqYiQkKl9g83sfgwjhjPFqpGp3Bksc97mL68WjfdqbKXzFQ8OzlpZYtZ7OftybbIGm4xAMtPTsH/eXU6UY1DiVBfC7p2GC8GXVHERaQFR2IEXr9hasytBeHuA2JuObIE1UEhnj+NYgg0kpdOsKxWHBuHOmcBe1oxdsXCOlweoHu95eAPRFbXh8ojIj/eWkAOV4goFb9HP0haNxdIzkPvyuVDusILXLTFaU0KAKdApcOuaF9S5vOQomOqKnULNZRmqUbBaxSAZIWmyoteaFcr197Jt9NN9Lbe1ltYKLPOWtfKD9JKZff/2W+ub7Uf7d43+rXywMmdX1KzCd8m4/3+z7AOOWrty2VR9FmMalXyYkLSOD3PIgmgsVKFwPl6rCuVYUdjMGVZh9BN5tB2aJXmUZ6z5WhZobq5QqAtsLbEXDnGn0AbGvxw6vG/XeSHdLsIIWPB4gJuPB8OGmM325m0aMQuheAx1qCF5gGPEiXQ79MWjYMbywiDTRZ0VwhmLOuSJr/j6t9T+2jp5q/1B4OQ4XAv7+fFxuGLqjyC/HSqhQat5YbLNWmDRn7yF6bBS4jWhEA3L0nSRcevGo6E0Ww8JnUnW/XQIizcaXt1a9jNY7ZZPEyHqrp+kseCB7uudDeorL9Brkw+QOw5FPgeww3MESObHCt/Pn3+F5/YiN2ZVeOWwmlqrerortHSYlcR4Tqd3w2H3CSOkA0cU//uNAp6/j37l4cPsIx+3nwhpvBQm0EcgcyIh2yqJ5o+taErX1MLWcRZRt4e7MpYiwEZnPHPbmCcIefdDjxzMLyBG3ZseERZG1tddz20hG95WdzdA346hzpKq/IHT0bJ+c7aSW2VduLCoVw6h+7X9eKfZpG11fEZQmZiFza131Rl/RjYHj+8jlL1oHSc4pzpuff78ioa9hg/0aQOdkEIKpCnEnDNZZ4EyTHgQb6++5OF+jnFEIGmHfqJ2IGUhbQGURcD6pHU7KZUYdkxjfVWr+QWPzVF3Mm0dgxLpaGOeOVAp3Yvwi03qX4I5wOLfgreL1Kbs3zIiJ9ttIP1k6d2rQmQMFiYklYPu1VWklANg6YTc8H/x4Ma767kPBV9tweHQuMXbVoJWeKSZI+BOWibLi6g3j/PCkeLB/yqiJ5aNcEPFylHV2KBmIo9WGSB/I4smfxvJYqW702khhgC7Wm/hUU8Qln379JUzdf5ADl2ETLYgMzXbqEh/UszV9HH5LwAA//8MYuTR" } diff --git a/metricbeat/module/logstash/node/_meta/data.json b/metricbeat/module/logstash/node/_meta/data.json index a847bea944a..cfc36e09d31 100644 --- a/metricbeat/module/logstash/node/_meta/data.json +++ b/metricbeat/module/logstash/node/_meta/data.json @@ -9,6 +9,11 @@ "cluster": { "id": "VUwnkX_lTzCFP9VUoXT1IQ" }, + "elasticsearch": { + "cluster": { + "id": "VUwnkX_lTzCFP9VUoXT1IQ" + } + }, "node": { "host": "7dc1b688baf4", "id": "9a1f83e1-52b9-4625-a98a-6aa336f41719", @@ -101,4 +106,4 @@ "type": "logstash", "version": "7.12.0" } -} \ No newline at end of file +} diff --git a/metricbeat/module/logstash/node/data.go b/metricbeat/module/logstash/node/data.go index bb9f51c9847..1d5725ed969 100644 --- a/metricbeat/module/logstash/node/data.go +++ b/metricbeat/module/logstash/node/data.go @@ -122,6 +122,7 @@ func eventMapping(r mb.ReporterV2, content []byte, pipelines []logstash.Pipeline if clusterUUID != "" { event.ModuleFields.Put("cluster.id", clusterUUID) + event.ModuleFields.Put("elasticsearch.cluster.id", clusterUUID) } event.ID = pipeline.EphemeralID diff --git a/metricbeat/module/logstash/node_stats/_meta/data.json b/metricbeat/module/logstash/node_stats/_meta/data.json index 5343737c3b4..b218c10246e 100644 --- a/metricbeat/module/logstash/node_stats/_meta/data.json +++ b/metricbeat/module/logstash/node_stats/_meta/data.json @@ -6,7 +6,14 @@ "module": "logstash" }, "logstash": { - "cluster.id": "VUwnkX_lTzCFP9VUoXT1IQ", + "cluster": { + "id": "VUwnkX_lTzCFP9VUoXT1IQ" + }, + "elasticsearch": { + "cluster": { + "id": "VUwnkX_lTzCFP9VUoXT1IQ" + } + }, "node": { "stats": { "events": { @@ -136,4 +143,4 @@ "type": "logstash", "version": "7.12.0" } -} \ No newline at end of file +} diff --git a/metricbeat/module/logstash/node_stats/data.go b/metricbeat/module/logstash/node_stats/data.go index 85eaaa8b493..d91e2724548 100644 --- a/metricbeat/module/logstash/node_stats/data.go +++ b/metricbeat/module/logstash/node_stats/data.go @@ -204,7 +204,8 @@ func eventMapping(r mb.ReporterV2, content []byte, isXpack bool) error { event.RootFields.Put("service.version", nodeStats.Version) if clusterUUID != "" { - event.ModuleFields["cluster.id"] = clusterUUID + event.ModuleFields.Put("cluster.id", clusterUUID) + event.ModuleFields.Put("elasticsearch.cluster.id", clusterUUID) } // xpack.enabled in config using standalone metricbeat writes to `.monitoring` instead of `metricbeat-*` diff --git a/metricbeat/module/openmetrics/collector/_meta/data.json b/metricbeat/module/openmetrics/collector/_meta/data.json index 668e6a88751..d60063a9157 100644 --- a/metricbeat/module/openmetrics/collector/_meta/data.json +++ b/metricbeat/module/openmetrics/collector/_meta/data.json @@ -11,7 +11,7 @@ }, "openmetrics": { "labels": { - "device": "br-33d819d5f834", + "device": "br-3a285aa5e58c", "job": "openmetrics" }, "metrics": { diff --git a/metricbeat/module/prometheus/collector/_meta/data.json b/metricbeat/module/prometheus/collector/_meta/data.json index a46b63c74fe..dba9f7771c4 100644 --- a/metricbeat/module/prometheus/collector/_meta/data.json +++ b/metricbeat/module/prometheus/collector/_meta/data.json @@ -11,10 +11,12 @@ }, "prometheus": { "labels": { - "job": "prometheus" + "job": "prometheus", + "listener_name": "http" }, "metrics": { - "up": 1 + "net_conntrack_listener_conn_accepted_total": 3, + "net_conntrack_listener_conn_closed_total": 0 } }, "service": { diff --git a/metricbeat/module/system/_meta/config.reference.yml b/metricbeat/module/system/_meta/config.reference.yml index 929f585e7d9..974df87cb0b 100644 --- a/metricbeat/module/system/_meta/config.reference.yml +++ b/metricbeat/module/system/_meta/config.reference.yml @@ -20,7 +20,7 @@ processes: ['.*'] # Configure the mount point of the host’s filesystem for use in monitoring a host from within a container - #system.hostfs: "/hostfs" + #hostfs: "/hostfs" # Configure the metric types that are included by these metricsets. cpu.metrics: ["percentages","normalized_percentages"] # The other available option is ticks. diff --git a/metricbeat/module/system/_meta/config.yml b/metricbeat/module/system/_meta/config.yml index d13c0ca4683..4f3a66dcfa9 100644 --- a/metricbeat/module/system/_meta/config.yml +++ b/metricbeat/module/system/_meta/config.yml @@ -18,7 +18,7 @@ by_cpu: 5 # include top 5 processes by CPU by_memory: 5 # include top 5 processes by memory # Configure the mount point of the host’s filesystem for use in monitoring a host from within a container -#system.hostfs: "/hostfs" +# hostfs: "/hostfs" - module: system period: 1m diff --git a/metricbeat/module/system/core/core.go b/metricbeat/module/system/core/core.go index 349d45b838f..7d46bf95a7f 100644 --- a/metricbeat/module/system/core/core.go +++ b/metricbeat/module/system/core/core.go @@ -23,10 +23,10 @@ package core import ( "github.com/pkg/errors" + "github.com/elastic/beats/v7/libbeat/metric/system/resolve" metrics "github.com/elastic/beats/v7/metricbeat/internal/metrics/cpu" "github.com/elastic/beats/v7/metricbeat/mb" "github.com/elastic/beats/v7/metricbeat/mb/parse" - "github.com/elastic/beats/v7/metricbeat/module/system" ) func init() { @@ -57,11 +57,11 @@ func New(base mb.BaseMetricSet) (mb.MetricSet, error) { if config.CPUTicks != nil && *config.CPUTicks { config.Metrics = append(config.Metrics, "ticks") } - sys := base.Module().(system.SystemModule) + sys := base.Module().(resolve.Resolver) return &MetricSet{ BaseMetricSet: base, opts: opts, - cores: metrics.New(sys.GetHostFS()), + cores: metrics.New(sys), }, nil } diff --git a/metricbeat/module/system/core/core_test.go b/metricbeat/module/system/core/core_test.go index dd1b2d87d36..d10bd6f2e44 100644 --- a/metricbeat/module/system/core/core_test.go +++ b/metricbeat/module/system/core/core_test.go @@ -28,6 +28,7 @@ import ( mbtest "github.com/elastic/beats/v7/metricbeat/mb/testing" "github.com/elastic/beats/v7/metricbeat/mb/testing/flags" + _ "github.com/elastic/beats/v7/metricbeat/module/system" ) func TestFetch(t *testing.T) { diff --git a/metricbeat/module/system/cpu/cpu.go b/metricbeat/module/system/cpu/cpu.go index b530dab0879..704cc73b16c 100644 --- a/metricbeat/module/system/cpu/cpu.go +++ b/metricbeat/module/system/cpu/cpu.go @@ -24,10 +24,10 @@ import ( "github.com/pkg/errors" "github.com/elastic/beats/v7/libbeat/common" + "github.com/elastic/beats/v7/libbeat/metric/system/resolve" metrics "github.com/elastic/beats/v7/metricbeat/internal/metrics/cpu" "github.com/elastic/beats/v7/metricbeat/mb" "github.com/elastic/beats/v7/metricbeat/mb/parse" - "github.com/elastic/beats/v7/metricbeat/module/system" ) func init() { @@ -59,11 +59,11 @@ func New(base mb.BaseMetricSet) (mb.MetricSet, error) { if config.CPUTicks != nil && *config.CPUTicks { config.Metrics = append(config.Metrics, "ticks") } - sys := base.Module().(system.SystemModule) + sys := base.Module().(resolve.Resolver) return &MetricSet{ BaseMetricSet: base, opts: opts, - cpu: metrics.New(sys.GetHostFS()), + cpu: metrics.New(sys), }, nil } diff --git a/metricbeat/module/system/cpu/cpu_test.go b/metricbeat/module/system/cpu/cpu_test.go index cbdf3e8b0a9..980f1b097fb 100644 --- a/metricbeat/module/system/cpu/cpu_test.go +++ b/metricbeat/module/system/cpu/cpu_test.go @@ -27,6 +27,7 @@ import ( "github.com/stretchr/testify/assert" mbtest "github.com/elastic/beats/v7/metricbeat/mb/testing" + _ "github.com/elastic/beats/v7/metricbeat/module/system" ) func TestFetch(t *testing.T) { diff --git a/metricbeat/module/system/diskio/diskio_test.go b/metricbeat/module/system/diskio/diskio_test.go index 6aaf55e4e8c..57a3fd34a5d 100644 --- a/metricbeat/module/system/diskio/diskio_test.go +++ b/metricbeat/module/system/diskio/diskio_test.go @@ -22,37 +22,22 @@ package diskio import ( - "os" - "path/filepath" "testing" "time" - "github.com/stretchr/testify/assert" - - "github.com/elastic/beats/v7/libbeat/paths" + "github.com/elastic/beats/v7/metricbeat/internal/sysinit" mbtest "github.com/elastic/beats/v7/metricbeat/mb/testing" -) -func setHostfs(pathString string) { - os.Setenv("HOST_PROC", filepath.Join(pathString, "proc")) - path := paths.Path{ - Hostfs: pathString, - } - paths.InitPaths(&path) -} + "github.com/stretchr/testify/assert" +) func TestDataNameFilter(t *testing.T) { - oldFS := paths.Paths.Hostfs - setHostfs("_meta/testdata") - - defer func() { - setHostfs(oldFS) - }() - + sysinit.InitModule("./_meta/testdata") conf := map[string]interface{}{ "module": "system", "metricsets": []string{"diskio"}, - "diskio.include_devices": []string{"sda", "sda1", "sda2"}, + "diskio.include_devices": []string{"sdb", "sdb1", "sdb2"}, + "hostfs": "./_meta/testdata", } f := mbtest.NewReportingMetricSetV2Error(t, conf) @@ -62,16 +47,10 @@ func TestDataNameFilter(t *testing.T) { } func TestDataEmptyFilter(t *testing.T) { - oldFS := paths.Paths.Hostfs - setHostfs("_meta/testdata") - - defer func() { - setHostfs(oldFS) - }() - conf := map[string]interface{}{ "module": "system", "metricsets": []string{"diskio"}, + "hostfs": "./_meta/testdata", } f := mbtest.NewReportingMetricSetV2Error(t, conf) diff --git a/metricbeat/module/system/entropy/entropy.go b/metricbeat/module/system/entropy/entropy.go index f42ac41bac5..e3ced9ea307 100644 --- a/metricbeat/module/system/entropy/entropy.go +++ b/metricbeat/module/system/entropy/entropy.go @@ -22,8 +22,6 @@ package entropy import ( "io/ioutil" - "path" - "path/filepath" "strconv" "strings" @@ -31,8 +29,8 @@ import ( "github.com/elastic/beats/v7/libbeat/common" "github.com/elastic/beats/v7/libbeat/common/cfgwarn" + "github.com/elastic/beats/v7/libbeat/metric/system/resolve" "github.com/elastic/beats/v7/metricbeat/mb" - "github.com/elastic/beats/v7/metricbeat/module/system" ) // init registers the MetricSet with the central registry as soon as the program @@ -49,7 +47,7 @@ func init() { // interface methods except for Fetch. type MetricSet struct { mb.BaseMetricSet - randomPath string + mod resolve.Resolver } // New creates a new instance of the MetricSet. New is responsible for unpacking @@ -57,12 +55,11 @@ type MetricSet struct { func New(base mb.BaseMetricSet) (mb.MetricSet, error) { cfgwarn.Beta("The system entropy metricset is beta.") - sys := base.Module().(system.SystemModule) - totalPath := filepath.Join(sys.GetHostFS(), "/proc/sys/kernel/random") + sys := base.Module().(resolve.Resolver) return &MetricSet{ BaseMetricSet: base, - randomPath: totalPath, + mod: sys, }, nil } @@ -70,11 +67,11 @@ func New(base mb.BaseMetricSet) (mb.MetricSet, error) { // format. It publishes the event which is then forwarded to the output. In case // of an error set the Error field of mb.Event or simply call report.Error(). func (m *MetricSet) Fetch(report mb.ReporterV2) error { - entropy, err := getEntropyData(path.Join(m.randomPath, "entropy_avail")) + entropy, err := getEntropyData(m.mod.ResolveHostFS("/proc/sys/kernel/random/entropy_avail")) if err != nil { return errors.Wrap(err, "error getting entropy") } - poolsize, err := getEntropyData(path.Join(m.randomPath, "poolsize")) + poolsize, err := getEntropyData(m.mod.ResolveHostFS("/proc/sys/kernel/random/poolsize")) if err != nil { return errors.Wrap(err, "error getting poolsize") } diff --git a/metricbeat/module/system/entropy/entropy_test.go b/metricbeat/module/system/entropy/entropy_test.go index 27142581eb0..131affbb41a 100644 --- a/metricbeat/module/system/entropy/entropy_test.go +++ b/metricbeat/module/system/entropy/entropy_test.go @@ -25,19 +25,12 @@ import ( "github.com/stretchr/testify/assert" - "github.com/elastic/beats/v7/libbeat/paths" mbtest "github.com/elastic/beats/v7/metricbeat/mb/testing" + _ "github.com/elastic/beats/v7/metricbeat/module/system" ) func TestData(t *testing.T) { - testPath := paths.Path{ - Hostfs: "./_meta/testdata", - } - if err := paths.InitPaths(&testPath); err != nil { - t.Errorf("error setting default paths: %+v", err) - t.FailNow() - } f := mbtest.NewReportingMetricSetV2Error(t, getConfig()) err := mbtest.WriteEventsReporterV2Error(f, t, ".") if err != nil { @@ -46,14 +39,7 @@ func TestData(t *testing.T) { } func TestFetch(t *testing.T) { - testPath := paths.Path{ - Hostfs: "./_meta/testdata", - } - if err := paths.InitPaths(&testPath); err != nil { - t.Errorf("error setting default paths: %+v", err) - t.FailNow() - } f := mbtest.NewReportingMetricSetV2Error(t, getConfig()) events, errs := mbtest.ReportingFetchV2Error(f) @@ -68,5 +54,6 @@ func getConfig() map[string]interface{} { return map[string]interface{}{ "module": "system", "metricsets": []string{"entropy"}, + "hostfs": "./_meta/testdata", } } diff --git a/metricbeat/module/system/filesystem/filesystem.go b/metricbeat/module/system/filesystem/filesystem.go index 98633fd4345..9d157f76ec5 100644 --- a/metricbeat/module/system/filesystem/filesystem.go +++ b/metricbeat/module/system/filesystem/filesystem.go @@ -24,6 +24,7 @@ import ( "strings" "github.com/elastic/beats/v7/libbeat/logp" + "github.com/elastic/beats/v7/libbeat/metric/system/resolve" "github.com/elastic/beats/v7/metricbeat/mb" "github.com/elastic/beats/v7/metricbeat/mb/parse" @@ -50,9 +51,9 @@ func New(base mb.BaseMetricSet) (mb.MetricSet, error) { if err := base.Module().UnpackConfig(&config); err != nil { return nil, err } - + sys := base.Module().(resolve.Resolver) if config.IgnoreTypes == nil { - config.IgnoreTypes = DefaultIgnoredTypes() + config.IgnoreTypes = DefaultIgnoredTypes(sys) } if len(config.IgnoreTypes) > 0 { logp.Info("Ignoring filesystem types: %s", strings.Join(config.IgnoreTypes, ", ")) diff --git a/metricbeat/module/system/filesystem/filesystem_test.go b/metricbeat/module/system/filesystem/filesystem_test.go index bc3ba234469..a0ac2cf97ed 100644 --- a/metricbeat/module/system/filesystem/filesystem_test.go +++ b/metricbeat/module/system/filesystem/filesystem_test.go @@ -25,7 +25,9 @@ import ( "github.com/stretchr/testify/assert" + "github.com/elastic/beats/v7/libbeat/metric/system/resolve" mbtest "github.com/elastic/beats/v7/metricbeat/mb/testing" + _ "github.com/elastic/beats/v7/metricbeat/module/system" ) func TestFetch(t *testing.T) { @@ -49,7 +51,7 @@ func TestData(t *testing.T) { } func getConfig() map[string]interface{} { - ignoreTypes := append(DefaultIgnoredTypes(), "fuse.lxcfs", "fuse.gvfsd-fuse", "nsfs", "squashfs") + ignoreTypes := append(DefaultIgnoredTypes(resolve.NewTestResolver("")), "fuse.lxcfs", "fuse.gvfsd-fuse", "nsfs", "squashfs") return map[string]interface{}{ "module": "system", "metricsets": []string{"filesystem"}, diff --git a/metricbeat/module/system/filesystem/helper.go b/metricbeat/module/system/filesystem/helper.go index 29b68a34d4d..ec4dd1be14c 100644 --- a/metricbeat/module/system/filesystem/helper.go +++ b/metricbeat/module/system/filesystem/helper.go @@ -30,7 +30,7 @@ import ( "runtime" "github.com/elastic/beats/v7/libbeat/common" - "github.com/elastic/beats/v7/libbeat/paths" + "github.com/elastic/beats/v7/libbeat/metric/system/resolve" sigar "github.com/elastic/gosigar" ) @@ -186,10 +186,10 @@ func BuildTypeFilter(ignoreType ...string) Predicate { // DefaultIgnoredTypes tries to guess a sane list of filesystem types that // could be ignored in the running system -func DefaultIgnoredTypes() (types []string) { +func DefaultIgnoredTypes(sys resolve.Resolver) (types []string) { // If /proc/filesystems exist, default ignored types are all marked // as nodev - fsListFile := paths.Resolve(paths.Hostfs, "/proc/filesystems") + fsListFile := sys.ResolveHostFS("/proc/filesystems") if f, err := os.Open(fsListFile); err == nil { scanner := bufio.NewScanner(f) for scanner.Scan() { diff --git a/metricbeat/module/system/fsstat/fsstat.go b/metricbeat/module/system/fsstat/fsstat.go index 6a963dbaf6f..ff404cdccee 100644 --- a/metricbeat/module/system/fsstat/fsstat.go +++ b/metricbeat/module/system/fsstat/fsstat.go @@ -25,6 +25,7 @@ import ( "strings" "github.com/elastic/beats/v7/libbeat/common" + "github.com/elastic/beats/v7/libbeat/metric/system/resolve" "github.com/elastic/beats/v7/metricbeat/mb" "github.com/elastic/beats/v7/metricbeat/mb/parse" "github.com/elastic/beats/v7/metricbeat/module/system/filesystem" @@ -50,9 +51,9 @@ func New(base mb.BaseMetricSet) (mb.MetricSet, error) { if err := base.Module().UnpackConfig(&config); err != nil { return nil, err } - + sys := base.Module().(resolve.Resolver) if config.IgnoreTypes == nil { - config.IgnoreTypes = filesystem.DefaultIgnoredTypes() + config.IgnoreTypes = filesystem.DefaultIgnoredTypes(sys) } if len(config.IgnoreTypes) > 0 { base.Logger().Info("Ignoring filesystem types: %s", strings.Join(config.IgnoreTypes, ", ")) diff --git a/metricbeat/module/system/fsstat/fsstat_test.go b/metricbeat/module/system/fsstat/fsstat_test.go index acfc08b12ec..e64fc24c265 100644 --- a/metricbeat/module/system/fsstat/fsstat_test.go +++ b/metricbeat/module/system/fsstat/fsstat_test.go @@ -27,6 +27,7 @@ import ( "github.com/stretchr/testify/assert" mbtest "github.com/elastic/beats/v7/metricbeat/mb/testing" + _ "github.com/elastic/beats/v7/metricbeat/module/system" ) func TestFetch(t *testing.T) { diff --git a/metricbeat/module/system/load/load_test.go b/metricbeat/module/system/load/load_test.go index 208f75e2157..208178307bf 100644 --- a/metricbeat/module/system/load/load_test.go +++ b/metricbeat/module/system/load/load_test.go @@ -26,6 +26,7 @@ import ( "github.com/stretchr/testify/assert" mbtest "github.com/elastic/beats/v7/metricbeat/mb/testing" + _ "github.com/elastic/beats/v7/metricbeat/module/system" ) func TestFetch(t *testing.T) { diff --git a/metricbeat/module/system/memory/memory.go b/metricbeat/module/system/memory/memory.go index af4dbb7f9d2..9ff4a777aad 100644 --- a/metricbeat/module/system/memory/memory.go +++ b/metricbeat/module/system/memory/memory.go @@ -25,10 +25,10 @@ import ( "github.com/elastic/beats/v7/libbeat/common" "github.com/elastic/beats/v7/libbeat/common/transform/typeconv" + "github.com/elastic/beats/v7/libbeat/metric/system/resolve" metrics "github.com/elastic/beats/v7/metricbeat/internal/metrics/memory" "github.com/elastic/beats/v7/metricbeat/mb" "github.com/elastic/beats/v7/metricbeat/mb/parse" - "github.com/elastic/beats/v7/metricbeat/module/system" ) func init() { @@ -41,19 +41,19 @@ func init() { // MetricSet for fetching system memory metrics. type MetricSet struct { mb.BaseMetricSet - mod system.SystemModule + mod resolve.Resolver } // New is a mb.MetricSetFactory that returns a memory.MetricSet. func New(base mb.BaseMetricSet) (mb.MetricSet, error) { - sys := base.Module().(system.SystemModule) + sys := base.Module().(resolve.Resolver) return &MetricSet{BaseMetricSet: base, mod: sys}, nil } // Fetch fetches memory metrics from the OS. func (m *MetricSet) Fetch(r mb.ReporterV2) error { - eventRaw, err := metrics.Get(m.mod.GetHostFS()) + eventRaw, err := metrics.Get(m.mod) if err != nil { return errors.Wrap(err, "error fetching memory metrics") } diff --git a/metricbeat/module/system/memory/memory_test.go b/metricbeat/module/system/memory/memory_test.go index 4a5da887ea4..7d7a11a1263 100644 --- a/metricbeat/module/system/memory/memory_test.go +++ b/metricbeat/module/system/memory/memory_test.go @@ -26,6 +26,7 @@ import ( "github.com/stretchr/testify/assert" mbtest "github.com/elastic/beats/v7/metricbeat/mb/testing" + _ "github.com/elastic/beats/v7/metricbeat/module/system" ) func TestFetch(t *testing.T) { diff --git a/metricbeat/module/system/network/network_test.go b/metricbeat/module/system/network/network_test.go index d7fda561b15..712cce2c44b 100644 --- a/metricbeat/module/system/network/network_test.go +++ b/metricbeat/module/system/network/network_test.go @@ -26,6 +26,7 @@ import ( "github.com/stretchr/testify/assert" mbtest "github.com/elastic/beats/v7/metricbeat/mb/testing" + _ "github.com/elastic/beats/v7/metricbeat/module/system" ) func TestFetch(t *testing.T) { diff --git a/metricbeat/module/system/network_summary/network_summary_test.go b/metricbeat/module/system/network_summary/network_summary_test.go index bac14f51921..cb0d44ce344 100644 --- a/metricbeat/module/system/network_summary/network_summary_test.go +++ b/metricbeat/module/system/network_summary/network_summary_test.go @@ -25,6 +25,7 @@ import ( "github.com/elastic/beats/v7/libbeat/common" "github.com/elastic/beats/v7/libbeat/metric/system/network" mbtest "github.com/elastic/beats/v7/metricbeat/mb/testing" + _ "github.com/elastic/beats/v7/metricbeat/module/system" "github.com/elastic/go-sysinfo/types" ) diff --git a/metricbeat/module/system/process/_meta/data.json b/metricbeat/module/system/process/_meta/data.json index 54c24ddd7f7..28bd98f6af1 100644 --- a/metricbeat/module/system/process/_meta/data.json +++ b/metricbeat/module/system/process/_meta/data.json @@ -11,26 +11,32 @@ }, "process": { "args": [ - "/usr/lib/systemd/systemd", - "rhgb", - "--switched-root", - "--system", - "--deserialize", - "31" + "/home/alexk/.vscode-server/bin/7f6ab5485bbc008386c4386d08766667e155244e/node", + "/home/alexk/.vscode-server/bin/7f6ab5485bbc008386c4386d08766667e155244e/out/vs/server/main.js", + "--start-server", + "--host=127.0.0.1", + "--enable-remote-auto-shutdown", + "--port=0", + "--connection-secret", + "/home/alexk/.vscode-server/.7f6ab5485bbc008386c4386d08766667e155244e.token" ], - "command_line": "/usr/lib/systemd/systemd rhgb --switched-root --system --deserialize 31", + "command_line": "/home/alexk/.vscode-server/bin/7f6ab5485bbc008386c4386d08766667e155244e/node /home/alexk/.vscode-server/bin/7f6ab5485bbc008386c4386d08766667e155244e/out/vs/server/main.js --start-server --host=127.0.0.1 --enable-remote-auto-shutdown --port=0 --connection-secret /home/alexk/.vscode-server/.7f6ab5485bbc008386c4386d08766667e155244e.token", "cpu": { "pct": 0, - "start_time": "2021-09-29T22:29:55.000Z" + "start_time": "2021-11-15T05:02:43.000Z" }, + "executable": "/home/alexk/.vscode-server/bin/7f6ab5485bbc008386c4386d08766667e155244e/node", "memory": { - "pct": 0.0003 + "pct": 0.001 }, - "name": "systemd", - "pgid": 1, - "pid": 1, - "ppid": 0, - "state": "sleeping" + "name": "node", + "parent": { + "pid": 932570 + }, + "pgid": 932516, + "pid": 932578, + "state": "sleeping", + "working_directory": "/home/alexk" }, "service": { "type": "system" @@ -40,8 +46,8 @@ "cgroup": { "cgroups_version": 2, "cpu": { - "id": "init.scope", - "path": "/init.scope", + "id": "session-6.scope", + "path": "/user.slice/user-1000.slice/session-6.scope", "pressure": { "full": { "10": { @@ -53,7 +59,7 @@ "60": { "pct": 0 }, - "total": 50432 + "total": 3879840 }, "some": { "10": { @@ -65,101 +71,36 @@ "60": { "pct": 0 }, - "total": 50879 + "total": 3899569 } }, "stats": { - "periods": 0, "system": { "norm": { "pct": 0 }, - "ns": 2293648, + "ns": 69699800, "pct": 0 }, - "throttled": { - "periods": 0, - "us": 0 - }, "usage": { "norm": { "pct": 0 }, - "ns": 4958009, + "ns": 311034237, "pct": 0 }, "user": { "norm": { "pct": 0 }, - "ns": 2664361, + "ns": 241334437, "pct": 0 } } }, - "id": "init.scope", - "io": { - "id": "init.scope", - "path": "/init.scope", - "pressure": { - "full": { - "10": { - "pct": 0 - }, - "300": { - "pct": 0 - }, - "60": { - "pct": 0 - }, - "total": 2393048 - }, - "some": { - "10": { - "pct": 0 - }, - "300": { - "pct": 0 - }, - "60": { - "pct": 0 - }, - "total": 2402448 - } - }, - "stats": { - "dm-0": { - "discarded": { - "bytes": 0, - "ios": 0 - }, - "read": { - "bytes": 8192, - "ios": 2 - }, - "write": { - "bytes": 0, - "ios": 0 - } - }, - "sda": { - "discarded": { - "bytes": 0, - "ios": 0 - }, - "read": { - "bytes": 8192, - "ios": 2 - }, - "write": { - "bytes": 0, - "ios": 0 - } - } - } - }, + "id": "session-6.scope", "memory": { - "id": "init.scope", + "id": "session-6.scope", "mem": { "events": { "high": 0, @@ -172,7 +113,7 @@ "bytes": 0 }, "usage": { - "bytes": 45223936 + "bytes": 81653760 } }, "memsw": { @@ -188,28 +129,28 @@ "bytes": 0 } }, - "path": "/init.scope", + "path": "/user.slice/user-1000.slice/session-6.scope", "stats": { "active_anon": { - "bytes": 24576 + "bytes": 12288 }, "active_file": { - "bytes": 21671936 + "bytes": 507904 }, "anon": { - "bytes": 8499200 + "bytes": 42983424 }, "anon_thp": { "bytes": 0 }, "file": { - "bytes": 30720000 + "bytes": 34598912 }, "file_dirty": { "bytes": 0 }, "file_mapped": { - "bytes": 14823424 + "bytes": 28467200 }, "file_thp": { "bytes": 0 @@ -219,43 +160,43 @@ }, "htp_collapse_alloc": 0, "inactive_anon": { - "bytes": 8503296 + "bytes": 42967040 }, "inactive_file": { - "bytes": 9019392 + "bytes": 34091008 }, "kernel_stack": { - "bytes": 442368 + "bytes": 376832 }, - "major_page_faults": 169, - "page_activate": 5454, + "major_page_faults": 289, + "page_activate": 135, "page_deactivate": 0, - "page_faults": 105959, + "page_faults": 766278, "page_lazy_free": 0, "page_lazy_freed": 0, "page_refill": 0, "page_scan": 0, "page_steal": 0, "page_tables": { - "bytes": 102400 + "bytes": 2310144 }, "per_cpu": { - "bytes": 36288 + "bytes": 0 }, "shmem": { - "bytes": 28672 + "bytes": 0 }, "shmem_thp": { "bytes": 0 }, "slab": { - "bytes": 5320160 + "bytes": 766496 }, "slab_reclaimable": { - "bytes": 4626072 + "bytes": 298512 }, "slab_unreclaimable": { - "bytes": 694088 + "bytes": 467984 }, "sock": { "bytes": 0 @@ -276,31 +217,38 @@ "workingset_restore_file": 0 } }, - "path": "/init.scope" + "path": "/user.slice/user-1000.slice/session-6.scope" }, - "cmdline": "/usr/lib/systemd/systemd rhgb --switched-root --system --deserialize 31", + "cmdline": "/home/alexk/.vscode-server/bin/7f6ab5485bbc008386c4386d08766667e155244e/node /home/alexk/.vscode-server/bin/7f6ab5485bbc008386c4386d08766667e155244e/out/vs/server/main.js --start-server --host=127.0.0.1 --enable-remote-auto-shutdown --port=0 --connection-secret /home/alexk/.vscode-server/.7f6ab5485bbc008386c4386d08766667e155244e.token", "cpu": { - "start_time": "2021-09-29T22:29:55.000Z", + "start_time": "2021-11-15T05:02:43.000Z", "total": { "norm": { "pct": 0 }, "pct": 0, - "value": 4640 + "value": 226260 } }, + "fd": { + "limit": { + "hard": 524288, + "soft": 524288 + }, + "open": 23 + }, "memory": { "rss": { - "bytes": 18153472, - "pct": 0.0003 + "bytes": 64372736, + "pct": 0.001 }, - "share": 11046912, - "size": 181272576 + "share": 32768000, + "size": 948490240 }, "state": "sleeping" } }, "user": { - "name": "root" + "name": "alexk" } } \ No newline at end of file diff --git a/metricbeat/module/system/process/_meta/docs.asciidoc b/metricbeat/module/system/process/_meta/docs.asciidoc index af9223c9761..6263b194818 100644 --- a/metricbeat/module/system/process/_meta/docs.asciidoc +++ b/metricbeat/module/system/process/_meta/docs.asciidoc @@ -113,4 +113,4 @@ A workaround is also required if metricbeat is running inside docker on a hybrid Within docker, metricbeat won't be able to see any V2 cgroups components. If you wish to monitor cgroups V2 from within docker on a hybrid system, you must mount the unified sysfs hierarchy (usually `/sys/fs/cgroups/unified`) inside the container, and then use -`--system.hostfs` to specify the filesystem root within the container. \ No newline at end of file +`system.hostfs` to specify the filesystem root within the container. \ No newline at end of file diff --git a/metricbeat/module/system/process/process.go b/metricbeat/module/system/process/process.go index 72eefa19d54..a90538e4f6c 100644 --- a/metricbeat/module/system/process/process.go +++ b/metricbeat/module/system/process/process.go @@ -30,9 +30,9 @@ import ( "github.com/elastic/beats/v7/libbeat/logp" "github.com/elastic/beats/v7/libbeat/metric/system/cgroup" "github.com/elastic/beats/v7/libbeat/metric/system/process" + "github.com/elastic/beats/v7/libbeat/metric/system/resolve" "github.com/elastic/beats/v7/metricbeat/mb" "github.com/elastic/beats/v7/metricbeat/mb/parse" - "github.com/elastic/beats/v7/metricbeat/module/system" ) var debugf = logp.MakeDebug("system.process") @@ -59,13 +59,13 @@ func New(base mb.BaseMetricSet) (mb.MetricSet, error) { return nil, err } - sys := base.Module().(system.SystemModule) + sys := base.Module().(resolve.Resolver) enableCgroups := false if runtime.GOOS == "linux" { if config.Cgroups == nil || *config.Cgroups { enableCgroups = true - debugf("process cgroup data collection is enabled, using hostfs='%v'", sys.GetHostFS()) + debugf("process cgroup data collection is enabled, using hostfs='%v'", sys.ResolveHostFS("")) } } @@ -79,7 +79,7 @@ func New(base mb.BaseMetricSet) (mb.MetricSet, error) { IncludeTop: config.IncludeTop, EnableCgroups: enableCgroups, CgroupOpts: cgroup.ReaderOptions{ - RootfsMountpoint: sys.GetHostFS(), + RootfsMountpoint: sys, IgnoreRootCgroups: true, }, }, @@ -87,7 +87,7 @@ func New(base mb.BaseMetricSet) (mb.MetricSet, error) { } // If hostfs is set, we may not want to force the hierarchy override, as the user could be expecting a custom path. - if len(sys.GetHostFS()) < 2 { + if !sys.IsSet() { override, isset := os.LookupEnv("LIBBEAT_MONITORING_CGROUPS_HIERARCHY_OVERRIDE") if isset { m.stats.CgroupOpts.CgroupsHierarchyOverride = override diff --git a/metricbeat/module/system/process/process_test.go b/metricbeat/module/system/process/process_test.go index 0a585141cf4..b1fea79c154 100644 --- a/metricbeat/module/system/process/process_test.go +++ b/metricbeat/module/system/process/process_test.go @@ -29,6 +29,7 @@ import ( "github.com/elastic/beats/v7/libbeat/common" mbtest "github.com/elastic/beats/v7/metricbeat/mb/testing" + _ "github.com/elastic/beats/v7/metricbeat/module/system" ) func TestFetch(t *testing.T) { diff --git a/metricbeat/module/system/process_summary/process_summary_test.go b/metricbeat/module/system/process_summary/process_summary_test.go index 22bdf2ae69f..9eaa85dc86d 100644 --- a/metricbeat/module/system/process_summary/process_summary_test.go +++ b/metricbeat/module/system/process_summary/process_summary_test.go @@ -29,6 +29,7 @@ import ( "github.com/elastic/beats/v7/libbeat/common" mbtest "github.com/elastic/beats/v7/metricbeat/mb/testing" + _ "github.com/elastic/beats/v7/metricbeat/module/system" ) func TestData(t *testing.T) { diff --git a/metricbeat/module/system/raid/_meta/docs.asciidoc b/metricbeat/module/system/raid/_meta/docs.asciidoc index e8465147e51..91528bea99d 100644 --- a/metricbeat/module/system/raid/_meta/docs.asciidoc +++ b/metricbeat/module/system/raid/_meta/docs.asciidoc @@ -4,4 +4,3 @@ This metricset is available on: - Linux -The config option `raid.mount_point:` can be used to configure the location of the raid metadata. If running this metricset inside a container, you will need to mount `/sys/block` inside the container under the path specified by `--system.hostfs` diff --git a/metricbeat/module/system/raid/blockinfo/getdev.go b/metricbeat/module/system/raid/blockinfo/getdev.go index 457a816c8be..460b46d60d3 100644 --- a/metricbeat/module/system/raid/blockinfo/getdev.go +++ b/metricbeat/module/system/raid/blockinfo/getdev.go @@ -46,7 +46,7 @@ func ListAll(path string) ([]MDDevice, error) { } if len(mds) == 0 { - return nil, fmt.Errorf("no matches from path %s,", path) + return nil, fmt.Errorf("no matches from path %s", path) } return mds, nil diff --git a/metricbeat/module/system/raid/raid.go b/metricbeat/module/system/raid/raid.go index 9af6e87a9a3..4f03d2e9db6 100644 --- a/metricbeat/module/system/raid/raid.go +++ b/metricbeat/module/system/raid/raid.go @@ -18,15 +18,12 @@ package raid import ( - "path/filepath" - "github.com/pkg/errors" - "github.com/prometheus/procfs" "github.com/elastic/beats/v7/libbeat/common" + "github.com/elastic/beats/v7/libbeat/metric/system/resolve" "github.com/elastic/beats/v7/metricbeat/mb" "github.com/elastic/beats/v7/metricbeat/mb/parse" - "github.com/elastic/beats/v7/metricbeat/module/system" "github.com/elastic/beats/v7/metricbeat/module/system/raid/blockinfo" ) @@ -39,38 +36,17 @@ func init() { // MetricSet contains proc fs data. type MetricSet struct { mb.BaseMetricSet - fs procfs.FS - sysblock string + mod resolve.Resolver } // New creates a new instance of the raid metricset. func New(base mb.BaseMetricSet) (mb.MetricSet, error) { - // Additional configuration options - config := struct { - MountPoint string `config:"raid.mount_point"` - }{} - - if err := base.Module().UnpackConfig(&config); err != nil { - return nil, err - } - sys := base.Module().(system.SystemModule) - if config.MountPoint == "" { - config.MountPoint = sys.GetHostFS() - } - - mountPoint := filepath.Join(config.MountPoint, procfs.DefaultMountPoint) - fs, err := procfs.NewFS(mountPoint) - if err != nil { - return nil, err - } - - sysMountPoint := filepath.Join(config.MountPoint, "/sys/block") - + sys := base.Module().(resolve.Resolver) return &MetricSet{ BaseMetricSet: base, - fs: fs, - sysblock: sysMountPoint, + + mod: sys, }, nil } @@ -84,7 +60,7 @@ func blockto1024(b int64) int64 { // Fetch fetches one event for each device func (m *MetricSet) Fetch(r mb.ReporterV2) error { - devices, err := blockinfo.ListAll(m.sysblock) + devices, err := blockinfo.ListAll(m.mod.ResolveHostFS("/sys/block")) if err != nil { return errors.Wrap(err, "failed to parse sysfs") } diff --git a/metricbeat/module/system/raid/raid_test.go b/metricbeat/module/system/raid/raid_test.go index f1ebaa97270..4c35394413a 100644 --- a/metricbeat/module/system/raid/raid_test.go +++ b/metricbeat/module/system/raid/raid_test.go @@ -23,6 +23,7 @@ import ( "github.com/stretchr/testify/assert" mbtest "github.com/elastic/beats/v7/metricbeat/mb/testing" + _ "github.com/elastic/beats/v7/metricbeat/module/system" ) func TestData(t *testing.T) { @@ -47,8 +48,8 @@ func TestFetch(t *testing.T) { func getConfig() map[string]interface{} { return map[string]interface{}{ - "module": "system", - "metricsets": []string{"raid"}, - "raid.mount_point": "./_meta/testdata", + "module": "system", + "metricsets": []string{"raid"}, + "hostfs": "./_meta/testdata", } } diff --git a/metricbeat/module/system/service/service_test.go b/metricbeat/module/system/service/service_test.go index 1875b4f8737..3aeba519bc9 100644 --- a/metricbeat/module/system/service/service_test.go +++ b/metricbeat/module/system/service/service_test.go @@ -28,6 +28,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/elastic/beats/v7/libbeat/common" + _ "github.com/elastic/beats/v7/metricbeat/module/system" ) var exampleUnits = []dbus.UnitStatus{ diff --git a/metricbeat/module/system/socket/socket.go b/metricbeat/module/system/socket/socket.go index 2e290bddaf2..560e4aa7803 100644 --- a/metricbeat/module/system/socket/socket.go +++ b/metricbeat/module/system/socket/socket.go @@ -32,7 +32,7 @@ import ( "github.com/elastic/beats/v7/libbeat/common" "github.com/elastic/beats/v7/libbeat/logp" - "github.com/elastic/beats/v7/libbeat/paths" + "github.com/elastic/beats/v7/libbeat/metric/system/resolve" sock "github.com/elastic/beats/v7/metricbeat/helper/socket" "github.com/elastic/beats/v7/metricbeat/mb" "github.com/elastic/beats/v7/metricbeat/mb/parse" @@ -69,12 +69,13 @@ type MetricSet struct { // New creates a new instance of the MetricSet. New is responsible for unpacking // any MetricSet specific configuration options if there are any. func New(base mb.BaseMetricSet) (mb.MetricSet, error) { + sys := base.Module().(resolve.Resolver) c := defaultConfig if err := base.Module().UnpackConfig(&c); err != nil { return nil, err } - ptable, err := sock.NewProcTable(paths.Resolve(paths.Hostfs, "/proc")) + ptable, err := sock.NewProcTable(sys.ResolveHostFS("/proc")) if err != nil { return nil, err } diff --git a/metricbeat/module/system/socket/socket_test.go b/metricbeat/module/system/socket/socket_test.go index 38d63c55026..bd5c485806a 100644 --- a/metricbeat/module/system/socket/socket_test.go +++ b/metricbeat/module/system/socket/socket_test.go @@ -35,6 +35,7 @@ import ( "github.com/elastic/beats/v7/libbeat/common" sock "github.com/elastic/beats/v7/metricbeat/helper/socket" mbtest "github.com/elastic/beats/v7/metricbeat/mb/testing" + _ "github.com/elastic/beats/v7/metricbeat/module/system" ) func TestData(t *testing.T) { diff --git a/metricbeat/module/system/socket_summary/socket_summary.go b/metricbeat/module/system/socket_summary/socket_summary.go index d34779ab345..bdc89011f70 100644 --- a/metricbeat/module/system/socket_summary/socket_summary.go +++ b/metricbeat/module/system/socket_summary/socket_summary.go @@ -24,6 +24,7 @@ import ( "github.com/shirou/gopsutil/net" "github.com/elastic/beats/v7/libbeat/common" + "github.com/elastic/beats/v7/libbeat/metric/system/resolve" "github.com/elastic/beats/v7/metricbeat/mb" ) @@ -45,12 +46,15 @@ func init() { type MetricSet struct { mb.BaseMetricSet sockstat string + mod resolve.Resolver } // New creates a new instance of the MetricSet. New is responsible for unpacking // any MetricSet specific configuration options if there are any. func New(base mb.BaseMetricSet) (mb.MetricSet, error) { + sys := base.Module().(resolve.Resolver) return &MetricSet{ + mod: sys, BaseMetricSet: base, }, nil } @@ -155,7 +159,7 @@ func (m *MetricSet) Fetch(report mb.ReporterV2) error { } stats := calculateConnStats(conns) - newStats, err := applyEnhancements(stats) + newStats, err := applyEnhancements(stats, m.mod) if err != nil { m.Logger().Debugf("error applying enhancements: %s", err) newStats = stats diff --git a/metricbeat/module/system/socket_summary/sockstat_linux.go b/metricbeat/module/system/socket_summary/sockstat_linux.go index 9aff1d6b002..b66b8afb7f3 100644 --- a/metricbeat/module/system/socket_summary/sockstat_linux.go +++ b/metricbeat/module/system/socket_summary/sockstat_linux.go @@ -29,7 +29,7 @@ import ( "github.com/shirou/gopsutil/net" "github.com/elastic/beats/v7/libbeat/common" - "github.com/elastic/beats/v7/libbeat/paths" + "github.com/elastic/beats/v7/libbeat/metric/system/resolve" ) // SockStat contains data from /proc/net/sockstat @@ -61,8 +61,8 @@ type SockStat struct { } // applyEnhancements gets a list of platform-specific enhancements and apply them to our mapStr object. -func applyEnhancements(data common.MapStr) (common.MapStr, error) { - dir := paths.Resolve(paths.Hostfs, "/proc/net/sockstat") +func applyEnhancements(data common.MapStr, sys resolve.Resolver) (common.MapStr, error) { + dir := sys.ResolveHostFS("/proc/net/sockstat") pageSize := os.Getpagesize() stat, err := parseSockstat(dir) diff --git a/metricbeat/module/system/socket_summary/sockstat_other.go b/metricbeat/module/system/socket_summary/sockstat_other.go index 1df924647b8..03832b40342 100644 --- a/metricbeat/module/system/socket_summary/sockstat_other.go +++ b/metricbeat/module/system/socket_summary/sockstat_other.go @@ -24,11 +24,12 @@ import ( "github.com/shirou/gopsutil/net" "github.com/elastic/beats/v7/libbeat/common" + "github.com/elastic/beats/v7/libbeat/metric/system/resolve" ) //a stub function for non-linux systems //get a list of platform-specific enhancements and apply them to our mapStr object. -func applyEnhancements(data common.MapStr) (common.MapStr, error) { +func applyEnhancements(data common.MapStr, sys resolve.Resolver) (common.MapStr, error) { return data, nil } diff --git a/metricbeat/module/system/system.go b/metricbeat/module/system/system.go index dd1e514c60d..e78cac59078 100644 --- a/metricbeat/module/system/system.go +++ b/metricbeat/module/system/system.go @@ -20,9 +20,7 @@ package system import ( "sync" - "github.com/elastic/beats/v7/libbeat/common/fleetmode" - "github.com/elastic/beats/v7/libbeat/logp" - "github.com/elastic/beats/v7/libbeat/paths" + "github.com/elastic/beats/v7/metricbeat/internal/sysinit" "github.com/elastic/beats/v7/metricbeat/mb" ) @@ -30,57 +28,7 @@ var once sync.Once func init() { // Register the ModuleFactory function for the "system" module. - if err := mb.Registry.AddModule("system", NewModule); err != nil { + if err := mb.Registry.AddModule("system", sysinit.InitSystemModule); err != nil { panic(err) } } - -type HostFSConfig struct { - HostFS string `config:"system.hostfs"` -} - -// Module represents the system module -type Module struct { - mb.BaseModule - HostFS string -} - -type SystemModule interface { - GetHostFS() string -} - -func NewModule(base mb.BaseModule) (mb.Module, error) { - var hostfs string - - // If this is fleet, ignore the global path, as its not being set. - // This is a temporary hack - if fleetmode.Enabled() { - partialConfig := HostFSConfig{} - base.UnpackConfig(&partialConfig) - - if partialConfig.HostFS != "" { - hostfs = partialConfig.HostFS - } else { - hostfs = "/" - } - - logp.Info("In Fleet, using HostFS: %s", hostfs) - } else { - hostfs = paths.Paths.Hostfs - } - - once.Do(func() { - initModule(hostfs) - }) - - // set the main Path, - if fleetmode.Enabled() && len(paths.Paths.Hostfs) < 2 { - paths.Paths.Hostfs = hostfs - } - - return &Module{BaseModule: base, HostFS: hostfs}, nil -} - -func (m Module) GetHostFS() string { - return m.HostFS -} diff --git a/metricbeat/module/system/uptime/uptime_test.go b/metricbeat/module/system/uptime/uptime_test.go index d1ae484cac6..9969cea5f32 100644 --- a/metricbeat/module/system/uptime/uptime_test.go +++ b/metricbeat/module/system/uptime/uptime_test.go @@ -26,6 +26,7 @@ import ( "github.com/stretchr/testify/assert" mbtest "github.com/elastic/beats/v7/metricbeat/mb/testing" + _ "github.com/elastic/beats/v7/metricbeat/module/system" ) func TestData(t *testing.T) { diff --git a/metricbeat/modules.d/kubernetes.yml.disabled b/metricbeat/modules.d/kubernetes.yml.disabled index 08203350e93..fcfeec14875 100644 --- a/metricbeat/modules.d/kubernetes.yml.disabled +++ b/metricbeat/modules.d/kubernetes.yml.disabled @@ -25,6 +25,16 @@ #host: node_name # If kube_config is not set, KUBECONFIG environment variable will be checked # and if not present it will fall back to InCluster + # To configure additionally node and namespace metadata, added to pod, service and container resource types, + # `add_resource_metadata` can be defined. + # By default all labels will be included while annotations are not added by default. + # add_resource_metadata: + # namespace: + # include_labels: ["namespacelabel1"] + # node: + # include_labels: ["nodelabel2"] + # include_annotations: ["nodeannotation1"] + # deployment: false #kube_config: ~/.kube/config # Kubernetes client QPS and burst can be configured additionally #kube_client_options: @@ -51,7 +61,24 @@ # hosts: ["kube-state-metrics:8080"] # add_metadata: true -# Kubernetes events +# Kubernetes Events #- module: kubernetes +# enabled: true # metricsets: # - event +# period: 10s +# # Skip events older than Metricbeat's statup time is enabled by default. +# # Setting to false the skip_older setting will stop filtering older events. +# # This setting is also useful went Event's timestamps are not populated properly. +# skip_older: false +# # If kube_config is not set, KUBECONFIG environment variable will be checked +# # and if not present it will fall back to InCluster +# kube_config: ~/.kube/config +# # Set the namespace to watch for events +# namespace: staging +# # Set the sync period of the watchers +# sync_period: 10m +# # Kubernetes client QPS and burst can be configured additionally +# kube_client_options: +# qps: 5 +# burst: 10 diff --git a/metricbeat/modules.d/system.yml b/metricbeat/modules.d/system.yml index f3f929e8f58..3c511e77439 100644 --- a/metricbeat/modules.d/system.yml +++ b/metricbeat/modules.d/system.yml @@ -21,7 +21,7 @@ by_cpu: 5 # include top 5 processes by CPU by_memory: 5 # include top 5 processes by memory # Configure the mount point of the host’s filesystem for use in monitoring a host from within a container -#system.hostfs: "/hostfs" +# hostfs: "/hostfs" - module: system period: 1m diff --git a/metricbeat/tests/system/test_base.py b/metricbeat/tests/system/test_base.py index 5d7cf103929..43b548013e9 100644 --- a/metricbeat/tests/system/test_base.py +++ b/metricbeat/tests/system/test_base.py @@ -39,9 +39,9 @@ def test_start_stop(self): assert self.log_contains("metricbeat stopped") @unittest.skipUnless(INTEGRATION_TESTS, "integration test") - def test_template(self): + def test_index_management(self): """ - Test that the template can be loaded with `setup --template` + Test that the template can be loaded with `setup --index-management` """ es = Elasticsearch([self.get_elasticsearch_url()]) self.render_config_template( @@ -52,7 +52,7 @@ def test_template(self): }], elasticsearch={"host": self.get_elasticsearch_url()}, ) - exit_code = self.run_beat(extra_args=["setup", "--template", "-E", "setup.template.overwrite=true"]) + exit_code = self.run_beat(extra_args=["setup", "--index-management", "-E", "setup.template.overwrite=true"]) assert exit_code == 0 assert self.log_contains('Loaded index template') @@ -100,7 +100,7 @@ def test_migration(self): }], elasticsearch={"host": self.get_elasticsearch_url()}, ) - exit_code = self.run_beat(extra_args=["setup", "--template", + exit_code = self.run_beat(extra_args=["setup", "--index-management", "-E", "setup.template.overwrite=true", "-E", "migration.6_to_7.enabled=true"]) assert exit_code == 0 diff --git a/metricbeat/tests/system/test_template.py b/metricbeat/tests/system/test_template.py index 75b366ab15d..17df56cf552 100644 --- a/metricbeat/tests/system/test_template.py +++ b/metricbeat/tests/system/test_template.py @@ -41,7 +41,7 @@ def test_export_template(self): break t = json.loads(template_content) - properties = t["mappings"]["properties"] + properties = t["template"]["mappings"]["properties"] # Check libbeat fields assert properties["@timestamp"] == {"type": "date"} diff --git a/packetbeat/Dockerfile b/packetbeat/Dockerfile index d7d9ed89fe6..0a5a4a84128 100644 --- a/packetbeat/Dockerfile +++ b/packetbeat/Dockerfile @@ -1,8 +1,8 @@ -FROM golang:1.17.2 +FROM golang:1.17.5 RUN \ apt-get update \ - && apt-get install -y --no-install-recommends \ + && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \ python3 \ python3-pip \ python3-venv \ diff --git a/packetbeat/Jenkinsfile.yml b/packetbeat/Jenkinsfile.yml index 5d09046407a..bc0f8a13bee 100644 --- a/packetbeat/Jenkinsfile.yml +++ b/packetbeat/Jenkinsfile.yml @@ -42,7 +42,7 @@ stages: macos: mage: "mage build unitTest" platforms: ## override default label in this specific stage. - - "macosx&&x86_64" + - "orka && darwin && poc" when: ## Override the top-level when. comments: - "/test packetbeat for macos" diff --git a/packetbeat/beater/worker.go b/packetbeat/beater/worker.go index 5dd6a514454..2c7f1d7eff6 100644 --- a/packetbeat/beater/worker.go +++ b/packetbeat/beater/worker.go @@ -18,7 +18,7 @@ package beater import ( - "github.com/tsg/gopacket/layers" + "github.com/google/gopacket/layers" "github.com/elastic/beats/v7/packetbeat/config" "github.com/elastic/beats/v7/packetbeat/decoder" diff --git a/packetbeat/cmd/root.go b/packetbeat/cmd/root.go index 808de836fb3..6032089c9fc 100644 --- a/packetbeat/cmd/root.go +++ b/packetbeat/cmd/root.go @@ -50,7 +50,7 @@ var RootCmd *cmd.BeatsRootCmd // PacketbeatSettings contains the default settings for packetbeat func PacketbeatSettings() instance.Settings { - var runFlags = pflag.NewFlagSet(Name, pflag.ExitOnError) + runFlags := pflag.NewFlagSet(Name, pflag.ExitOnError) runFlags.AddGoFlag(flag.CommandLine.Lookup("I")) runFlags.AddGoFlag(flag.CommandLine.Lookup("t")) runFlags.AddGoFlag(flag.CommandLine.Lookup("O")) diff --git a/packetbeat/config/agent.go b/packetbeat/config/agent.go index 36e3c977b44..34df1721597 100644 --- a/packetbeat/config/agent.go +++ b/packetbeat/config/agent.go @@ -66,7 +66,7 @@ func (i agentInput) addProcessorsAndIndex(cfg *common.Config) (*common.Config, e mergeConfig, err := common.NewConfigFrom(common.MapStr{ "index": datastreamConfig.Datastream.Type + "-" + datastreamConfig.Datastream.Dataset + "-" + namespace, "processors": append([]common.MapStr{ - common.MapStr{ + { "add_fields": common.MapStr{ "target": "data_stream", "fields": common.MapStr{ @@ -76,7 +76,7 @@ func (i agentInput) addProcessorsAndIndex(cfg *common.Config) (*common.Config, e }, }, }, - common.MapStr{ + { "add_fields": common.MapStr{ "target": "event", "fields": common.MapStr{ diff --git a/packetbeat/decoder/decoder.go b/packetbeat/decoder/decoder.go index 50e8f595481..025b0899d00 100644 --- a/packetbeat/decoder/decoder.go +++ b/packetbeat/decoder/decoder.go @@ -20,15 +20,15 @@ package decoder import ( "fmt" + "github.com/google/gopacket" + "github.com/google/gopacket/layers" + "github.com/elastic/beats/v7/libbeat/logp" "github.com/elastic/beats/v7/packetbeat/flows" "github.com/elastic/beats/v7/packetbeat/protos" "github.com/elastic/beats/v7/packetbeat/protos/icmp" "github.com/elastic/beats/v7/packetbeat/protos/tcp" "github.com/elastic/beats/v7/packetbeat/protos/udp" - - "github.com/tsg/gopacket" - "github.com/tsg/gopacket/layers" ) var debugf = logp.MakeDebug("decoder") @@ -87,7 +87,8 @@ func New( d := Decoder{ flows: f, decoders: make(map[gopacket.LayerType]gopacket.DecodingLayer), - icmp4Proc: icmp4, icmp6Proc: icmp6, tcpProc: tcp, udpProc: udp} + icmp4Proc: icmp4, icmp6Proc: icmp6, tcpProc: tcp, udpProc: udp, + } d.stD1Q.init(&d.d1q[0], &d.d1q[1]) d.stIP4.init(&d.ip4[0], &d.ip4[1]) d.stIP6.init(&d.ip6[0], &d.ip6[1]) @@ -312,6 +313,11 @@ func (d *Decoder) onICMPv6(packet *protos.Packet) { } if d.icmp6Proc != nil { + // google/gopacket treats the first four bytes + // after the typo, code and checksum as part of + // the payload. So drop those bytes. + // See https://github.com/google/gopacket/pull/423/ + d.icmp6.Payload = d.icmp6.Payload[4:] packet.Payload = d.icmp6.Payload packet.Tuple.ComputeHashables() d.icmp6Proc.ProcessICMPv6(d.flowID, &d.icmp6, packet) diff --git a/packetbeat/decoder/decoder_test.go b/packetbeat/decoder/decoder_test.go index 8e6fad990a8..19cf7e51ab2 100644 --- a/packetbeat/decoder/decoder_test.go +++ b/packetbeat/decoder/decoder_test.go @@ -28,9 +28,9 @@ import ( "github.com/elastic/beats/v7/packetbeat/flows" "github.com/elastic/beats/v7/packetbeat/protos" + "github.com/google/gopacket" + "github.com/google/gopacket/layers" "github.com/stretchr/testify/assert" - "github.com/tsg/gopacket" - "github.com/tsg/gopacket/layers" ) type TestIcmp4Processor struct { diff --git a/packetbeat/decoder/util.go b/packetbeat/decoder/util.go index 4afa18262b7..ad53199ccce 100644 --- a/packetbeat/decoder/util.go +++ b/packetbeat/decoder/util.go @@ -17,7 +17,7 @@ package decoder -import "github.com/tsg/gopacket" +import "github.com/google/gopacket" // implement DecodingLayer with support of switching between multiple layers to // remember outter layer results diff --git a/packetbeat/docs/fields.asciidoc b/packetbeat/docs/fields.asciidoc index ac1d316d238..c46253bd052 100644 --- a/packetbeat/docs/fields.asciidoc +++ b/packetbeat/docs/fields.asciidoc @@ -17610,47 +17610,16 @@ type: ip -- - -*`kubernetes.namespace.name`*:: +*`kubernetes.namespace`*:: + -- -Kubernetes namespace name +Kubernetes namespace type: keyword -- -*`kubernetes.namespace.uuid`*:: -+ --- -Kubernetes namespace uuid - - -type: keyword - --- - -*`kubernetes.namespace.labels.*`*:: -+ --- -Kubernetes namespace labels map - - -type: object - --- - -*`kubernetes.namespace.annotations.*`*:: -+ --- -Kubernetes namespace annotations map - - -type: object - --- - *`kubernetes.node.name`*:: + -- diff --git a/packetbeat/flows/flows_test.go b/packetbeat/flows/flows_test.go index 601613e61d1..9cee1c59e2d 100644 --- a/packetbeat/flows/flows_test.go +++ b/packetbeat/flows/flows_test.go @@ -56,12 +56,16 @@ func TestFlowsCounting(t *testing.T) { assert.NoError(t, err) uint1, err := module.NewUint("uint1") + assert.NoError(t, err) uint2, err := module.NewUint("uint2") + assert.NoError(t, err) int1, err := module.NewInt("int1") + assert.NoError(t, err) int2, err := module.NewInt("int2") + assert.NoError(t, err) float1, err := module.NewFloat("float1") + assert.NoError(t, err) float2, err := module.NewFloat("float2") - assert.NoError(t, err) pub := &flowsChan{make(chan []beat.Event, 1)} diff --git a/packetbeat/flows/worker.go b/packetbeat/flows/worker.go index f0080cf68d2..b339a75fa4d 100644 --- a/packetbeat/flows/worker.go +++ b/packetbeat/flows/worker.go @@ -107,7 +107,7 @@ func makeWorker( if align > 0 { // round time to nearest 10 seconds for alignment aligned := time.Unix(((time.Now().Unix()+(align-1))/align)*align, 0) - waitStart := aligned.Sub(time.Now()) + waitStart := time.Until(aligned) debugf("worker wait start(%v): %v", aligned, waitStart) if cont := w.sleep(waitStart); !cont { return diff --git a/packetbeat/flows/worker_test.go b/packetbeat/flows/worker_test.go index 3bec75f2fe3..520d107f9ab 100644 --- a/packetbeat/flows/worker_test.go +++ b/packetbeat/flows/worker_test.go @@ -33,10 +33,8 @@ import ( "github.com/elastic/beats/v7/packetbeat/procs" ) -var ( - // Use `go test -data` to update sample event files. - dataFlag = flag.Bool("data", false, "Write updated data.json files") -) +// Use `go test -data` to update sample event files. +var dataFlag = flag.Bool("data", false, "Write updated data.json files") func TestCreateEvent(t *testing.T) { logp.TestingSetup() @@ -124,7 +122,7 @@ func TestCreateEvent(t *testing.T) { t.Fatal(err) } - if err := ioutil.WriteFile("../_meta/sample_outputs/flow.json", output, 0644); err != nil { + if err := ioutil.WriteFile("../_meta/sample_outputs/flow.json", output, 0o644); err != nil { t.Fatal(err) } } diff --git a/packetbeat/include/fields.go b/packetbeat/include/fields.go index 870da081b5a..bbd0afc526c 100644 --- a/packetbeat/include/fields.go +++ b/packetbeat/include/fields.go @@ -32,5 +32,5 @@ func init() { // AssetFieldsYml returns asset data. // This is the base64 encoded zlib format compressed contents of fields.yml. func AssetFieldsYml() string { - return "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" + return "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" } diff --git a/packetbeat/packetbeat.reference.yml b/packetbeat/packetbeat.reference.yml index 3377abc029a..739fe5c5332 100644 --- a/packetbeat/packetbeat.reference.yml +++ b/packetbeat/packetbeat.reference.yml @@ -692,66 +692,6 @@ packetbeat.ignore_outgoing: false # length of its retry interval each time, up to this maximum. #max_retry_interval: 30s - # The spool queue will store events in a local spool file, before - # forwarding the events to the outputs. - # Note: the spool queue is deprecated and will be removed in the future. - # Use the disk queue instead. - # - # The spool file is a circular buffer, which blocks once the file/buffer is full. - # Events are put into a write buffer and flushed once the write buffer - # is full or the flush_timeout is triggered. - # Once ACKed by the output, events are removed immediately from the queue, - # making space for new events to be persisted. - #spool: - # The file namespace configures the file path and the file creation settings. - # Once the file exists, the `size`, `page_size` and `prealloc` settings - # will have no more effect. - #file: - # Location of spool file. The default value is ${path.data}/spool.dat. - #path: "${path.data}/spool.dat" - - # Configure file permissions if file is created. The default value is 0600. - #permissions: 0600 - - # File size hint. The spool blocks, once this limit is reached. The default value is 100 MiB. - #size: 100MiB - - # The files page size. A file is split into multiple pages of the same size. The default value is 4KiB. - #page_size: 4KiB - - # If prealloc is set, the required space for the file is reserved using - # truncate. The default value is true. - #prealloc: true - - # Spool writer settings - # Events are serialized into a write buffer. The write buffer is flushed if: - # - The buffer limit has been reached. - # - The configured limit of buffered events is reached. - # - The flush timeout is triggered. - #write: - # Sets the write buffer size. - #buffer_size: 1MiB - - # Maximum duration after which events are flushed if the write buffer - # is not full yet. The default value is 1s. - #flush.timeout: 1s - - # Number of maximum buffered events. The write buffer is flushed once the - # limit is reached. - #flush.events: 16384 - - # Configure the on-disk event encoding. The encoding can be changed - # between restarts. - # Valid encodings are: json, ubjson, and cbor. - #codec: cbor - #read: - # Reader flush timeout, waiting for more events to become available, so - # to fill a complete batch as required by the outputs. - # If flush_timeout is 0, all available events are forwarded to the - # outputs immediately. - # The default value is 0s. - #flush.timeout: 0s - # Sets the maximum number of CPUs that can be executing simultaneously. The # default is the number of logical CPUs available in the system. #max_procs: @@ -1068,6 +1008,13 @@ output.elasticsearch: # The pin is a base64 encoded string of the SHA-256 fingerprint. #ssl.ca_sha256: "" + # A root CA HEX encoded fingerprint. During the SSL handshake if the + # fingerprint matches the root CA certificate, it will be added to + # the provided list of root CAs (`certificate_authorities`), if the + # list is empty or not defined, the matching certificate will be the + # only one in the list. Then the normal SSL validation happens. + #ssl.ca_trusted_fingerprint: "" + # Enable Kerberos support. Kerberos is automatically enabled if any Kerberos setting is set. #kerberos.enabled: true @@ -1200,6 +1147,13 @@ output.elasticsearch: # The pin is a base64 encoded string of the SHA-256 fingerprint. #ssl.ca_sha256: "" + # A root CA HEX encoded fingerprint. During the SSL handshake if the + # fingerprint matches the root CA certificate, it will be added to + # the provided list of root CAs (`certificate_authorities`), if the + # list is empty or not defined, the matching certificate will be the + # only one in the list. Then the normal SSL validation happens. + #ssl.ca_trusted_fingerprint: "" + # The number of times to retry publishing an event after a publishing failure. # After the specified number of retries, the events are typically dropped. # Some Beats, such as Filebeat and Winlogbeat, ignore the max_retries setting @@ -1401,6 +1355,13 @@ output.elasticsearch: # The pin is a base64 encoded string of the SHA-256 fingerprint. #ssl.ca_sha256: "" + # A root CA HEX encoded fingerprint. During the SSL handshake if the + # fingerprint matches the root CA certificate, it will be added to + # the provided list of root CAs (`certificate_authorities`), if the + # list is empty or not defined, the matching certificate will be the + # only one in the list. Then the normal SSL validation happens. + #ssl.ca_trusted_fingerprint: "" + # Enable Kerberos support. Kerberos is automatically enabled if any Kerberos setting is set. #kerberos.enabled: true @@ -1565,6 +1526,13 @@ output.elasticsearch: # The pin is a base64 encoded string of the SHA-256 fingerprint. #ssl.ca_sha256: "" + # A root CA HEX encoded fingerprint. During the SSL handshake if the + # fingerprint matches the root CA certificate, it will be added to + # the provided list of root CAs (`certificate_authorities`), if the + # list is empty or not defined, the matching certificate will be the + # only one in the list. Then the normal SSL validation happens. + #ssl.ca_trusted_fingerprint: "" + # -------------------------------- File Output --------------------------------- #output.file: @@ -1584,7 +1552,7 @@ output.elasticsearch: #path: "/tmp/packetbeat" # Name of the generated files. The default is `packetbeat` and it generates - # files: `packetbeat`, `packetbeat.1`, `packetbeat.2`, etc. + # files: `packetbeat-{datetime}.ndjson`, `packetbeat-{datetime}-1.ndjson`, etc. #filename: packetbeat # Maximum size in kilobytes of each file. When this size is reached, and on @@ -1602,6 +1570,7 @@ output.elasticsearch: # Configure automatic file rotation on every startup. The default is true. #rotate_on_startup: true + # ------------------------------- Console Output ------------------------------- #output.console: # Boolean flag to enable or disable the output module. @@ -1700,19 +1669,13 @@ output.elasticsearch: # Set to false to disable template loading. #setup.template.enabled: true -# Select the kind of index template. From Elasticsearch 7.8, it is possible to -# use component templates. Available options: legacy, component, index. -# By default packetbeat uses the legacy index templates. -#setup.template.type: legacy - # Template name. By default the template name is "packetbeat-%{[agent.version]}" # The template name and pattern has to be set in case the Elasticsearch index pattern is modified. #setup.template.name: "packetbeat-%{[agent.version]}" -# Template pattern. By default the template pattern is "-%{[agent.version]}-*" to apply to the default index settings. -# The first part is the version of the beat and then -* is used to match all daily indices. +# Template pattern. By default the template pattern is "packetbeat-%{[agent.version]}" to apply to the default index settings. # The template name and pattern has to be set in case the Elasticsearch index pattern is modified. -#setup.template.pattern: "packetbeat-%{[agent.version]}-*" +#setup.template.pattern: "packetbeat-%{[agent.version]}" # Path to fields.yml file to generate the template #setup.template.fields: "${path.config}/fields.yml" @@ -1759,17 +1722,8 @@ setup.template.settings: # output.elasticsearch.index is ignored, and the write alias is used to set the # index name. -# Enable ILM support. Valid values are true, false, and auto. When set to auto -# (the default), the Beat uses index lifecycle management when it connects to a -# cluster that supports ILM; otherwise, it creates daily indices. -#setup.ilm.enabled: auto - -# Set the prefix used in the index lifecycle write alias name. The default alias -# name is 'packetbeat-%{[agent.version]}'. -#setup.ilm.rollover_alias: 'packetbeat' - -# Set the rollover index pattern. The default is "%{now/d}-000001". -#setup.ilm.pattern: "{now/d}-000001" +# Enable ILM support. Valid values are true, false. +#setup.ilm.enabled: true # Set the lifecycle policy name. The default policy name is # 'beatname'. @@ -1867,6 +1821,13 @@ setup.kibana: # The pin is a base64 encoded string of the SHA-256 fingerprint. #ssl.ca_sha256: "" + # A root CA HEX encoded fingerprint. During the SSL handshake if the + # fingerprint matches the root CA certificate, it will be added to + # the provided list of root CAs (`certificate_authorities`), if the + # list is empty or not defined, the matching certificate will be the + # only one in the list. Then the normal SSL validation happens. + #ssl.ca_trusted_fingerprint: "" + # ================================== Logging =================================== @@ -1938,11 +1899,6 @@ logging.files: # file. Defaults to true. # rotateonstartup: true - # Rotated files are either suffixed with a number e.g. packetbeat.1 when - # renamed during rotation. Or when set to date, the date is added to - # the end of the file. On rotation a new file is created, older files are untouched. - #suffix: count - # ============================= X-Pack Monitoring ============================== # Packetbeat can export internal metrics to a central Elasticsearch monitoring # cluster. This requires xpack monitoring to be enabled in Elasticsearch. The @@ -2070,6 +2026,13 @@ logging.files: # The pin is a base64 encoded string of the SHA-256 fingerprint. #ssl.ca_sha256: "" + # A root CA HEX encoded fingerprint. During the SSL handshake if the + # fingerprint matches the root CA certificate, it will be added to + # the provided list of root CAs (`certificate_authorities`), if the + # list is empty or not defined, the matching certificate will be the + # only one in the list. Then the normal SSL validation happens. + #ssl.ca_trusted_fingerprint: "" + # Enable Kerberos support. Kerberos is automatically enabled if any Kerberos setting is set. #kerberos.enabled: true diff --git a/packetbeat/pb/event.go b/packetbeat/pb/event.go index 683e22253be..4ba7e4acf15 100644 --- a/packetbeat/pb/event.go +++ b/packetbeat/pb/event.go @@ -237,14 +237,14 @@ func (f *Fields) ComputeValues(localIPs []net.IP, internalNetworks []string) err } // network.community_id - switch { - case f.Network.Transport == "udp": + switch f.Network.Transport { + case "udp": flow.Protocol = 17 - case f.Network.Transport == "tcp": + case "tcp": flow.Protocol = 6 - case f.Network.Transport == "icmp": + case "icmp": flow.Protocol = 1 - case f.Network.Transport == "ipv6-icmp": + case "ipv6-icmp": flow.Protocol = 58 } flow.ICMP.Type = f.ICMPType diff --git a/packetbeat/processor/add_kubernetes_metadata/indexers.go b/packetbeat/processor/add_kubernetes_metadata/indexers.go index 474f111e97f..3e547e3a8c1 100644 --- a/packetbeat/processor/add_kubernetes_metadata/indexers.go +++ b/packetbeat/processor/add_kubernetes_metadata/indexers.go @@ -26,14 +26,14 @@ func init() { // Register default indexers cfg := common.NewConfig() - //Add IP Port Indexer as a default indexer + // Add IP Port Indexer as a default indexer kubernetes.Indexing.AddDefaultIndexerConfig(kubernetes.IPPortIndexerName, *cfg) formatCfg, err := common.NewConfigFrom(map[string]interface{}{ "format": "%{[ip]}:%{[port]}", }) if err == nil { - //Add field matcher with field to lookup as metricset.host + // Add field matcher with field to lookup as metricset.host kubernetes.Indexing.AddDefaultMatcherConfig(kubernetes.FieldFormatMatcherName, *formatCfg) } } diff --git a/packetbeat/procs/procs.go b/packetbeat/procs/procs.go index bf3daab9ff2..a3d031ec72f 100644 --- a/packetbeat/procs/procs.go +++ b/packetbeat/procs/procs.go @@ -213,7 +213,7 @@ func (proc *ProcessesWatcher) updateMap(transport applayer.Transport) { if logp.HasSelector("procsdetailed") { start := time.Now() defer func() { - logp.Debug("procsdetailed", "updateMap() took %v", time.Now().Sub(start)) + logp.Debug("procsdetailed", "updateMap() took %v", time.Since(start)) }() } diff --git a/packetbeat/procs/procs_linux_test.go b/packetbeat/procs/procs_linux_test.go index 39c8a937741..e36bd50a208 100644 --- a/packetbeat/procs/procs_linux_test.go +++ b/packetbeat/procs/procs_linux_test.go @@ -39,14 +39,14 @@ func createFakeDirectoryStructure(prefix string, files []testProcFile) error { var err error for _, file := range files { dir := filepath.Dir(file.path) - err = os.MkdirAll(filepath.Join(prefix, dir), 0755) + err = os.MkdirAll(filepath.Join(prefix, dir), 0o755) if err != nil { return err } if !file.isLink { err = ioutil.WriteFile(filepath.Join(prefix, file.path), - []byte(file.contents), 0644) + []byte(file.contents), 0o644) if err != nil { return err } diff --git a/packetbeat/procs/procs_windows.go b/packetbeat/procs/procs_windows.go index 50807691efa..ee3eee1a28d 100644 --- a/packetbeat/procs/procs_windows.go +++ b/packetbeat/procs/procs_windows.go @@ -42,13 +42,17 @@ type extractor interface { Size() int } -type callbackFn func(net.IP, uint16, int) -type extractorFactory func(fn callbackFn) extractor +type ( + callbackFn func(net.IP, uint16, int) + extractorFactory func(fn callbackFn) extractor +) -type tcpRowOwnerPIDExtractor callbackFn -type tcp6RowOwnerPIDExtractor callbackFn -type udpRowOwnerPIDExtractor callbackFn -type udp6RowOwnerPIDExtractor callbackFn +type ( + tcpRowOwnerPIDExtractor callbackFn + tcp6RowOwnerPIDExtractor callbackFn + udpRowOwnerPIDExtractor callbackFn + udp6RowOwnerPIDExtractor callbackFn +) var tablesByTransport = map[applayer.Transport][]struct { family uint32 diff --git a/packetbeat/procs/procs_windows_test.go b/packetbeat/procs/procs_windows_test.go index 51cc8391d68..4abfe359b71 100644 --- a/packetbeat/procs/procs_windows_test.go +++ b/packetbeat/procs/procs_windows_test.go @@ -42,21 +42,33 @@ func TestParseTableRaw(t *testing.T) { expected []portProcMapping mustErr bool }{ - {"Empty table IPv4", IPv4, - "00000000", nil, false}, - {"Empty table IPv6", IPv6, - "00000000", nil, false}, - {"Short table (no length)", IPv4, - "000000", nil, true}, - {"Short table (partial entry)", IPv6, - "01000000AAAAAAAAAAAAAAAAAAAA", nil, true}, - {"One entry (IPv4)", IPv4, + { + "Empty table IPv4", IPv4, + "00000000", nil, false, + }, + { + "Empty table IPv6", IPv6, + "00000000", nil, false, + }, + { + "Short table (no length)", IPv4, + "000000", nil, true, + }, + { + "Short table (partial entry)", IPv6, + "01000000AAAAAAAAAAAAAAAAAAAA", nil, true, + }, + { + "One entry (IPv4)", IPv4, "01000000" + "77777777AAAAAAAA12340000BBBBBBBBFFFF0000CCCCCCCC", []portProcMapping{ {endpoint: endpoint{address: "170.170.170.170", port: 0x1234}, pid: int(pid)}, - }, false}, - {"Two entries (IPv6)", IPv6, + }, + false, + }, + { + "Two entries (IPv6)", IPv6, "02000000" + // First entry "11112222333344445555666677778888F0F0F0F0" + @@ -76,7 +88,9 @@ func TestParseTableRaw(t *testing.T) { []portProcMapping{ {endpoint: endpoint{address: "1111:2222:3333:4444:5555:6666:7777:8888", port: 0xABCD}, pid: 1}, {endpoint: endpoint{address: "aaaa:aaaa:aaaa:aaaa:aaaa:aaaa:aaaa:aaaa", port: 0}, pid: 0xffff}, - }, false}, + }, + false, + }, } { msg := fmt.Sprintf("Test case #%d: %s", idx+1, testCase.name) table, err := hex.DecodeString(testCase.raw) diff --git a/packetbeat/procs/zsyscall_windows.go b/packetbeat/procs/zsyscall_windows.go index b313698211e..f938c08f792 100644 --- a/packetbeat/procs/zsyscall_windows.go +++ b/packetbeat/procs/zsyscall_windows.go @@ -34,9 +34,7 @@ const ( errnoERROR_IO_PENDING = 997 ) -var ( - errERROR_IO_PENDING error = syscall.Errno(errnoERROR_IO_PENDING) -) +var errERROR_IO_PENDING error = syscall.Errno(errnoERROR_IO_PENDING) // errnoErr returns common boxed Errno values, to prevent // allocations at runtime. diff --git a/packetbeat/protos/amqp/amqp.go b/packetbeat/protos/amqp/amqp.go index f0c1e26dd28..2402b9150e3 100644 --- a/packetbeat/protos/amqp/amqp.go +++ b/packetbeat/protos/amqp/amqp.go @@ -50,7 +50,7 @@ type amqpPlugin struct { results protos.Reporter watcher procs.ProcessesWatcher - //map containing functions associated with different method numbers + // map containing functions associated with different method numbers methodMap map[codeClass]map[codeMethod]amqpMethod } @@ -87,7 +87,7 @@ func (amqp *amqpPlugin) init(results protos.Reporter, watcher procs.ProcessesWat amqp.initMethodMap() amqp.setFromConfig(config) - if amqp.hideConnectionInformation == false { + if !amqp.hideConnectionInformation { amqp.addConnectionMethods() } amqp.transactions = common.NewCache( @@ -194,8 +194,8 @@ func (amqp *amqpPlugin) ConnectionTimeout() time.Duration { } func (amqp *amqpPlugin) Parse(pkt *protos.Packet, tcptuple *common.TCPTuple, - dir uint8, private protos.ProtocolData) protos.ProtocolData { - + dir uint8, private protos.ProtocolData, +) protos.ProtocolData { defer logp.Recover("ParseAmqp exception") detailedf("Parse method triggered") @@ -284,7 +284,7 @@ func (amqp *amqpPlugin) handleAmqpRequest(msg *amqpMessage) { } else { trans.request = msg.method } - //length = message + 4 bytes header + frame end octet + // length = message + 4 bytes header + frame end octet trans.bytesIn = msg.bodySize + 12 if msg.fields != nil { trans.amqp = msg.fields @@ -292,9 +292,9 @@ func (amqp *amqpPlugin) handleAmqpRequest(msg *amqpMessage) { trans.amqp = common.MapStr{} } - //if error or exception, publish it now. sometimes client or server never send - //an ack message and the error is lost. Also, if nowait flag set, don't expect - //any response and publish + // if error or exception, publish it now. sometimes client or server never send + // an ack message and the error is lost. Also, if nowait flag set, don't expect + // any response and publish if isAsynchronous(trans) { amqp.publishTransaction(trans) debugf("Amqp transaction completed") @@ -317,9 +317,9 @@ func (amqp *amqpPlugin) handleAmqpResponse(msg *amqpMessage) { return } - //length = message + 4 bytes class/method + frame end octet + header + // length = message + 4 bytes class/method + frame end octet + header trans.bytesOut = msg.bodySize + 12 - //merge the both fields from request and response + // merge the both fields from request and response trans.amqp.Update(msg.fields) trans.response = common.OK_STATUS @@ -344,8 +344,8 @@ func (amqp *amqpPlugin) handleAmqpResponse(msg *amqpMessage) { func (amqp *amqpPlugin) expireTransaction(trans *amqpTransaction) { debugf("Transaction expired") - //possibility of a connection.close or channel.close method that didn't get an - //ok answer. Let's publish it. + // possibility of a connection.close or channel.close method that didn't get an + // ok answer. Let's publish it. if isCloseError(trans) { trans.notes = append(trans.notes, "Close-ok method not received by sender") amqp.publishTransaction(trans) @@ -354,8 +354,8 @@ func (amqp *amqpPlugin) expireTransaction(trans *amqpTransaction) { amqp.transactions.Delete(trans.tuple.Hashable()) } -//This method handles published messages from clients. Being an async -//process, the method, header and body frames are regrouped in one transaction +// This method handles published messages from clients. Being an async +// process, the method, header and body frames are regrouped in one transaction func (amqp *amqpPlugin) handlePublishing(client *amqpMessage) { tuple := client.tcpTuple trans := amqp.getTransaction(tuple.Hashable()) @@ -369,8 +369,8 @@ func (amqp *amqpPlugin) handlePublishing(client *amqpMessage) { trans.src, trans.dst = common.MakeEndpointPair(client.tcpTuple.BaseTuple, client.cmdlineTuple) trans.method = client.method - //for publishing and delivering, bytes in and out represent the length of the - //message itself + // for publishing and delivering, bytes in and out represent the length of the + // message itself trans.bytesIn = client.bodySize if client.bodySize > uint64(amqp.maxBodyLength) { @@ -384,13 +384,13 @@ func (amqp *amqpPlugin) handlePublishing(client *amqpMessage) { trans.amqp = client.fields amqp.publishTransaction(trans) debugf("Amqp transaction completed") - //delete trans from map + // delete trans from map amqp.transactions.Delete(trans.tuple.Hashable()) } -//This method handles delivered messages via basic.deliver and basic.get-ok AND -//returned messages to clients. Being an async process, the method, header and -//body frames are regrouped in one transaction +// This method handles delivered messages via basic.deliver and basic.get-ok AND +// returned messages to clients. Being an async process, the method, header and +// body frames are regrouped in one transaction func (amqp *amqpPlugin) handleDelivering(server *amqpMessage) { tuple := server.tcpTuple trans := amqp.getTransaction(tuple.Hashable()) @@ -403,8 +403,8 @@ func (amqp *amqpPlugin) handleDelivering(server *amqpMessage) { trans.ts = server.ts trans.src, trans.dst = common.MakeEndpointPair(server.tcpTuple.BaseTuple, server.cmdlineTuple) - //for publishing and delivering, bytes in and out represent the length of the - //message itself + // for publishing and delivering, bytes in and out represent the length of the + // message itself trans.bytesOut = server.bodySize if server.bodySize > uint64(amqp.maxBodyLength) { @@ -422,7 +422,7 @@ func (amqp *amqpPlugin) handleDelivering(server *amqpMessage) { amqp.publishTransaction(trans) debugf("Amqp transaction completed") - //delete trans from map + // delete trans from map amqp.transactions.Delete(trans.tuple.Hashable()) } @@ -459,7 +459,7 @@ func (amqp *amqpPlugin) publishTransaction(t *amqpTransaction) { fields["user.id"] = userID } - //let's try to convert request/response to a readable format + // let's try to convert request/response to a readable format if amqp.sendRequest { if t.method == "basic.publish" { if t.toString { @@ -503,7 +503,7 @@ func (amqp *amqpPlugin) publishTransaction(t *amqpTransaction) { amqp.results(evt) } -//function to check if method is async or not +// function to check if method is async or not func isAsynchronous(trans *amqpTransaction) bool { if val, ok := trans.amqp["no-wait"]; ok && val == true { return true @@ -514,7 +514,7 @@ func isAsynchronous(trans *amqpTransaction) bool { trans.method == "basic.nack" } -//function to convert a body slice into a readable format +// function to convert a body slice into a readable format func bodyToString(data []byte) string { ret := make([]string, len(data)) for i, c := range data { @@ -523,7 +523,7 @@ func bodyToString(data []byte) string { return strings.Join(ret, " ") } -//function used to check if a body message can be converted to readable string +// function used to check if a body message can be converted to readable string func isStringable(m *amqpMessage) bool { stringable := false diff --git a/packetbeat/protos/amqp/amqp_fields.go b/packetbeat/protos/amqp/amqp_fields.go index ff4f7c382b5..d7536572978 100644 --- a/packetbeat/protos/amqp/amqp_fields.go +++ b/packetbeat/protos/amqp/amqp_fields.go @@ -28,9 +28,9 @@ import ( "github.com/elastic/beats/v7/libbeat/logp" ) +// getTable updates fields with the table data at the given offset. +// fields must be non_nil on entry. func getTable(fields common.MapStr, data []byte, offset uint32) (next uint32, err bool, exists bool) { - ret := common.MapStr{} - length := binary.BigEndian.Uint32(data[offset : offset+4]) // size declared too big @@ -39,23 +39,20 @@ func getTable(fields common.MapStr, data []byte, offset uint32) (next uint32, er } if length > 0 { exists = true - err := fieldUnmarshal(ret, data[offset+4:offset+4+length], 0, length, -1) + table := common.MapStr{} + err := fieldUnmarshal(table, data[offset+4:offset+4+length], 0, length, -1) if err { logp.Warn("Error while parsing a field table") return 0, true, false } - if fields == nil { - fields = ret - } else { - fields.Update(ret) - } + fields.Update(table) } return length + 4 + offset, false, exists } +// getTable updates fields with the array data at the given offset. +// fields must be non_nil on entry. func getArray(fields common.MapStr, data []byte, offset uint32) (next uint32, err bool, exists bool) { - ret := common.MapStr{} - length := binary.BigEndian.Uint32(data[offset : offset+4]) // size declared too big @@ -64,30 +61,27 @@ func getArray(fields common.MapStr, data []byte, offset uint32) (next uint32, er } if length > 0 { exists = true - err := fieldUnmarshal(ret, data[offset+4:offset+4+length], 0, length, 0) + array := common.MapStr{} + err := fieldUnmarshal(array, data[offset+4:offset+4+length], 0, length, 0) if err { logp.Warn("Error while parsing a field array") return 0, true, false } - if fields == nil { - fields = ret - } else { - fields.Update(ret) - } + fields.Update(array) } return length + 4 + offset, false, exists } -//The index parameter, when set at -1, indicates that the entry is a field table. -//If it's set at 0, it is an array. +// The index parameter, when set at -1, indicates that the entry is a field table. +// If it's set at 0, it is an array. func fieldUnmarshal(table common.MapStr, data []byte, offset uint32, length uint32, index int) (err bool) { var name string if offset >= length { return false } - //get name of the field. If it's an array, it will be the index parameter as a - //string. If it's a table, it will be the name of the field. + // get name of the field. If it's an array, it will be the index parameter as a + // string. If it's a table, it will be the name of the field. if index < 0 { fieldName, offsetTemp, err := getShortString(data, offset+1, uint32(data[offset])) if err { @@ -199,10 +193,10 @@ func fieldUnmarshal(table common.MapStr, data []byte, offset uint32, length uint table[name] = bodyToByteArray(data[offset+1+size : offset+5+size]) offset += 5 + size default: - //unknown field + // unknown field return true } - //advance to next field recursively + // advance to next field recursively return fieldUnmarshal(table, data, offset, length, index) } diff --git a/packetbeat/protos/amqp/amqp_methods.go b/packetbeat/protos/amqp/amqp_methods.go index 93cec5f2747..d74148026c5 100644 --- a/packetbeat/protos/amqp/amqp_methods.go +++ b/packetbeat/protos/amqp/amqp_methods.go @@ -32,7 +32,7 @@ func connectionStartMethod(m *amqpMessage, args []byte) (bool, bool) { properties := make(common.MapStr) next, err, exists := getTable(properties, args, 2) if err { - //failed to get de peer-properties, size may be wrong, let's quit + // failed to get de peer-properties, size may be wrong, let's quit logp.Warn("Failed to parse server properties in connection.start method") return false, false } @@ -54,7 +54,7 @@ func connectionStartMethod(m *amqpMessage, args []byte) (bool, bool) { "mechanisms": mechanisms, "locales": locales, } - //if there is a server properties table, add it + // if there is a server properties table, add it if exists { m.fields["server-properties"] = properties } @@ -65,7 +65,7 @@ func connectionStartOkMethod(m *amqpMessage, args []byte) (bool, bool) { properties := make(common.MapStr) next, err, exists := getTable(properties, args, 0) if err { - //failed to get de peer-properties, size may be wrong, let's quit + // failed to get de peer-properties, size may be wrong, let's quit logp.Warn("Failed to parse server properties in connection.start method") return false, false } @@ -89,7 +89,7 @@ func connectionStartOkMethod(m *amqpMessage, args []byte) (bool, bool) { "mechanism": mechanism, "locale": locale, } - //if there is a client properties table, add it + // if there is a client properties table, add it if exists { m.fields["client-properties"] = properties } @@ -99,8 +99,8 @@ func connectionStartOkMethod(m *amqpMessage, args []byte) (bool, bool) { func connectionTuneMethod(m *amqpMessage, args []byte) (bool, bool) { m.isRequest = true m.method = "connection.tune" - //parameters are not parsed here, they are further negotiated by the server - //in the connection.tune-ok method + // parameters are not parsed here, they are further negotiated by the server + // in the connection.tune-ok method return true, true } @@ -163,7 +163,7 @@ func channelCloseMethod(m *amqpMessage, args []byte) (bool, bool) { return true, true } -//function to fetch fields from channel close and connection close +// function to fetch fields from channel close and connection close func getCloseInfo(args []byte, m *amqpMessage) bool { code := binary.BigEndian.Uint16(args[0:2]) m.isRequest = true @@ -411,7 +411,7 @@ func exchangeDeleteMethod(m *amqpMessage, args []byte) (bool, bool) { return true, true } -//this is a method exclusive to RabbitMQ +// this is a method exclusive to RabbitMQ func exchangeBindMethod(m *amqpMessage, args []byte) (bool, bool) { m.method = "exchange.bind" err := exchangeBindUnbindInfo(m, args) @@ -421,7 +421,7 @@ func exchangeBindMethod(m *amqpMessage, args []byte) (bool, bool) { return true, true } -//this is a method exclusive to RabbitMQ +// this is a method exclusive to RabbitMQ func exchangeUnbindMethod(m *amqpMessage, args []byte) (bool, bool) { m.method = "exchange.unbind" err := exchangeBindUnbindInfo(m, args) @@ -588,7 +588,7 @@ func basicPublishMethod(m *amqpMessage, args []byte) (bool, bool) { func basicReturnMethod(m *amqpMessage, args []byte) (bool, bool) { code := binary.BigEndian.Uint16(args[0:2]) if code < 300 { - //not an error or exception ? not interesting + // not an error or exception ? not interesting return true, false } replyText, nextOffset, err := getShortString(args, 3, uint32(args[2])) @@ -707,7 +707,7 @@ func basicAckMethod(m *amqpMessage, args []byte) (bool, bool) { return true, true } -//this is a rabbitMQ specific method +// this is a rabbitMQ specific method func basicNackMethod(m *amqpMessage, args []byte) (bool, bool) { params := getBitParams(args[8]) m.method = "basic.nack" @@ -761,14 +761,14 @@ func txRollbackMethod(m *amqpMessage, args []byte) (bool, bool) { return true, true } -//simple function used when server/client responds to a sync method with no new info +// simple function used when server/client responds to a sync method with no new info func okMethod(m *amqpMessage, args []byte) (bool, bool) { return true, true } // function to get a short string. It sends back an error if slice is too short -//for declared length. if length == 0, the function sends back an empty string and -//advances the offset. Otherwise, it returns the string and the new offset +// for declared length. if length == 0, the function sends back an empty string and +// advances the offset. Otherwise, it returns the string and the new offset func getShortString(data []byte, start uint32, length uint32) (short string, nextOffset uint32, err bool) { if length == 0 { return "", start, false @@ -779,7 +779,7 @@ func getShortString(data []byte, start uint32, length uint32) (short string, nex return string(data[start : start+length]), start + length, false } -//function to extract bit information in various AMQP methods +// function to extract bit information in various AMQP methods func getBitParams(bits byte) (ret [5]bool) { if bits&16 == 16 { ret[4] = true diff --git a/packetbeat/protos/amqp/amqp_parser.go b/packetbeat/protos/amqp/amqp_parser.go index 6ab15ec8159..a623219ca0b 100644 --- a/packetbeat/protos/amqp/amqp_parser.go +++ b/packetbeat/protos/amqp/amqp_parser.go @@ -42,10 +42,10 @@ func (amqp *amqpPlugin) amqpMessageParser(s *amqpStream) (ok bool, complete bool f, err := readFrameHeader(s.data[s.parseOffset:]) if err { - //incorrect header + // incorrect header return false, false } else if f == nil { - //header not complete + // header not complete return true, false } @@ -67,17 +67,14 @@ func (amqp *amqpPlugin) amqpMessageParser(s *amqpStream) (ok bool, complete bool s.parseOffset += 8 + int(f.size) if !ok { return false, false - } else if complete { + } + if complete { return true, true } } return ok, complete } -func (s *amqpStream) prepareForNewMessage() { - s.message = nil -} - func isProtocolHeader(data []byte) (isHeader bool, version string) { if (string(data[:4]) == "AMQP") && data[4] == 0 { return true, string(data[5:8]) @@ -85,7 +82,7 @@ func isProtocolHeader(data []byte) (isHeader bool, version string) { return false, "" } -//func to read a frame header and check if it is valid and complete +// func to read a frame header and check if it is valid and complete func readFrameHeader(data []byte) (ret *amqpFrame, err bool) { var frame amqpFrame if len(data) < 8 { @@ -103,7 +100,7 @@ func readFrameHeader(data []byte) (ret *amqpFrame, err bool) { } frame.Type = frameType(data[0]) if frame.size == 0 { - //frame content is nil with heartbeat frames + // frame content is nil with heartbeat frames frame.content = nil } else { frame.content = data[7 : frame.size+7] @@ -159,7 +156,7 @@ func (amqp *amqpPlugin) decodeHeaderFrame(s *amqpStream, buf []byte) bool { s.message.bodySize = binary.BigEndian.Uint64(buf[4:12]) debugf("Received Header frame. A message of %d bytes is expected", s.message.bodySize) - if amqp.parseHeaders == true { + if amqp.parseHeaders { err := getMessageProperties(s, buf[12:]) if err { return false @@ -180,7 +177,7 @@ func (s *amqpStream) decodeBodyFrame(buf []byte) (ok bool, complete bool) { debugf("A body frame of %d bytes long has been transmitted", len(buf)) - //is the message complete ? If yes, let's publish it + // is the message complete ? If yes, let's publish it complete = uint64(len(s.message.body)) >= s.message.bodySize return true, complete @@ -190,16 +187,16 @@ func hasProperty(prop, flag byte) bool { return (prop & flag) == flag } -//function to get message content-type and content-encoding +// function to get message content-type and content-encoding func getMessageProperties(s *amqpStream, data []byte) bool { m := s.message - //properties are coded in the two first bytes + // properties are coded in the two first bytes prop1 := data[0] prop2 := data[1] var offset uint32 = 2 - //while last bit set, we have another property flag field + // while last bit set, we have another property flag field for lastbit := 1; data[lastbit]&1 == 1; { lastbit += 2 offset += 2 @@ -238,9 +235,10 @@ func getMessageProperties(s *amqpStream, data []byte) bool { } if hasProperty(prop1, deliveryModeProp) { - if data[offset] == 1 { + switch data[offset] { + case 1: m.fields["delivery-mode"] = "non-persistent" - } else if data[offset] == 2 { + case 2: m.fields["delivery-mode"] = "persistent" } offset++ @@ -337,20 +335,20 @@ func (amqp *amqpPlugin) handleAmqp(m *amqpMessage, tcptuple *common.TCPTuple, di m.direction = dir m.cmdlineTuple = amqp.watcher.FindProcessesTupleTCP(tcptuple.IPPort()) - if m.method == "basic.publish" { + switch { + case m.method == "basic.publish": amqp.handlePublishing(m) - } else if m.method == "basic.deliver" || m.method == "basic.return" || - m.method == "basic.get-ok" { + case m.method == "basic.deliver" || m.method == "basic.return" || m.method == "basic.get-ok": amqp.handleDelivering(m) - } else if m.isRequest == true { + case m.isRequest: amqp.handleAmqpRequest(m) - } else if m.isRequest == false { + default: // !m.isRequest amqp.handleAmqpResponse(m) } } func (amqp *amqpPlugin) mustHideCloseMethod(m *amqpMessage) bool { - return amqp.hideConnectionInformation == true && + return amqp.hideConnectionInformation && (m.method == "connection.close" || m.method == "channel.close") && - getReplyCode(m.fields) < uint16(300) + getReplyCode(m.fields) < 300 } diff --git a/packetbeat/protos/amqp/amqp_structs.go b/packetbeat/protos/amqp/amqp_structs.go index 387e8df6fcb..ada8441c45a 100644 --- a/packetbeat/protos/amqp/amqp_structs.go +++ b/packetbeat/protos/amqp/amqp_structs.go @@ -30,12 +30,12 @@ const ( transactionTimeout = 10 * 1e9 ) -//layout used when a timestamp must be parsed +// layout used when a timestamp must be parsed const ( amqpTimeLayout = "January _2 15:04:05 2006" ) -//Frame types and codes +// Frame types and codes type frameType byte @@ -50,7 +50,7 @@ const ( frameEndOctet byte = 206 ) -//Codes for MethodMap +// Codes for MethodMap type codeClass uint16 const ( @@ -137,7 +137,7 @@ const ( txRollbackOk codeMethod = 31 ) -//Message properties codes for byte prop1 in getMessageProperties +// Message properties codes for byte prop1 in getMessageProperties const ( expirationProp byte = 1 replyToProp byte = 2 @@ -149,7 +149,7 @@ const ( contentTypeProp byte = 128 ) -//Message properties codes for byte prop2 in getMessageProperties +// Message properties codes for byte prop2 in getMessageProperties const ( appIDProp byte = 8 @@ -159,7 +159,7 @@ const ( messageIDProp byte = 128 ) -//table types +// table types const ( boolean = 't' shortShortInt = 'b' @@ -179,7 +179,7 @@ const ( timestamp = 'T' fieldTable = 'F' noField = 'V' - byteArray = 'x' //rabbitMQ specific field + byteArray = 'x' // rabbitMQ specific field ) type amqpPrivateData struct { @@ -203,7 +203,7 @@ type amqpMessage struct { direction uint8 parseArguments bool - //mapstr containing all the options for the methods and header fields + // mapstr containing all the options for the methods and header fields fields common.MapStr body []byte diff --git a/packetbeat/protos/amqp/amqp_test.go b/packetbeat/protos/amqp/amqp_test.go index 725de0f3d11..9b7f7dca35c 100644 --- a/packetbeat/protos/amqp/amqp_test.go +++ b/packetbeat/protos/amqp/amqp_test.go @@ -96,7 +96,7 @@ func TestAmqp_FrameSize(t *testing.T) { _, amqp := amqpModForTests() - //incomplete frame + // incomplete frame data, err := hex.DecodeString("0100000000000c000a001fffff000200") assert.NoError(t, err) @@ -118,7 +118,7 @@ func TestAmqp_PartialFrameSize(t *testing.T) { _, amqp := amqpModForTests() - //incomplete frame + // incomplete frame data, err := hex.DecodeString("414d515000060606010000000000") assert.NoError(t, err) @@ -275,7 +275,7 @@ func TestAmqp_ExchangeDeletion(t *testing.T) { assert.Equal(t, false, m.fields["no-wait"]) } -//this method is exclusive to RabbitMQ +// this method is exclusive to RabbitMQ func TestAmqp_ExchangeBind(t *testing.T) { logp.TestingSetup(logp.WithSelectors("amqp", "amqpdetailed")) @@ -308,7 +308,7 @@ func TestAmqp_ExchangeBind(t *testing.T) { } } -//this method is exclusive to RabbitMQ +// this method is exclusive to RabbitMQ func TestAmqp_ExchangeUnbindTransaction(t *testing.T) { logp.TestingSetup(logp.WithSelectors("amqp", "amqpdetailed")) @@ -365,13 +365,13 @@ func TestAmqp_PublishMessage(t *testing.T) { req := protos.Packet{Payload: data} private := protos.ProtocolData(new(amqpPrivateData)) - //method frame + // method frame private = amqp.Parse(&req, tcptuple, 0, private) req = protos.Packet{Payload: data2} - //header frame + // header frame private = amqp.Parse(&req, tcptuple, 0, private) req = protos.Packet{Payload: data3} - //body frame + // body frame amqp.Parse(&req, tcptuple, 0, private) trans := expectTransaction(t, results) @@ -414,13 +414,13 @@ func TestAmqp_DeliverMessage(t *testing.T) { req := protos.Packet{Payload: data} private := protos.ProtocolData(new(amqpPrivateData)) - //method frame + // method frame private = amqp.Parse(&req, tcptuple, 0, private) req = protos.Packet{Payload: data2} - //header frame + // header frame private = amqp.Parse(&req, tcptuple, 0, private) req = protos.Packet{Payload: data3} - //body frame + // body frame amqp.Parse(&req, tcptuple, 0, private) trans := expectTransaction(t, results) @@ -467,7 +467,7 @@ func TestAmqp_MessagePropertiesFields(t *testing.T) { assert.Equal(t, "el mensaje", m.fields["message-id"]) assert.Equal(t, "love message", m.fields["type"]) assert.Equal(t, "text/plain", m.fields["content-type"]) - //assert.Equal(t, "September 15 15:31:44 2015", m.Fields["timestamp"]) + // assert.Equal(t, "September 15 15:31:44 2015", m.Fields["timestamp"]) priority, ok := m.fields["priority"].(uint8) if !ok { t.Errorf("Field should be present") @@ -576,7 +576,7 @@ func TestAmqp_RejectMessage(t *testing.T) { req := protos.Packet{Payload: data} private := protos.ProtocolData(new(amqpPrivateData)) - //method frame + // method frame amqp.Parse(&req, tcptuple, 0, private) trans := expectTransaction(t, results) @@ -668,8 +668,8 @@ func TestAmqp_MaxBodyLength(t *testing.T) { req := protos.Packet{Payload: data} private := protos.ProtocolData(new(amqpPrivateData)) - //method frame - private = amqp.Parse(&req, tcptuple, 0, private) + // method frame + amqp.Parse(&req, tcptuple, 0, private) trans := expectTransaction(t, results) @@ -699,7 +699,7 @@ func TestAmqp_MaxBodyLength(t *testing.T) { req = protos.Packet{Payload: data} private = protos.ProtocolData(new(amqpPrivateData)) - //method frame + // method frame amqp.Parse(&req, tcptuple, 0, private) trans = expectTransaction(t, results) @@ -728,7 +728,7 @@ func TestAmqp_HideArguments(t *testing.T) { amqp.parseHeaders = false amqp.parseArguments = false - //parse args + // parse args data, err := hex.DecodeString("0100010000004d0032000a00000a5465737448656164" + "6572180000003704626f6f6c74010362697462050568656c6c6f530000001f4869206461" + "726c696e6720c3aac3aac3aac3aac3aac3aac3aae697a5e69cacce") @@ -736,7 +736,7 @@ func TestAmqp_HideArguments(t *testing.T) { tcptuple := testTCPTuple() req := protos.Packet{Payload: data} private := protos.ProtocolData(new(amqpPrivateData)) - private = amqp.Parse(&req, tcptuple, 0, private) + amqp.Parse(&req, tcptuple, 0, private) trans := expectTransaction(t, results) assert.Equal(t, "queue.declare", trans["method"]) @@ -753,7 +753,7 @@ func TestAmqp_HideArguments(t *testing.T) { t.Errorf("Arguments field should not be present") } - //parse headers + // parse headers data, err = hex.DecodeString("01000100000013003c00280000000a546573744865616" + "4657200ce02000100000026003c0000000000000000001a98800a746578742f706c61696" + "e02060a656c206d656e73616a65ce0300010000001a54657374206865616465722066696" + @@ -808,7 +808,7 @@ func TestAmqp_RecoverMethod(t *testing.T) { assert.Equal(t, common.MapStr{"requeue": true}, trans["amqp"]) } -//this is a specific rabbitMQ method +// this is a specific rabbitMQ method func TestAmqp_BasicNack(t *testing.T) { logp.TestingSetup(logp.WithSelectors("amqp", "amqpdetailed")) @@ -887,7 +887,7 @@ func TestAmqp_GetTable(t *testing.T) { assert.Equal(t, true, m.fields["no-wait"]) assert.Equal(t, true, m.fields["auto-delete"]) assert.Equal(t, false, m.fields["exclusive"]) - //assert.Equal(t, "September 15 11:25:29 2015", args["timestamp"]) + // assert.Equal(t, "September 15 11:25:29 2015", args["timestamp"]) assert.Equal(t, "TestHeader", m.request) } @@ -948,7 +948,7 @@ func TestAmqp_ArrayFields(t *testing.T) { _, amqp := amqpModForTests() - //byte array, rabbitMQ specific field + // byte array, rabbitMQ specific field data, err := hex.DecodeString("010001000000260028000a0000057465737431057" + "46f706963020000000f05617272617978000000040a007dd2ce") assert.NoError(t, err) @@ -1025,7 +1025,7 @@ func TestAmqp_WrongTable(t *testing.T) { _, amqp := amqpModForTests() - //declared table size too big + // declared table size too big data, err := hex.DecodeString("010001000000890032000a00000a54657374486561646" + "57218000000da0974696d657374616d70540000000055f7e409036269746205076465636" + "96d616c440500ec49050568656c6c6f530000001f4869206461726c696e6720c3aac3aac" + @@ -1048,7 +1048,7 @@ func TestAmqp_WrongTable(t *testing.T) { } assert.Equal(t, []string{"Failed to parse additional arguments"}, m.notes) - //table size ok, but total non-sense inside + // table size ok, but total non-sense inside data, err = hex.DecodeString("010001000000890032000a00000a54657374486561646" + "57218000000730974696d657374616d7054004400005521e409036269743705076400036" + "96d616c447600ec49180568036c6c0b536400001f480a2064076e6c696e0520c3aac3aac" + diff --git a/packetbeat/protos/amqp/config.go b/packetbeat/protos/amqp/config.go index 2939530046e..4cbd5a5200a 100644 --- a/packetbeat/protos/amqp/config.go +++ b/packetbeat/protos/amqp/config.go @@ -30,14 +30,12 @@ type amqpConfig struct { HideConnectionInformation bool `config:"hide_connection_information"` } -var ( - defaultConfig = amqpConfig{ - ProtocolCommon: config.ProtocolCommon{ - TransactionTimeout: protos.DefaultTransactionExpiration, - }, - ParseHeaders: true, - ParseArguments: true, - MaxBodyLength: 1000, - HideConnectionInformation: true, - } -) +var defaultConfig = amqpConfig{ + ProtocolCommon: config.ProtocolCommon{ + TransactionTimeout: protos.DefaultTransactionExpiration, + }, + ParseHeaders: true, + ParseArguments: true, + MaxBodyLength: 1000, + HideConnectionInformation: true, +} diff --git a/packetbeat/protos/cassandra/cassandra.go b/packetbeat/protos/cassandra/cassandra.go index 7d3001a5159..5c7cbd003d1 100644 --- a/packetbeat/protos/cassandra/cassandra.go +++ b/packetbeat/protos/cassandra/cassandra.go @@ -50,9 +50,7 @@ type stream struct { parser parser } -var ( - debugf = logp.MakeDebug("cassandra") -) +var debugf = logp.MakeDebug("cassandra") func init() { protos.Register("cassandra", New) @@ -202,11 +200,6 @@ func (cassandra *cassandra) ensureConnection(private protos.ProtocolData) *conne return conn } -func (conn *connection) dropStreams() { - conn.streams[0] = nil - conn.streams[1] = nil -} - func getConnection(private protos.ProtocolData) *connection { if private == nil { return nil diff --git a/packetbeat/protos/cassandra/config.go b/packetbeat/protos/cassandra/config.go index 0eafddcd1ee..8e93239bc6b 100644 --- a/packetbeat/protos/cassandra/config.go +++ b/packetbeat/protos/cassandra/config.go @@ -34,20 +34,18 @@ type cassandraConfig struct { OPsIgnored []gocql.FrameOp `config:"ignored_ops"` } -var ( - defaultConfig = cassandraConfig{ - ProtocolCommon: config.ProtocolCommon{ - TransactionTimeout: protos.DefaultTransactionExpiration, - SendRequest: true, - SendResponse: true, - }, - SendRequestHeader: true, - SendResponseHeader: true, - } -) +var defaultConfig = cassandraConfig{ + ProtocolCommon: config.ProtocolCommon{ + TransactionTimeout: protos.DefaultTransactionExpiration, + SendRequest: true, + SendResponse: true, + }, + SendRequestHeader: true, + SendResponseHeader: true, +} func (c *cassandraConfig) Validate() error { - if !(c.Compressor == "" || c.Compressor == "snappy") { + if c.Compressor != "" && c.Compressor != "snappy" { return fmt.Errorf("invalid compressor config: %s, only snappy supported", c.Compressor) } return nil diff --git a/packetbeat/protos/cassandra/internal/gocql/array_decoder.go b/packetbeat/protos/cassandra/internal/gocql/array_decoder.go index a224dc7d1b5..b64ecf8e146 100644 --- a/packetbeat/protos/cassandra/internal/gocql/array_decoder.go +++ b/packetbeat/protos/cassandra/internal/gocql/array_decoder.go @@ -26,10 +26,6 @@ type ByteArrayDecoder struct { Data *[]byte } -func readInt(p []byte) int32 { - return int32(p[0])<<24 | int32(p[1])<<16 | int32(p[2])<<8 | int32(p[3]) -} - func (f ByteArrayDecoder) ReadByte() (byte, error) { data := *f.Data if len(data) < 1 { @@ -167,7 +163,7 @@ func (f ByteArrayDecoder) ReadInet() (net.IP, int) { size := data[0] *f.Data = data[1:] - if !(size == 4 || size == 16) { + if size != 4 && size != 16 { panic(fmt.Errorf("invalid IP size: %d", size)) } diff --git a/packetbeat/protos/cassandra/internal/gocql/compressor.go b/packetbeat/protos/cassandra/internal/gocql/compressor.go index cfbff208ade..fe6583c3a77 100644 --- a/packetbeat/protos/cassandra/internal/gocql/compressor.go +++ b/packetbeat/protos/cassandra/internal/gocql/compressor.go @@ -49,11 +49,11 @@ func (s SnappyCompressor) Decode(data []byte) ([]byte, error) { const LZ4 string = "lz4" type LZ4Compressor struct { - //TODO + // TODO } const Deflate string = "deflate" type DeflateCompressor struct { - //TODO + // TODO } diff --git a/packetbeat/protos/cassandra/internal/gocql/decoder.go b/packetbeat/protos/cassandra/internal/gocql/decoder.go index 734a940d8bd..f628aa65120 100644 --- a/packetbeat/protos/cassandra/internal/gocql/decoder.go +++ b/packetbeat/protos/cassandra/internal/gocql/decoder.go @@ -23,34 +23,19 @@ import ( type Decoder interface { ReadByte() (byte, error) - ReadInt() (n int) - ReadShort() (n uint16) - ReadLong() (n int64) - ReadString() (s string) - ReadLongString() (s string) - ReadUUID() *UUID - ReadStringList() []string - ReadBytesInternal() []byte - ReadBytes() []byte - ReadShortBytes() []byte - ReadInet() (net.IP, int) - ReadConsistency() Consistency - ReadStringMap() map[string]string - ReadBytesMap() map[string][]byte - ReadStringMultiMap() map[string][]string } diff --git a/packetbeat/protos/cassandra/internal/gocql/frame.go b/packetbeat/protos/cassandra/internal/gocql/frame.go index 25e7df5bac8..b8ae7eeac4e 100644 --- a/packetbeat/protos/cassandra/internal/gocql/frame.go +++ b/packetbeat/protos/cassandra/internal/gocql/frame.go @@ -182,18 +182,17 @@ func (f *Framer) ReadFrame() (data map[string]interface{}, err error) { data = make(map[string]interface{}) - //Only QUERY, PREPARE and EXECUTE queries support tracing - //If a response frame has the tracing flag set, its body contains - //a tracing ID. The tracing ID is a [uuid] and is the first thing in - //the frame body. The rest of the body will then be the usual body - //corresponding to the response opcode. + // Only QUERY, PREPARE and EXECUTE queries support tracing + // If a response frame has the tracing flag set, its body contains + // a tracing ID. The tracing ID is a [uuid] and is the first thing in + // the frame body. The rest of the body will then be the usual body + // corresponding to the response opcode. if f.Header.Flags&flagTracing == flagTracing && (f.Header.Op&opQuery == opQuery || f.Header.Op&opExecute == opExecute || f.Header.Op&opPrepare == opPrepare) { - debugf("tracing enabled") - //seems no UUID to read, protocol incorrect? - //uid := decoder.ReadUUID() - //data["trace_id"] = uid.String() + // seems no UUID to read, protocol incorrect? + // uid := decoder.ReadUUID() + // data["trace_id"] = uid.String() } if f.Header.Flags&flagWarning == flagWarning { @@ -211,7 +210,7 @@ func (f *Framer) ReadFrame() (data map[string]interface{}, err error) { } if f.Header.Flags&flagCompress == flagCompress { - //decompress data and switch to use bytearray decoder + // decompress data and switch to use bytearray decoder if f.compres == nil { logp.Err("hit compress flag, but compressor was not set") panic(errors.New("hit compress flag, but compressor was not set")) @@ -234,13 +233,13 @@ func (f *Framer) ReadFrame() (data map[string]interface{}, err error) { // assumes that the frame body has been read into rbuf switch f.Header.Op { - //below ops are requests + // below ops are requests case opStartup, opAuthResponse, opOptions, opPrepare, opExecute, opBatch, opRegister: - //ignored + // ignored case opQuery: data = f.parseQueryFrame() - //below ops are responses + // below ops are responses case opError: data["error"] = f.parseErrorFrame() case opResult: @@ -259,7 +258,7 @@ func (f *Framer) ReadFrame() (data map[string]interface{}, err error) { // the body should be empty default: - //ignore + // ignore debugf("unknow ops, not processed, %v", f.Header) } @@ -348,7 +347,7 @@ func (f *Framer) parseErrorFrame() (data map[string]interface{}) { case errInvalid, errBootstrapping, errConfig, errCredentials, errOverloaded, errProtocol, errServer, errSyntax, errTruncate, errUnauthorized: - //ignored + // ignored default: logp.Err("unknown error code: 0x%x", code) } @@ -375,8 +374,7 @@ func (f *Framer) parseResultMetadata(getPKinfo bool) map[string]interface{} { meta["col_count"] = colCount if getPKinfo { - - //only for prepared result + // only for prepared result if f.proto >= protoVersion4 { pkeyCount := decoder.ReadInt() pkeys := make([]int, pkeyCount) @@ -450,7 +448,6 @@ func (f *Framer) parseResultPrepared() map[string]interface{} { result := make(map[string]interface{}) uuid, err := UUIDFromBytes((f.decoder).ReadShortBytes()) - if err != nil { logp.Err("Error in parsing UUID") } diff --git a/packetbeat/protos/cassandra/internal/gocql/marshal.go b/packetbeat/protos/cassandra/internal/gocql/marshal.go index 2061bb2f11e..3c55781cc81 100644 --- a/packetbeat/protos/cassandra/internal/gocql/marshal.go +++ b/packetbeat/protos/cassandra/internal/gocql/marshal.go @@ -349,8 +349,8 @@ const ( errUnprepared ErrType = 0x2500 ) -func (this ErrType) String() string { - switch this { +func (e ErrType) String() string { + switch e { case errUnavailable: return "errUnavailable" case errWriteTimeout: @@ -680,7 +680,7 @@ func (u UUID) Bytes() []byte { // String returns the UUID in it's canonical form, a 32 digit hexadecimal // number in the form of xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx. func (u UUID) String() string { - var offsets = [...]int{0, 2, 4, 6, 9, 11, 14, 16, 19, 21, 24, 26, 28, 30, 32, 34} + offsets := [...]int{0, 2, 4, 6, 9, 11, 14, 16, 19, 21, 24, 26, 28, 30, 32, 34} const hexString = "0123456789abcdef" r := make([]byte, 36) for i, b := range u { diff --git a/packetbeat/protos/cassandra/internal/gocql/stream_decoder.go b/packetbeat/protos/cassandra/internal/gocql/stream_decoder.go index ae107a95e9e..f39cde2d11e 100644 --- a/packetbeat/protos/cassandra/internal/gocql/stream_decoder.go +++ b/packetbeat/protos/cassandra/internal/gocql/stream_decoder.go @@ -149,7 +149,7 @@ func (f StreamDecoder) ReadInet() (net.IP, int) { panic(err) } - if !(size == 4 || size == 16) { + if size != 4 && size != 16 { panic(fmt.Errorf("invalid IP size: %d", size)) } diff --git a/packetbeat/protos/cassandra/parser.go b/packetbeat/protos/cassandra/parser.go index f699187b03f..65ff347a1ea 100644 --- a/packetbeat/protos/cassandra/parser.go +++ b/packetbeat/protos/cassandra/parser.go @@ -44,14 +44,7 @@ type parserConfig struct { // check whether this ops is enabled or not func (p *parser) CheckFrameOpsIgnored() bool { - if p.config.ignoredOps != nil && len(p.config.ignoredOps) > 0 { - //default map value is false - v := p.config.ignoredOps[p.framer.Header.Op] - if v { - return true - } - } - return false + return p.config.ignoredOps[p.framer.Header.Op] } type message struct { @@ -69,8 +62,6 @@ type message struct { // list element use by 'transactions' for correlation next *message - transactionTimeout time.Duration - results transactions } @@ -91,7 +82,6 @@ func (p *parser) init( } isDebug = logp.IsDebug("cassandra") - } func (p *parser) append(data []byte) error { @@ -153,7 +143,7 @@ func (p *parser) parserBody() (bool, error) { return true, nil } - //let's wait for enough buf + // let's wait for enough buf debugf("bodyLength: %d", bdyLen) if !p.buf.Avail(bdyLen) { if isDebug { @@ -162,7 +152,7 @@ func (p *parser) parserBody() (bool, error) { return false, nil } - //check if the ops already ignored + // check if the ops already ignored if p.message.ignored { if isDebug { debugf("message marked to be ignored, let's do this") @@ -232,7 +222,7 @@ func (p *parser) parse() (*message, error) { } } - //check if the ops need to be ignored + // check if the ops need to be ignored if p.CheckFrameOpsIgnored() { // as we already ignore the content, we now mark the result is ignored p.message.ignored = true @@ -248,7 +238,7 @@ func (p *parser) parse() (*message, error) { return nil, err } - //ignore and wait for more data + // ignore and wait for more data if !finished { return nil, nil } diff --git a/packetbeat/protos/cassandra/pub.go b/packetbeat/protos/cassandra/pub.go index 3b90c53feae..82effab92d3 100644 --- a/packetbeat/protos/cassandra/pub.go +++ b/packetbeat/protos/cassandra/pub.go @@ -33,7 +33,6 @@ type transPub struct { sendResponse bool sendRequestHeader bool sendResponseHeader bool - ignoredOps string results protos.Reporter } @@ -82,7 +81,7 @@ func (pub *transPub) createEvent(requ, resp *message) beat.Event { cassandra := common.MapStr{} status := common.OK_STATUS - //requ can be null, if the message is a PUSHed message + // requ can be null, if the message is a PUSHed message if requ != nil { pbf.Source.Bytes = int64(requ.Size) pbf.Event.Start = requ.Ts @@ -101,7 +100,7 @@ func (pub *transPub) createEvent(requ, resp *message) beat.Event { } } } else { - //dealing with PUSH message + // dealing with PUSH message cassandra["no_request"] = true } diff --git a/packetbeat/protos/cassandra/trans.go b/packetbeat/protos/cassandra/trans.go index 9b055d22c88..d7a9ae60d5f 100644 --- a/packetbeat/protos/cassandra/trans.go +++ b/packetbeat/protos/cassandra/trans.go @@ -132,7 +132,6 @@ func (trans *transactions) onResponse( func (trans *transactions) tryMergeRequests( prev, msg *message, ) (merged bool, err error) { - msg.isComplete = true return false, nil } @@ -150,7 +149,7 @@ func (trans *transactions) correlate() error { if requests.empty() { for !responses.empty() { - //if the response is EVENT, which pushed from server, we can accept that + // if the response is EVENT, which pushed from server, we can accept that resp := responses.first() if !resp.isComplete { break diff --git a/packetbeat/protos/dhcpv4/config.go b/packetbeat/protos/dhcpv4/config.go index 4121ee66ba7..7245e3c641b 100644 --- a/packetbeat/protos/dhcpv4/config.go +++ b/packetbeat/protos/dhcpv4/config.go @@ -25,10 +25,8 @@ type dhcpv4Config struct { config.ProtocolCommon `config:",inline"` } -var ( - defaultConfig = dhcpv4Config{ - ProtocolCommon: config.ProtocolCommon{ - Ports: []int{67, 68}, - }, - } -) +var defaultConfig = dhcpv4Config{ + ProtocolCommon: config.ProtocolCommon{ + Ports: []int{67, 68}, + }, +} diff --git a/packetbeat/protos/dns/config.go b/packetbeat/protos/dns/config.go index c98d52f8257..c1044cf2f7c 100644 --- a/packetbeat/protos/dns/config.go +++ b/packetbeat/protos/dns/config.go @@ -28,10 +28,8 @@ type dnsConfig struct { IncludeAdditionals bool `config:"include_additionals"` } -var ( - defaultConfig = dnsConfig{ - ProtocolCommon: config.ProtocolCommon{ - TransactionTimeout: protos.DefaultTransactionExpiration, - }, - } -) +var defaultConfig = dnsConfig{ + ProtocolCommon: config.ProtocolCommon{ + TransactionTimeout: protos.DefaultTransactionExpiration, + }, +} diff --git a/packetbeat/protos/dns/dns.go b/packetbeat/protos/dns/dns.go index 125d6112bae..04be88a36b1 100644 --- a/packetbeat/protos/dns/dns.go +++ b/packetbeat/protos/dns/dns.go @@ -59,18 +59,10 @@ type dnsPlugin struct { watcher procs.ProcessesWatcher } -var ( - debugf = logp.MakeDebug("dns") -) +var debugf = logp.MakeDebug("dns") const maxDNSTupleRawSize = 16 + 16 + 2 + 2 + 4 + 1 -// Constants used to associate the DNS QR flag with a meaningful value. -const ( - query = false - response = true -) - // Transport protocol. type transport uint8 @@ -203,13 +195,12 @@ func (dns *dnsPlugin) getTransaction(k hashableDNSTuple) *dnsTransaction { } type dnsTransaction struct { - ts time.Time // Time when the request was received. - tuple dnsTuple // Key used to track this transaction in the transactionsMap. - responseTime int32 // Elapsed time in milliseconds between the request and response. - src common.Endpoint - dst common.Endpoint - transport transport - notes []string + ts time.Time // Time when the request was received. + tuple dnsTuple // Key used to track this transaction in the transactionsMap. + src common.Endpoint + dst common.Endpoint + transport transport + notes []string request *dnsMessage response *dnsMessage diff --git a/packetbeat/protos/dns/dns_tcp.go b/packetbeat/protos/dns/dns_tcp.go index bbf7e736926..8addcdd6896 100644 --- a/packetbeat/protos/dns/dns_tcp.go +++ b/packetbeat/protos/dns/dns_tcp.go @@ -107,7 +107,6 @@ func (dns *dnsPlugin) doParse(conn *dnsConnectionData, pkt *protos.Packet, tcpTu } } decodedData, err := stream.handleTCPRawData() - if err != nil { if err == incompleteMsg { @@ -259,8 +258,8 @@ func (dns *dnsPlugin) publishResponseError(conn *dnsConnectionData, err error) { trans.notes = append(trans.notes, errDNS.responseError()) // Should we publish the length (bytes_out) of the failed Response? - //streamReverse.message.Length = len(streamReverse.rawData) - //trans.Response = streamReverse.message + // streamReverse.message.Length = len(streamReverse.rawData) + // trans.Response = streamReverse.message dns.publishTransaction(trans) dns.deleteTransaction(hashDNSTupleOrigin) @@ -296,7 +295,6 @@ func (stream *dnsStream) handleTCPRawData() (*mkdns.Msg, error) { } decodedData, err := decodeDNSData(transportTCP, rawData[:stream.parseOffset]) - if err != nil { return nil, err } diff --git a/packetbeat/protos/dns/dns_test.go b/packetbeat/protos/dns/dns_test.go index 9427ebeaecf..1ba03b2bd61 100644 --- a/packetbeat/protos/dns/dns_test.go +++ b/packetbeat/protos/dns/dns_test.go @@ -316,8 +316,10 @@ func TestRRsToMapStrsWithOPTRecord(t *testing.T) { o.Hdr.Rrtype = mkdns.TypeOPT r := new(mkdns.MX) - r.Hdr = mkdns.RR_Header{Name: "miek.nl", Rrtype: mkdns.TypeMX, - Class: mkdns.ClassINET, Ttl: 3600} + r.Hdr = mkdns.RR_Header{ + Name: "miek.nl", Rrtype: mkdns.TypeMX, + Class: mkdns.ClassINET, Ttl: 3600, + } r.Preference = 10 r.Mx = "mx.miek.nl" diff --git a/packetbeat/protos/dns/dns_udp_test.go b/packetbeat/protos/dns/dns_udp_test.go index 3711fb50e00..62713502e0a 100644 --- a/packetbeat/protos/dns/dns_udp_test.go +++ b/packetbeat/protos/dns/dns_udp_test.go @@ -155,10 +155,12 @@ var ( qSubdomain: "131.252.30", qTLD: "in-addr.arpa", answers: []string{"github.com"}, - authorities: []string{"a.root-servers.net", "b.root-servers.net", "c.root-servers.net", + authorities: []string{ + "a.root-servers.net", "b.root-servers.net", "c.root-servers.net", "d.root-servers.net", "e.root-servers.net", "f.root-servers.net", "g.root-servers.net", "h.root-servers.net", "i.root-servers.net", "j.root-servers.net", "k.root-servers.net", - "l.root-servers.net", "m.root-servers.net"}, + "l.root-servers.net", "m.root-servers.net", + }, request: []byte{ 0x01, 0x58, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x31, 0x33, 0x31, 0x03, 0x32, 0x35, 0x32, 0x02, 0x33, 0x30, 0x03, 0x31, 0x39, 0x32, 0x07, 0x69, 0x6e, 0x2d, 0x61, diff --git a/packetbeat/protos/http/config.go b/packetbeat/protos/http/config.go index 86f59fb36b1..45878934b0c 100644 --- a/packetbeat/protos/http/config.go +++ b/packetbeat/protos/http/config.go @@ -39,12 +39,10 @@ type httpConfig struct { RedactHeaders []string `config:"redact_headers"` } -var ( - defaultConfig = httpConfig{ - ProtocolCommon: config.ProtocolCommon{ - TransactionTimeout: protos.DefaultTransactionExpiration, - }, - MaxMessageSize: tcp.TCPMaxDataInStream, - DecodeBody: true, - } -) +var defaultConfig = httpConfig{ + ProtocolCommon: config.ProtocolCommon{ + TransactionTimeout: protos.DefaultTransactionExpiration, + }, + MaxMessageSize: tcp.TCPMaxDataInStream, + DecodeBody: true, +} diff --git a/packetbeat/protos/http/http.go b/packetbeat/protos/http/http.go index e86cb665587..9cc436f84f0 100644 --- a/packetbeat/protos/http/http.go +++ b/packetbeat/protos/http/http.go @@ -39,8 +39,10 @@ import ( "github.com/elastic/beats/v7/packetbeat/protos" ) -var debugf = logp.MakeDebug("http") -var detailedf = logp.MakeDebug("httpdetailed") +var ( + debugf = logp.MakeDebug("http") + detailedf = logp.MakeDebug("httpdetailed") +) type parserState uint8 @@ -300,7 +302,6 @@ func (http *httpPlugin) doParse( tcptuple *common.TCPTuple, dir uint8, ) *httpConnectionData { - if isDetailed { detailedf("Payload received: [%s]", pkt.Payload) } @@ -368,8 +369,8 @@ func newStream(pkt *protos.Packet, tcptuple *common.TCPTuple) *stream { // ReceivedFin will be called when TCP transaction is terminating. func (http *httpPlugin) ReceivedFin(tcptuple *common.TCPTuple, dir uint8, - private protos.ProtocolData) protos.ProtocolData { - + private protos.ProtocolData, +) protos.ProtocolData { debugf("Received FIN") conn := getHTTPConnection(private) if conn == nil { @@ -396,8 +397,8 @@ func (http *httpPlugin) ReceivedFin(tcptuple *common.TCPTuple, dir uint8, // GapInStream is called when a gap of nbytes bytes is found in the stream (due // to packet loss). func (http *httpPlugin) GapInStream(tcptuple *common.TCPTuple, dir uint8, - nbytes int, private protos.ProtocolData) (priv protos.ProtocolData, drop bool) { - + nbytes int, private protos.ProtocolData) (priv protos.ProtocolData, drop bool, +) { defer logp.Recover("GapInStream(http) exception") conn := getHTTPConnection(private) @@ -436,7 +437,6 @@ func (http *httpPlugin) handleHTTP( tcptuple *common.TCPTuple, dir uint8, ) { - m.tcpTuple = *tcptuple m.direction = dir m.cmdlineTuple = http.watcher.FindProcessesTupleTCP(tcptuple.IPPort()) @@ -488,7 +488,6 @@ func (http *httpPlugin) flushRequests(conn *httpConnectionData) { } func (http *httpPlugin) correlate(conn *httpConnectionData) { - // drop responses with missing requests if conn.requests.empty() { http.flushResponses(conn) @@ -724,8 +723,7 @@ func splitCookiesHeader(headerVal string) map[string]string { for _, cval := range cstring { cookie := strings.SplitN(cval, "=", 2) if len(cookie) == 2 { - cookies[strings.ToLower(strings.TrimSpace(cookie[0]))] = - parseCookieValue(strings.TrimSpace(cookie[1])) + cookies[strings.ToLower(strings.TrimSpace(cookie[0]))] = parseCookieValue(strings.TrimSpace(cookie[1])) } } @@ -928,10 +926,6 @@ func (ml *messageList) pop() *message { return msg } -func (ml *messageList) last() *message { - return ml.tail -} - func extractBasicAuthUser(headers map[string]common.NetString) string { const prefix = "Basic " diff --git a/packetbeat/protos/http/http_parser.go b/packetbeat/protos/http/http_parser.go index be4343ea120..a903460f772 100644 --- a/packetbeat/protos/http/http_parser.go +++ b/packetbeat/protos/http/http_parser.go @@ -45,7 +45,7 @@ type message struct { cmdlineTuple *common.ProcessTuple direction uint8 - //Request Info + // Request Info requestURI common.NetString method common.NetString statusCode uint16 @@ -187,7 +187,7 @@ func (*parser) parseHTTPLine(s *stream, m *message) (cont, ok, complete bool) { return false, false, false } if bytes.Equal(fline[0:5], constHTTPVersion) { - //RESPONSE + // RESPONSE m.isRequest = false version = fline[5:8] m.statusCode, m.statusPhrase, err = parseResponseStatus(fline[9:]) @@ -289,7 +289,7 @@ func (parser *parser) parseHeaders(s *stream, m *message) (cont, ok, complete bo s.parseOffset = 0 if !m.isRequest && ((100 <= m.statusCode && m.statusCode < 200) || m.statusCode == 204 || m.statusCode == 304) { - //response with a 1xx, 204 , or 304 status code is always terminated + // response with a 1xx, 204 , or 304 status code is always terminated // by the first empty line after the header fields if isDebug { debugf("Terminate response, status code %d", m.statusCode) diff --git a/packetbeat/protos/http/http_test.go b/packetbeat/protos/http/http_test.go index 0fa9077a5ed..4179a047d56 100644 --- a/packetbeat/protos/http/http_test.go +++ b/packetbeat/protos/http/http_test.go @@ -56,10 +56,6 @@ func (e *eventStore) publish(event beat.Event) { e.events = append(e.events, event) } -func (e *eventStore) empty() bool { - return len(e.events) == 0 -} - func newTestParser(http *httpPlugin, payloads ...string) *testParser { if http == nil { http = httpModForTests(nil) @@ -538,7 +534,7 @@ func TestHttpParser_RequestResponseBody(t *testing.T) { tp.stream.PrepareForNewMessage() tp.stream.message = &message{ts: time.Now()} - msg, ok, complete = tp.parse() + _, ok, complete = tp.parse() assert.True(t, ok) assert.True(t, complete) } @@ -646,17 +642,23 @@ func TestEatBodyChunked(t *testing.T) { st.data = append(st.data, msgs[1]...) cont, ok, complete = parser.parseBodyChunkedStart(st, msg) assert.True(t, cont) + assert.True(t, ok) + assert.False(t, complete) assert.Equal(t, 3, msg.chunkedLength) assert.Equal(t, 0, len(msg.body)) assert.Equal(t, stateBodyChunked, st.parseState) cont, ok, complete = parser.parseBodyChunked(st, msg) assert.True(t, cont) + assert.True(t, ok) + assert.False(t, complete) assert.Equal(t, stateBodyChunkedStart, st.parseState) assert.Equal(t, 3, msg.contentLength) cont, ok, complete = parser.parseBodyChunkedStart(st, msg) assert.True(t, cont) + assert.True(t, ok) + assert.False(t, complete) assert.Equal(t, 3, msg.chunkedLength) assert.Equal(t, 3, msg.contentLength) assert.Equal(t, stateBodyChunked, st.parseState) @@ -672,6 +674,8 @@ func TestEatBodyChunked(t *testing.T) { st.data = append(st.data, msgs[2]...) cont, ok, complete = parser.parseBodyChunked(st, msg) assert.True(t, cont) + assert.True(t, ok) + assert.False(t, complete) assert.Equal(t, 6, msg.contentLength) assert.Equal(t, stateBodyChunkedStart, st.parseState) @@ -729,7 +733,6 @@ func TestEatBodyChunkedWaitCRLF(t *testing.T) { ok, complete = parser.parseBodyChunkedWaitFinalCRLF(st, msg) if ok != true || complete != false { t.Error("Wrong return values", ok, complete) - } st.data = append(st.data, msgs[1]...) @@ -817,13 +820,12 @@ func TestHttpParser_censorPasswordPOST(t *testing.T) { http.parserConfig.sendHeaders = true http.parserConfig.sendAllHeaders = true - data1 := - "POST /users/login HTTP/1.1\r\n" + - "HOST: www.example.com\r\n" + - "Content-Type: application/x-www-form-urlencoded\r\n" + - "Content-Length: 28\r\n" + - "\r\n" + - "username=ME&password=secret\r\n" + data1 := "POST /users/login HTTP/1.1\r\n" + + "HOST: www.example.com\r\n" + + "Content-Type: application/x-www-form-urlencoded\r\n" + + "Content-Length: 28\r\n" + + "\r\n" + + "username=ME&password=secret\r\n" tp := newTestParser(http, data1) msg, ok, complete := tp.parse() @@ -1511,7 +1513,8 @@ func TestHTTP_Encodings(t *testing.T) { gzipDeflateBody := string([]byte{ 0x1f, 0x8b, 0x08, 0x00, 0x65, 0xdb, 0x6a, 0x5b, 0x00, 0x03, 0x3b, 0x7d, 0xe2, 0xbc, 0xe7, 0x13, 0x26, 0x06, 0x00, 0x95, 0xfa, 0x49, 0xbf, 0x07, - 0x00, 0x00, 0x00}) + 0x00, 0x00, 0x00, + }) var store eventStore http := httpModForTests(&store) diff --git a/packetbeat/protos/icmp/config.go b/packetbeat/protos/icmp/config.go index cb3ee28d7f9..4fcdb6667e5 100644 --- a/packetbeat/protos/icmp/config.go +++ b/packetbeat/protos/icmp/config.go @@ -29,8 +29,6 @@ type icmpConfig struct { TransactionTimeout time.Duration `config:"transaction_timeout"` } -var ( - defaultConfig = icmpConfig{ - TransactionTimeout: protos.DefaultTransactionExpiration, - } -) +var defaultConfig = icmpConfig{ + TransactionTimeout: protos.DefaultTransactionExpiration, +} diff --git a/packetbeat/protos/icmp/icmp.go b/packetbeat/protos/icmp/icmp.go index 521bb019ce6..d6804322c43 100644 --- a/packetbeat/protos/icmp/icmp.go +++ b/packetbeat/protos/icmp/icmp.go @@ -21,6 +21,8 @@ import ( "net" "time" + "github.com/google/gopacket/layers" + "github.com/elastic/beats/v7/libbeat/common" "github.com/elastic/beats/v7/libbeat/ecs" "github.com/elastic/beats/v7/libbeat/logp" @@ -30,8 +32,6 @@ import ( "github.com/elastic/beats/v7/packetbeat/pb" "github.com/elastic/beats/v7/packetbeat/procs" "github.com/elastic/beats/v7/packetbeat/protos" - - "github.com/tsg/gopacket/layers" ) type icmpPlugin struct { @@ -102,7 +102,7 @@ func (icmp *icmpPlugin) init(results protos.Reporter, watcher procs.ProcessesWat } logp.Debug("icmp", "Local IP addresses: %s", icmp.localIps) - var removalListener = func(k common.Key, v common.Value) { + removalListener := func(k common.Key, v common.Value) { icmp.expireTransaction(k.(hashableIcmpTuple), v.(*icmpTransaction)) } @@ -145,7 +145,7 @@ func (icmp *icmpPlugin) ProcessICMPv4( ts: pkt.Ts, Type: typ, code: code, - length: len(icmp4.BaseLayer.Payload), + length: len(icmp4.Payload), } if isRequest(tuple, msg) { @@ -180,7 +180,7 @@ func (icmp *icmpPlugin) ProcessICMPv6( ts: pkt.Ts, Type: typ, code: code, - length: len(icmp6.BaseLayer.Payload), + length: len(icmp6.Payload), } if isRequest(tuple, msg) { @@ -257,14 +257,6 @@ func (icmp *icmpPlugin) isLocalIP(ip net.IP) bool { return false } -func (icmp *icmpPlugin) getTransaction(k hashableIcmpTuple) *icmpTransaction { - v := icmp.transactions.Get(k) - if v != nil { - return v.(*icmpTransaction) - } - return nil -} - func (icmp *icmpPlugin) deleteTransaction(k hashableIcmpTuple) *icmpTransaction { v := icmp.transactions.Delete(k) if v != nil { diff --git a/packetbeat/protos/icmp/icmp_test.go b/packetbeat/protos/icmp/icmp_test.go index a74e097fe04..6b03139396c 100644 --- a/packetbeat/protos/icmp/icmp_test.go +++ b/packetbeat/protos/icmp/icmp_test.go @@ -25,6 +25,9 @@ import ( "net" "testing" + "github.com/google/gopacket" + "github.com/google/gopacket/layers" + "github.com/elastic/beats/v7/libbeat/beat" "github.com/elastic/beats/v7/libbeat/common" "github.com/elastic/beats/v7/libbeat/logp" @@ -32,9 +35,6 @@ import ( "github.com/elastic/beats/v7/packetbeat/procs" "github.com/elastic/beats/v7/packetbeat/protos" - "github.com/tsg/gopacket" - "github.com/tsg/gopacket/layers" - "github.com/stretchr/testify/assert" ) diff --git a/packetbeat/protos/icmp/message.go b/packetbeat/protos/icmp/message.go index 873809a212a..425505deffb 100644 --- a/packetbeat/protos/icmp/message.go +++ b/packetbeat/protos/icmp/message.go @@ -21,7 +21,7 @@ import ( "encoding/binary" "time" - "github.com/tsg/gopacket/layers" + "github.com/google/gopacket/layers" "github.com/elastic/beats/v7/libbeat/logp" ) diff --git a/packetbeat/protos/icmp/message_test.go b/packetbeat/protos/icmp/message_test.go index 6ebc00fe351..8f8ac56e3ee 100644 --- a/packetbeat/protos/icmp/message_test.go +++ b/packetbeat/protos/icmp/message_test.go @@ -23,7 +23,7 @@ package icmp import ( "testing" - "github.com/tsg/gopacket/layers" + "github.com/google/gopacket/layers" "github.com/stretchr/testify/assert" ) @@ -113,5 +113,5 @@ func TestIcmpMessageHumanReadableICMPv6(t *testing.T) { tuple := &icmpTuple{icmpVersion: 6} msg := &icmpMessage{Type: layers.ICMPv6TypeDestinationUnreachable, code: 3} - assert.Equal(t, "DestinationUnreachable(Address)", humanReadable(tuple, msg)) + assert.Equal(t, "DestinationUnreachable(AddressUnreachable)", humanReadable(tuple, msg)) } diff --git a/packetbeat/protos/icmp/transaction_test.go b/packetbeat/protos/icmp/transaction_test.go index 3c1f7fe64c5..1846b19e671 100644 --- a/packetbeat/protos/icmp/transaction_test.go +++ b/packetbeat/protos/icmp/transaction_test.go @@ -23,7 +23,7 @@ package icmp import ( "testing" - "github.com/tsg/gopacket/layers" + "github.com/google/gopacket/layers" "github.com/stretchr/testify/assert" ) diff --git a/packetbeat/protos/icmp/tuple_test.go b/packetbeat/protos/icmp/tuple_test.go index 7c9112decb1..b8d09e6753f 100644 --- a/packetbeat/protos/icmp/tuple_test.go +++ b/packetbeat/protos/icmp/tuple_test.go @@ -79,7 +79,8 @@ func TestIcmpTupleHashable(t *testing.T) { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 192, 168, 0, 2, 1, 0, 0, 1, - 4} + 4, + } assert.Equal(t, expectedHashable, actualHashable) } diff --git a/packetbeat/protos/memcache/binary.go b/packetbeat/protos/memcache/binary.go index f9db915ce8a..ee831055317 100644 --- a/packetbeat/protos/memcache/binary.go +++ b/packetbeat/protos/memcache/binary.go @@ -28,8 +28,6 @@ import ( "github.com/elastic/beats/v7/libbeat/common/streambuf" ) -type memcacheMagic uint8 - const ( memcacheMagicRequest = 0x80 memcacheMagicResponse = 0x81 @@ -56,10 +54,11 @@ var binStatsValue = argDef{ serialize: serializeStats, } -var extraValue = makeValueExtra("value") -var extraDelta = makeValueExtra("delta") -var extraInitial = makeValue2Extra("initial") -var extraVerbosity = make32ValueExtra("verbosity") +var ( + extraDelta = makeValueExtra("delta") + extraInitial = makeValue2Extra("initial") + extraVerbosity = make32ValueExtra("verbosity") +) func init() { // define all memcache opcode commands: diff --git a/packetbeat/protos/memcache/config.go b/packetbeat/protos/memcache/config.go index e558c84153d..dfe01e86e3b 100644 --- a/packetbeat/protos/memcache/config.go +++ b/packetbeat/protos/memcache/config.go @@ -32,11 +32,9 @@ type memcacheConfig struct { ParseUnknown bool } -var ( - defaultConfig = memcacheConfig{ - ProtocolCommon: config.ProtocolCommon{ - TransactionTimeout: protos.DefaultTransactionExpiration, - }, - UDPTransactionTimeout: protos.DefaultTransactionExpiration, - } -) +var defaultConfig = memcacheConfig{ + ProtocolCommon: config.ProtocolCommon{ + TransactionTimeout: protos.DefaultTransactionExpiration, + }, + UDPTransactionTimeout: protos.DefaultTransactionExpiration, +} diff --git a/packetbeat/protos/memcache/errors.go b/packetbeat/protos/memcache/errors.go index 3b6b5b9ae45..282812a3492 100644 --- a/packetbeat/protos/memcache/errors.go +++ b/packetbeat/protos/memcache/errors.go @@ -23,9 +23,7 @@ import ( "errors" ) -var ( - errNotImplemented = errors.New("not implemented") -) +var errNotImplemented = errors.New("not implemented") // memcache text parser errors var ( diff --git a/packetbeat/protos/memcache/parse.go b/packetbeat/protos/memcache/parse.go index 2fe774c19e5..01ce9a05acb 100644 --- a/packetbeat/protos/memcache/parse.go +++ b/packetbeat/protos/memcache/parse.go @@ -25,11 +25,6 @@ import ( "github.com/elastic/beats/v7/libbeat/common/streambuf" ) -const ( - codeSpace byte = ' ' - codeTab = '\t' -) - type parserConfig struct { maxValues int maxBytesPerValue int diff --git a/packetbeat/protos/memcache/parse_test.go b/packetbeat/protos/memcache/parse_test.go index 95fdac5bad3..e1ac77160f5 100644 --- a/packetbeat/protos/memcache/parse_test.go +++ b/packetbeat/protos/memcache/parse_test.go @@ -56,8 +56,10 @@ type binValueWriter interface { WriteNetUint64At(uint64, int) error } -type extraFn func(binValueWriter) int -type valueFn func(*streambuf.Buffer, int) int +type ( + extraFn func(binValueWriter) int + valueFn func(*streambuf.Buffer, int) int +) type offsetBinWriter struct { w binValueWriter diff --git a/packetbeat/protos/memcache/plugin_tcp.go b/packetbeat/protos/memcache/plugin_tcp.go index 830a0cd64a5..c16abb3c712 100644 --- a/packetbeat/protos/memcache/plugin_tcp.go +++ b/packetbeat/protos/memcache/plugin_tcp.go @@ -60,8 +60,6 @@ type messageList struct { tail *message } -const defaultTCPTransDuration uint = 200 - func ensureMemcacheConnection(private protos.ProtocolData) *tcpConnectionData { if private == nil { return &tcpConnectionData{} diff --git a/packetbeat/protos/memcache/text.go b/packetbeat/protos/memcache/text.go index 72b36442c9a..86baa8d0627 100644 --- a/packetbeat/protos/memcache/text.go +++ b/packetbeat/protos/memcache/text.go @@ -109,12 +109,14 @@ var argStat = argDef{ serialize: serializeStats, } -var argDelta = makeValueArg("delta") -var argSleepUs = makeValueArg("sleep_us") -var argValue = makeValueArg("value") -var argVerbosity = makeValueArg("verbosity") -var argSourceClass = makeIValueArg("source_class") -var argDestClass = makeIValue2Arg("dest_class") +var ( + argDelta = makeValueArg("delta") + argSleepUs = makeValueArg("sleep_us") + argValue = makeValueArg("value") + argVerbosity = makeValueArg("verbosity") + argSourceClass = makeIValueArg("source_class") + argDestClass = makeIValue2Arg("dest_class") +) var argNoReply = argDef{ parse: func(parser *parser, hdr, buf *streambuf.Buffer) error { @@ -297,8 +299,10 @@ func makeDefTextDataMessage( } } -var defTextDataRequest = makeDefTextDataMessage(true) -var defTextDataResponse = makeDefTextDataMessage(false) +var ( + defTextDataRequest = makeDefTextDataMessage(true) + defTextDataResponse = makeDefTextDataMessage(false) +) func loadCommand(name string, code commandCode) textCommandType { return defTextMessage(name, memcacheLoadMsg, code, argMultiKeys) @@ -403,13 +407,6 @@ func makeValueArg(name string) argDef { } } -func makeValue2Arg(name string) argDef { - return argDef{ - parse: textUint64Arg(setValue2), - serialize: serializeValue2(name), - } -} - func makeIValueArg(name string) argDef { return argDef{ parse: func(parser *parser, hdr, buf *streambuf.Buffer) error { @@ -592,7 +589,7 @@ func parseNoReplyArg(buf *streambuf.Buffer) (bool, error) { return false, textArgError(err) } - var noreplyArg = []byte("noreply") + noreplyArg := []byte("noreply") noreply := bytes.HasPrefix(buf.Bytes(), noreplyArg) if !noreply { return false, errExpectedNoReply diff --git a/packetbeat/protos/mongodb/config.go b/packetbeat/protos/mongodb/config.go index e7e2143b647..c90aeb67290 100644 --- a/packetbeat/protos/mongodb/config.go +++ b/packetbeat/protos/mongodb/config.go @@ -28,12 +28,10 @@ type mongodbConfig struct { MaxDocs int `config:"max_docs"` } -var ( - defaultConfig = mongodbConfig{ - ProtocolCommon: config.ProtocolCommon{ - TransactionTimeout: protos.DefaultTransactionExpiration, - }, - MaxDocLength: 5000, - MaxDocs: 10, - } -) +var defaultConfig = mongodbConfig{ + ProtocolCommon: config.ProtocolCommon{ + TransactionTimeout: protos.DefaultTransactionExpiration, + }, + MaxDocLength: 5000, + MaxDocs: 10, +} diff --git a/packetbeat/protos/mongodb/mongodb.go b/packetbeat/protos/mongodb/mongodb.go index b05ebce9150..0fcc5464b45 100644 --- a/packetbeat/protos/mongodb/mongodb.go +++ b/packetbeat/protos/mongodb/mongodb.go @@ -55,9 +55,7 @@ type transactionKey struct { id int } -var ( - unmatchedRequests = monitoring.NewInt(nil, "mongodb.unmatched_requests") -) +var unmatchedRequests = monitoring.NewInt(nil, "mongodb.unmatched_requests") func init() { protos.Register("mongodb", New) @@ -218,7 +216,6 @@ func (mongodb *mongodbPlugin) handleMongodb( tcptuple *common.TCPTuple, dir uint8, ) { - m.tcpTuple = *tcptuple m.direction = dir m.cmdlineTuple = mongodb.watcher.FindProcessesTupleTCP(tcptuple.IPPort()) @@ -345,11 +342,12 @@ func reconstructQuery(t *transaction, full bool) (query string) { if !full { // remove the actual data. // TODO: review if we need to add other commands here - if t.method == "insert" { + switch t.method { + case "insert": params, err = doc2str(copyMapWithoutKey(t.params, "documents")) - } else if t.method == "update" { + case "update": params, err = doc2str(copyMapWithoutKey(t.params, "updates")) - } else if t.method == "findandmodify" { + case "findandmodify": params, err = doc2str(copyMapWithoutKey(t.params, "update")) } } else { diff --git a/packetbeat/protos/mongodb/mongodb_parser.go b/packetbeat/protos/mongodb/mongodb_parser.go index a5ff5fa0625..1abc6f890f2 100644 --- a/packetbeat/protos/mongodb/mongodb_parser.go +++ b/packetbeat/protos/mongodb/mongodb_parser.go @@ -116,10 +116,26 @@ func mongodbMessageParser(s *stream) (bool, bool) { // see http://docs.mongodb.org/meta-driver/latest/legacy/mongodb-wire-protocol/#op-reply func opReplyParse(d *decoder, m *mongodbMessage) (bool, bool) { _, err := d.readInt32() // ignore flags for now + if err != nil { + logp.Err("An error occurred while parsing OP_REPLY message: %s", err) + return false, false + } m.event["cursorId"], err = d.readInt64() + if err != nil { + logp.Err("An error occurred while parsing OP_REPLY message: %s", err) + return false, false + } m.event["startingFrom"], err = d.readInt32() + if err != nil { + logp.Err("An error occurred while parsing OP_REPLY message: %s", err) + return false, false + } numberReturned, err := d.readInt32() + if err != nil { + logp.Err("An error occurred while parsing OP_REPLY message: %s", err) + return false, false + } m.event["numberReturned"] = numberReturned debugf("Prepare to read %d document from reply", m.event["numberReturned"]) @@ -128,15 +144,27 @@ func opReplyParse(d *decoder, m *mongodbMessage) (bool, bool) { for i := 0; i < numberReturned; i++ { var document bson.M document, err = d.readDocument() + if err != nil { + logp.Err("An error occurred while parsing OP_REPLY message: %s", err) + return false, false + } // Check if the result is actually an error if i == 0 { if mongoError, present := document["$err"]; present { m.error, err = doc2str(mongoError) + if err != nil { + logp.Err("An error occurred while parsing OP_REPLY message: %s", err) + return false, false + } } if writeErrors, present := document["writeErrors"]; present { m.error, err = doc2str(writeErrors) + if err != nil { + logp.Err("An error occurred while parsing OP_REPLY message: %s", err) + return false, false + } } } @@ -144,10 +172,6 @@ func opReplyParse(d *decoder, m *mongodbMessage) (bool, bool) { } m.documents = documents - if err != nil { - logp.Err("An error occurred while parsing OP_REPLY message: %s", err) - return false, false - } return true, true } @@ -163,12 +187,26 @@ func opMsgLegacyParse(d *decoder, m *mongodbMessage) (bool, bool) { func opUpdateParse(d *decoder, m *mongodbMessage) (bool, bool) { _, err := d.readInt32() // always ZERO, a slot reserved in the protocol for future use + if err != nil { + logp.Err("An error occurred while parsing OP_UPDATE message: %s", err) + return false, false + } m.event["fullCollectionName"], err = d.readCStr() + if err != nil { + logp.Err("An error occurred while parsing OP_UPDATE message: %s", err) + return false, false + } _, err = d.readInt32() // ignore flags for now - + if err != nil { + logp.Err("An error occurred while parsing OP_UPDATE message: %s", err) + return false, false + } m.event["selector"], err = d.readDocumentStr() + if err != nil { + logp.Err("An error occurred while parsing OP_UPDATE message: %s", err) + return false, false + } m.event["update"], err = d.readDocumentStr() - if err != nil { logp.Err("An error occurred while parsing OP_UPDATE message: %s", err) return false, false @@ -179,6 +217,10 @@ func opUpdateParse(d *decoder, m *mongodbMessage) (bool, bool) { func opInsertParse(d *decoder, m *mongodbMessage) (bool, bool) { _, err := d.readInt32() // ignore flags for now + if err != nil { + logp.Err("An error occurred while parsing OP_INSERT message: %s", err) + return false, false + } m.event["fullCollectionName"], err = d.readCStr() // TODO parse bson documents @@ -230,11 +272,27 @@ func isDatabaseCommand(key string, val interface{}) bool { func opQueryParse(d *decoder, m *mongodbMessage) (bool, bool) { _, err := d.readInt32() // ignore flags for now + if err != nil { + logp.Err("An error occurred while parsing OP_QUERY message: %s", err) + return false, false + } fullCollectionName, err := d.readCStr() + if err != nil { + logp.Err("An error occurred while parsing OP_QUERY message: %s", err) + return false, false + } m.event["fullCollectionName"] = fullCollectionName m.event["numberToSkip"], err = d.readInt32() + if err != nil { + logp.Err("An error occurred while parsing OP_QUERY message: %s", err) + return false, false + } m.event["numberToReturn"], err = d.readInt32() + if err != nil { + logp.Err("An error occurred while parsing OP_QUERY message: %s", err) + return false, false + } query, err := d.readDocument() if d.i < len(d.in) { @@ -275,10 +333,21 @@ func opQueryParse(d *decoder, m *mongodbMessage) (bool, bool) { func opGetMoreParse(d *decoder, m *mongodbMessage) (bool, bool) { _, err := d.readInt32() // always ZERO, a slot reserved in the protocol for future use + if err != nil { + logp.Err("An error occurred while parsing OP_GET_MORE message: %s", err) + return false, false + } m.event["fullCollectionName"], err = d.readCStr() + if err != nil { + logp.Err("An error occurred while parsing OP_GET_MORE message: %s", err) + return false, false + } m.event["numberToReturn"], err = d.readInt32() + if err != nil { + logp.Err("An error occurred while parsing OP_GET_MORE message: %s", err) + return false, false + } m.event["cursorId"], err = d.readInt64() - if err != nil { logp.Err("An error occurred while parsing OP_GET_MORE message: %s", err) return false, false @@ -288,11 +357,21 @@ func opGetMoreParse(d *decoder, m *mongodbMessage) (bool, bool) { func opDeleteParse(d *decoder, m *mongodbMessage) (bool, bool) { _, err := d.readInt32() // always ZERO, a slot reserved in the protocol for future use + if err != nil { + logp.Err("An error occurred while parsing OP_DELETE message: %s", err) + return false, false + } m.event["fullCollectionName"], err = d.readCStr() + if err != nil { + logp.Err("An error occurred while parsing OP_DELETE message: %s", err) + return false, false + } _, err = d.readInt32() // ignore flags for now - + if err != nil { + logp.Err("An error occurred while parsing OP_DELETE message: %s", err) + return false, false + } m.event["selector"], err = d.readDocumentStr() - if err != nil { logp.Err("An error occurred while parsing OP_DELETE message: %s", err) return false, false @@ -405,7 +484,6 @@ func (d *decoder) readByte() (byte, error) { func (d *decoder) readInt32() (int, error) { b, err := d.readBytes(4) - if err != nil { return 0, err } @@ -418,7 +496,6 @@ func (d *decoder) readInt32() (int, error) { func (d *decoder) readInt64() (int, error) { b, err := d.readBytes(8) - if err != nil { return 0, err } @@ -436,6 +513,9 @@ func (d *decoder) readInt64() (int, error) { func (d *decoder) readDocument() (bson.M, error) { start := d.i documentLength, err := d.readInt32() + if err != nil { + return nil, err + } d.i = start + documentLength if len(d.in) < d.i { return nil, errors.New("document out of bounds") @@ -461,6 +541,9 @@ func doc2str(documentMap interface{}) (string, error) { func (d *decoder) readDocumentStr() (string, error) { documentMap, err := d.readDocument() + if err != nil { + return "", err + } document, err := doc2str(documentMap) return document, err } diff --git a/packetbeat/protos/mongodb/mongodb_test.go b/packetbeat/protos/mongodb/mongodb_test.go index ece0e1cf4aa..a1415dfa0a2 100644 --- a/packetbeat/protos/mongodb/mongodb_test.go +++ b/packetbeat/protos/mongodb/mongodb_test.go @@ -170,6 +170,7 @@ func TestSimpleFindLimit1_split(t *testing.T) { "1b000000013000e6762ff7c97652c001" + "3100d5b14ae9996c4440000273747265" + "657400100000004d6f72726973205061") + assert.NoError(t, err) respData2, err := hex.DecodeString( "726b2041766500027a6970636f646500" + @@ -183,6 +184,7 @@ func TestSimpleFindLimit1_split(t *testing.T) { "0000000964617465000044510a410100" + "00026772616465000200000041001073" + "636f72650006000000000332002b0000") + assert.NoError(t, err) respData3, err := hex.DecodeString( "00096461746500009cda693c01000002" + diff --git a/packetbeat/protos/mysql/config.go b/packetbeat/protos/mysql/config.go index d53429c3a2c..0c634b98291 100644 --- a/packetbeat/protos/mysql/config.go +++ b/packetbeat/protos/mysql/config.go @@ -31,13 +31,11 @@ type mysqlConfig struct { StatementTimeout time.Duration `config:"statement_timeout"` } -var ( - defaultConfig = mysqlConfig{ - ProtocolCommon: config.ProtocolCommon{ - TransactionTimeout: protos.DefaultTransactionExpiration, - }, - MaxRowLength: 1024, - MaxRows: 10, - StatementTimeout: 3600 * time.Second, - } -) +var defaultConfig = mysqlConfig{ + ProtocolCommon: config.ProtocolCommon{ + TransactionTimeout: protos.DefaultTransactionExpiration, + }, + MaxRowLength: 1024, + MaxRows: 10, + StatementTimeout: 3600 * time.Second, +} diff --git a/packetbeat/protos/mysql/mysql.go b/packetbeat/protos/mysql/mysql.go index 1553bdf9901..49ca17ece85 100644 --- a/packetbeat/protos/mysql/mysql.go +++ b/packetbeat/protos/mysql/mysql.go @@ -62,8 +62,6 @@ type mysqlMessage struct { numberOfRows int numberOfFields int size uint64 - fields []string - rows [][]string tables string isOK bool affectedRows uint64 @@ -83,7 +81,6 @@ type mysqlMessage struct { statementID int numberOfParams int - params []string } type mysqlTransaction struct { @@ -337,7 +334,7 @@ func mysqlMessageParser(s *mysqlStream) (bool, bool) { return true, false } - s.parseOffset += 4 //header + s.parseOffset += 4 // header s.parseOffset += int(m.packetLength) m.end = s.parseOffset if m.isRequest { @@ -347,7 +344,6 @@ func mysqlMessageParser(s *mysqlStream) (bool, bool) { } else { m.query = string(s.data[m.start+5 : m.end]) } - } else if m.isOK { // affected rows affectedRows, off, complete, err := readLinteger(s.data, m.start+5) @@ -475,7 +471,7 @@ func mysqlMessageParser(s *mysqlStream) (bool, bool) { return true, false } - s.parseOffset += 4 //header + s.parseOffset += 4 // header if s.data[s.parseOffset] == 0xfe { logp.Debug("mysqldetailed", "Received EOF packet") @@ -553,8 +549,8 @@ func (mysql *mysqlPlugin) ConnectionTimeout() time.Duration { } func (mysql *mysqlPlugin) Parse(pkt *protos.Packet, tcptuple *common.TCPTuple, - dir uint8, private protos.ProtocolData) protos.ProtocolData { - + dir uint8, private protos.ProtocolData, +) protos.ProtocolData { defer logp.Recover("ParseMysql exception") priv := mysqlPrivateData{} @@ -613,8 +609,8 @@ func (mysql *mysqlPlugin) Parse(pkt *protos.Packet, tcptuple *common.TCPTuple, } func (mysql *mysqlPlugin) GapInStream(tcptuple *common.TCPTuple, dir uint8, - nbytes int, private protos.ProtocolData) (priv protos.ProtocolData, drop bool) { - + nbytes int, private protos.ProtocolData) (priv protos.ProtocolData, drop bool, +) { defer logp.Recover("GapInStream(mysql) exception") if private == nil { @@ -642,16 +638,16 @@ func (mysql *mysqlPlugin) GapInStream(tcptuple *common.TCPTuple, dir uint8, } func (mysql *mysqlPlugin) ReceivedFin(tcptuple *common.TCPTuple, dir uint8, - private protos.ProtocolData) protos.ProtocolData { - + private protos.ProtocolData, +) protos.ProtocolData { // TODO: check if we have data pending and either drop it to free // memory or send it up the stack. return private } func handleMysql(mysql *mysqlPlugin, m *mysqlMessage, tcptuple *common.TCPTuple, - dir uint8, rawMsg []byte) { - + dir uint8, rawMsg []byte, +) { m.tcpTuple = *tcptuple m.direction = dir m.cmdlineTuple = mysql.watcher.FindProcessesTupleTCP(tcptuple.IPPort()) @@ -689,9 +685,10 @@ func (mysql *mysqlPlugin) receivedMysqlRequest(msg *mysqlMessage) { trans.statementID = msg.statementID stmts := mysql.getStmtsMap(msg.tcpTuple.Hashable()) if stmts == nil { - if msg.typ == mysqlCmdStmtExecute { + switch msg.typ { + case mysqlCmdStmtExecute: trans.query = "Request Execute Statement" - } else if msg.typ == mysqlCmdStmtClose { + case mysqlCmdStmtClose: trans.query = "Request Close Statement" } trans.notes = append(trans.notes, "The actual query being used is unknown") @@ -699,7 +696,8 @@ func (mysql *mysqlPlugin) receivedMysqlRequest(msg *mysqlMessage) { trans.bytesIn = msg.size return } - if msg.typ == mysqlCmdStmtExecute { + switch msg.typ { + case mysqlCmdStmtExecute: if value, ok := stmts[trans.statementID]; ok { trans.query = value.query // parse parameters @@ -711,7 +709,7 @@ func (mysql *mysqlPlugin) receivedMysqlRequest(msg *mysqlMessage) { trans.bytesIn = msg.size return } - } else if msg.typ == mysqlCmdStmtClose { + case mysqlCmdStmtClose: delete(stmts, trans.statementID) trans.query = "CmdStmtClose" mysql.transactions.Delete(tuple.Hashable()) @@ -899,7 +897,7 @@ func (mysql *mysqlPlugin) parseMysqlExecuteStatement(data []byte, stmtdata *mysq valueString := strconv.Itoa(int(binary.LittleEndian.Uint32(data[paramOffset:]))) paramString = append(paramString, valueString) paramOffset += 4 - //FIELD_TYPE_FLOAT + // FIELD_TYPE_FLOAT case 0x04: paramString = append(paramString, "TYPE_FLOAT") paramOffset += 4 @@ -1012,19 +1010,19 @@ func (mysql *mysqlPlugin) parseMysqlResponse(data []byte) ([]string, [][]string) return []string{}, [][]string{} } - fields := []string{} - rows := [][]string{} - if len(data) < 5 { - logp.Warn("Invalid response: data less than 4 bytes") + logp.Warn("Invalid response: data less than 5 bytes") return []string{}, [][]string{} } - if data[4] == 0x00 { + fields := []string{} + rows := [][]string{} + switch data[4] { + case 0x00: // OK response - } else if data[4] == 0xff { + case 0xff: // Error response - } else { + default: offset := 5 logp.Debug("mysql", "Data len: %d", len(data)) @@ -1100,7 +1098,7 @@ func (mysql *mysqlPlugin) parseMysqlResponse(data []byte) ([]string, [][]string) if data[offset+4] == 0xfe { // EOF - offset += length + 4 + offset += length + 4 // ineffassign break } diff --git a/packetbeat/protos/mysql/mysql_test.go b/packetbeat/protos/mysql/mysql_test.go index 309fd45cb0f..dd942399073 100644 --- a/packetbeat/protos/mysql/mysql_test.go +++ b/packetbeat/protos/mysql/mysql_test.go @@ -49,10 +49,6 @@ func (e *eventStore) publish(event beat.Event) { e.events = append(e.events, event) } -func (e *eventStore) empty() bool { - return len(e.events) == 0 -} - func mysqlModForTests(store *eventStore) *mysqlPlugin { callback := func(beat.Event) {} if store != nil { @@ -110,6 +106,7 @@ func TestMySQLParser_simpleRequest(t *testing.T) { t.Errorf("Wrong message size %d", stream.message.size) } } + func TestMySQLParser_OKResponse(t *testing.T) { data := []byte( "0700000100010401000000") @@ -363,11 +360,11 @@ func TestParseMySQL_simpleUpdateResponse(t *testing.T) { var tuple common.TCPTuple var private mysqlPrivateData - var countHandleMysql = 0 + countHandleMysql := 0 mysql.handleMysql = func(mysql *mysqlPlugin, m *mysqlMessage, tcp *common.TCPTuple, - dir uint8, raw_msg []byte) { - + dir uint8, raw_msg []byte, + ) { countHandleMysql++ } @@ -404,11 +401,11 @@ func TestParseMySQL_threeResponses(t *testing.T) { var tuple common.TCPTuple var private mysqlPrivateData - var countHandleMysql = 0 + countHandleMysql := 0 mysql.handleMysql = func(mysql *mysqlPlugin, m *mysqlMessage, tcptuple *common.TCPTuple, - dir uint8, raw_msg []byte) { - + dir uint8, raw_msg []byte, + ) { countHandleMysql++ } @@ -431,7 +428,6 @@ func TestParseMySQL_splitResponse(t *testing.T) { "3b00000303646566086d696e697477697404706f737404706f73740d706f73745f757365726e616d6508757365726e616d650c2100f0000000fd0000000000" + "3500000403646566086d696e697477697404706f737404706f73740a706f73745f7469746c65057469746c650c2100f0000000fd0000000000" + "3300000503646566086d696e697477697404706f737404706f737409706f73745f626f647904626f64790c2100fdff0200fc1000000000") - if err != nil { t.Errorf("Failed to decode string") } @@ -446,11 +442,11 @@ func TestParseMySQL_splitResponse(t *testing.T) { var tuple common.TCPTuple var private mysqlPrivateData - var countHandleMysql = 0 + countHandleMysql := 0 mysql.handleMysql = func(mysql *mysqlPlugin, m *mysqlMessage, tcptuple *common.TCPTuple, - dir uint8, raw_msg []byte) { - + dir uint8, raw_msg []byte, + ) { countHandleMysql++ } @@ -623,12 +619,18 @@ func Test_parseMysqlResponse_invalid(t *testing.T) { {0x05, 0x00, 0x00, 0x01, 0x01, 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00}, {0x05, 0x00, 0x00, 0x01, 0x01, 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00}, {0x05, 0x00, 0x00, 0x01, 0x01, 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00}, - {0x05, 0x00, 0x00, 0x01, 0x01, 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, - 0x01, 0x00}, - {0x15, 0x00, 0x00, 0x01, 0x01, 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, - 0x01, 0x00, 0x01}, - {0x15, 0x00, 0x00, 0x01, 0x01, 0x05, 0x15, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, - 0x01, 0x00, 0x01, 0x00}, + { + 0x05, 0x00, 0x00, 0x01, 0x01, 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, + 0x01, 0x00, + }, + { + 0x15, 0x00, 0x00, 0x01, 0x01, 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, + 0x01, 0x00, 0x01, + }, + { + 0x15, 0x00, 0x00, 0x01, 0x01, 0x05, 0x15, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, + 0x01, 0x00, 0x01, 0x00, + }, } for _, input := range tests { @@ -638,12 +640,14 @@ func Test_parseMysqlResponse_invalid(t *testing.T) { } tests = [][]byte{ - {0x15, 0x00, 0x00, 0x01, 0x01, - 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0xfe, 0x00, 0x01, //field + { + 0x15, 0x00, 0x00, 0x01, 0x01, + 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0xfe, 0x00, 0x01, // field 0x01, 0x00, 0x00, 0x00, 0xfe, // EOF }, - {0x15, 0x00, 0x00, 0x01, 0x01, - 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0xfe, 0x00, 0x01, //field + { + 0x15, 0x00, 0x00, 0x01, 0x01, + 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0xfe, 0x00, 0x01, // field 0x01, 0x00, 0x00, 0x00, 0xfe, // EOF 0x00, 0x00, }, @@ -668,7 +672,7 @@ func Test_PreparedStatement(t *testing.T) { packet := protos.Packet{Payload: rawData} var private protos.ProtocolData - private = mysql.Parse(&packet, tcpTuple, dir, private) + mysql.Parse(&packet, tcpTuple, dir, private) } send(tcp.TCPDirectionOriginal, "c00000001673656c6563742064697374696e637420636f756e742864697374696e63742070757263686173656465305f2e69642920617320636f6c5f305f305f2066726f6d2070757263686173655f64656d616e642070757263686173656465305f2077686572652070757263686173656465305f2e636861696e5f6d61737465723d3f20616e642070757263686173656465305f2e6372656174655f74696d653e3d3f20616e642070757263686173656465305f2e6372656174655f74696d653c3d3f") diff --git a/packetbeat/protos/nfs/config.go b/packetbeat/protos/nfs/config.go index 639bdad525d..e23672024c8 100644 --- a/packetbeat/protos/nfs/config.go +++ b/packetbeat/protos/nfs/config.go @@ -27,10 +27,8 @@ type rpcConfig struct { config.ProtocolCommon `config:",inline"` } -var ( - defaultConfig = rpcConfig{ - ProtocolCommon: config.ProtocolCommon{ - TransactionTimeout: 1 * time.Minute, - }, - } -) +var defaultConfig = rpcConfig{ + ProtocolCommon: config.ProtocolCommon{ + TransactionTimeout: 1 * time.Minute, + }, +} diff --git a/packetbeat/protos/nfs/request_handler.go b/packetbeat/protos/nfs/request_handler.go index fea417f4dc1..1225f9f6012 100644 --- a/packetbeat/protos/nfs/request_handler.go +++ b/packetbeat/protos/nfs/request_handler.go @@ -41,9 +41,7 @@ var acceptStatus = [...]string{ "system_err", } -var ( - unmatchedRequests = monitoring.NewInt(nil, "nfs.unmatched_requests") -) +var unmatchedRequests = monitoring.NewInt(nil, "nfs.unmatched_requests") // called by Cache, when re reply seen within expected time window func (r *rpc) handleExpiredPacket(nfs *nfs) { diff --git a/packetbeat/protos/nfs/rpc.go b/packetbeat/protos/nfs/rpc.go index 9cde7ab5aac..64fffe47606 100644 --- a/packetbeat/protos/nfs/rpc.go +++ b/packetbeat/protos/nfs/rpc.go @@ -126,7 +126,6 @@ func (r *rpc) Parse( dir uint8, private protos.ProtocolData, ) protos.ProtocolData { - defer logp.Recover("ParseRPC exception") conn := ensureRPCConnection(private) @@ -140,8 +139,8 @@ func (r *rpc) Parse( // Called when the FIN flag is seen in the TCP stream. func (r *rpc) ReceivedFin(tcptuple *common.TCPTuple, dir uint8, - private protos.ProtocolData) protos.ProtocolData { - + private protos.ProtocolData, +) protos.ProtocolData { defer logp.Recover("ReceivedFinRpc exception") // forced by TCP interface @@ -151,8 +150,8 @@ func (r *rpc) ReceivedFin(tcptuple *common.TCPTuple, dir uint8, // Called when a packets are missing from the tcp // stream. func (r *rpc) GapInStream(tcptuple *common.TCPTuple, dir uint8, - nbytes int, private protos.ProtocolData) (priv protos.ProtocolData, drop bool) { - + nbytes int, private protos.ProtocolData) (priv protos.ProtocolData, drop bool, +) { defer logp.Recover("GapInRpcStream exception") // forced by TCP interface @@ -199,7 +198,6 @@ func (r *rpc) handleRPCFragment( tcptuple *common.TCPTuple, dir uint8, ) *rpcConnectionData { - st := conn.streams[dir] if st == nil { st = newStream(pkt, tcptuple) diff --git a/packetbeat/protos/nfs/xdr.go b/packetbeat/protos/nfs/xdr.go index de63fc755a2..168fb274cfd 100644 --- a/packetbeat/protos/nfs/xdr.go +++ b/packetbeat/protos/nfs/xdr.go @@ -40,24 +40,12 @@ func (r *xdr) size() int { return len(r.data) } -func (r *xdr) getInt() int32 { - i := int32(binary.BigEndian.Uint32(r.data[r.offset : r.offset+4])) - r.offset += 4 - return int32(i) -} - func (r *xdr) getUInt() uint32 { i := uint32(binary.BigEndian.Uint32(r.data[r.offset : r.offset+4])) r.offset += 4 return i } -func (r *xdr) getHyper() int64 { - i := int64(binary.BigEndian.Uint64(r.data[r.offset : r.offset+8])) - r.offset += 8 - return i -} - func (r *xdr) getUHyper() uint64 { i := uint64(binary.BigEndian.Uint64(r.data[r.offset : r.offset+8])) r.offset += 8 diff --git a/packetbeat/protos/pgsql/config.go b/packetbeat/protos/pgsql/config.go index 54a9a1b9e2e..13c11531409 100644 --- a/packetbeat/protos/pgsql/config.go +++ b/packetbeat/protos/pgsql/config.go @@ -28,12 +28,10 @@ type pgsqlConfig struct { MaxRows int `config:"max_rows"` } -var ( - defaultConfig = pgsqlConfig{ - ProtocolCommon: config.ProtocolCommon{ - TransactionTimeout: protos.DefaultTransactionExpiration, - }, - MaxRowLength: 1024, - MaxRows: 10, - } -) +var defaultConfig = pgsqlConfig{ + ProtocolCommon: config.ProtocolCommon{ + TransactionTimeout: protos.DefaultTransactionExpiration, + }, + MaxRowLength: 1024, + MaxRows: 10, +} diff --git a/packetbeat/protos/pgsql/parse.go b/packetbeat/protos/pgsql/parse.go index a7bcdb44770..9a302f99a18 100644 --- a/packetbeat/protos/pgsql/parse.go +++ b/packetbeat/protos/pgsql/parse.go @@ -158,7 +158,7 @@ func (pgsql *pgsqlPlugin) parseSimpleQuery(s *pgsqlStream, length int) (bool, bo m.start = s.parseOffset m.isRequest = true - s.parseOffset++ //type + s.parseOffset++ // type s.parseOffset += length m.end = s.parseOffset m.size = uint64(m.end - m.start) @@ -190,8 +190,8 @@ func (pgsql *pgsqlPlugin) parseRowDescription(s *pgsqlStream, length int) (bool, } pgsql.detailf("Fields: %s", m.fields) - s.parseOffset++ //type - s.parseOffset += length //length + s.parseOffset++ // type + s.parseOffset += length // length s.parseState = pgsqlGetDataState return pgsql.parseMessageData(s) } @@ -238,7 +238,7 @@ func (pgsql *pgsqlPlugin) parseCommandComplete(s *pgsqlStream, length int) (bool m.isOK = true m.toExport = true - s.parseOffset++ //type + s.parseOffset++ // type name, err := pgsqlString(s.data[s.parseOffset+4:], length-4) if err != nil { return false, false @@ -276,10 +276,10 @@ func (pgsql *pgsqlPlugin) parseErrorResponse(s *pgsqlStream, length int) (bool, m.isError = true m.toExport = true - s.parseOffset++ //type + s.parseOffset++ // type pgsql.parseError(s, s.data[s.parseOffset+4:s.parseOffset+length]) - s.parseOffset += length //length + s.parseOffset += length // length m.end = s.parseOffset m.size = uint64(m.end - m.start) @@ -294,7 +294,7 @@ func (pgsql *pgsqlPlugin) parseExtReq(s *pgsqlStream, length int) (bool, bool) { m.start = s.parseOffset m.isRequest = true - s.parseOffset++ //type + s.parseOffset++ // type s.parseOffset += length m.end = s.parseOffset m.size = uint64(m.end - m.start) @@ -326,7 +326,7 @@ func (pgsql *pgsqlPlugin) parseExtResp(s *pgsqlStream, length int) (bool, bool) m.isOK = true m.toExport = true - s.parseOffset++ //type + s.parseOffset++ // type s.parseOffset += length pgsql.detailf("Parse completion in an extended query response") s.parseState = pgsqlGetDataState @@ -336,7 +336,7 @@ func (pgsql *pgsqlPlugin) parseExtResp(s *pgsqlStream, length int) (bool, bool) func (pgsql *pgsqlPlugin) parseSkipMessage(s *pgsqlStream, length int) (bool, bool) { // TODO: add info from NoticeResponse in case there are warning messages for a query // ignore command - s.parseOffset++ //type + s.parseOffset++ // type s.parseOffset += length m := s.message @@ -615,21 +615,21 @@ func (pgsql *pgsqlPlugin) parseMessageExtendedQuery(s *pgsqlStream) (bool, bool) // skip type s.parseOffset++ s.parseOffset += length - //TODO: pgsql.parseBind(s) + // TODO: pgsql.parseBind(s) case 'D': // Bind -> Describe // skip type s.parseOffset++ s.parseOffset += length - //TODO: pgsql.parseDescribe(s) + // TODO: pgsql.parseDescribe(s) case 'E': // Bind(or Describe) -> Execute // skip type s.parseOffset++ s.parseOffset += length - //TODO: pgsql.parseExecute(s) + // TODO: pgsql.parseExecute(s) case 'S': // Execute -> Sync diff --git a/packetbeat/protos/pgsql/pgsql.go b/packetbeat/protos/pgsql/pgsql.go index 5ad6f6e305a..20ad2fc5461 100644 --- a/packetbeat/protos/pgsql/pgsql.go +++ b/packetbeat/protos/pgsql/pgsql.go @@ -126,13 +126,9 @@ const ( cancelRequest ) -var ( - errInvalidLength = errors.New("invalid length") -) +var errInvalidLength = errors.New("invalid length") -var ( - unmatchedResponses = monitoring.NewInt(nil, "pgsql.unmatched_responses") -) +var unmatchedResponses = monitoring.NewInt(nil, "pgsql.unmatched_responses") func init() { protos.Register("pgsql", New) @@ -240,8 +236,8 @@ func (pgsql *pgsqlPlugin) ConnectionTimeout() time.Duration { } func (pgsql *pgsqlPlugin) Parse(pkt *protos.Packet, tcptuple *common.TCPTuple, - dir uint8, private protos.ProtocolData) protos.ProtocolData { - + dir uint8, private protos.ProtocolData, +) protos.ProtocolData { defer logp.Recover("ParsePgsql exception") priv := pgsqlPrivateData{} @@ -334,8 +330,8 @@ func messageHasEnoughData(msg *pgsqlMessage) bool { // Called when there's a drop packet func (pgsql *pgsqlPlugin) GapInStream(tcptuple *common.TCPTuple, dir uint8, - nbytes int, private protos.ProtocolData) (priv protos.ProtocolData, drop bool) { - + nbytes int, private protos.ProtocolData) (priv protos.ProtocolData, drop bool, +) { defer logp.Recover("GapInPgsqlStream exception") if private == nil { @@ -378,8 +374,8 @@ func (pgsql *pgsqlPlugin) ReceivedFin(tcptuple *common.TCPTuple, dir uint8, } var handlePgsql = func(pgsql *pgsqlPlugin, m *pgsqlMessage, tcptuple *common.TCPTuple, - dir uint8, raw_msg []byte) { - + dir uint8, raw_msg []byte, +) { m.tcpTuple = *tcptuple m.direction = dir m.cmdlineTuple = pgsql.watcher.FindProcessesTupleTCP(tcptuple.IPPort()) @@ -433,7 +429,7 @@ func (pgsql *pgsqlPlugin) receivedPgsqlRequest(msg *pgsqlMessage) { func (pgsql *pgsqlPlugin) receivedPgsqlResponse(msg *pgsqlMessage) { tuple := msg.tcpTuple transList := pgsql.getTransaction(tuple.Hashable()) - if transList == nil || len(transList) == 0 { + if len(transList) == 0 { pgsql.debugf("Response from unknown transaction. Ignoring.") unmatchedResponses.Add(1) return @@ -511,8 +507,8 @@ func (pgsql *pgsqlPlugin) publishTransaction(t *pgsqlTransaction) { } func (pgsql *pgsqlPlugin) removeTransaction(transList []*pgsqlTransaction, - tuple common.TCPTuple, index int) *pgsqlTransaction { - + tuple common.TCPTuple, index int, +) *pgsqlTransaction { trans := transList[index] transList = append(transList[:index], transList[index+1:]...) if len(transList) == 0 { diff --git a/packetbeat/protos/pgsql/pgsql_test.go b/packetbeat/protos/pgsql/pgsql_test.go index 328b31e28c2..82075eaacae 100644 --- a/packetbeat/protos/pgsql/pgsql_test.go +++ b/packetbeat/protos/pgsql/pgsql_test.go @@ -46,10 +46,6 @@ func (e *eventStore) publish(event beat.Event) { e.events = append(e.events, event) } -func (e *eventStore) empty() bool { - return len(e.events) == 0 -} - func pgsqlModForTests(store *eventStore) *pgsqlPlugin { callback := func(beat.Event) {} if store != nil { @@ -234,11 +230,11 @@ func TestPgsqlParser_threeResponses(t *testing.T) { } var tuple common.TCPTuple var private pgsqlPrivateData - var countHandlePgsql = 0 + countHandlePgsql := 0 pgsql.handlePgsql = func(pgsql *pgsqlPlugin, m *pgsqlMessage, tcptuple *common.TCPTuple, - dir uint8, raw_msg []byte) { - + dir uint8, raw_msg []byte, + ) { countHandlePgsql++ } diff --git a/packetbeat/protos/protos.go b/packetbeat/protos/protos.go index e0343a0ee87..39dc09d8b7d 100644 --- a/packetbeat/protos/protos.go +++ b/packetbeat/protos/protos.go @@ -79,7 +79,6 @@ type Protocols interface { BpfFilter(withVlans bool, withICMP bool) string GetTCP(proto Protocol) TCPPlugin GetUDP(proto Protocol) UDPPlugin - GetAllTCP() map[Protocol]TCPPlugin GetAllUDP() map[Protocol]UDPPlugin diff --git a/packetbeat/protos/protos_test.go b/packetbeat/protos/protos_test.go index 22269a192d2..b3c1a912069 100644 --- a/packetbeat/protos/protos_test.go +++ b/packetbeat/protos/protos_test.go @@ -70,9 +70,7 @@ func (proto *UDPProtocol) GetPorts() []int { return proto.Ports } -func (proto *UDPProtocol) ParseUDP(pkt *Packet) { - return -} +func (proto *UDPProtocol) ParseUDP(pkt *Packet) {} type TCPUDPProtocol TestProtocol @@ -99,9 +97,7 @@ func (proto *TCPUDPProtocol) GapInStream(tcptuple *common.TCPTuple, dir uint8, return private, true } -func (proto *TCPUDPProtocol) ParseUDP(pkt *Packet) { - return -} +func (proto *TCPUDPProtocol) ParseUDP(pkt *Packet) {} func (proto *TCPUDPProtocol) ConnectionTimeout() time.Duration { return 0 } diff --git a/packetbeat/protos/redis/config.go b/packetbeat/protos/redis/config.go index beb1caed2e2..a1fd48f4149 100644 --- a/packetbeat/protos/redis/config.go +++ b/packetbeat/protos/redis/config.go @@ -27,14 +27,12 @@ type redisConfig struct { QueueLimits MessageQueueConfig `config:",inline"` } -var ( - defaultConfig = redisConfig{ - ProtocolCommon: config.ProtocolCommon{ - TransactionTimeout: protos.DefaultTransactionExpiration, - }, - QueueLimits: MessageQueueConfig{ - MaxBytes: 1024 * 1024, - MaxMessages: 20000, - }, - } -) +var defaultConfig = redisConfig{ + ProtocolCommon: config.ProtocolCommon{ + TransactionTimeout: protos.DefaultTransactionExpiration, + }, + QueueLimits: MessageQueueConfig{ + MaxBytes: 1024 * 1024, + MaxMessages: 20000, + }, +} diff --git a/packetbeat/protos/redis/redis.go b/packetbeat/protos/redis/redis.go index 23dd1ad8696..a219e8a14f9 100644 --- a/packetbeat/protos/redis/redis.go +++ b/packetbeat/protos/redis/redis.go @@ -140,6 +140,7 @@ func (redis *redisPlugin) Parse( } return conn } + func (redis *redisPlugin) newConnectionData() *redisConnectionData { return &redisConnectionData{ requests: NewMessageQueue(redis.queueConfig), @@ -171,7 +172,6 @@ func (redis *redisPlugin) doParse( tcptuple *common.TCPTuple, dir uint8, ) *redisConnectionData { - st := conn.streams[dir] if st == nil { st = newStream(pkt.Ts, tcptuple) @@ -339,8 +339,8 @@ func (redis *redisPlugin) newTransaction(requ, resp *redisMessage) beat.Event { } func (redis *redisPlugin) GapInStream(tcptuple *common.TCPTuple, dir uint8, - nbytes int, private protos.ProtocolData) (priv protos.ProtocolData, drop bool) { - + nbytes int, private protos.ProtocolData) (priv protos.ProtocolData, drop bool, +) { // tsg: being packet loss tolerant is probably not very useful for Redis, // because most requests/response tend to fit in a single packet. @@ -348,8 +348,8 @@ func (redis *redisPlugin) GapInStream(tcptuple *common.TCPTuple, dir uint8, } func (redis *redisPlugin) ReceivedFin(tcptuple *common.TCPTuple, dir uint8, - private protos.ProtocolData) protos.ProtocolData { - + private protos.ProtocolData, +) protos.ProtocolData { // TODO: check if we have pending data that we can send up the stack return private diff --git a/packetbeat/protos/sip/config.go b/packetbeat/protos/sip/config.go index 58a92606e80..309558a225f 100644 --- a/packetbeat/protos/sip/config.go +++ b/packetbeat/protos/sip/config.go @@ -29,13 +29,11 @@ type config struct { KeepOriginal bool `config:"keep_original"` } -var ( - defaultConfig = config{ - ProtocolCommon: cfg.ProtocolCommon{ - TransactionTimeout: protos.DefaultTransactionExpiration, - }, - ParseAuthorization: true, - ParseBody: true, - KeepOriginal: true, - } -) +var defaultConfig = config{ + ProtocolCommon: cfg.ProtocolCommon{ + TransactionTimeout: protos.DefaultTransactionExpiration, + }, + ParseAuthorization: true, + ParseBody: true, + KeepOriginal: true, +} diff --git a/packetbeat/protos/sip/parser.go b/packetbeat/protos/sip/parser.go index 8d49ad61742..db63f05b429 100644 --- a/packetbeat/protos/sip/parser.go +++ b/packetbeat/protos/sip/parser.go @@ -269,8 +269,7 @@ func parseVersion(s []byte) (uint8, uint8, error) { func (parser *parser) parseHeaders(pi *parsingInfo, m *message) error { // check if it isn't headers end yet with /r/n/r/n - if !(len(pi.data)-pi.parseOffset >= 2 && - bytes.Equal(pi.data[pi.parseOffset:pi.parseOffset+2], constCRLF)) { + if len(pi.data)-pi.parseOffset < 2 || !bytes.Equal(pi.data[pi.parseOffset:pi.parseOffset+2], constCRLF) { offset, err := parser.parseHeader(m, pi.data[pi.parseOffset:]) if err != nil { return err diff --git a/packetbeat/protos/tcp/tcp.go b/packetbeat/protos/tcp/tcp.go index e9db7b94897..c275925cbcf 100644 --- a/packetbeat/protos/tcp/tcp.go +++ b/packetbeat/protos/tcp/tcp.go @@ -22,14 +22,14 @@ import ( "sync" "time" + "github.com/google/gopacket/layers" + "github.com/elastic/beats/v7/libbeat/common" "github.com/elastic/beats/v7/libbeat/logp" "github.com/elastic/beats/v7/libbeat/monitoring" "github.com/elastic/beats/v7/packetbeat/flows" "github.com/elastic/beats/v7/packetbeat/protos" - - "github.com/tsg/gopacket/layers" ) const TCPMaxDataInStream = 10 * (1 << 20) @@ -61,9 +61,7 @@ type Processor interface { Process(flow *flows.FlowID, hdr *layers.TCP, pkt *protos.Packet) } -var ( - droppedBecauseOfGaps = monitoring.NewInt(nil, "tcp.dropped_because_of_gaps") -) +var droppedBecauseOfGaps = monitoring.NewInt(nil, "tcp.dropped_because_of_gaps") type seqCompare int @@ -271,7 +269,8 @@ func (tcp *TCP) getStream(pkt *protos.Packet) (stream TCPStream, created bool) { id: tcp.getID(), tuple: &pkt.Tuple, protocol: protocol, - tcp: tcp} + tcp: tcp, + } conn.tcptuple = common.TCPTupleFromIPPort(conn.tuple, conn.id) tcp.streams.PutWithTimeout(pkt.Tuple.Hashable(), conn, timeout) return TCPStream{conn: conn, dir: TCPDirectionOriginal}, true @@ -289,16 +288,12 @@ func tcpSeqCompare(seq1, seq2 uint32) seqCompare { } } -func tcpSeqBefore(seq1 uint32, seq2 uint32) bool { - return int32(seq1-seq2) < 0 -} - func tcpSeqBeforeEq(seq1 uint32, seq2 uint32) bool { return int32(seq1-seq2) <= 0 } func buildPortsMap(plugins map[protos.Protocol]protos.TCPPlugin) (map[uint16]protos.Protocol, error) { - var res = map[uint16]protos.Protocol{} + res := map[uint16]protos.Protocol{} for proto, protoPlugin := range plugins { for _, port := range protoPlugin.GetPorts() { diff --git a/packetbeat/protos/tcp/tcp_test.go b/packetbeat/protos/tcp/tcp_test.go index 9dd910799b6..31aba7f39e4 100644 --- a/packetbeat/protos/tcp/tcp_test.go +++ b/packetbeat/protos/tcp/tcp_test.go @@ -26,12 +26,13 @@ import ( "testing" "time" + "github.com/google/gopacket/layers" + "github.com/elastic/beats/v7/libbeat/common" "github.com/elastic/beats/v7/packetbeat/procs" "github.com/elastic/beats/v7/packetbeat/protos" "github.com/stretchr/testify/assert" - "github.com/tsg/gopacket/layers" ) // Test Constants @@ -41,9 +42,7 @@ const ( ClientIP = "10.0.0.1" ) -var ( - httpProtocol, mysqlProtocol, redisProtocol protos.Protocol -) +var httpProtocol, mysqlProtocol, redisProtocol protos.Protocol func init() { new := func(_ bool, _ protos.Reporter, _ procs.ProcessesWatcher, _ *common.Config) (protos.Plugin, error) { @@ -199,7 +198,7 @@ func (p protocols) GetUDP(proto protos.Protocol) protos.UDPPlugin { retur func (p protocols) GetAll() map[protos.Protocol]protos.Plugin { return nil } func (p protocols) GetAllTCP() map[protos.Protocol]protos.TCPPlugin { return p.tcp } func (p protocols) GetAllUDP() map[protos.Protocol]protos.UDPPlugin { return nil } -func (p protocols) Register(proto protos.Protocol, plugin protos.Plugin) { return } +func (p protocols) Register(proto protos.Protocol, plugin protos.Plugin) {} func TestTCSeqPayload(t *testing.T) { type segment struct { @@ -213,7 +212,8 @@ func TestTCSeqPayload(t *testing.T) { expectedGaps int expectedState []byte }{ - {"No overlap", + { + "No overlap", []segment{ {1, []byte{1, 2, 3, 4, 5}}, {6, []byte{6, 7, 8, 9, 10}}, @@ -221,7 +221,8 @@ func TestTCSeqPayload(t *testing.T) { 0, []byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, }, - {"Gap drop state", + { + "Gap drop state", []segment{ {1, []byte{1, 2, 3, 4}}, {15, []byte{5, 6, 7, 8}}, @@ -229,7 +230,8 @@ func TestTCSeqPayload(t *testing.T) { 10, []byte{5, 6, 7, 8}, }, - {"ACK same sequence number", + { + "ACK same sequence number", []segment{ {1, []byte{1, 2}}, {3, nil}, @@ -239,7 +241,8 @@ func TestTCSeqPayload(t *testing.T) { 0, []byte{1, 2, 3, 4, 5, 6}, }, - {"ACK same sequence number 2", + { + "ACK same sequence number 2", []segment{ {1, nil}, {2, nil}, @@ -253,7 +256,8 @@ func TestTCSeqPayload(t *testing.T) { 0, []byte{1, 2, 3, 4, 5, 6, 7, 8}, }, - {"Overlap, first segment bigger", + { + "Overlap, first segment bigger", []segment{ {1, []byte{1, 2}}, {3, []byte{3, 4}}, @@ -263,7 +267,8 @@ func TestTCSeqPayload(t *testing.T) { 0, []byte{1, 2, 3, 4, 5, 6}, }, - {"Overlap, second segment bigger", + { + "Overlap, second segment bigger", []segment{ {1, []byte{1, 2}}, {3, []byte{3}}, @@ -273,7 +278,8 @@ func TestTCSeqPayload(t *testing.T) { 0, []byte{1, 2, 3, 4, 5, 6}, }, - {"Overlap, covered", + { + "Overlap, covered", []segment{ {1, []byte{1, 2, 3, 4}}, {2, []byte{2, 3}}, diff --git a/packetbeat/protos/thrift/config.go b/packetbeat/protos/thrift/config.go index f687da9ac0c..0d946a02438 100644 --- a/packetbeat/protos/thrift/config.go +++ b/packetbeat/protos/thrift/config.go @@ -34,16 +34,14 @@ type thriftConfig struct { IdlFiles []string `config:"idl_files"` } -var ( - defaultConfig = thriftConfig{ - ProtocolCommon: config.ProtocolCommon{ - TransactionTimeout: protos.DefaultTransactionExpiration, - }, - StringMaxSize: 200, - CollectionMaxSize: 15, - DropAfterNStructFields: 500, - TransportType: "socket", - ProtocolType: "binary", - CaptureReply: true, - } -) +var defaultConfig = thriftConfig{ + ProtocolCommon: config.ProtocolCommon{ + TransactionTimeout: protos.DefaultTransactionExpiration, + }, + StringMaxSize: 200, + CollectionMaxSize: 15, + DropAfterNStructFields: 500, + TransportType: "socket", + ProtocolType: "binary", + CaptureReply: true, +} diff --git a/packetbeat/protos/thrift/thrift.go b/packetbeat/protos/thrift/thrift.go index d9778031d76..04c73747f7f 100644 --- a/packetbeat/protos/thrift/thrift.go +++ b/packetbeat/protos/thrift/thrift.go @@ -656,8 +656,8 @@ func (thrift *thriftPlugin) readStruct(data []byte) (value string, ok bool, comp } func (thrift *thriftPlugin) formatStruct(fields []thriftField, resolveNames bool, - fieldnames []*string) string { - + fieldnames []*string, +) string { toJoin := []string{} for i, field := range fields { if i == thrift.collectionMaxSize { @@ -746,7 +746,7 @@ func (thrift *thriftPlugin) readField(s *thriftStream) (ok bool, complete bool, func (thrift *thriftPlugin) messageParser(s *thriftStream) (bool, bool) { var ok, complete bool - var m = s.message + m := s.message logp.Debug("thriftdetailed", "messageParser called parseState=%v offset=%v", s.parseState, s.parseOffset) @@ -860,7 +860,7 @@ func (stream *thriftStream) prepareForNewMessage(flush bool) { } else { stream.data = stream.data[stream.parseOffset:] } - //logp.Debug("thrift", "remaining data: [%s]", stream.data) + // logp.Debug("thrift", "remaining data: [%s]", stream.data) stream.parseOffset = 0 stream.message = nil stream.parseState = thriftStartState @@ -871,8 +871,8 @@ type thriftPrivateData struct { } func (thrift *thriftPlugin) messageComplete(tcptuple *common.TCPTuple, dir uint8, - stream *thriftStream, priv *thriftPrivateData) { - + stream *thriftStream, priv *thriftPrivateData, +) { flush := false if stream.message.isRequest { @@ -906,7 +906,6 @@ func (thrift *thriftPlugin) messageComplete(tcptuple *common.TCPTuple, dir uint8 // and reset message stream.prepareForNewMessage(flush) - } func (thrift *thriftPlugin) ConnectionTimeout() time.Duration { @@ -914,8 +913,8 @@ func (thrift *thriftPlugin) ConnectionTimeout() time.Duration { } func (thrift *thriftPlugin) Parse(pkt *protos.Packet, tcptuple *common.TCPTuple, dir uint8, - private protos.ProtocolData) protos.ProtocolData { - + private protos.ProtocolData, +) protos.ProtocolData { defer logp.Recover("ParseThrift exception") priv := thriftPrivateData{} @@ -1040,8 +1039,8 @@ func (thrift *thriftPlugin) receivedReply(msg *thriftMessage) { } func (thrift *thriftPlugin) ReceivedFin(tcptuple *common.TCPTuple, dir uint8, - private protos.ProtocolData) protos.ProtocolData { - + private protos.ProtocolData, +) protos.ProtocolData { trans := thrift.getTransaction(tcptuple.Hashable()) if trans != nil { if trans.request != nil && trans.reply == nil { @@ -1055,8 +1054,8 @@ func (thrift *thriftPlugin) ReceivedFin(tcptuple *common.TCPTuple, dir uint8, } func (thrift *thriftPlugin) GapInStream(tcptuple *common.TCPTuple, dir uint8, - nbytes int, private protos.ProtocolData) (priv protos.ProtocolData, drop bool) { - + nbytes int, private protos.ProtocolData) (priv protos.ProtocolData, drop bool, +) { defer logp.Recover("GapInStream(thrift) exception") logp.Debug("thriftdetailed", "GapInStream called") diff --git a/packetbeat/protos/thrift/thrift_idl.go b/packetbeat/protos/thrift/thrift_idl.go index 82d8dedbe93..8bc8bec5b3b 100644 --- a/packetbeat/protos/thrift/thrift_idl.go +++ b/packetbeat/protos/thrift/thrift_idl.go @@ -49,7 +49,7 @@ func fieldsToArrayByID(fields []*parser.Field) []*string { } } - output := make([]*string, max+1, max+1) + output := make([]*string, max+1) for _, field := range fields { if len(field.Name) > 0 { diff --git a/packetbeat/protos/thrift/thrift_test.go b/packetbeat/protos/thrift/thrift_test.go index b5377eb4665..0938c60a3be 100644 --- a/packetbeat/protos/thrift/thrift_test.go +++ b/packetbeat/protos/thrift/thrift_test.go @@ -122,7 +122,6 @@ func TestThrift_readMessageBegin(t *testing.T) { data, _ = hex.DecodeString("800100010000000570696e6700000001") stream = thriftStream{data: data, message: new(thriftMessage)} - m = stream.message ok, complete = thrift.readMessageBegin(&stream) if !ok || complete { t.Errorf("Bad result: %v %v", ok, complete) @@ -130,7 +129,6 @@ func TestThrift_readMessageBegin(t *testing.T) { data, _ = hex.DecodeString("800100010000000570696e6700000001") stream = thriftStream{data: data, message: new(thriftMessage)} - m = stream.message ok, complete = thrift.readMessageBegin(&stream) if !ok || complete { t.Errorf("Bad result: %v %v", ok, complete) @@ -150,7 +148,6 @@ func TestThrift_readMessageBegin(t *testing.T) { data, _ = hex.DecodeString("0000000570696e670100000000") stream = thriftStream{data: data, message: new(thriftMessage)} - m = stream.message ok, complete = thrift.readMessageBegin(&stream) if !ok || complete { t.Error("Bad result:", ok, complete) diff --git a/packetbeat/protos/tls/alerts.go b/packetbeat/protos/tls/alerts.go index 4713e7e81f6..4da5c7d5b75 100644 --- a/packetbeat/protos/tls/alerts.go +++ b/packetbeat/protos/tls/alerts.go @@ -25,8 +25,10 @@ import ( "github.com/elastic/beats/v7/libbeat/logp" ) -type alertSeverity uint8 -type alertCode uint8 +type ( + alertSeverity uint8 + alertCode uint8 +) type alert struct { severity alertSeverity @@ -67,9 +69,7 @@ var alertNames = map[alertCode]string{ 115: "unknown_psk_identity", } -var ( - errRead = errors.New("Buffer read error") -) +var errRead = errors.New("Buffer read error") func (severity alertSeverity) String() string { switch severity { diff --git a/packetbeat/protos/tls/algos.go b/packetbeat/protos/tls/algos.go index b3ba6ea1867..8abd7021b67 100644 --- a/packetbeat/protos/tls/algos.go +++ b/packetbeat/protos/tls/algos.go @@ -22,11 +22,13 @@ import ( "fmt" ) -type cipherSuite uint16 -type signatureScheme uint16 -type pointsGroup uint16 -type compressionMethod uint8 -type ecPointsFormat uint8 +type ( + cipherSuite uint16 + signatureScheme uint16 + pointsGroup uint16 + compressionMethod uint8 + ecPointsFormat uint8 +) // from https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-4 var cipherSuites = map[cipherSuite]string{ @@ -440,26 +442,26 @@ var supportedGroups = map[pointsGroup]string{ } var signatureSchemes = map[signatureScheme]string{ - /* RSASSA-PKCS1-v1_5 algorithms */ + // RSASSA-PKCS1-v1_5 algorithms 0x0401: "rsa_pkcs1_sha256", 0x0501: "rsa_pkcs1_sha384", 0x0601: "rsa_pkcs1_sha512", - /* ECDSA algorithms */ + // ECDSA algorithms 0x0403: "ecdsa_secp256r1_sha256", 0x0503: "ecdsa_secp384r1_sha384", 0x0603: "ecdsa_secp521r1_sha512", - /* RSASSA-PSS algorithms */ + // RSASSA-PSS algorithms 0x0804: "rsa_pss_sha256", 0x0805: "rsa_pss_sha384", 0x0806: "rsa_pss_sha512", - /* EdDSA algorithms */ + // EdDSA algorithms 0x0807: "ed25519", 0x0808: "ed448", - /* Legacy algorithms */ + // Legacy algorithms 0x0201: "rsa_pkcs1_sha1", 0x0203: "ecdsa_sha1", } diff --git a/packetbeat/protos/tls/config.go b/packetbeat/protos/tls/config.go index 775a8f69cc1..2190ccc18dd 100644 --- a/packetbeat/protos/tls/config.go +++ b/packetbeat/protos/tls/config.go @@ -30,13 +30,11 @@ type tlsConfig struct { Fingerprints []string `config:"fingerprints"` } -var ( - defaultConfig = tlsConfig{ - ProtocolCommon: config.ProtocolCommon{ - TransactionTimeout: protos.DefaultTransactionExpiration, - }, - SendCertificates: true, - IncludeDetailedFields: true, - Fingerprints: []string{"sha1"}, - } -) +var defaultConfig = tlsConfig{ + ProtocolCommon: config.ProtocolCommon{ + TransactionTimeout: protos.DefaultTransactionExpiration, + }, + SendCertificates: true, + IncludeDetailedFields: true, + Fingerprints: []string{"sha1"}, +} diff --git a/packetbeat/protos/tls/extensions.go b/packetbeat/protos/tls/extensions.go index 0021705c7f7..1ffceb3c235 100644 --- a/packetbeat/protos/tls/extensions.go +++ b/packetbeat/protos/tls/extensions.go @@ -35,12 +35,14 @@ type Extensions struct { InOrder []ExtensionID } -type extensionParser func(reader bufferView) interface{} -type extension struct { - label string - parser extensionParser - saveRaw bool -} +type ( + extensionParser func(reader bufferView) interface{} + extension struct { + label string + parser extensionParser + saveRaw bool + } +) const ( // ExtensionSupportedGroups identifies the supported group extension @@ -72,7 +74,6 @@ var extensionMap = map[uint16]extension{ // ParseExtensions returns an Extensions object parsed from the supplied buffer func ParseExtensions(buffer bufferView) Extensions { - var extensionsLength uint16 if !buffer.read16Net(0, &extensionsLength) || extensionsLength == 0 { // No extensions diff --git a/packetbeat/protos/tls/extensions_test.go b/packetbeat/protos/tls/extensions_test.go index 23caec09019..c61937411a9 100644 --- a/packetbeat/protos/tls/extensions_test.go +++ b/packetbeat/protos/tls/extensions_test.go @@ -27,7 +27,6 @@ import ( ) func TestSni(t *testing.T) { - // Single element buf := mkBuf(t, "000d"+ // 13 bytes @@ -126,7 +125,6 @@ func TestSni(t *testing.T) { } func TestParseMaxFragmentLength(t *testing.T) { - r := parseMaxFragmentLen(*mkBuf(t, "01", 1)) assert.Equal(t, "2^9", r.(string)) r = parseMaxFragmentLen(*mkBuf(t, "04", 1)) diff --git a/packetbeat/protos/tls/fingerprint.go b/packetbeat/protos/tls/fingerprint.go index 8768ff448e7..70489b687f9 100644 --- a/packetbeat/protos/tls/fingerprint.go +++ b/packetbeat/protos/tls/fingerprint.go @@ -36,8 +36,10 @@ type FingerprintAlgorithm struct { algo AlgorithmFactory } -var hashMap = make(map[string]*FingerprintAlgorithm) -var hashNames []string +var ( + hashMap = make(map[string]*FingerprintAlgorithm) + hashNames []string +) func init() { registerAlgo(func() hash.Hash { return md5.New() }, "md5", "") diff --git a/packetbeat/protos/tls/ja3.go b/packetbeat/protos/tls/ja3.go index 6e6faf5e26c..09a0aec5ea4 100644 --- a/packetbeat/protos/tls/ja3.go +++ b/packetbeat/protos/tls/ja3.go @@ -25,7 +25,6 @@ import ( ) func getJa3Fingerprint(hello *helloMessage) (hash string, ja3str string) { - // build the array of arrays of numbers data := make([][]uint16, 5) diff --git a/packetbeat/protos/tls/parse.go b/packetbeat/protos/tls/parse.go index d0ec3be75ef..fa4515e2248 100644 --- a/packetbeat/protos/tls/parse.go +++ b/packetbeat/protos/tls/parse.go @@ -54,9 +54,9 @@ type recordType uint8 const ( recordTypeChangeCipherSpec recordType = 20 - recordTypeAlert = 21 - recordTypeHandshake = 22 - recordTypeApplicationData = 23 + recordTypeAlert recordType = 21 + recordTypeHandshake recordType = 22 + recordTypeApplicationData recordType = 23 ) type handshakeType uint8 @@ -169,8 +169,10 @@ func readHandshakeHeader(buf *streambuf.Buffer) (*handshakeHeader, error) { if len16, err = buf.ReadNetUint16At(2); err != nil { return nil, err } - return &handshakeHeader{handshakeType(typ), - int(len16) | (int(len8) << 16)}, nil + return &handshakeHeader{ + handshakeType(typ), + int(len16) | (int(len8) << 16), + }, nil } func (header *recordHeader) String() string { @@ -215,7 +217,6 @@ func (hello *helloMessage) supportedCiphers() []string { } func (parser *parser) parse(buf *streambuf.Buffer) parserResult { - for buf.Avail(recordHeaderSize) { header, err := readRecordHeader(buf) diff --git a/packetbeat/protos/tls/parse_test.go b/packetbeat/protos/tls/parse_test.go index 37f4a1b1956..f599b30c44c 100644 --- a/packetbeat/protos/tls/parse_test.go +++ b/packetbeat/protos/tls/parse_test.go @@ -125,12 +125,6 @@ func mapGet(t *testing.T, m common.MapStr, key string) interface{} { return value } -func mapInt(t *testing.T, m common.MapStr, key string) uint32 { - value, err := m.GetValue(key) - assert.NoError(t, err) - return value.(uint32) -} - func TestParseRecordHeader(t *testing.T) { if testing.Verbose() { isDebug = true @@ -173,6 +167,7 @@ func TestParseHandshakeHeader(t *testing.T) { _, err = readHandshakeHeader(sBuf(t, "112233")) assert.Error(t, err) header, err := readHandshakeHeader(sBuf(t, "11223344")) + assert.NoError(t, err) assert.Equal(t, handshakeType(0x11), header.handshakeType) assert.Equal(t, 0x223344, header.length) } @@ -202,7 +197,6 @@ func TestParserParse(t *testing.T) { // Certificate request assert.Equal(t, resultOK, parser.parse(sBuf(t, "16030300040d000000"))) assert.True(t, parser.certRequested) - } func TestParserHello(t *testing.T) { diff --git a/packetbeat/protos/tls/tls.go b/packetbeat/protos/tls/tls.go index 9db2a28f694..a785d101021 100644 --- a/packetbeat/protos/tls/tls.go +++ b/packetbeat/protos/tls/tls.go @@ -170,10 +170,9 @@ func (plugin *tlsPlugin) doParse( tcptuple *common.TCPTuple, dir uint8, ) *tlsConnectionData { - // Ignore further traffic after the handshake is completed (encrypted connection) // TODO: request/response analysis - if 0 != conn.handshakeCompleted&(1< 0 { desc = dev.Description } - r += fmt.Sprintf(" (%s)", desc) + fmt.Fprintf(&buf, " (%s)", desc) } if withIP { - ips := "Not assigned ip address" - if len(dev.Addresses) > 0 { - ips = "" - + buf.WriteString(" (") + if len(dev.Addresses) == 0 { + buf.WriteString("Not assigned ip address") + } else { for i, address := range []pcap.InterfaceAddress(dev.Addresses) { - // Add a space between the IP address. - if i > 0 { - ips += " " + if i != 0 { + buf.WriteByte(' ') } - - ips += fmt.Sprintf("%s", address.IP.String()) + fmt.Fprint(&buf, address.IP) } } - r += fmt.Sprintf(" (%s)", ips) - + buf.WriteByte(')') } - ret = append(ret, r) + names = append(names, buf.String()) } - return ret, nil + return names } func resolveDeviceName(name string) (string, error) { diff --git a/packetbeat/sniffer/device_test.go b/packetbeat/sniffer/device_test.go new file mode 100644 index 00000000000..e7bb9cfee5a --- /dev/null +++ b/packetbeat/sniffer/device_test.go @@ -0,0 +1,136 @@ +// Licensed to Elasticsearch B.V. under one or more contributor +// license agreements. See the NOTICE file distributed with +// this work for additional information regarding copyright +// ownership. Elasticsearch B.V. licenses this file to you 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 sniffer + +import ( + "net" + "reflect" + "testing" + + "github.com/google/gopacket/pcap" +) + +var formatDeviceNamesTests = []struct { + name string + interfaces []pcap.Interface + withDesc bool + withIP bool + want []string +}{ + {name: "empty"}, + { + name: "loopback no withs", + interfaces: []pcap.Interface{ + { + Name: "lo", Description: "loopback", + Addresses: []pcap.InterfaceAddress{ + {IP: net.IP{127, 0, 0, 1}, Netmask: net.IPMask{255, 0, 0, 0}}, + }, + }, + }, + want: []string{ + "lo", + }, + }, + { + name: "loopback with desc", + interfaces: []pcap.Interface{ + { + Name: "lo", Description: "loopback", + Addresses: []pcap.InterfaceAddress{ + {IP: net.IP{127, 0, 0, 1}, Netmask: net.IPMask{255, 0, 0, 0}}, + }, + }, + }, + withDesc: true, + want: []string{ + "lo (loopback)", + }, + }, + { + name: "loopback with IPs", + interfaces: []pcap.Interface{ + { + Name: "lo", Description: "loopback", + Addresses: []pcap.InterfaceAddress{ + {IP: net.IP{127, 0, 0, 1}, Netmask: net.IPMask{255, 0, 0, 0}}, + }, + }, + }, + withIP: true, + want: []string{ + "lo (127.0.0.1)", + }, + }, + { + name: "loopback with the lot", + interfaces: []pcap.Interface{ + { + Name: "lo", Description: "loopback", + Addresses: []pcap.InterfaceAddress{ + {IP: net.IP{127, 0, 0, 1}, Netmask: net.IPMask{255, 0, 0, 0}}, + }, + }, + }, + withDesc: true, + withIP: true, + want: []string{ + "lo (loopback) (127.0.0.1)", + }, + }, + { + name: "two addr loopback with the lot", + interfaces: []pcap.Interface{ + { + Name: "lo", Description: "loopback", + Addresses: []pcap.InterfaceAddress{ + {IP: net.IP{127, 0, 0, 1}, Netmask: net.IPMask{255, 0, 0, 0}}, + {IP: net.IP{127, 0, 1, 1}, Netmask: net.IPMask{255, 0, 0, 0}}, + }, + }, + }, + withDesc: true, + withIP: true, + want: []string{ + "lo (loopback) (127.0.0.1 127.0.1.1)", + }, + }, + { + name: "no IP loopback with the lot", + interfaces: []pcap.Interface{ + { + Name: "lo", Description: "loopback", + }, + }, + withDesc: true, + withIP: true, + want: []string{ + "lo (loopback) (Not assigned ip address)", + }, + }, +} + +func TestFormatDevices(t *testing.T) { + for _, test := range formatDeviceNamesTests { + got := formatDeviceNames(test.interfaces, test.withDesc, test.withIP) + if !reflect.DeepEqual(got, test.want) { + t.Errorf("unexpected result for test %s:\ngot: %v\nwant:%v", + test.name, got, test.want) + } + } +} diff --git a/packetbeat/sniffer/file.go b/packetbeat/sniffer/file.go index b112e4c90ed..ec0d16f554d 100644 --- a/packetbeat/sniffer/file.go +++ b/packetbeat/sniffer/file.go @@ -22,9 +22,9 @@ import ( "io" "time" - "github.com/tsg/gopacket" - "github.com/tsg/gopacket/layers" - "github.com/tsg/gopacket/pcap" + "github.com/google/gopacket" + "github.com/google/gopacket/layers" + "github.com/google/gopacket/pcap" "github.com/elastic/beats/v7/libbeat/logp" ) diff --git a/packetbeat/sniffer/sniffer.go b/packetbeat/sniffer/sniffer.go index bfe720c7b98..de0a1683a5f 100644 --- a/packetbeat/sniffer/sniffer.go +++ b/packetbeat/sniffer/sniffer.go @@ -25,9 +25,10 @@ import ( "syscall" "time" - "github.com/tsg/gopacket" - "github.com/tsg/gopacket/layers" - "github.com/tsg/gopacket/pcap" + "github.com/google/gopacket" + "github.com/google/gopacket/layers" + "github.com/google/gopacket/pcap" + "github.com/google/gopacket/pcapgo" "github.com/elastic/beats/v7/libbeat/common/atomic" "github.com/elastic/beats/v7/libbeat/logp" @@ -39,7 +40,6 @@ import ( // to a Worker. type Sniffer struct { config config.InterfacesConfig - dumper *pcap.Dumper state atomic.Int32 // store snifferState @@ -60,7 +60,6 @@ type Worker interface { type snifferHandle interface { gopacket.PacketDataSource - LinkType() layers.LinkType Close() } @@ -141,24 +140,22 @@ func New( // Run opens the sniffing device and processes packets being read from that device. // Worker instances are instantiated as needed. func (s *Sniffer) Run() error { - var ( - counter = 0 - dumper *pcap.Dumper - ) - handle, err := s.open() if err != nil { return fmt.Errorf("Error starting sniffer: %s", err) } defer handle.Close() + var w *pcapgo.Writer if s.config.Dumpfile != "" { - dumper, err = openDumper(s.config.Dumpfile, handle.LinkType()) + f, err := os.Create(s.config.Dumpfile) if err != nil { return err } + defer f.Close() - defer dumper.Close() + w = pcapgo.NewWriterNanos(f) + w.WriteFileHeader(65535, handle.LinkType()) } worker, err := s.factory(handle.LinkType()) @@ -174,6 +171,7 @@ func (s *Sniffer) Run() error { } defer s.state.Store(snifferInactive) + var packets int for s.state.Load() == snifferActive { if s.config.OneAtATime { fmt.Println("Press enter to read packet") @@ -193,7 +191,7 @@ func (s *Sniffer) Run() error { } s.state.Store(snifferInactive) - return fmt.Errorf("Sniffing error: %s", err) + return fmt.Errorf("Sniffing error: %w", err) } if len(data) == 0 { @@ -201,12 +199,16 @@ func (s *Sniffer) Run() error { continue } - if dumper != nil { - dumper.WritePacketData(data, ci) + packets++ + + if w != nil { + err = w.WritePacket(ci, data) + if err != nil { + return fmt.Errorf("failed to write packet %d: %w", packets, err) + } } - counter++ - logp.Debug("sniffer", "Packet number: %d", counter) + logp.Debug("sniffer", "Packet number: %d", packets) worker.OnPacket(data, &ci) } @@ -265,20 +267,8 @@ func validatePcapFilter(expr string) error { if expr == "" { return nil } - - // Open a dummy pcap handle to compile the filter - p, err := pcap.OpenDead(layers.LinkTypeEthernet, 65535) - if err != nil { - return fmt.Errorf("OpenDead: %s", err) - } - - defer p.Close() - - _, err = p.NewBPF(expr) - if err != nil { - return fmt.Errorf("invalid filter '%s': %v", expr, err) - } - return nil + _, err := pcap.NewBPF(layers.LinkTypeEthernet, 65535, expr) + return err } func openPcap(filter string, cfg *config.InterfacesConfig) (snifferHandle, error) { @@ -318,12 +308,3 @@ func openAFPacket(filter string, cfg *config.InterfacesConfig) (snifferHandle, e return h, nil } - -func openDumper(file string, linkType layers.LinkType) (*pcap.Dumper, error) { - p, err := pcap.OpenDead(linkType, 65535) - if err != nil { - return nil, err - } - - return p.NewDumper(file) -} diff --git a/packetbeat/sniffer/sniffer_test.go b/packetbeat/sniffer/sniffer_test.go index eea7821d889..52b0b57fb33 100644 --- a/packetbeat/sniffer/sniffer_test.go +++ b/packetbeat/sniffer/sniffer_test.go @@ -52,13 +52,16 @@ func TestSniffer_afpacketComputeSize(t *testing.T) { t.Error("Value too big", blockSize, numBlocks) } - frameSize, blockSize, numBlocks, err = afpacketComputeSize(0, 1514, 4096) + _, _, _, err = afpacketComputeSize(0, 1514, 4096) if err == nil { t.Error("Expected an error") } // 16436 is the default MTU size of the loopback interface frameSize, blockSize, numBlocks, err = afpacketComputeSize(30, 16436, 4096) + if err != nil { + t.Error(err) + } if frameSize != 4096*5 || blockSize != 4096*5*128 || numBlocks != 12 { t.Error("Bad result", frameSize, blockSize, numBlocks) } diff --git a/packetbeat/tests/system/packetbeat.py b/packetbeat/tests/system/packetbeat.py index 32a9366ee33..c4727d13183 100644 --- a/packetbeat/tests/system/packetbeat.py +++ b/packetbeat/tests/system/packetbeat.py @@ -33,7 +33,7 @@ def setUpClass(self): def run_packetbeat(self, pcap, cmd=None, config="packetbeat.yml", - output="packetbeat.log", + output=None, extra_args=[], debug_selectors=[], exit_code=0, @@ -44,6 +44,9 @@ def run_packetbeat(self, pcap, the caller. """ + if output is None: + output = "packetbeat-" + self.today + ".ndjson" + if cmd is None: cmd = self.beat_path + "/packetbeat.test" @@ -87,7 +90,7 @@ def run_packetbeat(self, pcap, def start_packetbeat(self, cmd=None, config="packetbeat.yml", - output="packetbeat.log", + output=None, extra_args=[], debug_selectors=[]): """ @@ -95,6 +98,9 @@ def start_packetbeat(self, caller is responsible for stopping / waiting for the Proc instance. """ + if output is None: + output = "packetbeat-" + self.today + ".ndjson" + if cmd is None: cmd = self.beat_path + "/packetbeat.test" @@ -119,9 +125,14 @@ def start_packetbeat(self, return proc def read_output(self, - output_file="output/packetbeat", + output_file=None, types=None, required_fields=None): + + if output_file is None: + output_file = "output/packetbeat-"+self.today+".ndjson" + print(output_file) + jsons = [] with open(os.path.join(self.working_dir, output_file), "r", encoding='utf_8') as f: for line in f: diff --git a/packetbeat/tests/system/test_0002_thrift_basics.py b/packetbeat/tests/system/test_0002_thrift_basics.py index 6e0154a437c..a1a66742bdc 100644 --- a/packetbeat/tests/system/test_0002_thrift_basics.py +++ b/packetbeat/tests/system/test_0002_thrift_basics.py @@ -208,7 +208,7 @@ def test_thrift_send_request_response(self): self.run_packetbeat(pcap="thrift_integration.pcap", debug_selectors=["thrift"]) - objs = self.read_output() + objs = self.read_output(output_file="output/packetbeat-" + self.today + "-1.ndjson") assert all(["request" not in o for o in objs]) assert all(["response" not in o for o in objs]) diff --git a/packetbeat/tests/system/test_0006_wsgi.py b/packetbeat/tests/system/test_0006_wsgi.py index 6f905942449..02e52b885a3 100644 --- a/packetbeat/tests/system/test_0006_wsgi.py +++ b/packetbeat/tests/system/test_0006_wsgi.py @@ -100,7 +100,7 @@ def test_send_headers_options(self): ) self.run_packetbeat(pcap="wsgi_loopback.pcap") - objs = self.read_output() + objs = self.read_output(output_file="output/packetbeat-" + self.today + "-1.ndjson") assert len(objs) == 1 o = objs[0] @@ -119,7 +119,7 @@ def test_send_headers_options(self): ) self.run_packetbeat(pcap="wsgi_loopback.pcap") - objs = self.read_output() + objs = self.read_output(output_file="output/packetbeat-" + self.today + "-2.ndjson") assert len(objs) == 1 o = objs[0] diff --git a/packetbeat/tests/system/test_0050_icmp.py b/packetbeat/tests/system/test_0050_icmp.py index c0f876c1b73..05b21b845ed 100644 --- a/packetbeat/tests/system/test_0050_icmp.py +++ b/packetbeat/tests/system/test_0050_icmp.py @@ -82,10 +82,10 @@ def assert_common_icmp4_fields(self, obj): assert obj["related.ip"] == ["10.0.0.1", "10.0.0.2"] assert obj["path"] == "10.0.0.2" assert obj["status"] == "OK" - assert obj["icmp.request.message"] == "EchoRequest(0)" + assert obj["icmp.request.message"] == "EchoRequest" assert obj["icmp.request.type"] == 8 assert obj["icmp.request.code"] == 0 - assert obj["icmp.response.message"] == "EchoReply(0)" + assert obj["icmp.response.message"] == "EchoReply" assert obj["icmp.response.type"] == 0 assert obj["icmp.response.code"] == 0 @@ -95,9 +95,9 @@ def assert_common_icmp6_fields(self, obj): assert obj["client.ip"] == "::1" assert obj["path"] == "::2" assert obj["status"] == "OK" - assert obj["icmp.request.message"] == "EchoRequest(0)" + assert obj["icmp.request.message"] == "EchoRequest" assert obj["icmp.request.type"] == 128 assert obj["icmp.request.code"] == 0 - assert obj["icmp.response.message"] == "EchoReply(0)" + assert obj["icmp.response.message"] == "EchoReply" assert obj["icmp.response.type"] == 129 assert obj["icmp.response.code"] == 0 diff --git a/script/renamed_fields.py b/script/renamed_fields.py index 2de05c012b4..08059698bf1 100644 --- a/script/renamed_fields.py +++ b/script/renamed_fields.py @@ -3,7 +3,7 @@ def migration(): - beats = ["Auditbeat", "Filebeat", "Heartbeat", "Journalbeat", "Metricbeat", "Packetbeat", "Winlogbeat"] + beats = ["Auditbeat", "Filebeat", "Heartbeat", "Metricbeat", "Packetbeat", "Winlogbeat"] for beat in beats: print(".{} renamed fields in 7.0".format(beat)) diff --git a/testing/environments/snapshot-oss.yml b/testing/environments/snapshot-oss.yml index 2445bef8713..8a398f7b4c8 100644 --- a/testing/environments/snapshot-oss.yml +++ b/testing/environments/snapshot-oss.yml @@ -3,7 +3,7 @@ version: '2.3' services: elasticsearch: - image: docker.elastic.co/elasticsearch/elasticsearch:8.0.0-2f347a19-SNAPSHOT + image: docker.elastic.co/elasticsearch/elasticsearch:8.1.0-7004acda-SNAPSHOT healthcheck: test: ["CMD-SHELL", "curl -s http://localhost:9200/_cat/health?h=status | grep -q green"] retries: 300 @@ -21,7 +21,7 @@ services: - "script.context.template.cache_max_size=2000" logstash: - image: docker.elastic.co/logstash/logstash-oss:8.0.0-2f347a19-SNAPSHOT + image: docker.elastic.co/logstash/logstash-oss:8.1.0-7004acda-SNAPSHOT healthcheck: test: ["CMD", "curl", "-f", "http://localhost:9600/_node/stats"] retries: 600 @@ -31,7 +31,7 @@ services: - ./docker/logstash/pki:/etc/pki:ro kibana: - image: docker.elastic.co/kibana/kibana:8.0.0-2f347a19-SNAPSHOT + image: docker.elastic.co/kibana/kibana:8.1.0-7004acda-SNAPSHOT healthcheck: test: ["CMD-SHELL", "curl -s http://localhost:5601/api/status?v8format=true | grep -q '\"overall\":{\"level\":\"available\"'"] retries: 600 diff --git a/testing/environments/snapshot.yml b/testing/environments/snapshot.yml index c9215fe874b..c8552faf0c0 100644 --- a/testing/environments/snapshot.yml +++ b/testing/environments/snapshot.yml @@ -3,7 +3,7 @@ version: '2.3' services: elasticsearch: - image: docker.elastic.co/elasticsearch/elasticsearch:8.0.0-2f347a19-SNAPSHOT + image: docker.elastic.co/elasticsearch/elasticsearch:8.1.0-7004acda-SNAPSHOT healthcheck: test: ["CMD-SHELL", "curl -s http://localhost:9200/_cat/health?h=status | grep -q green"] retries: 300 @@ -14,10 +14,8 @@ services: - "transport.host=127.0.0.1" - "http.host=0.0.0.0" - "xpack.security.enabled=false" - - "script.context.template.max_compilations_rate=unlimited" - - "script.context.ingest.cache_max_size=2000" - - "script.context.processor_conditional.cache_max_size=2000" - - "script.context.template.cache_max_size=2000" + # We want something as unlimited compilation rate, but 'unlimited' is not valid. + - "script.max_compilations_rate=100000/1m" - "action.destructive_requires_name=false" # Disable geoip updates to prevent golden file test failures when the database # changes and prevent race conditions between tests and database updates. @@ -39,7 +37,7 @@ services: - ./docker/logstash/pki:/etc/pki:ro kibana: - image: docker.elastic.co/kibana/kibana:8.0.0-2f347a19-SNAPSHOT + image: docker.elastic.co/kibana/kibana:8.1.0-7004acda-SNAPSHOT healthcheck: test: ["CMD-SHELL", "curl -s http://localhost:5601/api/status?v8format=true | grep -q '\"overall\":{\"level\":\"available\"'"] retries: 600 diff --git a/winlogbeat/_meta/config/header.yml.tmpl b/winlogbeat/_meta/config/header.yml.tmpl index 7ace0063a18..b12d31c47d9 100644 --- a/winlogbeat/_meta/config/header.yml.tmpl +++ b/winlogbeat/_meta/config/header.yml.tmpl @@ -15,12 +15,25 @@ # directory in which it was started. #winlogbeat.registry_file: .winlogbeat.yml +# The timeout value that controls when registry entries are written to disk +# (flushed). When an unwritten update exceeds this value, it triggers a write +# to disk. When flush is set to 0s, the registry is written to disk after each +# batch of events has been published successfully. The default value is 5s. +#winlogbeat.registry_flush: 5s + +# By default Ingest pipelines are not updated if a pipeline with the same ID +# already exists. If this option is enabled Winlogbeat overwrites pipelines +# every time a new Elasticsearch connection is established. +#winlogbeat.overwrite_pipelines: false + {{end -}} # event_logs specifies a list of event logs to monitor as well as any # accompanying options. The YAML data type of event_logs is a list of # dictionaries. # -# The supported keys are name (required), tags, fields, fields_under_root, -# forwarded, ignore_older, level, event_id, provider, and include_xml. Please -# visit the documentation for the complete details of each option. +# The supported keys are name, id, xml_query, tags, fields, fields_under_root, +# forwarded, ignore_older, level, event_id, provider, and include_xml. +# The xml_query key requires an id and must not be used with the name, +# ignore_older, level, event_id, or provider keys. Please visit the +# documentation for the complete details of each option. # https://go.es.io/WinlogbeatConfig diff --git a/winlogbeat/beater/winlogbeat.go b/winlogbeat/beater/winlogbeat.go index baa798bef76..ec7ebf90ef6 100644 --- a/winlogbeat/beater/winlogbeat.go +++ b/winlogbeat/beater/winlogbeat.go @@ -29,14 +29,21 @@ import ( "github.com/elastic/beats/v7/libbeat/beat" "github.com/elastic/beats/v7/libbeat/common" + "github.com/elastic/beats/v7/libbeat/esleg/eslegclient" "github.com/elastic/beats/v7/libbeat/logp" + "github.com/elastic/beats/v7/libbeat/outputs/elasticsearch" "github.com/elastic/beats/v7/libbeat/paths" + "github.com/elastic/beats/v7/winlogbeat/module" "github.com/elastic/beats/v7/winlogbeat/checkpoint" "github.com/elastic/beats/v7/winlogbeat/config" "github.com/elastic/beats/v7/winlogbeat/eventlog" ) +const pipelinesWarning = "Winlogbeat is unable to load the ingest pipelines" + + " because the Elasticsearch output is not configured/enabled. If you have" + + " already loaded the ingest pipelines, you can ignore this warning." + // Time the application was started. var startTime = time.Now().UTC() @@ -100,7 +107,14 @@ func (eb *Winlogbeat) init(b *beat.Beat) error { eb.eventLogs = append(eb.eventLogs, logger) } - + b.OverwritePipelinesCallback = func(esConfig *common.Config) error { + overwritePipelines := config.OverwritePipelines + esClient, err := eslegclient.NewConnectedClient(esConfig, "Winlogbeat") + if err != nil { + return err + } + return module.UploadPipelines(b.Info, esClient, overwritePipelines) + } return nil } @@ -110,7 +124,7 @@ func (eb *Winlogbeat) setup(b *beat.Beat) error { config := &eb.config var err error - eb.checkpoint, err = checkpoint.NewCheckpoint(config.RegistryFile, 10, 5*time.Second) + eb.checkpoint, err = checkpoint.NewCheckpoint(config.RegistryFile, config.RegistryFlush) if err != nil { return err } @@ -125,6 +139,18 @@ func (eb *Winlogbeat) Run(b *beat.Beat) error { return err } + if b.Config.Output.Name() == "elasticsearch" { + callback := func(esClient *eslegclient.Connection) error { + return module.UploadPipelines(b.Info, esClient, eb.config.OverwritePipelines) + } + _, err := elasticsearch.RegisterConnectCallback(callback) + if err != nil { + return err + } + } else { + eb.log.Warn(pipelinesWarning) + } + acker := newEventACKer(eb.checkpoint) persistedState := eb.checkpoint.States() diff --git a/winlogbeat/checkpoint/checkpoint.go b/winlogbeat/checkpoint/checkpoint.go index 2ce455c97e3..a93b29abed1 100644 --- a/winlogbeat/checkpoint/checkpoint.go +++ b/winlogbeat/checkpoint/checkpoint.go @@ -42,7 +42,6 @@ type Checkpoint struct { file string // File where the state is persisted. fileLock sync.RWMutex // Lock that protects concurrent reads/writes to file. numUpdates int // Number of updates received since last persisting to disk. - maxUpdates int // Maximum number of updates to buffer before persisting to disk. flushInterval time.Duration // Maximum time interval that can pass before persisting to disk. sort []string // Slice used for sorting states map (store to save on mallocs). @@ -72,26 +71,18 @@ type EventLogState struct { // guarantee any in-memory state information is flushed to disk. // // file is the name of the file where event log state is persisted as YAML. -// maxUpdates is the maximum number of updates checkpoint will accept before -// triggering a flush to disk. interval is maximum amount of time that can -// pass since the last flush before triggering a flush to disk (minimum value -// is 1s). -func NewCheckpoint(file string, maxUpdates int, interval time.Duration) (*Checkpoint, error) { +// interval is maximum amount of time that can pass since the last flush +// before triggering a flush to disk (minimum value is 1s). +func NewCheckpoint(file string, interval time.Duration) (*Checkpoint, error) { c := &Checkpoint{ done: make(chan struct{}), file: file, - maxUpdates: maxUpdates, flushInterval: interval, sort: make([]string, 0, 10), states: make(map[string]EventLogState), save: make(chan EventLogState, 1), } - // Minimum batch size. - if c.maxUpdates < 1 { - c.maxUpdates = 1 - } - // Minimum flush interval. if c.flushInterval < time.Second { c.flushInterval = time.Second @@ -139,9 +130,6 @@ loop: c.states[s.Name] = s c.lock.Unlock() c.numUpdates++ - if c.numUpdates < c.maxUpdates { - continue - } case <-flushTimer.C: } diff --git a/winlogbeat/checkpoint/checkpoint_test.go b/winlogbeat/checkpoint/checkpoint_test.go index 0f515cf6881..ef9e70cbeb1 100644 --- a/winlogbeat/checkpoint/checkpoint_test.go +++ b/winlogbeat/checkpoint/checkpoint_test.go @@ -56,58 +56,6 @@ func eventually(t *testing.T, predicate func() (bool, error), timeout time.Durat t.Fatal("predicate is not true after", timeout) } -// Test that a write is triggered when the maximum number of updates is reached. -func TestWriteMaxUpdates(t *testing.T) { - dir, err := ioutil.TempDir("", "wlb-checkpoint-test") - if err != nil { - t.Fatal(err) - } - defer func() { - err := os.RemoveAll(dir) - if err != nil { - t.Fatal(err) - } - }() - - file := filepath.Join(dir, "some", "new", "dir", ".winlogbeat.yml") - if !assert.False(t, fileExists(file), "%s should not exist", file) { - return - } - - cp, err := NewCheckpoint(file, 2, time.Hour) - if err != nil { - t.Fatal(err) - } - defer cp.Shutdown() - - // Send update - it's not written to disk but it's in memory. - cp.Persist("App", 1, time.Now(), "") - found := false - eventually(t, func() (bool, error) { - _, found = cp.States()["App"] - return found, nil - }, time.Second*15) - assert.True(t, found) - - ps, err := cp.read() - if err != nil { - t.Fatal("read failed", err) - } - assert.Len(t, ps.States, 0) - - // Send update - it is written to disk. - cp.Persist("App", 2, time.Now(), "") - eventually(t, func() (bool, error) { - ps, err = cp.read() - return ps != nil && len(ps.States) > 0, err - }, time.Second*15) - - if assert.Len(t, ps.States, 1, "state not written, could be a flush timing issue, retry") { - assert.Equal(t, "App", ps.States[0].Name) - assert.Equal(t, uint64(2), ps.States[0].RecordNumber) - } -} - // Test that a write is triggered when the maximum time period since the last // write is reached. func TestWriteTimedFlush(t *testing.T) { @@ -127,7 +75,7 @@ func TestWriteTimedFlush(t *testing.T) { return } - cp, err := NewCheckpoint(file, 100, time.Second) + cp, err := NewCheckpoint(file, time.Second) if err != nil { t.Fatal(err) } diff --git a/winlogbeat/config/config.go b/winlogbeat/config/config.go index 9700554eacf..ed8f2195d02 100644 --- a/winlogbeat/config/config.go +++ b/winlogbeat/config/config.go @@ -34,15 +34,18 @@ const ( var ( DefaultSettings = WinlogbeatConfig{ - RegistryFile: DefaultRegistryFile, + RegistryFile: DefaultRegistryFile, + RegistryFlush: 5 * time.Second, } ) // WinlogbeatConfig contains all of Winlogbeat configuration data. type WinlogbeatConfig struct { - EventLogs []*common.Config `config:"event_logs"` - RegistryFile string `config:"registry_file"` - ShutdownTimeout time.Duration `config:"shutdown_timeout"` + EventLogs []*common.Config `config:"event_logs"` + RegistryFile string `config:"registry_file"` + RegistryFlush time.Duration `config:"registry_flush"` + ShutdownTimeout time.Duration `config:"shutdown_timeout"` + OverwritePipelines bool `config:"overwrite_pipelines"` } // Validate validates the WinlogbeatConfig data and returns an error describing diff --git a/winlogbeat/docs/fields.asciidoc b/winlogbeat/docs/fields.asciidoc index 27f561dba39..87762a519c6 100644 --- a/winlogbeat/docs/fields.asciidoc +++ b/winlogbeat/docs/fields.asciidoc @@ -15633,47 +15633,16 @@ type: ip -- - -*`kubernetes.namespace.name`*:: +*`kubernetes.namespace`*:: + -- -Kubernetes namespace name +Kubernetes namespace type: keyword -- -*`kubernetes.namespace.uuid`*:: -+ --- -Kubernetes namespace uuid - - -type: keyword - --- - -*`kubernetes.namespace.labels.*`*:: -+ --- -Kubernetes namespace labels map - - -type: object - --- - -*`kubernetes.namespace.annotations.*`*:: -+ --- -Kubernetes namespace annotations map - - -type: object - --- - *`kubernetes.node.name`*:: + -- diff --git a/winlogbeat/docs/index.asciidoc b/winlogbeat/docs/index.asciidoc index d953f0d641c..97c1023d4c2 100644 --- a/winlogbeat/docs/index.asciidoc +++ b/winlogbeat/docs/index.asciidoc @@ -21,6 +21,7 @@ include::{asciidoc-dir}/../../shared/attributes.asciidoc[] :no_decode_cef_processor: :no_decode_csv_fields_processor: :include_translate_sid_processor: +:export_pipeline: include::{libbeat-dir}/shared-beats-attributes.asciidoc[] diff --git a/winlogbeat/docs/winlogbeat-options.asciidoc b/winlogbeat/docs/winlogbeat-options.asciidoc index a9c968e0385..e703406061d 100644 --- a/winlogbeat/docs/winlogbeat-options.asciidoc +++ b/winlogbeat/docs/winlogbeat-options.asciidoc @@ -46,6 +46,23 @@ backslashes (\) for Windows compatibility. You can use either forward or backslashes. Forward slashes are easier to work with in YAML because there is no need to escape them. +[float] +==== `registry_flush` + +The timeout value that controls when registry entries are written to disk +(flushed). When an unwritten update exceeds this value, it triggers a write +to disk. When flush is set to 0s, the registry is written to disk after each +batch of events has been published successfully. + +The default value is 5s. + +Valid time units are `ns`, `us`, `ms`, `s`, `m`, `h`. + +[source,yaml] +-------------------------------------------------------------------------------- +winlogbeat.registry_flush: 5s +-------------------------------------------------------------------------------- + [float] ==== `shutdown_timeout` @@ -70,7 +87,6 @@ winlogbeat.shutdown_timeout: 30s A list of entries (called 'dictionaries' in YAML) that specify which event logs to monitor. Each entry in the list defines an event log to monitor as well as any information to be associated with the event log (filter, tags, and so on). -The `name` field is the only required field for each event log. [source,yaml] -------------------------------------------------------------------------------- @@ -96,9 +112,9 @@ reading additional event log records. ==== `event_logs.name` The name of the event log to monitor. Each dictionary under `event_logs` must -have a `name` field. You can get a list of available event logs by running -`Get-EventLog *` in PowerShell. Here is a sample of the output from the -command: +have a `name` field, except for those which use a custom XML query. You can +get a list of available event logs by running `Get-EventLog *` in PowerShell. +Here is a sample of the output from the command: [source,sh] -------------------------------------------------------------------------------- @@ -156,6 +172,28 @@ winlogbeat.event_logs: - name: 'C:\backup\sysmon-2019.08.evtx' -------------------------------------------------------------------------------- +The name key must not be used with custom XML queries. + +[float] +==== `event_logs.id` + +A unique identifier for the event log. This key is required when using a custom +XML query. + +It is used to uniquely identify the event log reader in the registry file. This is +useful if multiple event logs are being set up to watch the same channel or file. If an +ID is not given, the `event_logs.name` value will be used. + +This value must be unique. + +[source,yaml] +-------------------------------------------------------------------------------- +winlogbeat.event_logs: + - name: Application + id: application-logs + ignore_older: 168h +-------------------------------------------------------------------------------- + [float] ==== `event_logs.ignore_older` @@ -318,6 +356,35 @@ Microsoft-Windows-Security-Auditing Microsoft-Windows-Eventlog -------------------------------------------------------------------------------- +[float] +==== `event_logs.xml_query` + +Provide a custom XML query. This option is mutually exclusive with the `name`, `event_id`, +`ignore_older`, `level`, and `provider` options. These options should be included in +the XML query directly. Furthermore, an `id` must be provided. Custom XML queries +provide more flexibility and advanced options than the simpler query options in {beatname_uc}. +*{vista_and_newer}* + +Here is a configuration which will collect DHCP server events from multiple channels: + +[source,yaml] +-------------------------------------------------------------------------------- +winlogbeat.event_logs: + - id: dhcp-server-logs + xml_query: > + + + + + + + +-------------------------------------------------------------------------------- + +XML queries may also be created in Windows Event Viewer using custom views. The query +can be created using a graphical interface and the corresponding XML can be +retrieved from the XML tab. + [float] ==== `event_logs.include_xml` @@ -447,3 +514,12 @@ There are a few notable differences in the events: `winlog.event_data`. * Setting `include_xml: true` has no effect. + +[float] +==== `overwrite_pipelines` + +By default Ingest pipelines are not updated if a pipeline with the same ID +already exists. If this option is enabled Winlogbeat overwrites pipelines +every time a new Elasticsearch connection is established. + +The default value is `false`. diff --git a/winlogbeat/eventlog/factory.go b/winlogbeat/eventlog/factory.go index 9ee8e0d144f..bb07c07ba1e 100644 --- a/winlogbeat/eventlog/factory.go +++ b/winlogbeat/eventlog/factory.go @@ -29,8 +29,10 @@ import ( // EventLog. Each implementation is free to support additional configuration // options. type ConfigCommon struct { - API string `config:"api"` // Name of the API to use. Optional. - Name string `config:"name"` // Name of the event log or channel or file. + API string `config:"api"` // Name of the API to use. Optional. + Name string `config:"name"` // Name of the event log or channel or file. + ID string `config:"id"` // Identifier for the event log. + XMLQuery string `config:"xml_query"` // Custom query XML. Must not be used with the keys from eventlog.query. } type validator interface { diff --git a/winlogbeat/eventlog/wineventlog.go b/winlogbeat/eventlog/wineventlog.go index 9e52cf2bdaa..7ec830f220a 100644 --- a/winlogbeat/eventlog/wineventlog.go +++ b/winlogbeat/eventlog/wineventlog.go @@ -21,6 +21,7 @@ package eventlog import ( + "encoding/xml" "fmt" "io" "path/filepath" @@ -113,7 +114,30 @@ type query struct { // any problems or nil. func (c *winEventLogConfig) Validate() error { var errs multierror.Errors - if c.Name == "" { + + if c.XMLQuery != "" { + if c.ID == "" { + errs = append(errs, fmt.Errorf("event log is missing an 'id'")) + } + + // Check for XML syntax errors. This does not check the validity of the query itself. + if err := xml.Unmarshal([]byte(c.XMLQuery), &struct{}{}); err != nil { + errs = append(errs, fmt.Errorf("invalid xml_query: %w", err)) + } + + switch { + case c.Name != "": + errs = append(errs, fmt.Errorf("xml_query cannot be used with 'name'")) + case c.SimpleQuery.IgnoreOlder != 0: + errs = append(errs, fmt.Errorf("xml_query cannot be used with 'ignore_older'")) + case c.SimpleQuery.Level != "": + errs = append(errs, fmt.Errorf("xml_query cannot be used with 'level'")) + case c.SimpleQuery.EventID != "": + errs = append(errs, fmt.Errorf("xml_query cannot be used with 'event_id'")) + case len(c.SimpleQuery.Provider) != 0: + errs = append(errs, fmt.Errorf("xml_query cannot be used with 'provider'")) + } + } else if c.Name == "" { errs = append(errs, fmt.Errorf("event log is missing a 'name'")) } @@ -128,6 +152,7 @@ var _ EventLog = &winEventLog{} type winEventLog struct { config winEventLogConfig query string + id string // Identifier of this event log. channelName string // Name of the channel from which to read. file bool // Reading from file rather than channel. subscription win.EvtHandle // Handle to the subscription. @@ -144,7 +169,7 @@ type winEventLog struct { // Name returns the name of the event log (i.e. Application, Security, etc.). func (l *winEventLog) Name() string { - return l.channelName + return l.id } func (l *winEventLog) Open(state checkpoint.EventLogState) error { @@ -152,7 +177,7 @@ func (l *winEventLog) Open(state checkpoint.EventLogState) error { var err error if len(state.Bookmark) > 0 { bookmark, err = win.CreateBookmarkFromXML(state.Bookmark) - } else if state.RecordNumber > 0 { + } else if state.RecordNumber > 0 && l.channelName != "" { bookmark, err = win.CreateBookmarkFromRecordID(l.channelName, state.RecordNumber) } if err != nil { @@ -267,7 +292,7 @@ func (l *winEventLog) Read() ([]Record, error) { r, _ := l.buildRecordFromXML(l.outputBuf.Bytes(), err) r.Offset = checkpoint.EventLogState{ - Name: l.channelName, + Name: l.id, RecordNumber: r.RecordID, Timestamp: r.TimeCreated.SystemTime, } @@ -356,7 +381,7 @@ func (l *winEventLog) buildRecordFromXML(x []byte, recoveredErr error) (Record, } if l.file { - r.File = l.channelName + r.File = l.id } if includeXML { @@ -374,20 +399,32 @@ func newEventLogging(options *common.Config) (EventLog, error) { // newWinEventLog creates and returns a new EventLog for reading event logs // using the Windows Event Log. func newWinEventLog(options *common.Config) (EventLog, error) { + var xmlQuery string + var err error + c := defaultWinEventLogConfig - if err := readConfig(options, &c); err != nil { + if err = readConfig(options, &c); err != nil { return nil, err } - query, err := win.Query{ - Log: c.Name, - IgnoreOlder: c.SimpleQuery.IgnoreOlder, - Level: c.SimpleQuery.Level, - EventID: c.SimpleQuery.EventID, - Provider: c.SimpleQuery.Provider, - }.Build() - if err != nil { - return nil, err + id := c.ID + if id == "" { + id = c.Name + } + + if c.XMLQuery != "" { + xmlQuery = c.XMLQuery + } else { + xmlQuery, err = win.Query{ + Log: c.Name, + IgnoreOlder: c.SimpleQuery.IgnoreOlder, + Level: c.SimpleQuery.Level, + EventID: c.SimpleQuery.EventID, + Provider: c.SimpleQuery.Provider, + }.Build() + if err != nil { + return nil, err + } } eventMetadataHandle := func(providerName, sourceName string) sys.MessageFiles { @@ -411,15 +448,16 @@ func newWinEventLog(options *common.Config) (EventLog, error) { } l := &winEventLog{ + id: id, config: c, - query: query, + query: xmlQuery, channelName: c.Name, file: filepath.IsAbs(c.Name), maxRead: c.BatchReadSize, renderBuf: make([]byte, renderBufferSize), outputBuf: sys.NewByteBuffer(renderBufferSize), - cache: newMessageFilesCache(c.Name, eventMetadataHandle, freeHandle), - logPrefix: fmt.Sprintf("WinEventLog[%s]", c.Name), + cache: newMessageFilesCache(id, eventMetadataHandle, freeHandle), + logPrefix: fmt.Sprintf("WinEventLog[%s]", id), } // Forwarded events should be rendered using RenderEventXML. It is more diff --git a/winlogbeat/eventlog/wineventlog_experimental.go b/winlogbeat/eventlog/wineventlog_experimental.go index 3a3ae182686..87eb4b32802 100644 --- a/winlogbeat/eventlog/wineventlog_experimental.go +++ b/winlogbeat/eventlog/wineventlog_experimental.go @@ -47,6 +47,7 @@ const ( type winEventLogExp struct { config winEventLogConfig query string + id string // Identifier of this event log. channelName string // Name of the channel from which to read. file bool // Reading from file rather than channel. maxRead int // Maximum number returned in one Read. @@ -59,7 +60,7 @@ type winEventLogExp struct { // Name returns the name of the event log (i.e. Application, Security, etc.). func (l *winEventLogExp) Name() string { - return l.channelName + return l.id } func (l *winEventLogExp) Open(state checkpoint.EventLogState) error { @@ -205,11 +206,11 @@ func (l *winEventLogExp) processHandle(h win.EvtHandle) (*Record, error) { } if l.file { - r.File = l.channelName + r.File = l.id } r.Offset = checkpoint.EventLogState{ - Name: l.channelName, + Name: l.id, RecordNumber: r.RecordID, Timestamp: r.TimeCreated.SystemTime, } @@ -241,6 +242,11 @@ func (l *winEventLogExp) Close() error { // newWinEventLogExp creates and returns a new EventLog for reading event logs // using the Windows Event Log. func newWinEventLogExp(options *common.Config) (EventLog, error) { + var xmlQuery string + var err error + var isFile bool + var log *logp.Logger + cfgwarn.Experimental("The %s event log reader is experimental.", winEventLogExpAPIName) c := winEventLogConfig{BatchReadSize: 512} @@ -248,30 +254,39 @@ func newWinEventLogExp(options *common.Config) (EventLog, error) { return nil, err } - queryLog := c.Name - isFile := false - if info, err := os.Stat(c.Name); err == nil && info.Mode().IsRegular() { - path, err := filepath.Abs(c.Name) + id := c.ID + if id == "" { + id = c.Name + } + + if c.XMLQuery != "" { + xmlQuery = c.XMLQuery + log = logp.NewLogger("wineventlog").With("id", id) + } else { + queryLog := c.Name + if info, err := os.Stat(c.Name); err == nil && info.Mode().IsRegular() { + path, err := filepath.Abs(c.Name) + if err != nil { + return nil, err + } + isFile = true + queryLog = "file://" + path + } + + xmlQuery, err = win.Query{ + Log: queryLog, + IgnoreOlder: c.SimpleQuery.IgnoreOlder, + Level: c.SimpleQuery.Level, + EventID: c.SimpleQuery.EventID, + Provider: c.SimpleQuery.Provider, + }.Build() if err != nil { return nil, err } - isFile = true - queryLog = "file://" + path - } - query, err := win.Query{ - Log: queryLog, - IgnoreOlder: c.SimpleQuery.IgnoreOlder, - Level: c.SimpleQuery.Level, - EventID: c.SimpleQuery.EventID, - Provider: c.SimpleQuery.Provider, - }.Build() - if err != nil { - return nil, err + log = logp.NewLogger("wineventlog").With("id", id).With("channel", c.Name) } - log := logp.NewLogger("wineventlog").With("channel", c.Name) - renderer, err := win.NewRenderer(win.NilHandle, log) if err != nil { return nil, err @@ -279,7 +294,8 @@ func newWinEventLogExp(options *common.Config) (EventLog, error) { l := &winEventLogExp{ config: c, - query: query, + query: xmlQuery, + id: id, channelName: c.Name, file: isFile, maxRead: c.BatchReadSize, diff --git a/winlogbeat/eventlog/wineventlog_test.go b/winlogbeat/eventlog/wineventlog_test.go index d6ddddcdd8b..c5d92ce1873 100644 --- a/winlogbeat/eventlog/wineventlog_test.go +++ b/winlogbeat/eventlog/wineventlog_test.go @@ -39,8 +39,13 @@ import ( const ( // Names that are registered by the test for logging events. - providerName = "WinlogbeatTestGo" - sourceName = "Integration Test" + providerName = "WinlogbeatTestGo" + sourceName = "Integration Test" + customXMLQuery = ` + + + +` // Event message files used when logging events. @@ -54,6 +59,116 @@ const ( netEventMsgFile = "%SystemRoot%\\System32\\netevent.dll" ) +func TestWinEventLogConfig_Validate(t *testing.T) { + tests := []struct { + In winEventLogConfig + WantErr bool + Desc string + }{ + { + In: winEventLogConfig{ + ConfigCommon: ConfigCommon{ + ID: "test", + XMLQuery: customXMLQuery, + }, + }, + WantErr: false, + Desc: "xml query: all good", + }, + { + In: winEventLogConfig{ + ConfigCommon: ConfigCommon{ + ID: "test", + XMLQuery: customXMLQuery[:len(customXMLQuery)-4], // Malformed XML by truncation. + }, + }, + WantErr: true, + Desc: "xml query: malformed XML", + }, + { + In: winEventLogConfig{ + ConfigCommon: ConfigCommon{ + XMLQuery: customXMLQuery, + }, + }, + WantErr: true, + Desc: "xml query: missing ID", + }, + { + In: winEventLogConfig{ + ConfigCommon: ConfigCommon{ + ID: "test", + Name: "test", + XMLQuery: customXMLQuery, + }, + }, + WantErr: true, + Desc: "xml query: conflicting keys (xml query and name)", + }, + { + In: winEventLogConfig{ + ConfigCommon: ConfigCommon{ + ID: "test", + XMLQuery: customXMLQuery, + }, + SimpleQuery: query{IgnoreOlder: 1}, + }, + WantErr: true, + Desc: "xml query: conflicting keys (xml query and ignore_older)", + }, + { + In: winEventLogConfig{ + ConfigCommon: ConfigCommon{ + ID: "test", + XMLQuery: customXMLQuery, + }, + SimpleQuery: query{Level: "error"}, + }, + WantErr: true, + Desc: "xml query: conflicting keys (xml query and level)", + }, + { + In: winEventLogConfig{ + ConfigCommon: ConfigCommon{ + ID: "test", + XMLQuery: customXMLQuery, + }, + SimpleQuery: query{EventID: "1000"}, + }, + WantErr: true, + Desc: "xml query: conflicting keys (xml query and event_id)", + }, + { + In: winEventLogConfig{ + ConfigCommon: ConfigCommon{ + ID: "test", + XMLQuery: customXMLQuery, + }, + SimpleQuery: query{Provider: []string{providerName}}, + }, + WantErr: true, + Desc: "xml query: conflicting keys (xml query and provider)", + }, + { + In: winEventLogConfig{ + ConfigCommon: ConfigCommon{}, + }, + WantErr: true, + Desc: "missing name", + }, + } + + for _, tc := range tests { + gotErr := tc.In.Validate() + + if tc.WantErr { + assert.NotNil(t, gotErr, tc.Desc) + } else { + assert.Nil(t, gotErr, "%q got unexpected err: %v", tc.Desc, gotErr) + } + } +} + func TestWindowsEventLogAPI(t *testing.T) { testWindowsEventLog(t, winEventLogAPIName) } @@ -79,6 +194,34 @@ func testWindowsEventLog(t *testing.T, api string) { return openLog(t, api, nil, config) } + // Test reading from an event log using a custom XML query. + t.Run("custom_xml_query", func(t *testing.T) { + cfg := map[string]interface{}{ + "id": "custom-xml-query", + "xml_query": customXMLQuery, + } + + log := openLog(t, cfg) + defer log.Close() + + var eventCount int + + for eventCount < totalEvents { + records, err := log.Read() + if err != nil { + t.Fatal("read error", err) + } + if len(records) == 0 { + t.Fatal("read returned 0 records") + } + + t.Logf("Read() returned %d events.", len(records)) + eventCount += len(records) + } + + assert.Equal(t, totalEvents, eventCount) + }) + t.Run("batch_read_size_config", func(t *testing.T) { const batchReadSize = 2 diff --git a/winlogbeat/include/fields.go b/winlogbeat/include/fields.go index a89de8466ee..29bc38bff45 100644 --- a/winlogbeat/include/fields.go +++ b/winlogbeat/include/fields.go @@ -32,5 +32,5 @@ func init() { // AssetBuildFieldsFieldsCommonYml returns asset data. // This is the base64 encoded zlib format compressed contents of build/fields/fields.common.yml. func AssetBuildFieldsFieldsCommonYml() string { - return "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" + return "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" } diff --git a/winlogbeat/module/pipeline.go b/winlogbeat/module/pipeline.go new file mode 100644 index 00000000000..c134bd9068b --- /dev/null +++ b/winlogbeat/module/pipeline.go @@ -0,0 +1,212 @@ +// Licensed to Elasticsearch B.V. under one or more contributor +// license agreements. See the NOTICE file distributed with +// this work for additional information regarding copyright +// ownership. Elasticsearch B.V. licenses this file to you 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 module + +import ( + "embed" + "encoding/json" + "errors" + "fmt" + "os" + "path" + "path/filepath" + "strings" + + "github.com/joeshaw/multierror" + "gopkg.in/yaml.v2" + + "github.com/elastic/beats/v7/filebeat/fileset" + "github.com/elastic/beats/v7/libbeat/beat" + "github.com/elastic/beats/v7/libbeat/common" + "github.com/elastic/beats/v7/libbeat/esleg/eslegclient" + "github.com/elastic/beats/v7/libbeat/logp" +) + +// PipelinesFS is used from the x-pack/winlogbeat code to inject modules. The +// OSS version does not have modules. +var PipelinesFS *embed.FS + +var errNoFS = errors.New("no embedded file system") + +const logName = "pipeline" + +type pipeline struct { + id string + contents map[string]interface{} +} + +// UploadPipelines reads all pipelines embedded in the Winlogbeat executable +// and adapts the pipeline for a given ES version, converts to JSON if +// necessary and creates or updates ingest pipeline in ES. +func UploadPipelines(info beat.Info, esClient *eslegclient.Connection, overwritePipelines bool) error { + pipelines, err := readAll(info) + if err != nil { + return err + } + return load(esClient, pipelines, overwritePipelines) +} + +// ExportPipelines reads all pipelines embedded in the Winlogbeat executable +// and adapts the pipelines for a given ES version and writes the +// converted pipelines to the given directory in JSON format. +func ExportPipelines(info beat.Info, version common.Version, directory string) error { + log := logp.NewLogger(logName) + pipelines, err := readAll(info) + if err != nil { + return err + } + + for _, pipeline := range pipelines { + if err := fileset.AdaptPipelineForCompatibility(version, pipeline.id, pipeline.contents, log); err != nil { + return fmt.Errorf("failed to adapt pipeline with backwards compatibility changes for version %s: %w", version.String(), err) + } + f, err := os.Create(filepath.Join(directory, pipeline.id+".json")) + if err != nil { + return fmt.Errorf("unable to create file to export pipeline to: %w", err) + } + enc := json.NewEncoder(f) + enc.SetEscapeHTML(false) + err = enc.Encode(pipeline.contents) + if err != nil { + return fmt.Errorf("unable to JSON encode pipeline %s: %w", f.Name(), err) + } + } + return nil +} + +// readAll reads pipelines from the the embedded filesystem and +// returns a slice of pipelines suitable for sending to Elasticsearch +// with load. +func readAll(info beat.Info) (pipelines []pipeline, err error) { + p, err := readDir(".", info) + if err == errNoFS { + return nil, nil + } + return p, err +} + +func readDir(dir string, info beat.Info) (pipelines []pipeline, err error) { + if PipelinesFS == nil { + return nil, errNoFS + } + dirEntries, err := PipelinesFS.ReadDir(dir) + if err != nil { + return nil, err + } + for _, de := range dirEntries { + if de.IsDir() { + subPipelines, err := readDir(path.Join(dir, de.Name()), info) + if err != nil { + return nil, err + } + pipelines = append(pipelines, subPipelines...) + continue + } + p, err := readFile(path.Join(dir, de.Name()), info) + if err == errNoFS { + continue + } + if err != nil { + return nil, err + } + pipelines = append(pipelines, p) + } + return pipelines, nil +} + +func readFile(filename string, info beat.Info) (p pipeline, err error) { + if PipelinesFS == nil { + return pipeline{}, errNoFS + } + contents, err := PipelinesFS.ReadFile(filename) + if err != nil { + return pipeline{}, err + } + updatedContent, err := applyTemplates(info.IndexPrefix, info.Version, filename, contents) + if err != nil { + return pipeline{}, err + } + p = pipeline{ + id: fileset.FormatPipelineID(info.IndexPrefix, "", "", filename, info.Version), + contents: updatedContent, + } + return p, nil +} + +// load uses esClient to load pipelines to Elasticsearch cluster. +// Will only overwrite existing pipelines if overwritePipelines is +// true. An error in loading one of the pipelines will cause the +// successfully loaded ones to be deleted. +func load(esClient *eslegclient.Connection, pipelines []pipeline, overwritePipelines bool) (err error) { + var pipelineIDsLoaded []string + log := logp.NewLogger(logName) + + for _, pipeline := range pipelines { + err = fileset.LoadPipeline(esClient, pipeline.id, pipeline.contents, overwritePipelines, log) + if err != nil { + err = fmt.Errorf("error loading pipeline %s: %w", pipeline.id, err) + break + } + pipelineIDsLoaded = append(pipelineIDsLoaded, pipeline.id) + } + + if err != nil { + errs := multierror.Errors{err} + for _, pipelineID := range pipelineIDsLoaded { + err = fileset.DeletePipeline(esClient, pipelineID) + if err != nil { + errs = append(errs, err) + } + } + return errs.Err() + } + return nil +} + +func applyTemplates(prefix string, version string, filename string, original []byte) (converted map[string]interface{}, err error) { + vars := map[string]interface{}{ + "builtin": map[string]interface{}{ + "prefix": prefix, + "module": "", + "fileset": "", + "beatVersion": version, + }, + } + + encodedString, err := fileset.ApplyTemplate(vars, string(original), true) + + var content map[string]interface{} + switch extension := strings.ToLower(filepath.Ext(filename)); extension { + case ".json": + if err = json.Unmarshal([]byte(encodedString), &content); err != nil { + return nil, fmt.Errorf("error JSON decoding the pipeline file: %s: %w", filename, err) + } + case ".yaml", ".yml": + if err = yaml.Unmarshal([]byte(encodedString), &content); err != nil { + return nil, fmt.Errorf("error YAML decoding the pipeline file: %s: %w", filename, err) + } + newContent, err := fileset.FixYAMLMaps(content) + if err != nil { + return nil, fmt.Errorf("failed to sanitize the YAML pipeline file: %s: %w", filename, err) + } + content = newContent.(map[string]interface{}) + default: + return nil, fmt.Errorf("unsupported extension '%s' for pipeline file: %s", extension, filename) + } + return content, nil +} diff --git a/winlogbeat/sys/winevent/event_test.go b/winlogbeat/sys/winevent/event_test.go index 4ed391b91be..b6d893957ed 100644 --- a/winlogbeat/sys/winevent/event_test.go +++ b/winlogbeat/sys/winevent/event_test.go @@ -26,6 +26,8 @@ import ( "time" "github.com/stretchr/testify/assert" + + "github.com/elastic/beats/v7/libbeat/common" ) const allXML = ` @@ -79,9 +81,10 @@ const allXML = ` func TestXML(t *testing.T) { allXMLTimeCreated, _ := time.Parse(time.RFC3339Nano, "2016-01-28T20:33:27.990735300Z") - var tests = []struct { - xml string - event Event + tests := []struct { + xml string + event Event + mapstr common.MapStr }{ { xml: allXML, @@ -150,6 +153,14 @@ func TestXML(t *testing.T) { }, }, }, + mapstr: common.MapStr{ + "event_id": "0", + "time_created": time.Time{}, + "user_data": common.MapStr{ + "Id": "{00000000-0000-0000-0000-000000000000}", + "xml_name": "Operation_ClientFailure", + }, + }, }, } @@ -160,6 +171,9 @@ func TestXML(t *testing.T) { continue } assert.Equal(t, test.event, event) + if test.mapstr != nil { + assert.Equal(t, test.mapstr, event.Fields()) + } if testing.Verbose() { json, err := json.MarshalIndent(event, "", " ") @@ -174,7 +188,7 @@ func TestXML(t *testing.T) { // Tests that control characters other than CR and LF are escaped // when the event is decoded. func TestInvalidXML(t *testing.T) { - evXML := strings.Replace(allXML, "%1", "\t \n\x1b", -1) + evXML := strings.ReplaceAll(allXML, "%1", "\t \n\x1b") ev, err := UnmarshalXML([]byte(evXML)) assert.Equal(t, nil, err) assert.Equal(t, "Creating WSMan shell on server with ResourceUri: \t\r\n\\u001b", ev.Message) diff --git a/winlogbeat/sys/winevent/maputil.go b/winlogbeat/sys/winevent/maputil.go index 45a265ae8c6..82ae2ad2a3c 100644 --- a/winlogbeat/sys/winevent/maputil.go +++ b/winlogbeat/sys/winevent/maputil.go @@ -20,6 +20,7 @@ package winevent import ( "fmt" "reflect" + "time" "github.com/elastic/beats/v7/libbeat/common" "github.com/elastic/beats/v7/winlogbeat/sys" @@ -80,25 +81,12 @@ func AddPairs(m common.MapStr, key string, pairs []KeyValue) common.MapStr { // isZero return true if the given value is the zero value for its type. func isZero(i interface{}) bool { - if i == nil { + switch i := i.(type) { + case nil: return true + case time.Time: + return false + default: + return reflect.ValueOf(i).IsZero() } - - v := reflect.ValueOf(i) - switch v.Kind() { - case reflect.Array, reflect.String: - return v.Len() == 0 - case reflect.Bool: - return !v.Bool() - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - return v.Int() == 0 - case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: - return v.Uint() == 0 - case reflect.Float32, reflect.Float64: - return v.Float() == 0 - case reflect.Interface, reflect.Map, reflect.Ptr, reflect.Slice: - return v.IsNil() - } - - return false } diff --git a/winlogbeat/tests/system/test_config.py b/winlogbeat/tests/system/test_config.py index 306f6cf38ef..aefab4344ba 100644 --- a/winlogbeat/tests/system/test_config.py +++ b/winlogbeat/tests/system/test_config.py @@ -82,7 +82,7 @@ def run_config_tst(self, pcap=None, exit_code=0): args.extend(["test", "config"]) - output = "winlogbeat.log" + output = "winlogbeat-" + self.today + ".ndjson" with open(os.path.join(self.working_dir, output), "wb") as outfile: proc = subprocess.Popen(args, diff --git a/winlogbeat/tests/system/test_wineventlog.py b/winlogbeat/tests/system/test_wineventlog.py index 347b8585d05..9bbf5a7ded4 100644 --- a/winlogbeat/tests/system/test_wineventlog.py +++ b/winlogbeat/tests/system/test_wineventlog.py @@ -52,7 +52,7 @@ def test_resume_reading_events(self): # remove the output file, otherwise there is a race condition # in read_events() below where it reads the results of the previous # execution - os.unlink(os.path.join(self.working_dir, "output", self.beat_name)) + os.unlink(os.path.join(self.working_dir, "output", self.beat_name + "-" + self.today + ".ndjson")) msg = "Second event" self.write_event_log(msg) diff --git a/winlogbeat/winlogbeat.reference.yml b/winlogbeat/winlogbeat.reference.yml index 77886958368..17f40c8a5f9 100644 --- a/winlogbeat/winlogbeat.reference.yml +++ b/winlogbeat/winlogbeat.reference.yml @@ -14,13 +14,26 @@ # directory in which it was started. #winlogbeat.registry_file: .winlogbeat.yml +# The timeout value that controls when registry entries are written to disk +# (flushed). When an unwritten update exceeds this value, it triggers a write +# to disk. When flush is set to 0s, the registry is written to disk after each +# batch of events has been published successfully. The default value is 5s. +#winlogbeat.registry_flush: 5s + +# By default Ingest pipelines are not updated if a pipeline with the same ID +# already exists. If this option is enabled Winlogbeat overwrites pipelines +# every time a new Elasticsearch connection is established. +#winlogbeat.overwrite_pipelines: false + # event_logs specifies a list of event logs to monitor as well as any # accompanying options. The YAML data type of event_logs is a list of # dictionaries. # -# The supported keys are name (required), tags, fields, fields_under_root, -# forwarded, ignore_older, level, event_id, provider, and include_xml. Please -# visit the documentation for the complete details of each option. +# The supported keys are name, id, xml_query, tags, fields, fields_under_root, +# forwarded, ignore_older, level, event_id, provider, and include_xml. +# The xml_query key requires an id and must not be used with the name, +# ignore_older, level, event_id, or provider keys. Please visit the +# documentation for the complete details of each option. # https://go.es.io/WinlogbeatConfig winlogbeat.event_logs: @@ -120,66 +133,6 @@ winlogbeat.event_logs: # length of its retry interval each time, up to this maximum. #max_retry_interval: 30s - # The spool queue will store events in a local spool file, before - # forwarding the events to the outputs. - # Note: the spool queue is deprecated and will be removed in the future. - # Use the disk queue instead. - # - # The spool file is a circular buffer, which blocks once the file/buffer is full. - # Events are put into a write buffer and flushed once the write buffer - # is full or the flush_timeout is triggered. - # Once ACKed by the output, events are removed immediately from the queue, - # making space for new events to be persisted. - #spool: - # The file namespace configures the file path and the file creation settings. - # Once the file exists, the `size`, `page_size` and `prealloc` settings - # will have no more effect. - #file: - # Location of spool file. The default value is ${path.data}/spool.dat. - #path: "${path.data}/spool.dat" - - # Configure file permissions if file is created. The default value is 0600. - #permissions: 0600 - - # File size hint. The spool blocks, once this limit is reached. The default value is 100 MiB. - #size: 100MiB - - # The files page size. A file is split into multiple pages of the same size. The default value is 4KiB. - #page_size: 4KiB - - # If prealloc is set, the required space for the file is reserved using - # truncate. The default value is true. - #prealloc: true - - # Spool writer settings - # Events are serialized into a write buffer. The write buffer is flushed if: - # - The buffer limit has been reached. - # - The configured limit of buffered events is reached. - # - The flush timeout is triggered. - #write: - # Sets the write buffer size. - #buffer_size: 1MiB - - # Maximum duration after which events are flushed if the write buffer - # is not full yet. The default value is 1s. - #flush.timeout: 1s - - # Number of maximum buffered events. The write buffer is flushed once the - # limit is reached. - #flush.events: 16384 - - # Configure the on-disk event encoding. The encoding can be changed - # between restarts. - # Valid encodings are: json, ubjson, and cbor. - #codec: cbor - #read: - # Reader flush timeout, waiting for more events to become available, so - # to fill a complete batch as required by the outputs. - # If flush_timeout is 0, all available events are forwarded to the - # outputs immediately. - # The default value is 0s. - #flush.timeout: 0s - # Sets the maximum number of CPUs that can be executing simultaneously. The # default is the number of logical CPUs available in the system. #max_procs: @@ -496,6 +449,13 @@ output.elasticsearch: # The pin is a base64 encoded string of the SHA-256 fingerprint. #ssl.ca_sha256: "" + # A root CA HEX encoded fingerprint. During the SSL handshake if the + # fingerprint matches the root CA certificate, it will be added to + # the provided list of root CAs (`certificate_authorities`), if the + # list is empty or not defined, the matching certificate will be the + # only one in the list. Then the normal SSL validation happens. + #ssl.ca_trusted_fingerprint: "" + # Enable Kerberos support. Kerberos is automatically enabled if any Kerberos setting is set. #kerberos.enabled: true @@ -628,6 +588,13 @@ output.elasticsearch: # The pin is a base64 encoded string of the SHA-256 fingerprint. #ssl.ca_sha256: "" + # A root CA HEX encoded fingerprint. During the SSL handshake if the + # fingerprint matches the root CA certificate, it will be added to + # the provided list of root CAs (`certificate_authorities`), if the + # list is empty or not defined, the matching certificate will be the + # only one in the list. Then the normal SSL validation happens. + #ssl.ca_trusted_fingerprint: "" + # The number of times to retry publishing an event after a publishing failure. # After the specified number of retries, the events are typically dropped. # Some Beats, such as Filebeat and Winlogbeat, ignore the max_retries setting @@ -829,6 +796,13 @@ output.elasticsearch: # The pin is a base64 encoded string of the SHA-256 fingerprint. #ssl.ca_sha256: "" + # A root CA HEX encoded fingerprint. During the SSL handshake if the + # fingerprint matches the root CA certificate, it will be added to + # the provided list of root CAs (`certificate_authorities`), if the + # list is empty or not defined, the matching certificate will be the + # only one in the list. Then the normal SSL validation happens. + #ssl.ca_trusted_fingerprint: "" + # Enable Kerberos support. Kerberos is automatically enabled if any Kerberos setting is set. #kerberos.enabled: true @@ -993,6 +967,13 @@ output.elasticsearch: # The pin is a base64 encoded string of the SHA-256 fingerprint. #ssl.ca_sha256: "" + # A root CA HEX encoded fingerprint. During the SSL handshake if the + # fingerprint matches the root CA certificate, it will be added to + # the provided list of root CAs (`certificate_authorities`), if the + # list is empty or not defined, the matching certificate will be the + # only one in the list. Then the normal SSL validation happens. + #ssl.ca_trusted_fingerprint: "" + # -------------------------------- File Output --------------------------------- #output.file: @@ -1012,7 +993,7 @@ output.elasticsearch: #path: "/tmp/winlogbeat" # Name of the generated files. The default is `winlogbeat` and it generates - # files: `winlogbeat`, `winlogbeat.1`, `winlogbeat.2`, etc. + # files: `winlogbeat-{datetime}.ndjson`, `winlogbeat-{datetime}-1.ndjson`, etc. #filename: winlogbeat # Maximum size in kilobytes of each file. When this size is reached, and on @@ -1030,6 +1011,7 @@ output.elasticsearch: # Configure automatic file rotation on every startup. The default is true. #rotate_on_startup: true + # ------------------------------- Console Output ------------------------------- #output.console: # Boolean flag to enable or disable the output module. @@ -1128,19 +1110,13 @@ output.elasticsearch: # Set to false to disable template loading. #setup.template.enabled: true -# Select the kind of index template. From Elasticsearch 7.8, it is possible to -# use component templates. Available options: legacy, component, index. -# By default winlogbeat uses the legacy index templates. -#setup.template.type: legacy - # Template name. By default the template name is "winlogbeat-%{[agent.version]}" # The template name and pattern has to be set in case the Elasticsearch index pattern is modified. #setup.template.name: "winlogbeat-%{[agent.version]}" -# Template pattern. By default the template pattern is "-%{[agent.version]}-*" to apply to the default index settings. -# The first part is the version of the beat and then -* is used to match all daily indices. +# Template pattern. By default the template pattern is "winlogbeat-%{[agent.version]}" to apply to the default index settings. # The template name and pattern has to be set in case the Elasticsearch index pattern is modified. -#setup.template.pattern: "winlogbeat-%{[agent.version]}-*" +#setup.template.pattern: "winlogbeat-%{[agent.version]}" # Path to fields.yml file to generate the template #setup.template.fields: "${path.config}/fields.yml" @@ -1187,17 +1163,8 @@ setup.template.settings: # output.elasticsearch.index is ignored, and the write alias is used to set the # index name. -# Enable ILM support. Valid values are true, false, and auto. When set to auto -# (the default), the Beat uses index lifecycle management when it connects to a -# cluster that supports ILM; otherwise, it creates daily indices. -#setup.ilm.enabled: auto - -# Set the prefix used in the index lifecycle write alias name. The default alias -# name is 'winlogbeat-%{[agent.version]}'. -#setup.ilm.rollover_alias: 'winlogbeat' - -# Set the rollover index pattern. The default is "%{now/d}-000001". -#setup.ilm.pattern: "{now/d}-000001" +# Enable ILM support. Valid values are true, false. +#setup.ilm.enabled: true # Set the lifecycle policy name. The default policy name is # 'beatname'. @@ -1295,6 +1262,13 @@ setup.kibana: # The pin is a base64 encoded string of the SHA-256 fingerprint. #ssl.ca_sha256: "" + # A root CA HEX encoded fingerprint. During the SSL handshake if the + # fingerprint matches the root CA certificate, it will be added to + # the provided list of root CAs (`certificate_authorities`), if the + # list is empty or not defined, the matching certificate will be the + # only one in the list. Then the normal SSL validation happens. + #ssl.ca_trusted_fingerprint: "" + # ================================== Logging =================================== @@ -1366,11 +1340,6 @@ logging.files: # file. Defaults to true. # rotateonstartup: true - # Rotated files are either suffixed with a number e.g. winlogbeat.1 when - # renamed during rotation. Or when set to date, the date is added to - # the end of the file. On rotation a new file is created, older files are untouched. - #suffix: count - # ============================= X-Pack Monitoring ============================== # Winlogbeat can export internal metrics to a central Elasticsearch monitoring # cluster. This requires xpack monitoring to be enabled in Elasticsearch. The @@ -1498,6 +1467,13 @@ logging.files: # The pin is a base64 encoded string of the SHA-256 fingerprint. #ssl.ca_sha256: "" + # A root CA HEX encoded fingerprint. During the SSL handshake if the + # fingerprint matches the root CA certificate, it will be added to + # the provided list of root CAs (`certificate_authorities`), if the + # list is empty or not defined, the matching certificate will be the + # only one in the list. Then the normal SSL validation happens. + #ssl.ca_trusted_fingerprint: "" + # Enable Kerberos support. Kerberos is automatically enabled if any Kerberos setting is set. #kerberos.enabled: true diff --git a/winlogbeat/winlogbeat.yml b/winlogbeat/winlogbeat.yml index 614b2817225..bdb1f706fa6 100644 --- a/winlogbeat/winlogbeat.yml +++ b/winlogbeat/winlogbeat.yml @@ -13,9 +13,11 @@ # accompanying options. The YAML data type of event_logs is a list of # dictionaries. # -# The supported keys are name (required), tags, fields, fields_under_root, -# forwarded, ignore_older, level, event_id, provider, and include_xml. Please -# visit the documentation for the complete details of each option. +# The supported keys are name, id, xml_query, tags, fields, fields_under_root, +# forwarded, ignore_older, level, event_id, provider, and include_xml. +# The xml_query key requires an id and must not be used with the name, +# ignore_older, level, event_id, or provider keys. Please visit the +# documentation for the complete details of each option. # https://go.es.io/WinlogbeatConfig winlogbeat.event_logs: diff --git a/x-pack/auditbeat/Jenkinsfile.yml b/x-pack/auditbeat/Jenkinsfile.yml index aef0ec1fbe5..9dbb5f77dfa 100644 --- a/x-pack/auditbeat/Jenkinsfile.yml +++ b/x-pack/auditbeat/Jenkinsfile.yml @@ -42,7 +42,7 @@ stages: macos: mage: "mage build unitTest" platforms: ## override default label in this specific stage. - - "macosx&&x86_64" + - "orka && darwin && poc" when: ## Override the top-level when. comments: - "/test x-pack/auditbeat for macos" diff --git a/x-pack/auditbeat/auditbeat.reference.yml b/x-pack/auditbeat/auditbeat.reference.yml index bab59c339c1..b058641150c 100644 --- a/x-pack/auditbeat/auditbeat.reference.yml +++ b/x-pack/auditbeat/auditbeat.reference.yml @@ -253,66 +253,6 @@ auditbeat.modules: # length of its retry interval each time, up to this maximum. #max_retry_interval: 30s - # The spool queue will store events in a local spool file, before - # forwarding the events to the outputs. - # Note: the spool queue is deprecated and will be removed in the future. - # Use the disk queue instead. - # - # The spool file is a circular buffer, which blocks once the file/buffer is full. - # Events are put into a write buffer and flushed once the write buffer - # is full or the flush_timeout is triggered. - # Once ACKed by the output, events are removed immediately from the queue, - # making space for new events to be persisted. - #spool: - # The file namespace configures the file path and the file creation settings. - # Once the file exists, the `size`, `page_size` and `prealloc` settings - # will have no more effect. - #file: - # Location of spool file. The default value is ${path.data}/spool.dat. - #path: "${path.data}/spool.dat" - - # Configure file permissions if file is created. The default value is 0600. - #permissions: 0600 - - # File size hint. The spool blocks, once this limit is reached. The default value is 100 MiB. - #size: 100MiB - - # The files page size. A file is split into multiple pages of the same size. The default value is 4KiB. - #page_size: 4KiB - - # If prealloc is set, the required space for the file is reserved using - # truncate. The default value is true. - #prealloc: true - - # Spool writer settings - # Events are serialized into a write buffer. The write buffer is flushed if: - # - The buffer limit has been reached. - # - The configured limit of buffered events is reached. - # - The flush timeout is triggered. - #write: - # Sets the write buffer size. - #buffer_size: 1MiB - - # Maximum duration after which events are flushed if the write buffer - # is not full yet. The default value is 1s. - #flush.timeout: 1s - - # Number of maximum buffered events. The write buffer is flushed once the - # limit is reached. - #flush.events: 16384 - - # Configure the on-disk event encoding. The encoding can be changed - # between restarts. - # Valid encodings are: json, ubjson, and cbor. - #codec: cbor - #read: - # Reader flush timeout, waiting for more events to become available, so - # to fill a complete batch as required by the outputs. - # If flush_timeout is 0, all available events are forwarded to the - # outputs immediately. - # The default value is 0s. - #flush.timeout: 0s - # Sets the maximum number of CPUs that can be executing simultaneously. The # default is the number of logical CPUs available in the system. #max_procs: @@ -629,6 +569,13 @@ output.elasticsearch: # The pin is a base64 encoded string of the SHA-256 fingerprint. #ssl.ca_sha256: "" + # A root CA HEX encoded fingerprint. During the SSL handshake if the + # fingerprint matches the root CA certificate, it will be added to + # the provided list of root CAs (`certificate_authorities`), if the + # list is empty or not defined, the matching certificate will be the + # only one in the list. Then the normal SSL validation happens. + #ssl.ca_trusted_fingerprint: "" + # Enable Kerberos support. Kerberos is automatically enabled if any Kerberos setting is set. #kerberos.enabled: true @@ -761,6 +708,13 @@ output.elasticsearch: # The pin is a base64 encoded string of the SHA-256 fingerprint. #ssl.ca_sha256: "" + # A root CA HEX encoded fingerprint. During the SSL handshake if the + # fingerprint matches the root CA certificate, it will be added to + # the provided list of root CAs (`certificate_authorities`), if the + # list is empty or not defined, the matching certificate will be the + # only one in the list. Then the normal SSL validation happens. + #ssl.ca_trusted_fingerprint: "" + # The number of times to retry publishing an event after a publishing failure. # After the specified number of retries, the events are typically dropped. # Some Beats, such as Filebeat and Winlogbeat, ignore the max_retries setting @@ -962,6 +916,13 @@ output.elasticsearch: # The pin is a base64 encoded string of the SHA-256 fingerprint. #ssl.ca_sha256: "" + # A root CA HEX encoded fingerprint. During the SSL handshake if the + # fingerprint matches the root CA certificate, it will be added to + # the provided list of root CAs (`certificate_authorities`), if the + # list is empty or not defined, the matching certificate will be the + # only one in the list. Then the normal SSL validation happens. + #ssl.ca_trusted_fingerprint: "" + # Enable Kerberos support. Kerberos is automatically enabled if any Kerberos setting is set. #kerberos.enabled: true @@ -1126,6 +1087,13 @@ output.elasticsearch: # The pin is a base64 encoded string of the SHA-256 fingerprint. #ssl.ca_sha256: "" + # A root CA HEX encoded fingerprint. During the SSL handshake if the + # fingerprint matches the root CA certificate, it will be added to + # the provided list of root CAs (`certificate_authorities`), if the + # list is empty or not defined, the matching certificate will be the + # only one in the list. Then the normal SSL validation happens. + #ssl.ca_trusted_fingerprint: "" + # -------------------------------- File Output --------------------------------- #output.file: @@ -1145,7 +1113,7 @@ output.elasticsearch: #path: "/tmp/auditbeat" # Name of the generated files. The default is `auditbeat` and it generates - # files: `auditbeat`, `auditbeat.1`, `auditbeat.2`, etc. + # files: `auditbeat-{datetime}.ndjson`, `auditbeat-{datetime}-1.ndjson`, etc. #filename: auditbeat # Maximum size in kilobytes of each file. When this size is reached, and on @@ -1163,6 +1131,7 @@ output.elasticsearch: # Configure automatic file rotation on every startup. The default is true. #rotate_on_startup: true + # ------------------------------- Console Output ------------------------------- #output.console: # Boolean flag to enable or disable the output module. @@ -1261,19 +1230,13 @@ output.elasticsearch: # Set to false to disable template loading. #setup.template.enabled: true -# Select the kind of index template. From Elasticsearch 7.8, it is possible to -# use component templates. Available options: legacy, component, index. -# By default auditbeat uses the legacy index templates. -#setup.template.type: legacy - # Template name. By default the template name is "auditbeat-%{[agent.version]}" # The template name and pattern has to be set in case the Elasticsearch index pattern is modified. #setup.template.name: "auditbeat-%{[agent.version]}" -# Template pattern. By default the template pattern is "-%{[agent.version]}-*" to apply to the default index settings. -# The first part is the version of the beat and then -* is used to match all daily indices. +# Template pattern. By default the template pattern is "auditbeat-%{[agent.version]}" to apply to the default index settings. # The template name and pattern has to be set in case the Elasticsearch index pattern is modified. -#setup.template.pattern: "auditbeat-%{[agent.version]}-*" +#setup.template.pattern: "auditbeat-%{[agent.version]}" # Path to fields.yml file to generate the template #setup.template.fields: "${path.config}/fields.yml" @@ -1320,17 +1283,8 @@ setup.template.settings: # output.elasticsearch.index is ignored, and the write alias is used to set the # index name. -# Enable ILM support. Valid values are true, false, and auto. When set to auto -# (the default), the Beat uses index lifecycle management when it connects to a -# cluster that supports ILM; otherwise, it creates daily indices. -#setup.ilm.enabled: auto - -# Set the prefix used in the index lifecycle write alias name. The default alias -# name is 'auditbeat-%{[agent.version]}'. -#setup.ilm.rollover_alias: 'auditbeat' - -# Set the rollover index pattern. The default is "%{now/d}-000001". -#setup.ilm.pattern: "{now/d}-000001" +# Enable ILM support. Valid values are true, false. +#setup.ilm.enabled: true # Set the lifecycle policy name. The default policy name is # 'beatname'. @@ -1428,6 +1382,13 @@ setup.kibana: # The pin is a base64 encoded string of the SHA-256 fingerprint. #ssl.ca_sha256: "" + # A root CA HEX encoded fingerprint. During the SSL handshake if the + # fingerprint matches the root CA certificate, it will be added to + # the provided list of root CAs (`certificate_authorities`), if the + # list is empty or not defined, the matching certificate will be the + # only one in the list. Then the normal SSL validation happens. + #ssl.ca_trusted_fingerprint: "" + # ================================== Logging =================================== @@ -1499,11 +1460,6 @@ logging.files: # file. Defaults to true. # rotateonstartup: true - # Rotated files are either suffixed with a number e.g. auditbeat.1 when - # renamed during rotation. Or when set to date, the date is added to - # the end of the file. On rotation a new file is created, older files are untouched. - #suffix: count - # ============================= X-Pack Monitoring ============================== # Auditbeat can export internal metrics to a central Elasticsearch monitoring # cluster. This requires xpack monitoring to be enabled in Elasticsearch. The @@ -1631,6 +1587,13 @@ logging.files: # The pin is a base64 encoded string of the SHA-256 fingerprint. #ssl.ca_sha256: "" + # A root CA HEX encoded fingerprint. During the SSL handshake if the + # fingerprint matches the root CA certificate, it will be added to + # the provided list of root CAs (`certificate_authorities`), if the + # list is empty or not defined, the matching certificate will be the + # only one in the list. Then the normal SSL validation happens. + #ssl.ca_trusted_fingerprint: "" + # Enable Kerberos support. Kerberos is automatically enabled if any Kerberos setting is set. #kerberos.enabled: true diff --git a/x-pack/auditbeat/magefile.go b/x-pack/auditbeat/magefile.go index b2d52ebbcbc..72253937d47 100644 --- a/x-pack/auditbeat/magefile.go +++ b/x-pack/auditbeat/magefile.go @@ -12,8 +12,6 @@ import ( "time" "github.com/magefile/mage/mg" - "github.com/magefile/mage/sh" - "github.com/pkg/errors" auditbeat "github.com/elastic/beats/v7/auditbeat/scripts/mage" devtools "github.com/elastic/beats/v7/dev-tools/mage" @@ -45,9 +43,6 @@ func Build() error { // GolangCrossBuild build the Beat binary inside of the golang-builder. // Do not use directly, use crossBuild instead. func GolangCrossBuild() error { - if d, ok := deps[devtools.Platform.Name]; ok { - mg.Deps(d) - } return devtools.GolangCrossBuild(devtools.DefaultGolangCrossBuildArgs()) } @@ -125,95 +120,3 @@ func ExportDashboard() error { func Dashboards() error { return devtools.KibanaDashboards(devtools.OSSBeatDir("module"), "module") } - -// ----------------------------------------------------------------------------- -// - Install the librpm-dev package -var ( - deps = map[string]func() error{ - "linux/386": installLinux386, - "linux/amd64": installLinuxAMD64, - "linux/arm64": installLinuxARM64, - "linux/armv5": installLinuxARMEL, - "linux/armv6": installLinuxARMEL, - "linux/armv7": installLinuxARMHF, - "linux/mips": installLinuxMIPS, - "linux/mipsle": installLinuxMIPSEL, - "linux/mips64le": installLinuxMIPS64EL, - "linux/ppc64le": installLinuxPPC64EL, - "linux/s390x": installLinuxS390X, - - //"linux/ppc64": installLinuxPpc64, - //"linux/mips64": installLinuxMips64, - } -) - -const ( - librpmDevPkgName = "librpm-dev" - - // Dependency of librpm-dev in ARM architectures, that needs to be explicitly - // installed to replace other conflicting packages pre-installed in the image. - libicuDevPkgName = "libicu-dev" -) - -func installLinuxAMD64() error { - return installDependencies("", librpmDevPkgName) -} - -func installLinuxARM64() error { - return installDependencies("arm64", librpmDevPkgName+":arm64") -} - -func installLinuxARMHF() error { - return installDependencies("armhf", librpmDevPkgName+":armhf", libicuDevPkgName+":armhf") -} - -func installLinuxARMEL() error { - return installDependencies("armel", librpmDevPkgName+":armel", libicuDevPkgName+":armel") -} - -func installLinux386() error { - return installDependencies("i386", librpmDevPkgName+":i386") -} - -func installLinuxMIPS() error { - return installDependencies("mips", librpmDevPkgName+":mips") -} - -func installLinuxMIPS64EL() error { - return installDependencies("mips64el", librpmDevPkgName+":mips64el") -} - -func installLinuxMIPSEL() error { - return installDependencies("mispel", librpmDevPkgName+":mipsel") -} - -func installLinuxPPC64EL() error { - return installDependencies("ppc64el", librpmDevPkgName+":ppc64el") -} - -func installLinuxS390X() error { - return installDependencies("s390x", librpmDevPkgName+":s390x") -} - -func installDependencies(arch string, pkgs ...string) error { - if len(pkgs) == 0 { - return nil - } - if arch != "" { - err := sh.Run("dpkg", "--add-architecture", arch) - if err != nil { - return errors.Wrap(err, "error while adding architecture") - } - } - - // TODO: This is only for debian 7 and should be removed when move to a newer OS. This flag is - // going to be used unnecessary when building using non-debian7 images - // (like when making the linux/arm binaries) and we should remove it soonish. - // See https://github.com/elastic/beats/v7/issues/11750 for more details. - if err := sh.Run("apt-get", "update", "-o", "Acquire::Check-Valid-Until=false"); err != nil { - return err - } - - args := append([]string{"install", "-y", "--no-install-recommends"}, pkgs...) - return sh.Run("apt-get", args...) -} diff --git a/x-pack/auditbeat/module/system/socket/events.go b/x-pack/auditbeat/module/system/socket/events.go index 157d5ec92d0..74b31cc7e7f 100644 --- a/x-pack/auditbeat/module/system/socket/events.go +++ b/x-pack/auditbeat/module/system/socket/events.go @@ -189,6 +189,7 @@ type tcpAcceptResult struct { } func (e *tcpAcceptResult) asFlow() flow { + evTime := kernelTime(e.Meta.Timestamp) f := flow{ sock: e.Sock, pid: e.Meta.PID, @@ -196,7 +197,8 @@ func (e *tcpAcceptResult) asFlow() flow { proto: protoTCP, dir: directionIngress, complete: true, - lastSeen: kernelTime(e.Meta.Timestamp), + lastSeen: evTime, + created: evTime, } if e.Af == unix.AF_INET { f.local = newEndpointIPv4(e.LAddr, e.LPort, 0, 0) @@ -217,7 +219,7 @@ func (e *tcpAcceptResult) String() string { // Update the state with the contents of this event. func (e *tcpAcceptResult) Update(s *state) error { if e.Sock != 0 { - return s.UpdateFlow(e.asFlow()) + return s.CreateSocket(e.asFlow()) } return nil } @@ -233,6 +235,7 @@ type tcpAcceptResult4 struct { } func (e *tcpAcceptResult4) asFlow() flow { + evTime := kernelTime(e.Meta.Timestamp) f := flow{ sock: e.Sock, pid: e.Meta.PID, @@ -240,7 +243,8 @@ func (e *tcpAcceptResult4) asFlow() flow { proto: protoTCP, dir: directionIngress, complete: true, - lastSeen: kernelTime(e.Meta.Timestamp), + lastSeen: evTime, + created: evTime, } f.local = newEndpointIPv4(e.LAddr, e.LPort, 0, 0) f.remote = newEndpointIPv4(e.RAddr, e.RPort, 0, 0) @@ -256,7 +260,7 @@ func (e *tcpAcceptResult4) String() string { // Update the state with the contents of this event. func (e *tcpAcceptResult4) Update(s *state) error { if e.Sock != 0 { - return s.UpdateFlow(e.asFlow()) + return s.CreateSocket(e.asFlow()) } return nil } @@ -855,8 +859,10 @@ func (e *inetReleaseCall) Update(s *state) error { // kernels it needs to dump fixed-size arrays in 8-byte chunks. As the total // number of fetchargs available is limited, we have to dump only the first // 128 bytes of every argument. -const maxProgArgLen = 128 -const maxProgArgs = 5 +const ( + maxProgArgLen = 128 + maxProgArgs = 5 +) type execveCall struct { Meta tracing.Metadata `kprobe:"metadata"` @@ -876,38 +882,78 @@ type execveCall struct { func (e *execveCall) getProcess() *process { p := &process{ pid: e.Meta.PID, - path: readCString(e.Path[:]), created: kernelTime(e.Meta.Timestamp), } - p.name = filepath.Base(p.path) - var argc int - for argc = 0; argc <= maxProgArgs; argc++ { - if e.Ptrs[argc] == 0 { - break + + if idx := bytes.IndexByte(e.Path[:], 0); idx >= 0 { + // Fast path if we already have the path. + p.path = string(e.Path[:idx]) + } else { + // Attempt to get the path from the /prox//exe symlink. + var err error + p.path, err = filepath.EvalSymlinks(fmt.Sprintf("/proc/%d/exe", e.Meta.PID)) + if err != nil { + if pe, ok := err.(*os.PathError); ok && strings.Contains(pe.Path, "(deleted)") { + // Keep the deleted path from the PathError. + p.path = pe.Path + } else { + // Fallback to the truncated path. + p.path = string(e.Path[:]) + " ..." + } } } - p.args = make([]string, argc) - params := [maxProgArgs][]byte{ + + // Check for truncation of arg list or arguments. + params := [...][]byte{ e.Param0[:], e.Param1[:], e.Param2[:], e.Param3[:], e.Param4[:], } - limit := argc - if limit > maxProgArgs { - limit = maxProgArgs - p.args[limit] = "..." + var ( + argc int + truncatedArg bool + ) + for argc = 0; argc < len(e.Ptrs); argc++ { + if e.Ptrs[argc] == 0 { + break + } + if argc < len(params) && bytes.IndexByte(params[argc], 0) < 0 { + truncatedArg = true + } } - for i := 0; i < limit; i++ { - p.args[i] = readCString(params[i]) + if argc > maxProgArgs || truncatedArg { + // Attempt to get complete args list from /proc//cmdline. + cmdline, err := os.ReadFile(fmt.Sprintf("/proc/%d/cmdline", e.Meta.PID)) + if err == nil { + p.args = strings.Split(strings.TrimRight(string(cmdline), "\x00"), "\x00") + } } - if p.hasCreds = e.creds != nil; p.hasCreds { + + if p.args == nil { + // Fallback to arg list if unsuccessful or no truncation. + p.args = make([]string, argc) + if argc > maxProgArgs { + argc = maxProgArgs + p.args[argc] = "..." + } + for i, par := range params[:argc] { + p.args[i] = readCString(par) + } + } + + // Get name from first argument. + p.name = filepath.Base(p.args[0]) + + if e.creds != nil { + p.hasCreds = true p.uid = e.creds.UID p.gid = e.creds.GID p.euid = e.creds.EUID p.egid = e.creds.EGID } + return p } @@ -948,6 +994,24 @@ func (e *execveRet) Update(s *state) error { return nil } +type forkRet struct { + Meta tracing.Metadata `kprobe:"metadata"` + Retval int `kprobe:"retval"` +} + +// String returns a representation of the event. +func (e *forkRet) String() string { + return fmt.Sprintf("%s <- fork %d", header(e.Meta), e.Retval) +} + +// Update the state with the contents of this event. +func (e *forkRet) Update(s *state) error { + if e.Retval <= 0 { + return nil + } + return s.ForkProcess(e.Meta.PID, uint32(e.Retval), kernelTime(e.Meta.Timestamp)) +} + type doExit struct { Meta tracing.Metadata `kprobe:"metadata"` } diff --git a/x-pack/auditbeat/module/system/socket/kprobes.go b/x-pack/auditbeat/module/system/socket/kprobes.go index e5f5695177a..67d86d6237d 100644 --- a/x-pack/auditbeat/module/system/socket/kprobes.go +++ b/x-pack/auditbeat/module/system/socket/kprobes.go @@ -186,6 +186,15 @@ var sharedKProbes = []helper.ProbeDef{ Decoder: helper.NewStructDecoder(func() interface{} { return new(commitCreds) }), }, + { + Probe: tracing.Probe{ + Type: tracing.TypeKRetProbe, + Name: "clone3_ret", + Address: "{{.DO_FORK}}", + Fetchargs: "retval={{.RET}}", + }, + Decoder: helper.NewStructDecoder(func() interface{} { return new(forkRet) }), + }, /*************************************************************************** * IPv4 **************************************************************************/ diff --git a/x-pack/auditbeat/module/system/socket/socket_linux.go b/x-pack/auditbeat/module/system/socket/socket_linux.go index e7f1a059dd1..fb66f717d84 100644 --- a/x-pack/auditbeat/module/system/socket/socket_linux.go +++ b/x-pack/auditbeat/module/system/socket/socket_linux.go @@ -187,6 +187,15 @@ func (m *MetricSet) Run(r mb.PushReporterV2) { } else { for _, p := range procs { if i, err := p.Info(); err == nil { + if len(i.Name) == 16 && len(i.Args) != 0 { + // github.com/prometheus/procfs uses /proc//stat for + // the process name which is truncated to 16 bytes, so get + // the name from the cmdline data if it might be truncated. + // The guard for length of i.Args is for cases where there + // is no command line reported by proc fs; this should never + // happen, but does. + i.Name = filepath.Base(i.Args[0]) + } process := &process{ name: i.Name, pid: uint32(i.PID), diff --git a/x-pack/auditbeat/module/system/socket/state.go b/x-pack/auditbeat/module/system/socket/state.go index dc17108b52e..0ec22da3cb8 100644 --- a/x-pack/auditbeat/module/system/socket/state.go +++ b/x-pack/auditbeat/module/system/socket/state.go @@ -563,6 +563,38 @@ func (s *state) CreateProcess(p *process) error { return nil } +func (s *state) ForkProcess(parentPID, childPID uint32, ts kernelTime) error { + if parentPID == childPID { + return nil + } + s.Lock() + defer s.Unlock() + if _, found := s.processes[childPID]; found { + return errors.New("fork: child pid already registered to another process") + } + if parent, found := s.processes[parentPID]; found { + child := &process{ + pid: childPID, + name: parent.name, + path: parent.path, + args: parent.args, + created: ts, + uid: parent.uid, + gid: parent.gid, + euid: parent.euid, + egid: parent.egid, + hasCreds: parent.hasCreds, + createdTime: s.kernTimestampToTime(ts), + } + child.resolvedDomains = make(map[string]string, len(parent.resolvedDomains)) + for k, v := range parent.resolvedDomains { + child.resolvedDomains[k] = v + } + s.processes[childPID] = child + } + return nil +} + func (s *state) TerminateProcess(pid uint32) error { if pid == 0 { return errors.New("can't terminate process with PID 0") @@ -631,8 +663,16 @@ func (s *state) CreateSocket(ref flow) error { defer s.Unlock() ref.createdTime = s.kernTimestampToTime(ref.created) ref.lastSeenTime = s.kernTimestampToTime(ref.lastSeen) - // terminate existing if sock ptr is reused if prev, found := s.socks[ref.sock]; found { + // Fetch existing flow in case of TCP negotiation + if initial, found := prev.flows[ref.remote.String()]; found && ref.local.String() == initial.local.String() { + initial.dir = ref.dir + initial.pid = ref.pid + initial.process = ref.process + ref.updateWith(*initial, s) + delete(prev.flows, ref.remote.String()) + } + // terminate existing if sock ptr is reused s.onSockTerminated(prev) } return s.createFlow(ref) @@ -662,22 +702,21 @@ func (s *state) mutualEnrich(sock *socket, f *flow) { f.dir = sock.dir } } - if sockNoPID := sock.pid == 0; sockNoPID != (f.pid == 0) { - if sockNoPID { - sock.pid = f.pid - } else { - f.pid = sock.pid - } + if sock.pid == 0 { + sock.pid = f.pid + sock.process = f.process } - if sockNoProcess := sock.process == nil; sockNoProcess != (f.process == nil) { - if sockNoProcess { - sock.process = f.process - } else { + if sock.pid == f.pid && sock.pid != 0 { + if sockNoProcess := sock.process == nil; sockNoProcess != (f.process == nil) { + if sockNoProcess { + sock.process = f.process + } else { + f.process = sock.process + } + } else if sock.process == nil && sock.pid != 0 { + sock.process = s.getProcess(sock.pid) f.process = sock.process } - } else if sock.process == nil && sock.pid != 0 { - sock.process = s.getProcess(sock.pid) - f.process = sock.process } if !sock.closing { sock.lastSeenTime = s.clock() @@ -764,6 +803,11 @@ func (s *state) UpdateFlowWithCondition(ref flow, cond func(*flow) bool) error { } prev, found := sock.flows[ref.remote.addr.String()] if !found { + // Sock has been already closed and it may be receiving a SYN for a different + // flow. + if sock.closing { + return nil + } return s.createFlow(ref) } if cond != nil && !cond(prev) { @@ -901,8 +945,16 @@ func (f *flow) toEvent(final bool) (ev mb.Event, err error) { } src, dst := local, remote - if f.dir == directionIngress { + switch f.dir { + case directionIngress: src, dst = dst, src + case directionUnknown: + // For some flows we can miss information to determine the source (dir=unknown). + // As a last resort, assume that the client side uses a higher port number + // than the server. + if localAddr.Port < remoteAddr.Port { + src, dst = dst, src + } } inetType := f.inetType diff --git a/x-pack/auditbeat/module/system/socket/state_test.go b/x-pack/auditbeat/module/system/socket/state_test.go index dc059f4a43d..79f7838840e 100644 --- a/x-pack/auditbeat/module/system/socket/state_test.go +++ b/x-pack/auditbeat/module/system/socket/state_test.go @@ -29,19 +29,19 @@ import ( type logWrapper testing.T func (l *logWrapper) Errorf(format string, args ...interface{}) { - l.Logf("error: "+format, args) + l.Logf("error: "+format, args...) } func (l *logWrapper) Warnf(format string, args ...interface{}) { - l.Logf("warning: "+format, args) + l.Logf("warning: "+format, args...) } func (l *logWrapper) Infof(format string, args ...interface{}) { - l.Logf("info: "+format, args) + l.Logf("info: "+format, args...) } func (l *logWrapper) Debugf(format string, args ...interface{}) { - l.Logf("debug: "+format, args) + l.Logf("debug: "+format, args...) } func TestTCPConnWithProcess(t *testing.T) { diff --git a/x-pack/auditbeat/module/system/socket/template.go b/x-pack/auditbeat/module/system/socket/template.go index c5f2b5555de..43d520cd1c9 100644 --- a/x-pack/auditbeat/module/system/socket/template.go +++ b/x-pack/auditbeat/module/system/socket/template.go @@ -41,6 +41,7 @@ var functionAlternatives = map[string][]string{ "SYS_EXECVE": syscallAlternatives("execve"), "SYS_GETTIMEOFDAY": syscallAlternatives("gettimeofday"), "SYS_UNAME": syscallAlternatives("newuname"), + "DO_FORK": {"_do_fork", "do_fork", "kernel_clone"}, } func syscallAlternatives(syscall string) []string { diff --git a/x-pack/auditbeat/tests/system/test_metricsets.py b/x-pack/auditbeat/tests/system/test_metricsets.py index 2d34f8e4c18..6294d5a02d1 100644 --- a/x-pack/auditbeat/tests/system/test_metricsets.py +++ b/x-pack/auditbeat/tests/system/test_metricsets.py @@ -48,6 +48,7 @@ def test_metricset_login(self): @unittest.skipIf(sys.platform == "win32", "Not implemented for Windows") @unittest.skipIf(sys.platform.startswith('linux') and not (os.path.isdir("/var/lib/dpkg") or os.path.isdir("/var/lib/rpm")), "Only implemented for dpkg and rpm") + @unittest.skipIf(sys.platform.startswith('darwin'), "See https://github.com/elastic/beats/issues/21308") def test_metricset_package(self): """ package metricset collects information about installed packages on a system. diff --git a/x-pack/auditbeat/tracing/perfevent.go b/x-pack/auditbeat/tracing/perfevent.go index 181bc480141..79112a1c885 100644 --- a/x-pack/auditbeat/tracing/perfevent.go +++ b/x-pack/auditbeat/tracing/perfevent.go @@ -99,7 +99,8 @@ func NewPerfChannel(cfg ...PerfChannelConf) (channel *PerfChannel, err error) { streams: make(map[uint64]stream), pid: perf.AllThreads, attr: perf.Attr{ - Type: perf.TracepointEvent, + Type: perf.TracepointEvent, + ClockID: unix.CLOCK_MONOTONIC, SampleFormat: perf.SampleFormat{ Raw: true, StreamID: true, diff --git a/x-pack/dockerlogbeat/main.go b/x-pack/dockerlogbeat/main.go index e363aefb667..36472e2ec9e 100644 --- a/x-pack/dockerlogbeat/main.go +++ b/x-pack/dockerlogbeat/main.go @@ -20,7 +20,6 @@ import ( _ "github.com/elastic/beats/v7/libbeat/outputs/logstash" _ "github.com/elastic/beats/v7/libbeat/outputs/redis" _ "github.com/elastic/beats/v7/libbeat/publisher/queue/memqueue" - _ "github.com/elastic/beats/v7/libbeat/publisher/queue/spool" "github.com/elastic/beats/v7/libbeat/service" "github.com/elastic/beats/v7/x-pack/dockerlogbeat/pipelinemanager" ) diff --git a/x-pack/elastic-agent/CHANGELOG.next.asciidoc b/x-pack/elastic-agent/CHANGELOG.next.asciidoc index 4ebf989b89b..40cecf51b90 100644 --- a/x-pack/elastic-agent/CHANGELOG.next.asciidoc +++ b/x-pack/elastic-agent/CHANGELOG.next.asciidoc @@ -14,6 +14,7 @@ - Default to port 80 and 443 for Kibana and Fleet Server connections. {pull}25723[25723] - Remove deprecated/undocumented IncludeCreatorMetadata setting from kubernetes metadata config options {pull}28006[28006] - The `/processes/` endpoint proxies to the subprocess's monitoring endpoint, instead of querying its `/stats` endpoint {pull}28165[28165] +- Remove username/password for fleet-server authentication. {pull}29458[29458] ==== Bugfixes - Fix rename *ConfigChange to *PolicyChange to align on changes in the UI. {pull}20779[20779] @@ -91,6 +92,8 @@ - Snapshot artifact lookup will use agent.download proxy settings. {issue}27903[27903] {pull}27904[27904] - Fix lazy acker to only add new actions to the batch. {pull}27981[27981] - Allow HTTP metrics to run in bootstrap mode. Add ability to adjust timeouts for Fleet Server. {pull}28260[28260] +- Fix agent configuration overwritten by default fleet config. {pull}29297[29297] +- Allow agent containers to use basic auth to create a service token. {pull}29651[29651] ==== New features @@ -149,3 +152,8 @@ - Add diagnostics command to gather beat metadata. {pull}28265[28265] - Add diagnostics collect command to gather beat metadata, config, policy, and logs and bundle it into an archive. {pull}28461[28461] - Add `KIBANA_FLEET_SERVICE_TOKEN` to Elastic Agent container. {pull}28096[28096] +- Enable pprof endpoints for beats processes. Allow pprof endpoints for elastic-agent if enabled. {pull}28983[28983] +- Add `--pprof` flag to `elastic-agent diagnostics` and an `elastic-agent pprof` command to allow operators to gather pprof data from the agent and beats running under it. {pull}28798[28798] +- Allow pprof endpoints for elastic-agent or beats if enabled. {pull}28983[28983] {pull}29155[29155] +- Add --fleet-server-es-ca-trusted-fingerprint flag to allow agent/fleet-server to work with elasticsearch clusters using self signed certs. {pull}29128[29128] +- Discover changes in Kubernetes nodes metadata as soon as they happen. {pull}23139[23139] diff --git a/x-pack/elastic-agent/Dockerfile b/x-pack/elastic-agent/Dockerfile index 5b2e9d84586..9c7dce7a435 100644 --- a/x-pack/elastic-agent/Dockerfile +++ b/x-pack/elastic-agent/Dockerfile @@ -1,4 +1,4 @@ -ARG GO_VERSION=1.17.2 +ARG GO_VERSION=1.17.5 FROM circleci/golang:${GO_VERSION} diff --git a/x-pack/elastic-agent/GUIDELINES.md b/x-pack/elastic-agent/GUIDELINES.md new file mode 100644 index 00000000000..3fa741fc991 --- /dev/null +++ b/x-pack/elastic-agent/GUIDELINES.md @@ -0,0 +1,9 @@ +# Guidelines + +This document contains architecture details around Elastic Agent and guidelines on how new inputs and processes should be built. + +## Processes running as service and error handling + +All the processes started by Elastic Agent are running as service. Each service is expected to handle local errors on its own and continue working. A process should only fail on startup if an invalid configuration is passed in. As soon as a process is running and partial updates to the config are made without restart, the service is expected to keep running but report the errors. + +A service that needs to do setup tasks on startup is expected to retry until it succeeds and not error out after a certain timeout. diff --git a/x-pack/elastic-agent/Jenkinsfile.yml b/x-pack/elastic-agent/Jenkinsfile.yml index a80fdb1297c..96944541255 100644 --- a/x-pack/elastic-agent/Jenkinsfile.yml +++ b/x-pack/elastic-agent/Jenkinsfile.yml @@ -36,13 +36,10 @@ stages: unitTest: mage: "mage build unitTest" stage: mandatory - goIntegTest: - mage: "mage goIntegTest" - stage: mandatory macos: mage: "mage build unitTest" platforms: ## override default label in this specific stage. - - "macosx&&x86_64" + - "orka && darwin && poc" when: ## Override the top-level when. comments: - "/test x-pack/elastic-agent for macos" diff --git a/x-pack/elastic-agent/README.md b/x-pack/elastic-agent/README.md index 8d70b9b8420..de45ded8e46 100644 --- a/x-pack/elastic-agent/README.md +++ b/x-pack/elastic-agent/README.md @@ -3,7 +3,12 @@ The source files for the general Elastic Agent documentation are currently stored in the [observability-docs](https://github.com/elastic/observability-docs) repo. The following docs are only focused on getting developers started building code for Elastic Agent. -## Testing docker container +## Testing + +Prerequisites: +- installed [mage](https://github.com/magefile/mage) + +### Testing docker container Running Elastic Agent in a docker container is a common use case. To build the Elastic Agent and create a docker image run the following command: @@ -19,4 +24,61 @@ elastic-package stack up --version=7.13.0-SNAPSHOT -v Please note that the docker container is built in both standard and 'complete' variants. The 'complete' variant contains extra files, like the chromium browser, that are too large -for the standard variant. \ No newline at end of file +for the standard variant. + +### Testing Elastic Agent on Kubernetes + +#### Prerequisites +- create kubernetes cluster using kind, check [here](https://github.com/elastic/beats/blob/master/metricbeat/module/kubernetes/_meta/test/docs/README.md) for details +- deploy kube-state-metrics, check [here](https://github.com/elastic/beats/blob/master/metricbeat/module/kubernetes/_meta/test/docs/README.md) for details +- deploy required infrastructure: + - for elastic agent in standalone mode: EK stack or use [elastic cloud](https://cloud.elastic.co), check [here](https://github.com/elastic/beats/blob/master/metricbeat/module/kubernetes/_meta/test/docs/README.md) for details + - for managed mode: use [elastic cloud](https://cloud.elastic.co) or bring up the stack on docker and then connect docker network with kubernetes kind nodes: + ``` + elastic-package stack up -d -v + docker network connect elastic-package-stack_default + ``` + +1. Build elastic-agent: +```bash +cd x-pack/elastic-agent +DEV=true PLATFORMS=linux/amd64 TYPES=docker mage package +``` +2. Build docker image: +```bash +cd build/package/elastic-agent/elastic-agent-linux-amd64.docker/docker-build +docker build -t custom-agent-image . +``` +3. Load this image in your kind cluster: +``` +kind load docker-image custom-agent-image:latest +``` +4. Deploy agent with that image: +- download all-in-ome manifest for elastic-agent in standalone or managed mode, change version if needed +``` +ELASTIC_AGENT_VERSION="8.0" +ELASTIC_AGENT_MODE="standalone" # ELASTIC_AGENT_MODE="managed" +curl -L -O https://raw.githubusercontent.com/elastic/beats/${ELASTIC_AGENT_VERSION}/deploy/kubernetes/elastic-agent-${ELASTIC_AGENT_MODE}-kubernetes.yaml +``` +- Modify downloaded manifest: + - change image name to the one, that was created in the previous step and add `imagePullPolicy: Never`: + ``` + containers: + - name: elastic-agent + image: custom-agent-image:latest + imagePullPolicy: Never + ``` + - set environment variables accordingly to the used setup. + + Elastic-agent in standalone mode: set `ES_USERNAME`, `ES_PASSWORD`,`ES_HOST`. + + Elastic-agent in managed mode: set `FLEET_URL` and `FLEET_ENROLLMENT_TOKEN`. + +- create +``` +kubectl apply -f elastic-agent-${ELASTIC_AGENT_MODE}-kubernetes.yaml +``` +5. Check status of elastic-agent: +``` +kubectl -n kube-system get pods -l app=elastic-agent +``` diff --git a/x-pack/elastic-agent/_meta/config/common.p2.yml.tmpl b/x-pack/elastic-agent/_meta/config/common.p2.yml.tmpl index 1850c003f46..bbadcdc1055 100644 --- a/x-pack/elastic-agent/_meta/config/common.p2.yml.tmpl +++ b/x-pack/elastic-agent/_meta/config/common.p2.yml.tmpl @@ -5,8 +5,9 @@ outputs: default: type: elasticsearch hosts: [127.0.0.1:9200] - username: elastic - password: changeme + api-key: "example-key" + # username: "elastic" + # password: "changeme" inputs: - type: system/metrics @@ -33,6 +34,9 @@ inputs: # logs: true # # enables metrics monitoring # metrics: true +# # exposes /debug/pprof/ endpoints +# # recommended that these endpoints are only enabled if the monitoring endpoint is set to localhost +# pprof.enabled: false # # exposes agent metrics using http, by default sockets and named pipes are used # http: # # enables http endpoint @@ -71,8 +75,7 @@ inputs: # # optional values # #protocol: "https" -# #username: "elastic" -# #password: "changeme" +# #service_token: "example-token" # #path: "" # #ssl.verification_mode: full # #ssl.supported_protocols: [TLSv1.0, TLSv1.1, TLSv1.2] @@ -91,7 +94,7 @@ inputs: # # path to the directory containing downloaded packages # target_directory: "${path.data}/downloads" # # timeout for downloading package -# timeout: 30s +# timeout: 120s # # file path to a public key used for verifying downloaded artifacts # # if not file is present agent will try to load public key from elastic.co website. # pgpfile: "${path.data}/elastic.pgp" diff --git a/x-pack/elastic-agent/_meta/config/common.reference.p2.yml.tmpl b/x-pack/elastic-agent/_meta/config/common.reference.p2.yml.tmpl index f7593c383ac..bfb84102e3c 100644 --- a/x-pack/elastic-agent/_meta/config/common.reference.p2.yml.tmpl +++ b/x-pack/elastic-agent/_meta/config/common.reference.p2.yml.tmpl @@ -5,8 +5,9 @@ outputs: default: type: elasticsearch hosts: [127.0.0.1:9200] - username: elastic - password: changeme + api-key: "example-key" + # username: "elastic" + # password: "changeme" inputs: - type: system/metrics @@ -43,8 +44,7 @@ inputs: # # optional values # #protocol: "https" -# #username: "elastic" -# #password: "changeme" +# #service_token: "example-token" # #path: "" # #ssl.verification_mode: full # #ssl.supported_protocols: [TLSv1.0, TLSv1.1, TLSv1.2] @@ -63,7 +63,7 @@ inputs: # # path to the directory containing downloaded packages # target_directory: "${path.data}/downloads" # # timeout for downloading package -# timeout: 30s +# timeout: 120s # # file path to a public key used for verifying downloaded artifacts # # if not file is present agent will try to load public key from elastic.co website. # pgpfile: "${path.data}/elastic.pgp" @@ -107,6 +107,9 @@ inputs: # logs: false # # enables metrics monitoring # metrics: false +# # exposes /debug/pprof/ endpoints +# # recommended that these endpoints are only enabled if the monitoring endpoint is set to localhost +# pprof.enabled: false # # exposes agent metrics using http, by default sockets and named pipes are used # http: # # enables http endpoint diff --git a/x-pack/elastic-agent/_meta/config/elastic-agent.docker.yml.tmpl b/x-pack/elastic-agent/_meta/config/elastic-agent.docker.yml.tmpl index 0b73c9fcdb7..b039db33091 100644 --- a/x-pack/elastic-agent/_meta/config/elastic-agent.docker.yml.tmpl +++ b/x-pack/elastic-agent/_meta/config/elastic-agent.docker.yml.tmpl @@ -43,8 +43,7 @@ inputs: # # optional values # #protocol: "https" -# #username: "elastic" -# #password: "changeme" +# #service_token: "${FLEET_SERVER_SERVICE_TOKEN}" # #path: "" # #ssl.verification_mode: full # #ssl.supported_protocols: [TLSv1.0, TLSv1.1, TLSv1.2] @@ -63,7 +62,7 @@ inputs: # # path to the directory containing downloaded packages # target_directory: "${path.data}/downloads" # # timeout for downloading package -# timeout: 30s +# timeout: 120s # # file path to a public key used for verifying downloaded artifacts # # if not file is present agent will try to load public key from elastic.co website. # pgpfile: "${path.data}/elastic.pgp" @@ -107,6 +106,9 @@ inputs: # logs: false # # enables metrics monitoring # metrics: false +# # exposes /debug/pprof/ endpoints +# # recommended that these endpoints are only enabled if the monitoring endpoint is set to localhost +# pprof.enabled: false # # exposes agent metrics using http, by default sockets and named pipes are used # http: # # enables http endpoint diff --git a/x-pack/elastic-agent/_meta/elastic-agent.fleet.yml b/x-pack/elastic-agent/_meta/elastic-agent.fleet.yml index 5e73fbe0821..9189547155e 100644 --- a/x-pack/elastic-agent/_meta/elastic-agent.fleet.yml +++ b/x-pack/elastic-agent/_meta/elastic-agent.fleet.yml @@ -12,7 +12,7 @@ fleet: # # path to the directory containing downloaded packages # target_directory: "${path.data}/downloads" # # timeout for downloading package -# timeout: 30s +# timeout: 120s # # file path to a public key used for verifying downloaded artifacts # # if not file is present Elastic Agent will try to load public key from elastic.co website. # pgpfile: "${path.data}/elastic.pgp" diff --git a/x-pack/elastic-agent/_meta/elastic-agent.yml b/x-pack/elastic-agent/_meta/elastic-agent.yml index 6167575e769..7c24af477d2 100644 --- a/x-pack/elastic-agent/_meta/elastic-agent.yml +++ b/x-pack/elastic-agent/_meta/elastic-agent.yml @@ -43,8 +43,7 @@ inputs: # # optional values # #protocol: "https" -# #username: "elastic" -# #password: "changeme" +# #service_token: "example-token" # #path: "" # #ssl.verification_mode: full # #ssl.supported_protocols: [TLSv1.0, TLSv1.1, TLSv1.2] @@ -63,7 +62,7 @@ inputs: # # path to the directory containing downloaded packages # target_directory: "${path.data}/downloads" # # timeout for downloading package -# timeout: 30s +# timeout: 120s # # file path to a public key used for verifying downloaded artifacts # # if not file is present agent will try to load public key from elastic.co website. # pgpfile: "${path.data}/elastic.pgp" diff --git a/x-pack/elastic-agent/control.proto b/x-pack/elastic-agent/control.proto index 26b6552c395..53168f872ba 100644 --- a/x-pack/elastic-agent/control.proto +++ b/x-pack/elastic-agent/control.proto @@ -29,6 +29,19 @@ enum ActionStatus { FAILURE = 1; } +// pprof endpoint that can be requested. +enum PprofOption { + ALLOCS = 0; + BLOCK = 1; + CMDLINE = 2; + GOROUTINE = 3; + HEAP = 4; + MUTEX = 5; + PROFILE = 6; + THREADCREATE = 7; + TRACE = 8; +} + // Empty message. message Empty { } @@ -128,6 +141,32 @@ message ProcMetaResponse { repeated ProcMeta procs = 1; } +// PprofRequest is a request for pprof data from and http/pprof endpoint. +message PprofRequest { + // The profiles that are requested + repeated PprofOption pprofType = 1; + // A string representing a time.Duration to apply to trace, and profile options. + string traceDuration = 2; + // The application that will be profiled, if empty all applications are profiled. + string appName = 3; + // The route key to match for profiling, if empty all are profiled. + string routeKey = 4; +} + +// PprofResult is the result of a pprof request for a given application/route key. +message PprofResult { + string appName = 1; + string routeKey = 2; + PprofOption pprofType = 3; + bytes result = 4; + string error = 5; +} + +// PprofResponse is a wrapper to return all pprof responses. +message PprofResponse { + repeated PprofResult results = 1; +} + service ElasticAgentControl { // Fetches the currently running version of the Elastic Agent. rpc Version(Empty) returns (VersionResponse); @@ -143,4 +182,7 @@ service ElasticAgentControl { // Gather all running process metadata. rpc ProcMeta(Empty) returns (ProcMetaResponse); + + // Gather requested pprof data from specified applications. + rpc Pprof(PprofRequest) returns (PprofResponse); } diff --git a/x-pack/elastic-agent/elastic-agent.docker.yml b/x-pack/elastic-agent/elastic-agent.docker.yml index cb77ab59ffc..91148cee08e 100644 --- a/x-pack/elastic-agent/elastic-agent.docker.yml +++ b/x-pack/elastic-agent/elastic-agent.docker.yml @@ -43,8 +43,7 @@ inputs: # # optional values # #protocol: "https" -# #username: "elastic" -# #password: "changeme" +# #service_token: "${FLEET_SERVER_SERVICE_TOKEN}" # #path: "" # #ssl.verification_mode: full # #ssl.supported_protocols: [TLSv1.0, TLSv1.1, TLSv1.2] @@ -63,7 +62,7 @@ inputs: # # path to the directory containing downloaded packages # target_directory: "${path.data}/downloads" # # timeout for downloading package -# timeout: 30s +# timeout: 120s # # file path to a public key used for verifying downloaded artifacts # # if not file is present agent will try to load public key from elastic.co website. # pgpfile: "${path.data}/elastic.pgp" @@ -107,6 +106,9 @@ inputs: # logs: false # # enables metrics monitoring # metrics: false +# # exposes /debug/pprof/ endpoints +# # recommended that these endpoints are only enabled if the monitoring endpoint is set to localhost +# pprof.enabled: false # # exposes agent metrics using http, by default sockets and named pipes are used # http: # # enables http endpoint diff --git a/x-pack/elastic-agent/elastic-agent.reference.yml b/x-pack/elastic-agent/elastic-agent.reference.yml index 5456097ce3a..7770b036dba 100644 --- a/x-pack/elastic-agent/elastic-agent.reference.yml +++ b/x-pack/elastic-agent/elastic-agent.reference.yml @@ -11,8 +11,9 @@ outputs: default: type: elasticsearch hosts: [127.0.0.1:9200] - username: elastic - password: changeme + api-key: "example-key" + # username: "elastic" + # password: "changeme" inputs: - type: system/metrics @@ -49,8 +50,7 @@ inputs: # # optional values # #protocol: "https" -# #username: "elastic" -# #password: "changeme" +# #service_token: "example-token" # #path: "" # #ssl.verification_mode: full # #ssl.supported_protocols: [TLSv1.0, TLSv1.1, TLSv1.2] @@ -69,7 +69,7 @@ inputs: # # path to the directory containing downloaded packages # target_directory: "${path.data}/downloads" # # timeout for downloading package -# timeout: 30s +# timeout: 120s # # file path to a public key used for verifying downloaded artifacts # # if not file is present agent will try to load public key from elastic.co website. # pgpfile: "${path.data}/elastic.pgp" @@ -113,6 +113,9 @@ inputs: # logs: false # # enables metrics monitoring # metrics: false +# # exposes /debug/pprof/ endpoints +# # recommended that these endpoints are only enabled if the monitoring endpoint is set to localhost +# pprof.enabled: false # # exposes agent metrics using http, by default sockets and named pipes are used # http: # # enables http endpoint diff --git a/x-pack/elastic-agent/elastic-agent.yml b/x-pack/elastic-agent/elastic-agent.yml index 8204503be51..d2cfa19d384 100644 --- a/x-pack/elastic-agent/elastic-agent.yml +++ b/x-pack/elastic-agent/elastic-agent.yml @@ -11,8 +11,9 @@ outputs: default: type: elasticsearch hosts: [127.0.0.1:9200] - username: elastic - password: changeme + api-key: "example-key" + # username: "elastic" + # password: "changeme" inputs: - type: system/metrics @@ -39,6 +40,9 @@ inputs: # logs: true # # enables metrics monitoring # metrics: true +# # exposes /debug/pprof/ endpoints +# # recommended that these endpoints are only enabled if the monitoring endpoint is set to localhost +# pprof.enabled: false # # exposes agent metrics using http, by default sockets and named pipes are used # http: # # enables http endpoint @@ -77,8 +81,7 @@ inputs: # # optional values # #protocol: "https" -# #username: "elastic" -# #password: "changeme" +# #service_token: "example-token" # #path: "" # #ssl.verification_mode: full # #ssl.supported_protocols: [TLSv1.0, TLSv1.1, TLSv1.2] @@ -97,7 +100,7 @@ inputs: # # path to the directory containing downloaded packages # target_directory: "${path.data}/downloads" # # timeout for downloading package -# timeout: 30s +# timeout: 120s # # file path to a public key used for verifying downloaded artifacts # # if not file is present agent will try to load public key from elastic.co website. # pgpfile: "${path.data}/elastic.pgp" diff --git a/x-pack/elastic-agent/magefile.go b/x-pack/elastic-agent/magefile.go index 102ba5b86b0..ccceaf06935 100644 --- a/x-pack/elastic-agent/magefile.go +++ b/x-pack/elastic-agent/magefile.go @@ -595,7 +595,7 @@ func packageAgent(requiredPackages []string, packagingFn func()) { defer os.RemoveAll(dropPath) defer os.Unsetenv(agentDropPath) - packedBeats := []string{"filebeat", "heartbeat", "metricbeat"} + packedBeats := []string{"filebeat", "heartbeat", "metricbeat", "osquerybeat"} for _, b := range packedBeats { pwd, err := filepath.Abs(filepath.Join("..", b)) diff --git a/x-pack/elastic-agent/pkg/agent/application/application.go b/x-pack/elastic-agent/pkg/agent/application/application.go index e2f7a55ce3e..d0de160340d 100644 --- a/x-pack/elastic-agent/pkg/agent/application/application.go +++ b/x-pack/elastic-agent/pkg/agent/application/application.go @@ -39,10 +39,11 @@ type upgraderControl interface { } // New creates a new Agent and bootstrap the required subsystem. -func New(log *logger.Logger, pathConfigFile string, reexec reexecManager, statusCtrl status.Controller, uc upgraderControl, agentInfo *info.AgentInfo) (Application, error) { +func New(log *logger.Logger, reexec reexecManager, statusCtrl status.Controller, uc upgraderControl, agentInfo *info.AgentInfo) (Application, error) { // Load configuration from disk to understand in which mode of operation // we must start the elastic-agent, the mode of operation cannot be changed without restarting the // elastic-agent. + pathConfigFile := paths.ConfigFile() rawConfig, err := config.LoadFile(pathConfigFile) if err != nil { return nil, err @@ -66,7 +67,6 @@ func createApplication( ) (Application, error) { log.Info("Detecting execution mode") ctx := context.Background() - cfg, err := configuration.NewFromConfig(rawConfig) if err != nil { return nil, err diff --git a/x-pack/elastic-agent/pkg/agent/application/application_test.go b/x-pack/elastic-agent/pkg/agent/application/application_test.go index 7c1975fef64..7ae0032d483 100644 --- a/x-pack/elastic-agent/pkg/agent/application/application_test.go +++ b/x-pack/elastic-agent/pkg/agent/application/application_test.go @@ -3,3 +3,36 @@ // you may not use this file except in compliance with the Elastic License. package application + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/elastic/beats/v7/x-pack/elastic-agent/pkg/config" +) + +func TestMergeFleetConfig(t *testing.T) { + cfg := map[string]interface{}{ + "fleet": map[string]interface{}{ + "enabled": true, + "kibana": map[string]interface{}{"host": "demo"}, + "access_api_key": "123", + }, + "agent": map[string]interface{}{ + "grpc": map[string]interface{}{ + "port": uint16(6790), + }, + }, + } + + rawConfig := config.MustNewConfigFrom(cfg) + storage, conf, err := mergeFleetConfig(rawConfig) + require.NoError(t, err) + assert.NotNil(t, storage) + assert.NotNil(t, conf) + assert.Equal(t, conf.Fleet.Enabled, cfg["fleet"].(map[string]interface{})["enabled"]) + assert.Equal(t, conf.Fleet.AccessAPIKey, cfg["fleet"].(map[string]interface{})["access_api_key"]) + assert.Equal(t, conf.Settings.GRPC.Port, cfg["agent"].(map[string]interface{})["grpc"].(map[string]interface{})["port"].(uint16)) +} diff --git a/x-pack/elastic-agent/pkg/agent/application/configuration_embed.go b/x-pack/elastic-agent/pkg/agent/application/configuration_embed.go index 85c6137d7d3..eb1679a536e 100644 --- a/x-pack/elastic-agent/pkg/agent/application/configuration_embed.go +++ b/x-pack/elastic-agent/pkg/agent/application/configuration_embed.go @@ -15,7 +15,7 @@ var DefaultAgentFleetConfig []byte func init() { // Packed File // _meta/elastic-agent.fleet.yml - unpacked := packer.MustUnpack("eJycVUuTo7oV3udnzD43PJqpIVVZWHQjxLTpGF9LSJsUkjwytoSp2GCLVP57SuC2u29Npabugo2QzuN7nPOfL/8y23P9t62uT+dG/LVW2/b82w+93Z5/s0Z/+fsXZBfxP3/3fu1bg4yRSAuTntDzL755fN+RBQkjqScs6IQFex5EpibSFwYfUIZ7BrFFL+zECPZeExDxcKNokPYIlpoZ3bM1OPOw8FBWaJmVHTdyTJqlYm0+8DXwarhR60A3lEQ7lOL8tQHsHiPDFwZTj0339Igg6zjcKAm/KRrEPTO6lVWuUVYe2RqMrCq9mkStsO5+6rk81P2H0SATMMoKXHiYe4ysFG0PqjRXzapVn5i5/jd1VAjinpL8xMjqK8pKK8nm+xSHSM3bVc9gHHJzHShZfXXnKFnsUVYMssr3bA0G1sw90Sr3asJ2NCzH1wRYVqV+XeVaWKA5TEcJ9R7Ba1cHGyVCl6fwpl5g2rME9JT4HTdC8YAqCXcawbzjJrU1weM9L9z0zC4GGeipLmH9p7dn2m+Nvsx3wMhDbGmA8eZw+IqS/Ciz8iLG4/AapFZCbSgpPGGje02vphheg3KQQXTiQXoQNm5m/r81j37BTkI18TDXVnbC4L2Esd2uJ414lOjecYHgI5bDXcB0Xwdpy6rld2QXCmXlThipZRofHD40LAfRulrRYRtOeXqnAVp5wwP7ckTquEfJQiHHNfE1D7GHIBtEAw48lD2H8Y5B3TMLLpQU/3b83TC5339rFuMyu9WRLBUz+sTW4EKr8oiyckDwRYkMN3zi6qy3a+CLAB9ueQJW5R1r9cTTh9o0S8BOtGXHTLqXH+LXhCpuYu9dx3W1VCLLtQhwLxOQ3nXxkraMRB7KZMfhRcksj+Z6Jt39sSYjTHxGEJ9oVXg1WfY0+KZkgBsRaI+tn244g1bMeX+OLbnuRFh21EYXFi4eXEPdi7DccXj9IWDq1Qk4sKrYC6MbVi1v/F8HGqReTeIewdh8eOOwuOMvbHwRJm6FSc/CPql1tZowoOQ6cjtj+8g7YWwZSQ+TjjJgeSAtJZ4SIdA00KYmxU5CPfB22d+47XhbeJRcT9Xc3097rUk0SpieeII+eVtk+UADPIrxeOeMTzr2dzyZZweCkc9JrkUDDA+Rq2Ung2jqU5h4z6pivGsb+h3X8fTurVlcl8+Ly3Jx1+2ZVruOV/iMMjCIdqV4i8/UYHvrfRQwDfk0Z13vhRZhocVlfs9J+lSF07uv6Hl5cbEf/iw7TvAgq5ViJrYIFg5Hb/ZjpKX9VGuPMnlk5End+59nfc/DlRIh3k9nAfM5vEbvsd5nqIS7Tnzw4IeZ6LkZiGB8YVU+89Tcd8hYk1JPOwS+KGbSjmfYstXc2w3THxLqMyOxL5+PajmCMXGeh7M3XttcO1+8PeaA5iZtOHQxSy0hto67SaPBTjudTnqqSjejXB0XHhZj7Wb9+kmVEBta4ZNMpn/GafLunZ/shHd9CIM9YbQWfrzn4eTjUUC8rwnrXO4Hp7FB2VRzN2H+4vZj6vNs9sDSPt1jblzM9uB2nM+dLgKqlmtwZiTtHTcyAWFNricE3e67xSTuXqRn7jeKEuaxCs1nkO1qcvWF2bz7ZMLB7ZIqKAZJomkWPrxXun0Qoay4MFJ0zPVnwcHNCIcdb8BZWNCwqgwZwf3/7cvxNuec3/9+/HDmcvm7bRq/x/6MHUmfauL7fP1ncy8un/wSzH29NQufr+66SbcZGLjBvYTa+fzAKqdNt3/xOHmjKo8OSzbN2MMUW2a5ptVt1lugP8d4cIkD7dXJtGfu7ymJDuj5g3ZGh8nihJ7p5TVZXJf7D/j8oSdm0pMINu+6fBIw7p0fapKe3pqbblfHf3z571/+FwAA//9N0n8p") + unpacked := packer.MustUnpack("eJycVUuTo7oV3udnzD43PIauITsLN0KModO4jZA2KSS5BbaEqWsDhlT+e0rgtrtv3aSmsmAjpPP4Huf869s/9f5S/m2vyvOl5n8t5b65/Pau9vvLb6NW3/7+DY0r/x9v1q99WxBR7CmuwzNa/+Kbx/cTjSCgOLT4CFo+ggNzPF1iYXOdH1GUdxTmI3qmZ4pzaxMAj7k7SZywQzBTVKuObsGFuamFolSJKGuZFlNQJ5I2cc+2wCrhTm4dVRPsVSjM400N6D1GlA8Uhhad76kJQdoyuJMC/pDE8TuqVSOKWKEoO9EtmGiRWSX2Gj6a+6Fl8hDzH3q9CMAkCjAwN7YofpWkOcpMXxUtXrtAL/W/yJNEMO8Ijs8Uvz6hKBsF3v2c42ChWPPaUei7TF97gl+fzDkKVgcUpb0o4gPdgp7WS0+kiK0S04q42bQJwEiL0C6LWPERKAbDSUB1QPDals5OctfkSa25Fxh2NAAdwXbLNJfMIVLASiEYt0yHY4nz6Z4X7jo6rnrhqLkuPtrfX9ak22s1LHfAxNx8JE6e747HJxTEJxFlA59O/cYJRwGVJji1+Ojda9rotN84WS8c78yc8MhHv174/1E/+gWVgHLmYakta7nODwL64347a8QiWHWGCwQfsQzuHIaH0gkbWiQ/0biSKMoqroUSoX80+BA363ljakXHvTvn6YwGSGH1D+yzCcnTAQUriQzX2FbMzS0Eac9rcGSu6Bj0KwpVR0cwEJz+bvi7YXK//1KvrskBfMJz0ReHoVUGwGIjqFAEbKKvLRnB77Q4SlGkigZAMxdJofOxxNT7sz4/8/+Ir/RNi7rEV4WMpiOjjdRoS2b4WnE3M7kAdfJOBMAt8fVsdLjfzvXM8f9Y081LXzhEkVCkSVsBd92t74G6S96XelXH0WUgRXba6KwSMPQ3Tn4mRWqVOOk4FMMnfFvWpBbB13Ox8CEpzCfixi3R+XTz3pk5aSWg6lk9e+D+5g+c9zyKe+rGFSuSDj0ra8YAhmfu/FiwXd3zzhhznd955NpvuA4vKEoHitOWanUgRdYyx5s2t3pL7E0ChmcW+nN/f96r6ribVQwOdWDewbCh2LM2DRiZkyruJg9vQ+NDdSF4kBz6owhAJ7Bd0wJJqv3R1EIK0c19RnFPnHzizodHwaXE3vv8bn2SydtqSNarRfdBIhkOv5fYttl2mUsIejbDseL1rXeDt+MZvZneD7RIp7tvoF3tQ39+91KvpmS9GpLVf/XEweAoFhw7WvAvtW5q4JYw74wWb/3Lskgk076Z2zaZz1It8PVs/L3Eyo8Ixp7h39wVUF0o9m3xqMHwYPDqOczHhafvc1wzu7mjjrSITW8VgrQq8dXmenebCQumhZu1DOe9KF6f0DoZ+HAy+6havOGNtMjG/dvpjifFXkXMTA/AkRaZ4tpwZzQqTrTIToYzrnOLN8e5Dg79iTuqZnDXoWezr0KbRa/zP6qNJu/eUUyHNYP58aUGFm9y9ZiFsRJR3NIifSeObxsfcxco4ihtZvUnTo0v5prN+aYGzxTTSuDr4oF10t1jhnNMD8G0F9izEPQ1Wj9LhvOKNYabVykcdWYBqOn2HvOIoN/NuxLbZo9oYXbzcqYJVmezXz58MuOgleK2f2Bu3s36HO7cHSm+VvstmDjMDyWmLTWYQDMjjrLE3yUzPOrcEk6u2P/uy/A2x729f/p8hkZwIUX1/hH7K3Z2tYfqIrD1f+dOoi9+Wfp6O8kUW3fdZEU1MMdTrMla43MKc4sWsfGu2dfGG1Y5Y5mZGestczsbzV5cZn0i6dcYn7gUrZmZyQSmx3uz41fTQzvJjMkmWDlJMMjkDX3G52tPkFYsSj92mdpHoGc67wRUFVufPnT789u///KfAAAA//+w0n9F") raw, ok := unpacked["_meta/elastic-agent.fleet.yml"] if !ok { // ensure we have something loaded. diff --git a/x-pack/elastic-agent/pkg/agent/application/pipeline/actions/handlers/handler_action_policy_change.go b/x-pack/elastic-agent/pkg/agent/application/pipeline/actions/handlers/handler_action_policy_change.go index f14ec7aea81..e00ccfc844b 100644 --- a/x-pack/elastic-agent/pkg/agent/application/pipeline/actions/handlers/handler_action_policy_change.go +++ b/x-pack/elastic-agent/pkg/agent/application/pipeline/actions/handlers/handler_action_policy_change.go @@ -197,9 +197,10 @@ func fleetToReader(agentInfo *info.AgentInfo, cfg *configuration.Configuration) configToStore := map[string]interface{}{ "fleet": cfg.Fleet, "agent": map[string]interface{}{ - "id": agentInfo.AgentID(), - "logging.level": cfg.Settings.LoggingConfig.Level, - "monitoring.http": cfg.Settings.MonitoringConfig.HTTP, + "id": agentInfo.AgentID(), + "logging.level": cfg.Settings.LoggingConfig.Level, + "monitoring.http": cfg.Settings.MonitoringConfig.HTTP, + "monitoring.pprof": cfg.Settings.MonitoringConfig.Pprof, }, } diff --git a/x-pack/elastic-agent/pkg/agent/cmd/container.go b/x-pack/elastic-agent/pkg/agent/cmd/container.go index e7a64cec193..25ff4c15ddc 100644 --- a/x-pack/elastic-agent/pkg/agent/cmd/container.go +++ b/x-pack/elastic-agent/pkg/agent/cmd/container.go @@ -79,8 +79,6 @@ The following actions are possible and grouped based on the actions. The following vars are need in the scenario that Elastic Agent should automatically fetch its own token. KIBANA_FLEET_HOST - kibana host to enable create enrollment token on [$KIBANA_HOST] - KIBANA_FLEET_USERNAME - kibana username to create enrollment token [$KIBANA_USERNAME] - KIBANA_FLEET_PASSWORD - kibana password to create enrollment token [$KIBANA_PASSWORD] FLEET_TOKEN_NAME - token name to use for fetching token from Kibana. This requires Kibana configs to be set. FLEET_TOKEN_POLICY_NAME - token policy name to use for fetching token from Kibana. This requires Kibana configs to be set. @@ -93,9 +91,8 @@ The following actions are possible and grouped based on the actions. FLEET_SERVER_ENABLE - set to 1 enables bootstrapping of Fleet Server inside Elastic Agent (forces FLEET_ENROLL enabled) FLEET_SERVER_ELASTICSEARCH_HOST - elasticsearch host for Fleet Server to communicate with [$ELASTICSEARCH_HOST] - FLEET_SERVER_ELASTICSEARCH_USERNAME - elasticsearch username for Fleet Server [$ELASTICSEARCH_USERNAME] - FLEET_SERVER_ELASTICSEARCH_PASSWORD - elasticsearch password for Fleet Server [$ELASTICSEARCH_PASSWORD] FLEET_SERVER_ELASTICSEARCH_CA - path to certificate authority to use with communicate with elasticsearch [$ELASTICSEARCH_CA] + FLEET_SERVER_ELASTICSEARCH_CA_TRUSTED_FINGERPRINT - The sha-256 fingerprint value of the certificate authority to trust FLEET_SERVER_ELASTICSEARCH_INSECURE - disables cert validation for communication with Elasticsearch FLEET_SERVER_SERVICE_TOKEN - service token to use for communication with elasticsearch FLEET_SERVER_POLICY_ID - policy ID for Fleet Server to use for itself ("Default Fleet Server policy" used when undefined) @@ -112,8 +109,8 @@ The following actions are possible and grouped based on the actions. KIBANA_FLEET_SETUP - set to 1 enables the setup of Fleet in Kibana by Elastic Agent. This was previously FLEET_SETUP. KIBANA_FLEET_HOST - Kibana host accessible from fleet-server. [$KIBANA_HOST] - KIBANA_FLEET_USERNAME - kibana username to enable Fleet [$KIBANA_USERNAME] - KIBANA_FLEET_PASSWORD - kibana password to enable Fleet [$KIBANA_PASSWORD] + KIBANA_FLEET_USERNAME - kibana username to service token [$KIBANA_USERNAME] + KIBANA_FLEET_PASSWORD - kibana password to service token [$KIBANA_PASSWORD] KIBANA_FLEET_CA - path to certificate authority to use with communicate with Kibana [$KIBANA_CA] KIBANA_REQUEST_RETRY_SLEEP - specifies sleep duration taken when agent performs a request to kibana [default 1s] KIBANA_REQUEST_RETRY_COUNT - specifies number of retries agent performs when executing a request to kibana [default 30] @@ -126,8 +123,8 @@ be used when the same credentials will be used across all the possible actions a ELASTICSEARCH_PASSWORD - elasticsearch password [changeme] ELASTICSEARCH_CA - path to certificate authority to use with communicate with elasticsearch KIBANA_HOST - kibana host [http://kibana:5601] - KIBANA_USERNAME - kibana username [$ELASTICSEARCH_USERNAME] - KIBANA_PASSWORD - kibana password [$ELASTICSEARCH_PASSWORD] + KIBANA_FLEET_USERNAME - kibana username to enable Fleet [$ELASTICSEARCH_USERNAME] + KIBANA_FLEET_PASSWORD - kibana password to enable Fleet [$ELASTICSEARCH_PASSWORD] KIBANA_CA - path to certificate authority to use with communicate with Kibana [$ELASTICSEARCH_CA] @@ -272,11 +269,18 @@ func runContainerCmd(streams *cli.IOStreams, cmd *cobra.Command, cfg setupConfig return run(streams, logToStderr) } + if cfg.Kibana.Fleet.Setup || cfg.Fleet.Enroll { + err = ensureServiceToken(streams, &cfg) + if err != nil { + return err + } + } if cfg.Kibana.Fleet.Setup { client, err = kibanaClient(cfg.Kibana, cfg.Kibana.Headers) if err != nil { return err } + logInfo(streams, "Performing setup of Fleet in Kibana\n") err = kibanaSetup(cfg, client, streams) if err != nil { @@ -306,7 +310,10 @@ func runContainerCmd(streams *cli.IOStreams, cmd *cobra.Command, cfg setupConfig if policy != nil { policyID = policy.ID } - logInfo(streams, "Policy selected for enrollment: ", policyID) + if policyID != "" { + logInfo(streams, "Policy selected for enrollment: ", policyID) + } + cmdArgs, err := buildEnrollArgs(cfg, token, policyID) if err != nil { return err @@ -327,6 +334,50 @@ func runContainerCmd(streams *cli.IOStreams, cmd *cobra.Command, cfg setupConfig return run(streams, logToStderr) } +// TokenResp is used to decode a response for generating a service token +type TokenResp struct { + Name string `json:"name"` + Value string `json:"value"` +} + +// ensureServiceToken will ensure that the cfg specified has the service_token attributes filled. +// +// If no token is specified it will use the elasticsearch username/password to request a new token from Kibana +func ensureServiceToken(streams *cli.IOStreams, cfg *setupConfig) error { + // There's already a service token + if cfg.Kibana.Fleet.ServiceToken != "" || cfg.FleetServer.Elasticsearch.ServiceToken != "" { + return nil + } + if cfg.Kibana.Fleet.Username == "" || cfg.Kibana.Fleet.Password == "" { + return fmt.Errorf("username/password must be provided to retrieve service token") + } + + logInfo(streams, "Requesting service_token from Kibana.") + + // Client is not passed in to this function because this function will use username/password and then + // all the following clients will use the created service token. + client, err := kibanaClient(cfg.Kibana, cfg.Kibana.Headers) + if err != nil { + return err + } + code, r, err := client.Connection.Request("POST", "/api/fleet/service-tokens", nil, nil, nil) + if err != nil { + return fmt.Errorf("request to get security token from Kibana failed: %w", err) + } + if code >= 400 { + return fmt.Errorf("request to get security token from Kibana failed with status %d, body: %s", code, string(r)) + } + t := TokenResp{} + err = json.Unmarshal(r, &t) + if err != nil { + return fmt.Errorf("unable to decode response: %w", err) + } + logInfo(streams, "Created service_token named:", t.Name) + cfg.Kibana.Fleet.ServiceToken = t.Value + cfg.FleetServer.Elasticsearch.ServiceToken = t.Value + return nil +} + func buildEnrollArgs(cfg setupConfig, token string, policyID string) ([]string, error) { args := []string{ "enroll", "-f", @@ -359,6 +410,9 @@ func buildEnrollArgs(cfg setupConfig, token string, policyID string) ([]string, if cfg.FleetServer.Elasticsearch.CA != "" { args = append(args, "--fleet-server-es-ca", cfg.FleetServer.Elasticsearch.CA) } + if cfg.FleetServer.Elasticsearch.CATrustedFingerprint != "" { + args = append(args, "--fleet-server-es-ca-trusted-fingerprint", cfg.FleetServer.Elasticsearch.CATrustedFingerprint) + } if cfg.FleetServer.Host != "" { args = append(args, "--fleet-server-host", cfg.FleetServer.Host) } @@ -423,10 +477,7 @@ func buildFleetServerConnStr(cfg fleetServerConfig) (string, error) { if u.Path != "" { path += "/" + strings.TrimLeft(u.Path, "/") } - if cfg.Elasticsearch.ServiceToken != "" { - return fmt.Sprintf("%s://%s%s", u.Scheme, u.Host, path), nil - } - return fmt.Sprintf("%s://%s:%s@%s%s", u.Scheme, cfg.Elasticsearch.Username, cfg.Elasticsearch.Password, u.Host, path), nil + return fmt.Sprintf("%s://%s%s", u.Scheme, u.Host, path), nil } func kibanaSetup(cfg setupConfig, client *kibana.Client, streams *cli.IOStreams) error { @@ -670,12 +721,6 @@ func runLegacyAPMServer(streams *cli.IOStreams, path string) (*process.Info, err return nil, errors.New("expected one directory") } apmDir := filepath.Join(path, files[0].Name()) - // Extract the ingest pipeline definition to the HOME_DIR - if home := os.Getenv("HOME_PATH"); home != "" { - if err := syncDir(filepath.Join(apmDir, "ingest"), filepath.Join(home, "ingest")); err != nil { - return nil, fmt.Errorf("syncing APM ingest directory to HOME_PATH(%s) failed: %s", home, err) - } - } // Start apm-server process respecting path ENVs apmBinary := filepath.Join(apmDir, spec.Cmd) log, err := logger.New("apm-server", false) diff --git a/x-pack/elastic-agent/pkg/agent/cmd/diagnostics.go b/x-pack/elastic-agent/pkg/agent/cmd/diagnostics.go index e90e4ab13c1..b32edf6df2d 100644 --- a/x-pack/elastic-agent/pkg/agent/cmd/diagnostics.go +++ b/x-pack/elastic-agent/pkg/agent/cmd/diagnostics.go @@ -25,6 +25,7 @@ import ( "github.com/elastic/beats/v7/x-pack/elastic-agent/pkg/agent/application/paths" "github.com/elastic/beats/v7/x-pack/elastic-agent/pkg/agent/configuration" "github.com/elastic/beats/v7/x-pack/elastic-agent/pkg/agent/control/client" + "github.com/elastic/beats/v7/x-pack/elastic-agent/pkg/agent/control/proto" "github.com/elastic/beats/v7/x-pack/elastic-agent/pkg/agent/errors" "github.com/elastic/beats/v7/x-pack/elastic-agent/pkg/cli" "github.com/elastic/beats/v7/x-pack/elastic-agent/pkg/config/operations" @@ -63,6 +64,7 @@ func newDiagnosticsCommand(s []string, streams *cli.IOStreams) *cobra.Command { cmd.Flags().String("output", "human", "Output the diagnostics information in either human, json, or yaml (default: human)") cmd.AddCommand(newDiagnosticsCollectCommandWithArgs(s, streams)) + cmd.AddCommand(newDiagnosticsPprofCommandWithArgs(s, streams)) return cmd } @@ -72,7 +74,7 @@ func newDiagnosticsCollectCommandWithArgs(_ []string, streams *cli.IOStreams) *c Use: "collect", Short: "Collect diagnostics information from the elastic-agent and write it to a zip archive.", Long: "Collect diagnostics information from the elastic-agent and write it to a zip archive.\nNote that any credentials will appear in plain text.", - Args: cobra.MaximumNArgs(1), + Args: cobra.MaximumNArgs(3), RunE: func(c *cobra.Command, args []string) error { file, _ := c.Flags().GetString("file") @@ -89,12 +91,58 @@ func newDiagnosticsCollectCommandWithArgs(_ []string, streams *cli.IOStreams) *c return fmt.Errorf("unsupported output: %s", output) } - return diagnosticsCollectCmd(streams, file, output) + pprof, _ := c.Flags().GetBool("pprof") + d, _ := c.Flags().GetDuration("pprof-duration") + // get the command timeout value only if one is set explicitly. + // otherwise a value of 30s + pprof-duration will be used. + var timeout time.Duration + if c.Flags().Changed("timeout") { + timeout, _ = c.Flags().GetDuration("timeout") + } + + return diagnosticsCollectCmd(streams, file, output, pprof, d, timeout) }, } cmd.Flags().StringP("file", "f", "", "name of the output diagnostics zip archive") cmd.Flags().String("output", "yaml", "Output the collected information in either json, or yaml (default: yaml)") // replace output flag with different options + cmd.Flags().Bool("pprof", false, "Collect all pprof data from all running applications.") + cmd.Flags().Duration("pprof-duration", time.Second*30, "The duration to collect trace and profiling data from the debug/pprof endpoints. (default: 30s)") + cmd.Flags().Duration("timeout", time.Second*30, "The timeout for the diagnostics collect command, will be either 30s or 30s+pprof-duration by default. Should be longer then pprof-duration when pprof is enabled as the command needs time to process/archive the response.") + + return cmd +} + +func newDiagnosticsPprofCommandWithArgs(_ []string, streams *cli.IOStreams) *cobra.Command { + cmd := &cobra.Command{ + Use: "pprof", + Short: "Collect pprof information from a running process.", + Long: "Collect pprof information from the elastic-agent or one of its processes and write to stdout or a file.\nBy default it will gather a 30s profile of the elastic-agent and output on stdout.", + Args: cobra.MaximumNArgs(5), + RunE: func(c *cobra.Command, args []string) error { + file, _ := c.Flags().GetString("file") + pprofType, _ := c.Flags().GetString("pprof-type") + d, _ := c.Flags().GetDuration("pprof-duration") + // get the command timeout value only if one is set explicitly. + // otherwise a value of 30s + pprof-duration will be used. + var timeout time.Duration + if c.Flags().Changed("timeout") { + timeout, _ = c.Flags().GetDuration("timeout") + } + + pprofApp, _ := c.Flags().GetString("pprof-application") + pprofRK, _ := c.Flags().GetString("pprof-route-key") + + return diagnosticsPprofCmd(streams, d, timeout, file, pprofType, pprofApp, pprofRK) + }, + } + + cmd.Flags().StringP("file", "f", "", "name of the output file, stdout if unspecified.") + cmd.Flags().String("pprof-type", "profile", "Collect all pprof data from all running applications. Select one of [allocs, block, cmdline, goroutine, heap, mutex, profile, threadcreate, trace]") + cmd.Flags().Duration("pprof-duration", time.Second*30, "The duration to collect trace and profiling data from the debug/pprof endpoints. (default: 30s)") + cmd.Flags().Duration("timeout", time.Second*60, "The timeout for the pprof collect command, defaults to 30s+pprof-duration by default. Should be longer then pprof-duration as the command needs time to process the response.") + cmd.Flags().String("pprof-application", "elastic-agent", "Application name to collect pprof data from.") + cmd.Flags().String("pprof-route-key", "default", "Route key to collect pprof data from.") return cmd } @@ -127,14 +175,22 @@ func diagnosticCmd(streams *cli.IOStreams, cmd *cobra.Command, args []string) er return outputFunc(streams.Out, diag) } -func diagnosticsCollectCmd(streams *cli.IOStreams, fileName, outputFormat string) error { +func diagnosticsCollectCmd(streams *cli.IOStreams, fileName, outputFormat string, pprof bool, pprofDur, cmdTimeout time.Duration) error { err := tryContainerLoadPaths() if err != nil { return err } ctx := handleSignal(context.Background()) - innerCtx, cancel := context.WithTimeout(ctx, 30*time.Second) + // set command timeout to 30s or 30s+pprofDur if no timeout is specified + if cmdTimeout == time.Duration(0) { + cmdTimeout = time.Second * 30 + if pprof { + cmdTimeout += pprofDur + } + + } + innerCtx, cancel := context.WithTimeout(ctx, cmdTimeout) defer cancel() diag, err := getDiagnostics(innerCtx) @@ -151,7 +207,15 @@ func diagnosticsCollectCmd(streams *cli.IOStreams, fileName, outputFormat string return fmt.Errorf("unable to gather config data: %w", err) } - err = createZip(fileName, outputFormat, diag, cfg) + var pprofData map[string][]client.ProcPProf = nil + if pprof { + pprofData, err = getAllPprof(innerCtx, pprofDur) + if err != nil { + return fmt.Errorf("unable to gather pprof data: %w", err) + } + } + + err = createZip(fileName, outputFormat, diag, cfg, pprofData) if err != nil { return fmt.Errorf("unable to create archive %q: %w", fileName, err) } @@ -160,6 +224,68 @@ func diagnosticsCollectCmd(streams *cli.IOStreams, fileName, outputFormat string return nil } +func diagnosticsPprofCmd(streams *cli.IOStreams, dur, cmdTimeout time.Duration, outFile, pType, appName, rk string) error { + pt, ok := proto.PprofOption_value[strings.ToUpper(pType)] + if !ok { + return fmt.Errorf("unknown pprof-type %q, select one of [allocs, block, cmdline, goroutine, heap, mutex, profile, threadcreate, trace]", pType) + } + + // the elastic-agent application does not have a route key + if appName == "elastic-agent" { + rk = "" + } + + ctx := handleSignal(context.Background()) + // set cmdTimeout to 30s+dur if not set. + if cmdTimeout == time.Duration(0) { + cmdTimeout = time.Second*30 + dur + } + innerCtx, cancel := context.WithTimeout(ctx, cmdTimeout) + defer cancel() + + daemon := client.New() + err := daemon.Connect(ctx) + if err != nil { + return err + } + + pprofData, err := daemon.Pprof(innerCtx, dur, []proto.PprofOption{proto.PprofOption(pt)}, appName, rk) + if err != nil { + return err + } + + // validate response + pArr, ok := pprofData[proto.PprofOption_name[pt]] + if !ok { + return fmt.Errorf("route key %q not found in response data (map length: %d)", rk, len(pprofData)) + } + if len(pArr) != 1 { + return fmt.Errorf("pprof type length 1 expected, recieved %d", len(pArr)) + } + res := pArr[0] + + if res.Error != "" { + return fmt.Errorf(res.Error) + } + + // handle result + if outFile != "" { + f, err := os.Create(outFile) + if err != nil { + return err + } + defer f.Close() + _, err = f.Write(res.Result) + if err != nil { + return err + } + fmt.Fprintf(streams.Out, "pprof data written to %s\n", outFile) + return nil + } + _, err = streams.Out.Write(res.Result) + return err +} + func getDiagnostics(ctx context.Context) (DiagnosticsInfo, error) { daemon := client.New() diag := DiagnosticsInfo{} @@ -242,7 +368,7 @@ func gatherConfig() (AgentConfig, error) { // // The passed DiagnosticsInfo and AgentConfig data is written in the specified output format. // Any local log files are collected and copied into the archive. -func createZip(fileName, outputFormat string, diag DiagnosticsInfo, cfg AgentConfig) error { +func createZip(fileName, outputFormat string, diag DiagnosticsInfo, cfg AgentConfig, pprof map[string][]client.ProcPProf) error { f, err := os.Create(fileName) if err != nil { return err @@ -298,6 +424,13 @@ func createZip(fileName, outputFormat string, diag DiagnosticsInfo, cfg AgentCon return closeHandlers(err, zw, f) } + if pprof != nil { + err := zipProfs(zw, pprof) + if err != nil { + return closeHandlers(err, zw, f) + } + } + return closeHandlers(nil, zw, f) } @@ -371,3 +504,58 @@ func closeHandlers(err error, closers ...io.Closer) error { } return mErr.ErrorOrNil() } + +func getAllPprof(ctx context.Context, d time.Duration) (map[string][]client.ProcPProf, error) { + daemon := client.New() + err := daemon.Connect(ctx) + if err != nil { + return nil, err + } + pprofTypes := []proto.PprofOption{ + proto.PprofOption_ALLOCS, + proto.PprofOption_BLOCK, + proto.PprofOption_CMDLINE, + proto.PprofOption_GOROUTINE, + proto.PprofOption_HEAP, + proto.PprofOption_MUTEX, + proto.PprofOption_PROFILE, + proto.PprofOption_THREADCREATE, + proto.PprofOption_TRACE, + } + return daemon.Pprof(ctx, d, pprofTypes, "", "") +} + +func zipProfs(zw *zip.Writer, pprof map[string][]client.ProcPProf) error { + zf, err := zw.Create("pprof/") + if err != nil { + return err + } + for pType, profs := range pprof { + zf, err = zw.Create("pprof/" + pType + "/") + if err != nil { + return err + } + for _, p := range profs { + if p.Error != "" { + zf, err = zw.Create("pprof/" + pType + "/" + p.Name + "_" + p.RouteKey + "_error.txt") + if err != nil { + return err + } + _, err = zf.Write([]byte(p.Error)) + if err != nil { + return err + } + continue + } + zf, err = zw.Create("pprof/" + pType + "/" + p.Name + "_" + p.RouteKey + ".pprof") + if err != nil { + return err + } + _, err = zf.Write(p.Result) + if err != nil { + return err + } + } + } + return nil +} diff --git a/x-pack/elastic-agent/pkg/agent/cmd/enroll.go b/x-pack/elastic-agent/pkg/agent/cmd/enroll.go index a80a9abc22b..6a66b4fdfc1 100644 --- a/x-pack/elastic-agent/pkg/agent/cmd/enroll.go +++ b/x-pack/elastic-agent/pkg/agent/cmd/enroll.go @@ -53,6 +53,7 @@ func addEnrollFlags(cmd *cobra.Command) { cmd.Flags().StringP("enrollment-token", "t", "", "Enrollment token to use to enroll Agent into Fleet") cmd.Flags().StringP("fleet-server-es", "", "", "Start and run a Fleet Server along side this Elastic Agent connecting to the provided elasticsearch") cmd.Flags().StringP("fleet-server-es-ca", "", "", "Path to certificate authority to use with communicate with elasticsearch") + cmd.Flags().StringP("fleet-server-es-ca-trusted-fingerprint", "", "", "Elasticsearch certificate authority's SHA256 fingerprint") cmd.Flags().BoolP("fleet-server-es-insecure", "", false, "Disables validation of certificates") cmd.Flags().StringP("fleet-server-service-token", "", "", "Service token to use for communication with elasticsearch") cmd.Flags().StringP("fleet-server-policy", "", "", "Start and run a Fleet Server on this specific policy") @@ -103,6 +104,7 @@ func buildEnrollmentFlags(cmd *cobra.Command, url string, token string) []string } fServer, _ := cmd.Flags().GetString("fleet-server-es") fElasticSearchCA, _ := cmd.Flags().GetString("fleet-server-es-ca") + fElasticSearchCASHA256, _ := cmd.Flags().GetString("fleet-server-es-ca-trusted-fingerprint") fElasticSearchInsecure, _ := cmd.Flags().GetBool("fleet-server-es-insecure") fServiceToken, _ := cmd.Flags().GetString("fleet-server-service-token") fPolicy, _ := cmd.Flags().GetString("fleet-server-policy") @@ -140,6 +142,10 @@ func buildEnrollmentFlags(cmd *cobra.Command, url string, token string) []string args = append(args, "--fleet-server-es-ca") args = append(args, fElasticSearchCA) } + if fElasticSearchCASHA256 != "" { + args = append(args, "--fleet-server-es-ca-trusted-fingerprint") + args = append(args, fElasticSearchCASHA256) + } if fServiceToken != "" { args = append(args, "--fleet-server-service-token") args = append(args, fServiceToken) @@ -285,12 +291,14 @@ func enroll(streams *cli.IOStreams, cmd *cobra.Command, args []string) error { enrollmentToken, _ := cmd.Flags().GetString("enrollment-token") fServer, _ := cmd.Flags().GetString("fleet-server-es") fElasticSearchCA, _ := cmd.Flags().GetString("fleet-server-es-ca") + fElasticSearchCASHA256, _ := cmd.Flags().GetString("fleet-server-es-ca-trusted-fingerprint") fElasticSearchInsecure, _ := cmd.Flags().GetBool("fleet-server-es-insecure") fHeaders, _ := cmd.Flags().GetStringSlice("header") fServiceToken, _ := cmd.Flags().GetString("fleet-server-service-token") fPolicy, _ := cmd.Flags().GetString("fleet-server-policy") fHost, _ := cmd.Flags().GetString("fleet-server-host") fPort, _ := cmd.Flags().GetUint16("fleet-server-port") + fInternalPort, _ := cmd.Flags().GetUint16("fleet-server-internal-port") fCert, _ := cmd.Flags().GetString("fleet-server-cert") fCertKey, _ := cmd.Flags().GetString("fleet-server-cert-key") fInsecure, _ := cmd.Flags().GetBool("fleet-server-insecure-http") @@ -325,6 +333,7 @@ func enroll(streams *cli.IOStreams, cmd *cobra.Command, args []string) error { FleetServer: enrollCmdFleetServerOption{ ConnStr: fServer, ElasticsearchCA: fElasticSearchCA, + ElasticsearchCASHA256: fElasticSearchCASHA256, ElasticsearchInsecure: fElasticSearchInsecure, ServiceToken: fServiceToken, PolicyID: fPolicy, @@ -336,6 +345,7 @@ func enroll(streams *cli.IOStreams, cmd *cobra.Command, args []string) error { SpawnAgent: !fromInstall, Headers: mapFromEnvList(fHeaders), Timeout: fTimeout, + InternalPort: fInternalPort, }, } diff --git a/x-pack/elastic-agent/pkg/agent/cmd/enroll_cmd.go b/x-pack/elastic-agent/pkg/agent/cmd/enroll_cmd.go index 3a96a25330c..0023d83fde0 100644 --- a/x-pack/elastic-agent/pkg/agent/cmd/enroll_cmd.go +++ b/x-pack/elastic-agent/pkg/agent/cmd/enroll_cmd.go @@ -44,11 +44,13 @@ import ( ) const ( - maxRetriesstoreAgentInfo = 5 - waitingForAgent = "Waiting for Elastic Agent to start" - waitingForFleetServer = "Waiting for Elastic Agent to start Fleet Server" - defaultFleetServerHost = "0.0.0.0" - defaultFleetServerPort = 8220 + maxRetriesstoreAgentInfo = 5 + waitingForAgent = "Waiting for Elastic Agent to start" + waitingForFleetServer = "Waiting for Elastic Agent to start Fleet Server" + defaultFleetServerHost = "0.0.0.0" + defaultFleetServerPort = 8220 + defaultFleetServerInternalHost = "localhost" + defaultFleetServerInternalPort = 8221 ) var ( @@ -75,11 +77,13 @@ type enrollCmd struct { type enrollCmdFleetServerOption struct { ConnStr string ElasticsearchCA string + ElasticsearchCASHA256 string ElasticsearchInsecure bool ServiceToken string PolicyID string Host string Port uint16 + InternalPort uint16 Cert string CertKey string Insecure bool @@ -91,6 +95,7 @@ type enrollCmdFleetServerOption struct { // enrollCmdOption define all the supported enrollment option. type enrollCmdOption struct { URL string `yaml:"url,omitempty"` + InternalURL string `yaml:"-"` CAs []string `yaml:"ca,omitempty"` CASha256 []string `yaml:"ca_sha256,omitempty"` Insecure bool `yaml:"insecure,omitempty"` @@ -106,6 +111,7 @@ type enrollCmdOption struct { FleetServer enrollCmdFleetServerOption `yaml:"-"` } +// remoteConfig returns the configuration used to connect the agent to a fleet process. func (e *enrollCmdOption) remoteConfig() (remote.Config, error) { cfg, err := remote.NewConfigFromURL(e.URL) if err != nil { @@ -306,8 +312,8 @@ func (c *enrollCmd) fleetServerBootstrap(ctx context.Context, persistentConfig m fleetConfig, err := createFleetServerBootstrapConfig( c.options.FleetServer.ConnStr, c.options.FleetServer.ServiceToken, c.options.FleetServer.PolicyID, - c.options.FleetServer.Host, c.options.FleetServer.Port, - c.options.FleetServer.Cert, c.options.FleetServer.CertKey, c.options.FleetServer.ElasticsearchCA, + c.options.FleetServer.Host, c.options.FleetServer.Port, c.options.FleetServer.InternalPort, + c.options.FleetServer.Cert, c.options.FleetServer.CertKey, c.options.FleetServer.ElasticsearchCA, c.options.FleetServer.ElasticsearchCASHA256, c.options.FleetServer.Headers, c.options.ProxyURL, c.options.ProxyDisabled, @@ -401,6 +407,14 @@ func (c *enrollCmd) prepareFleetTLS() error { if c.options.URL == "" { return errors.New("url is required when a certificate is provided") } + + if c.options.FleetServer.InternalPort > 0 { + if c.options.FleetServer.InternalPort != defaultFleetServerInternalPort { + c.log.Warnf("Internal endpoint configured to: %d. Changing this value is not supported.", c.options.FleetServer.InternalPort) + } + c.options.InternalURL = fmt.Sprintf("%s:%d", defaultFleetServerInternalHost, c.options.FleetServer.InternalPort) + } + return nil } @@ -504,8 +518,8 @@ func (c *enrollCmd) enroll(ctx context.Context, persistentConfig map[string]inte serverConfig, err := createFleetServerBootstrapConfig( c.options.FleetServer.ConnStr, c.options.FleetServer.ServiceToken, c.options.FleetServer.PolicyID, - c.options.FleetServer.Host, c.options.FleetServer.Port, - c.options.FleetServer.Cert, c.options.FleetServer.CertKey, c.options.FleetServer.ElasticsearchCA, + c.options.FleetServer.Host, c.options.FleetServer.Port, c.options.FleetServer.InternalPort, + c.options.FleetServer.Cert, c.options.FleetServer.CertKey, c.options.FleetServer.ElasticsearchCA, c.options.FleetServer.ElasticsearchCASHA256, c.options.FleetServer.Headers, c.options.ProxyURL, c.options.ProxyDisabled, c.options.ProxyHeaders, c.options.FleetServer.ElasticsearchInsecure, @@ -516,6 +530,10 @@ func (c *enrollCmd) enroll(ctx context.Context, persistentConfig map[string]inte // no longer need bootstrap at this point serverConfig.Server.Bootstrap = false fleetConfig.Server = serverConfig.Server + // use internal URL for future requests + if c.options.InternalURL != "" { + fleetConfig.Client.Host = c.options.InternalURL + } } configToStore := map[string]interface{}{ @@ -836,8 +854,8 @@ func storeAgentInfo(s saver, reader io.Reader) error { func createFleetServerBootstrapConfig( connStr, serviceToken, policyID, host string, - port uint16, - cert, key, esCA string, + port uint16, internalPort uint16, + cert, key, esCA, esCASHA256 string, headers map[string]string, proxyURL string, proxyDisabled bool, @@ -859,12 +877,24 @@ func createFleetServerBootstrapConfig( es.TLS.CAs = []string{esCA} } } + if esCASHA256 != "" { + if es.TLS == nil { + es.TLS = &tlscommon.Config{ + CATrustedFingerprint: esCASHA256, + } + } else { + es.TLS.CATrustedFingerprint = esCASHA256 + } + } if host == "" { host = defaultFleetServerHost } if port == 0 { port = defaultFleetServerPort } + if internalPort == 0 { + internalPort = defaultFleetServerInternalPort + } if len(headers) > 0 { if es.Headers == nil { es.Headers = make(map[string]string) @@ -888,6 +918,7 @@ func createFleetServerBootstrapConfig( Host: host, Port: port, } + if policyID != "" { cfg.Server.Policy = &configuration.FleetServerPolicyConfig{ID: policyID} } @@ -905,6 +936,7 @@ func createFleetServerBootstrapConfig( if localFleetServer { cfg.Client.Transport.Proxy.Disable = true + cfg.Server.InternalPort = internalPort } if err := cfg.Valid(); err != nil { diff --git a/x-pack/elastic-agent/pkg/agent/cmd/enroll_cmd_test.go b/x-pack/elastic-agent/pkg/agent/cmd/enroll_cmd_test.go index d5820275371..17bcbcedd25 100644 --- a/x-pack/elastic-agent/pkg/agent/cmd/enroll_cmd_test.go +++ b/x-pack/elastic-agent/pkg/agent/cmd/enroll_cmd_test.go @@ -157,8 +157,6 @@ func TestEnroll(t *testing.T) { require.NoError(t, err) require.Equal(t, "my-access-api-key", config.AccessAPIKey) require.Equal(t, host, config.Client.Host) - require.Equal(t, "", config.Client.Username) - require.Equal(t, "", config.Client.Password) }, )) @@ -217,8 +215,6 @@ func TestEnroll(t *testing.T) { require.NoError(t, err) require.Equal(t, "my-access-api-key", config.AccessAPIKey) require.Equal(t, host, config.Client.Host) - require.Equal(t, "", config.Client.Username) - require.Equal(t, "", config.Client.Password) }, )) @@ -277,8 +273,6 @@ func TestEnroll(t *testing.T) { require.NoError(t, err) require.Equal(t, "my-access-api-key", config.AccessAPIKey) require.Equal(t, host, config.Client.Host) - require.Equal(t, "", config.Client.Username) - require.Equal(t, "", config.Client.Password) }, )) diff --git a/x-pack/elastic-agent/pkg/agent/cmd/run.go b/x-pack/elastic-agent/pkg/agent/cmd/run.go index 56a41e06895..7f10f9faa31 100644 --- a/x-pack/elastic-agent/pkg/agent/cmd/run.go +++ b/x-pack/elastic-agent/pkg/agent/cmd/run.go @@ -142,12 +142,13 @@ func run(streams *cli.IOStreams, override cfgOverrider) error { } defer control.Stop() - app, err := application.New(logger, pathConfigFile, rex, statusCtrl, control, agentInfo) + app, err := application.New(logger, rex, statusCtrl, control, agentInfo) if err != nil { return err } control.SetRouteFn(app.Routes) + control.SetMonitoringCfg(cfg.Settings.MonitoringConfig) serverStopFn, err := setupMetrics(agentInfo, logger, cfg.Settings.DownloadConfig.OS(), cfg.Settings.MonitoringConfig, app) if err != nil { @@ -313,6 +314,10 @@ func setupMetrics(agentInfo *info.AgentInfo, logger *logger.Logger, operatingSys } s.Start() + if cfg.Pprof != nil && cfg.Pprof.Enabled { + s.AttachPprof() + } + // return server stopper return s.Stop, nil } diff --git a/x-pack/elastic-agent/pkg/agent/cmd/setup_config.go b/x-pack/elastic-agent/pkg/agent/cmd/setup_config.go index 6b7e1edf8b3..ab163f4b5e7 100644 --- a/x-pack/elastic-agent/pkg/agent/cmd/setup_config.go +++ b/x-pack/elastic-agent/pkg/agent/cmd/setup_config.go @@ -40,12 +40,11 @@ type fleetServerConfig struct { } type elasticsearchConfig struct { - CA string `config:"ca"` - Host string `config:"host"` - Username string `config:"username"` - Password string `config:"password"` - ServiceToken string `config:"service_token"` - Insecure bool `config:"insecure"` + CA string `config:"ca"` + CATrustedFingerprint string `config:"ca_trusted_fingerprint"` + Host string `config:"host"` + ServiceToken string `config:"service_token"` + Insecure bool `config:"insecure"` } type kibanaConfig struct { @@ -58,9 +57,9 @@ type kibanaConfig struct { type kibanaFleetConfig struct { CA string `config:"ca"` Host string `config:"host"` - Password string `config:"password"` Setup bool `config:"setup"` Username string `config:"username"` + Password string `config:"password"` ServiceToken string `config:"service_token"` } @@ -91,12 +90,11 @@ func defaultAccessConfig() (setupConfig, error) { Cert: envWithDefault("", "FLEET_SERVER_CERT"), CertKey: envWithDefault("", "FLEET_SERVER_CERT_KEY"), Elasticsearch: elasticsearchConfig{ - Host: envWithDefault("http://elasticsearch:9200", "FLEET_SERVER_ELASTICSEARCH_HOST", "ELASTICSEARCH_HOST"), - Username: envWithDefault("elastic", "FLEET_SERVER_ELASTICSEARCH_USERNAME", "ELASTICSEARCH_USERNAME"), - Password: envWithDefault("changeme", "FLEET_SERVER_ELASTICSEARCH_PASSWORD", "ELASTICSEARCH_PASSWORD"), - ServiceToken: envWithDefault("", "FLEET_SERVER_SERVICE_TOKEN"), - CA: envWithDefault("", "FLEET_SERVER_ELASTICSEARCH_CA", "ELASTICSEARCH_CA"), - Insecure: envBool("FLEET_SERVER_ELASTICSEARCH_INSECURE"), + Host: envWithDefault("http://elasticsearch:9200", "FLEET_SERVER_ELASTICSEARCH_HOST", "ELASTICSEARCH_HOST"), + ServiceToken: envWithDefault("", "FLEET_SERVER_SERVICE_TOKEN"), + CA: envWithDefault("", "FLEET_SERVER_ELASTICSEARCH_CA", "ELASTICSEARCH_CA"), + CATrustedFingerprint: envWithDefault("", "FLEET_SERVER_ELASTICSEARCH_CA_TRUSTED_FINGERPRINT"), + Insecure: envBool("FLEET_SERVER_ELASTICSEARCH_INSECURE"), }, Enable: envBool("FLEET_SERVER_ENABLE"), Host: envWithDefault("", "FLEET_SERVER_HOST"), @@ -108,13 +106,10 @@ func defaultAccessConfig() (setupConfig, error) { }, Kibana: kibanaConfig{ Fleet: kibanaFleetConfig{ - // Remove FLEET_SETUP in 8.x - // The FLEET_SETUP environment variable boolean is a fallback to the old name. The name was updated to - // reflect that its setting up Fleet in Kibana versus setting up Fleet Server. - Setup: envBool("KIBANA_FLEET_SETUP", "FLEET_SETUP"), + Setup: envBool("KIBANA_FLEET_SETUP"), Host: envWithDefault("http://kibana:5601", "KIBANA_FLEET_HOST", "KIBANA_HOST"), - Username: envWithDefault("elastic", "KIBANA_FLEET_USERNAME", "KIBANA_USERNAME", "ELASTICSEARCH_USERNAME"), - Password: envWithDefault("changeme", "KIBANA_FLEET_PASSWORD", "KIBANA_PASSWORD", "ELASTICSEARCH_PASSWORD"), + Username: envWithDefault("elastic", "KIBANA_FLEET_USERNAME", "ELASTICSEARCH_USERNAME"), + Password: envWithDefault("changeme", "KIBANA_FLEET_PASSWORD", "ELASTICSEARCH_PASSWORD"), ServiceToken: envWithDefault("", "KIBANA_FLEET_SERVICE_TOKEN", "FLEET_SERVER_SERVICE_TOKEN"), CA: envWithDefault("", "KIBANA_FLEET_CA", "KIBANA_CA", "ELASTICSEARCH_CA"), }, diff --git a/x-pack/elastic-agent/pkg/agent/cmd/watch.go b/x-pack/elastic-agent/pkg/agent/cmd/watch.go index 2904d836108..6ee05c40932 100644 --- a/x-pack/elastic-agent/pkg/agent/cmd/watch.go +++ b/x-pack/elastic-agent/pkg/agent/cmd/watch.go @@ -95,7 +95,7 @@ func watchCmd(streams *cli.IOStreams, cmd *cobra.Command, args []string) error { ctx := context.Background() if err := watch(ctx, tilGrace, log); err != nil { - log.Debugf("Error detected proceeding to rollback", err) + log.Debugf("Error detected proceeding to rollback: %v", err) err = upgrade.Rollback(ctx, marker.PrevHash, marker.Hash) if err != nil { log.Error("rollback failed", err) diff --git a/x-pack/elastic-agent/pkg/agent/configuration/fleet_server.go b/x-pack/elastic-agent/pkg/agent/configuration/fleet_server.go index 25298c6e2b5..5a4e135afae 100644 --- a/x-pack/elastic-agent/pkg/agent/configuration/fleet_server.go +++ b/x-pack/elastic-agent/pkg/agent/configuration/fleet_server.go @@ -13,12 +13,13 @@ import ( // FleetServerConfig is the configuration written so Elastic Agent can run Fleet Server. type FleetServerConfig struct { - Bootstrap bool `config:"bootstrap" yaml:"bootstrap,omitempty"` - Policy *FleetServerPolicyConfig `config:"policy" yaml:"policy,omitempty"` - Output FleetServerOutputConfig `config:"output" yaml:"output,omitempty"` - Host string `config:"host" yaml:"host,omitempty"` - Port uint16 `config:"port" yaml:"port,omitempty"` - TLS *tlscommon.Config `config:"ssl" yaml:"ssl,omitempty"` + Bootstrap bool `config:"bootstrap" yaml:"bootstrap,omitempty"` + Policy *FleetServerPolicyConfig `config:"policy" yaml:"policy,omitempty"` + Output FleetServerOutputConfig `config:"output" yaml:"output,omitempty"` + Host string `config:"host" yaml:"host,omitempty"` + Port uint16 `config:"port" yaml:"port,omitempty"` + InternalPort uint16 `config:"internal_port" yaml:"internal_port,omitempty"` + TLS *tlscommon.Config `config:"ssl" yaml:"ssl,omitempty"` } // FleetServerPolicyConfig is the configuration for the policy Fleet Server should run on. @@ -36,8 +37,6 @@ type Elasticsearch struct { Protocol string `config:"protocol" yaml:"protocol"` Hosts []string `config:"hosts" yaml:"hosts"` Path string `config:"path" yaml:"path,omitempty"` - Username string `config:"username" yaml:"username,omitempty"` - Password string `config:"password" yaml:"password,omitempty"` ServiceToken string `config:"service_token" yaml:"service_token,omitempty"` TLS *tlscommon.Config `config:"ssl" yaml:"ssl,omitempty"` Headers map[string]string `config:"headers" yaml:"headers,omitempty"` @@ -69,18 +68,9 @@ func ElasticsearchFromConnStr(conn string, serviceToken string, insecure bool) ( VerificationMode: tlscommon.VerifyNone, } } - if serviceToken != "" { - cfg.ServiceToken = serviceToken - return cfg, nil + if serviceToken == "" { + return Elasticsearch{}, errors.New("invalid connection string: must include a service token") } - if u.User == nil || u.User.Username() == "" { - return Elasticsearch{}, errors.New("invalid connection string: must include a username unless a service token is provided") - } - password, ok := u.User.Password() - if !ok { - return Elasticsearch{}, errors.New("invalid connection string: must include a password unless a service token is provided") - } - cfg.Username = u.User.Username() - cfg.Password = password + cfg.ServiceToken = serviceToken return cfg, nil } diff --git a/x-pack/elastic-agent/pkg/agent/control/client/client.go b/x-pack/elastic-agent/pkg/agent/control/client/client.go index f7332b9896e..900718bc6a6 100644 --- a/x-pack/elastic-agent/pkg/agent/control/client/client.go +++ b/x-pack/elastic-agent/pkg/agent/control/client/client.go @@ -72,6 +72,14 @@ type ProcMeta struct { Error string } +// ProcPProf returns pprof data for a process. +type ProcPProf struct { + Name string + RouteKey string + Result []byte + Error string +} + // AgentStatus is the current status of the Elastic Agent. type AgentStatus struct { Status Status @@ -95,6 +103,8 @@ type Client interface { Upgrade(ctx context.Context, version string, sourceURI string) (string, error) // ProcMeta gathers running process meta-data. ProcMeta(ctx context.Context) ([]ProcMeta, error) + // Pprof gathers data from the /debug/pprof/ endpoints specified. + Pprof(ctx context.Context, d time.Duration, pprofTypes []proto.PprofOption, appName, routeKey string) (map[string][]ProcPProf, error) } // client manages the state and communication to the Elastic Agent. @@ -247,3 +257,29 @@ func (c *client) ProcMeta(ctx context.Context) ([]ProcMeta, error) { } return procMeta, nil } + +// Pprof gathers /debug/pprof data and returns a map of pprof-type: ProcPProf data +func (c *client) Pprof(ctx context.Context, d time.Duration, pprofTypes []proto.PprofOption, appName, routeKey string) (map[string][]ProcPProf, error) { + resp, err := c.client.Pprof(ctx, &proto.PprofRequest{ + PprofType: pprofTypes, + TraceDuration: d.String(), + AppName: appName, + RouteKey: routeKey, + }) + if err != nil { + return nil, err + } + res := map[string][]ProcPProf{} + for _, pType := range pprofTypes { + res[pType.String()] = make([]ProcPProf, 0) + } + for _, r := range resp.Results { + res[r.PprofType.String()] = append(res[r.PprofType.String()], ProcPProf{ + Name: r.AppName, + RouteKey: r.RouteKey, + Result: r.Result, + Error: r.Error, + }) + } + return res, nil +} diff --git a/x-pack/elastic-agent/pkg/agent/control/proto/control.pb.go b/x-pack/elastic-agent/pkg/agent/control/proto/control.pb.go index 2cdec52cf65..70c66acd4ab 100644 --- a/x-pack/elastic-agent/pkg/agent/control/proto/control.pb.go +++ b/x-pack/elastic-agent/pkg/agent/control/proto/control.pb.go @@ -143,6 +143,74 @@ func (ActionStatus) EnumDescriptor() ([]byte, []int) { return file_control_proto_rawDescGZIP(), []int{1} } +// pprof endpoint that can be requested. +type PprofOption int32 + +const ( + PprofOption_ALLOCS PprofOption = 0 + PprofOption_BLOCK PprofOption = 1 + PprofOption_CMDLINE PprofOption = 2 + PprofOption_GOROUTINE PprofOption = 3 + PprofOption_HEAP PprofOption = 4 + PprofOption_MUTEX PprofOption = 5 + PprofOption_PROFILE PprofOption = 6 + PprofOption_THREADCREATE PprofOption = 7 + PprofOption_TRACE PprofOption = 8 +) + +// Enum value maps for PprofOption. +var ( + PprofOption_name = map[int32]string{ + 0: "ALLOCS", + 1: "BLOCK", + 2: "CMDLINE", + 3: "GOROUTINE", + 4: "HEAP", + 5: "MUTEX", + 6: "PROFILE", + 7: "THREADCREATE", + 8: "TRACE", + } + PprofOption_value = map[string]int32{ + "ALLOCS": 0, + "BLOCK": 1, + "CMDLINE": 2, + "GOROUTINE": 3, + "HEAP": 4, + "MUTEX": 5, + "PROFILE": 6, + "THREADCREATE": 7, + "TRACE": 8, + } +) + +func (x PprofOption) Enum() *PprofOption { + p := new(PprofOption) + *p = x + return p +} + +func (x PprofOption) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (PprofOption) Descriptor() protoreflect.EnumDescriptor { + return file_control_proto_enumTypes[2].Descriptor() +} + +func (PprofOption) Type() protoreflect.EnumType { + return &file_control_proto_enumTypes[2] +} + +func (x PprofOption) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use PprofOption.Descriptor instead. +func (PprofOption) EnumDescriptor() ([]byte, []int) { + return file_control_proto_rawDescGZIP(), []int{2} +} + // Empty message. type Empty struct { state protoimpl.MessageState @@ -807,6 +875,210 @@ func (x *ProcMetaResponse) GetProcs() []*ProcMeta { return nil } +// PprofRequest is a request for pprof data from and http/pprof endpoint. +type PprofRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // The profiles that are requested + PprofType []PprofOption `protobuf:"varint,1,rep,packed,name=pprofType,proto3,enum=proto.PprofOption" json:"pprofType,omitempty"` + // A string representing a time.Duration to apply to trace, and profile options. + TraceDuration string `protobuf:"bytes,2,opt,name=traceDuration,proto3" json:"traceDuration,omitempty"` + // The application that will be profiled, if empty all applications are profiled. + AppName string `protobuf:"bytes,3,opt,name=appName,proto3" json:"appName,omitempty"` + // The route key to match for profiling, if empty all are profiled. + RouteKey string `protobuf:"bytes,4,opt,name=routeKey,proto3" json:"routeKey,omitempty"` +} + +func (x *PprofRequest) Reset() { + *x = PprofRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_control_proto_msgTypes[9] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *PprofRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PprofRequest) ProtoMessage() {} + +func (x *PprofRequest) ProtoReflect() protoreflect.Message { + mi := &file_control_proto_msgTypes[9] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PprofRequest.ProtoReflect.Descriptor instead. +func (*PprofRequest) Descriptor() ([]byte, []int) { + return file_control_proto_rawDescGZIP(), []int{9} +} + +func (x *PprofRequest) GetPprofType() []PprofOption { + if x != nil { + return x.PprofType + } + return nil +} + +func (x *PprofRequest) GetTraceDuration() string { + if x != nil { + return x.TraceDuration + } + return "" +} + +func (x *PprofRequest) GetAppName() string { + if x != nil { + return x.AppName + } + return "" +} + +func (x *PprofRequest) GetRouteKey() string { + if x != nil { + return x.RouteKey + } + return "" +} + +// PprofResult is the result of a pprof request for a given application/route key. +type PprofResult struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + AppName string `protobuf:"bytes,1,opt,name=appName,proto3" json:"appName,omitempty"` + RouteKey string `protobuf:"bytes,2,opt,name=routeKey,proto3" json:"routeKey,omitempty"` + PprofType PprofOption `protobuf:"varint,3,opt,name=pprofType,proto3,enum=proto.PprofOption" json:"pprofType,omitempty"` + Result []byte `protobuf:"bytes,4,opt,name=result,proto3" json:"result,omitempty"` + Error string `protobuf:"bytes,5,opt,name=error,proto3" json:"error,omitempty"` +} + +func (x *PprofResult) Reset() { + *x = PprofResult{} + if protoimpl.UnsafeEnabled { + mi := &file_control_proto_msgTypes[10] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *PprofResult) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PprofResult) ProtoMessage() {} + +func (x *PprofResult) ProtoReflect() protoreflect.Message { + mi := &file_control_proto_msgTypes[10] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PprofResult.ProtoReflect.Descriptor instead. +func (*PprofResult) Descriptor() ([]byte, []int) { + return file_control_proto_rawDescGZIP(), []int{10} +} + +func (x *PprofResult) GetAppName() string { + if x != nil { + return x.AppName + } + return "" +} + +func (x *PprofResult) GetRouteKey() string { + if x != nil { + return x.RouteKey + } + return "" +} + +func (x *PprofResult) GetPprofType() PprofOption { + if x != nil { + return x.PprofType + } + return PprofOption_ALLOCS +} + +func (x *PprofResult) GetResult() []byte { + if x != nil { + return x.Result + } + return nil +} + +func (x *PprofResult) GetError() string { + if x != nil { + return x.Error + } + return "" +} + +// PprofResponse is a wrapper to return all pprof responses. +type PprofResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Results []*PprofResult `protobuf:"bytes,1,rep,name=results,proto3" json:"results,omitempty"` +} + +func (x *PprofResponse) Reset() { + *x = PprofResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_control_proto_msgTypes[11] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *PprofResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PprofResponse) ProtoMessage() {} + +func (x *PprofResponse) ProtoReflect() protoreflect.Message { + mi := &file_control_proto_msgTypes[11] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PprofResponse.ProtoReflect.Descriptor instead. +func (*PprofResponse) Descriptor() ([]byte, []int) { + return file_control_proto_rawDescGZIP(), []int{11} +} + +func (x *PprofResponse) GetResults() []*PprofResult { + if x != nil { + return x.Results + } + return nil +} + var File_control_proto protoreflect.FileDescriptor var file_control_proto_rawDesc = []byte{ @@ -886,37 +1158,73 @@ var file_control_proto_rawDesc = []byte{ 0x10, 0x50, 0x72, 0x6f, 0x63, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x25, 0x0a, 0x05, 0x70, 0x72, 0x6f, 0x63, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x72, 0x6f, 0x63, 0x4d, 0x65, 0x74, - 0x61, 0x52, 0x05, 0x70, 0x72, 0x6f, 0x63, 0x73, 0x2a, 0x79, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, - 0x75, 0x73, 0x12, 0x0c, 0x0a, 0x08, 0x53, 0x54, 0x41, 0x52, 0x54, 0x49, 0x4e, 0x47, 0x10, 0x00, - 0x12, 0x0f, 0x0a, 0x0b, 0x43, 0x4f, 0x4e, 0x46, 0x49, 0x47, 0x55, 0x52, 0x49, 0x4e, 0x47, 0x10, - 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x48, 0x45, 0x41, 0x4c, 0x54, 0x48, 0x59, 0x10, 0x02, 0x12, 0x0c, - 0x0a, 0x08, 0x44, 0x45, 0x47, 0x52, 0x41, 0x44, 0x45, 0x44, 0x10, 0x03, 0x12, 0x0a, 0x0a, 0x06, - 0x46, 0x41, 0x49, 0x4c, 0x45, 0x44, 0x10, 0x04, 0x12, 0x0c, 0x0a, 0x08, 0x53, 0x54, 0x4f, 0x50, - 0x50, 0x49, 0x4e, 0x47, 0x10, 0x05, 0x12, 0x0d, 0x0a, 0x09, 0x55, 0x50, 0x47, 0x52, 0x41, 0x44, - 0x49, 0x4e, 0x47, 0x10, 0x06, 0x12, 0x0c, 0x0a, 0x08, 0x52, 0x4f, 0x4c, 0x4c, 0x42, 0x41, 0x43, - 0x4b, 0x10, 0x07, 0x2a, 0x28, 0x0a, 0x0c, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, - 0x74, 0x75, 0x73, 0x12, 0x0b, 0x0a, 0x07, 0x53, 0x55, 0x43, 0x43, 0x45, 0x53, 0x53, 0x10, 0x00, - 0x12, 0x0b, 0x0a, 0x07, 0x46, 0x41, 0x49, 0x4c, 0x55, 0x52, 0x45, 0x10, 0x01, 0x32, 0x93, 0x02, - 0x0a, 0x13, 0x45, 0x6c, 0x61, 0x73, 0x74, 0x69, 0x63, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x43, 0x6f, - 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x12, 0x2f, 0x0a, 0x07, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, - 0x12, 0x0c, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x16, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2d, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, - 0x12, 0x0c, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x15, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2f, 0x0a, 0x07, 0x52, 0x65, 0x73, 0x74, 0x61, 0x72, 0x74, - 0x12, 0x0c, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x16, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x52, 0x65, 0x73, 0x74, 0x61, 0x72, 0x74, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x38, 0x0a, 0x07, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, - 0x65, 0x12, 0x15, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, - 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x2e, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x31, 0x0a, 0x08, 0x50, 0x72, 0x6f, 0x63, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x0c, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x17, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x2e, 0x50, 0x72, 0x6f, 0x63, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x42, 0x22, 0x5a, 0x1d, 0x70, 0x6b, 0x67, 0x2f, 0x61, 0x67, 0x65, 0x6e, 0x74, - 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x3b, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0xf8, 0x01, 0x01, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x61, 0x52, 0x05, 0x70, 0x72, 0x6f, 0x63, 0x73, 0x22, 0x9c, 0x01, 0x0a, 0x0c, 0x50, 0x70, 0x72, + 0x6f, 0x66, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x30, 0x0a, 0x09, 0x70, 0x70, 0x72, + 0x6f, 0x66, 0x54, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0e, 0x32, 0x12, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x70, 0x72, 0x6f, 0x66, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, + 0x52, 0x09, 0x70, 0x70, 0x72, 0x6f, 0x66, 0x54, 0x79, 0x70, 0x65, 0x12, 0x24, 0x0a, 0x0d, 0x74, + 0x72, 0x61, 0x63, 0x65, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x0d, 0x74, 0x72, 0x61, 0x63, 0x65, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x70, 0x70, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x07, 0x61, 0x70, 0x70, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x72, + 0x6f, 0x75, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x72, + 0x6f, 0x75, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x22, 0xa3, 0x01, 0x0a, 0x0b, 0x50, 0x70, 0x72, 0x6f, + 0x66, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x70, 0x70, 0x4e, 0x61, + 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x70, 0x70, 0x4e, 0x61, 0x6d, + 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x08, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x12, 0x30, 0x0a, + 0x09, 0x70, 0x70, 0x72, 0x6f, 0x66, 0x54, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, + 0x32, 0x12, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x70, 0x72, 0x6f, 0x66, 0x4f, 0x70, + 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x09, 0x70, 0x70, 0x72, 0x6f, 0x66, 0x54, 0x79, 0x70, 0x65, 0x12, + 0x16, 0x0a, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, + 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, + 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x22, 0x3d, 0x0a, + 0x0d, 0x50, 0x70, 0x72, 0x6f, 0x66, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2c, + 0x0a, 0x07, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x12, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x70, 0x72, 0x6f, 0x66, 0x52, 0x65, 0x73, + 0x75, 0x6c, 0x74, 0x52, 0x07, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x2a, 0x79, 0x0a, 0x06, + 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x0c, 0x0a, 0x08, 0x53, 0x54, 0x41, 0x52, 0x54, 0x49, + 0x4e, 0x47, 0x10, 0x00, 0x12, 0x0f, 0x0a, 0x0b, 0x43, 0x4f, 0x4e, 0x46, 0x49, 0x47, 0x55, 0x52, + 0x49, 0x4e, 0x47, 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x48, 0x45, 0x41, 0x4c, 0x54, 0x48, 0x59, + 0x10, 0x02, 0x12, 0x0c, 0x0a, 0x08, 0x44, 0x45, 0x47, 0x52, 0x41, 0x44, 0x45, 0x44, 0x10, 0x03, + 0x12, 0x0a, 0x0a, 0x06, 0x46, 0x41, 0x49, 0x4c, 0x45, 0x44, 0x10, 0x04, 0x12, 0x0c, 0x0a, 0x08, + 0x53, 0x54, 0x4f, 0x50, 0x50, 0x49, 0x4e, 0x47, 0x10, 0x05, 0x12, 0x0d, 0x0a, 0x09, 0x55, 0x50, + 0x47, 0x52, 0x41, 0x44, 0x49, 0x4e, 0x47, 0x10, 0x06, 0x12, 0x0c, 0x0a, 0x08, 0x52, 0x4f, 0x4c, + 0x4c, 0x42, 0x41, 0x43, 0x4b, 0x10, 0x07, 0x2a, 0x28, 0x0a, 0x0c, 0x41, 0x63, 0x74, 0x69, 0x6f, + 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x0b, 0x0a, 0x07, 0x53, 0x55, 0x43, 0x43, 0x45, + 0x53, 0x53, 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x46, 0x41, 0x49, 0x4c, 0x55, 0x52, 0x45, 0x10, + 0x01, 0x2a, 0x7f, 0x0a, 0x0b, 0x50, 0x70, 0x72, 0x6f, 0x66, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, + 0x12, 0x0a, 0x0a, 0x06, 0x41, 0x4c, 0x4c, 0x4f, 0x43, 0x53, 0x10, 0x00, 0x12, 0x09, 0x0a, 0x05, + 0x42, 0x4c, 0x4f, 0x43, 0x4b, 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x43, 0x4d, 0x44, 0x4c, 0x49, + 0x4e, 0x45, 0x10, 0x02, 0x12, 0x0d, 0x0a, 0x09, 0x47, 0x4f, 0x52, 0x4f, 0x55, 0x54, 0x49, 0x4e, + 0x45, 0x10, 0x03, 0x12, 0x08, 0x0a, 0x04, 0x48, 0x45, 0x41, 0x50, 0x10, 0x04, 0x12, 0x09, 0x0a, + 0x05, 0x4d, 0x55, 0x54, 0x45, 0x58, 0x10, 0x05, 0x12, 0x0b, 0x0a, 0x07, 0x50, 0x52, 0x4f, 0x46, + 0x49, 0x4c, 0x45, 0x10, 0x06, 0x12, 0x10, 0x0a, 0x0c, 0x54, 0x48, 0x52, 0x45, 0x41, 0x44, 0x43, + 0x52, 0x45, 0x41, 0x54, 0x45, 0x10, 0x07, 0x12, 0x09, 0x0a, 0x05, 0x54, 0x52, 0x41, 0x43, 0x45, + 0x10, 0x08, 0x32, 0xc7, 0x02, 0x0a, 0x13, 0x45, 0x6c, 0x61, 0x73, 0x74, 0x69, 0x63, 0x41, 0x67, + 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x12, 0x2f, 0x0a, 0x07, 0x56, 0x65, + 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x0c, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x45, 0x6d, + 0x70, 0x74, 0x79, 0x1a, 0x16, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x56, 0x65, 0x72, 0x73, + 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2d, 0x0a, 0x06, 0x53, + 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x0c, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x45, 0x6d, + 0x70, 0x74, 0x79, 0x1a, 0x15, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x53, 0x74, 0x61, 0x74, + 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2f, 0x0a, 0x07, 0x52, 0x65, + 0x73, 0x74, 0x61, 0x72, 0x74, 0x12, 0x0c, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x45, 0x6d, + 0x70, 0x74, 0x79, 0x1a, 0x16, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x52, 0x65, 0x73, 0x74, + 0x61, 0x72, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x38, 0x0a, 0x07, 0x55, + 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x12, 0x15, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x55, + 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x31, 0x0a, 0x08, 0x50, 0x72, 0x6f, 0x63, 0x4d, 0x65, 0x74, + 0x61, 0x12, 0x0c, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, + 0x17, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x72, 0x6f, 0x63, 0x4d, 0x65, 0x74, 0x61, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x32, 0x0a, 0x05, 0x50, 0x70, 0x72, 0x6f, + 0x66, 0x12, 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x70, 0x72, 0x6f, 0x66, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x14, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, + 0x70, 0x72, 0x6f, 0x66, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x22, 0x5a, 0x1d, + 0x70, 0x6b, 0x67, 0x2f, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, + 0x6c, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x3b, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0xf8, 0x01, 0x01, + 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -931,43 +1239,52 @@ func file_control_proto_rawDescGZIP() []byte { return file_control_proto_rawDescData } -var file_control_proto_enumTypes = make([]protoimpl.EnumInfo, 2) -var file_control_proto_msgTypes = make([]protoimpl.MessageInfo, 9) +var file_control_proto_enumTypes = make([]protoimpl.EnumInfo, 3) +var file_control_proto_msgTypes = make([]protoimpl.MessageInfo, 12) var file_control_proto_goTypes = []interface{}{ (Status)(0), // 0: proto.Status (ActionStatus)(0), // 1: proto.ActionStatus - (*Empty)(nil), // 2: proto.Empty - (*VersionResponse)(nil), // 3: proto.VersionResponse - (*RestartResponse)(nil), // 4: proto.RestartResponse - (*UpgradeRequest)(nil), // 5: proto.UpgradeRequest - (*UpgradeResponse)(nil), // 6: proto.UpgradeResponse - (*ApplicationStatus)(nil), // 7: proto.ApplicationStatus - (*ProcMeta)(nil), // 8: proto.ProcMeta - (*StatusResponse)(nil), // 9: proto.StatusResponse - (*ProcMetaResponse)(nil), // 10: proto.ProcMetaResponse + (PprofOption)(0), // 2: proto.PprofOption + (*Empty)(nil), // 3: proto.Empty + (*VersionResponse)(nil), // 4: proto.VersionResponse + (*RestartResponse)(nil), // 5: proto.RestartResponse + (*UpgradeRequest)(nil), // 6: proto.UpgradeRequest + (*UpgradeResponse)(nil), // 7: proto.UpgradeResponse + (*ApplicationStatus)(nil), // 8: proto.ApplicationStatus + (*ProcMeta)(nil), // 9: proto.ProcMeta + (*StatusResponse)(nil), // 10: proto.StatusResponse + (*ProcMetaResponse)(nil), // 11: proto.ProcMetaResponse + (*PprofRequest)(nil), // 12: proto.PprofRequest + (*PprofResult)(nil), // 13: proto.PprofResult + (*PprofResponse)(nil), // 14: proto.PprofResponse } var file_control_proto_depIdxs = []int32{ 1, // 0: proto.RestartResponse.status:type_name -> proto.ActionStatus 1, // 1: proto.UpgradeResponse.status:type_name -> proto.ActionStatus 0, // 2: proto.ApplicationStatus.status:type_name -> proto.Status 0, // 3: proto.StatusResponse.status:type_name -> proto.Status - 7, // 4: proto.StatusResponse.applications:type_name -> proto.ApplicationStatus - 8, // 5: proto.ProcMetaResponse.procs:type_name -> proto.ProcMeta - 2, // 6: proto.ElasticAgentControl.Version:input_type -> proto.Empty - 2, // 7: proto.ElasticAgentControl.Status:input_type -> proto.Empty - 2, // 8: proto.ElasticAgentControl.Restart:input_type -> proto.Empty - 5, // 9: proto.ElasticAgentControl.Upgrade:input_type -> proto.UpgradeRequest - 2, // 10: proto.ElasticAgentControl.ProcMeta:input_type -> proto.Empty - 3, // 11: proto.ElasticAgentControl.Version:output_type -> proto.VersionResponse - 9, // 12: proto.ElasticAgentControl.Status:output_type -> proto.StatusResponse - 4, // 13: proto.ElasticAgentControl.Restart:output_type -> proto.RestartResponse - 6, // 14: proto.ElasticAgentControl.Upgrade:output_type -> proto.UpgradeResponse - 10, // 15: proto.ElasticAgentControl.ProcMeta:output_type -> proto.ProcMetaResponse - 11, // [11:16] is the sub-list for method output_type - 6, // [6:11] is the sub-list for method input_type - 6, // [6:6] is the sub-list for extension type_name - 6, // [6:6] is the sub-list for extension extendee - 0, // [0:6] is the sub-list for field type_name + 8, // 4: proto.StatusResponse.applications:type_name -> proto.ApplicationStatus + 9, // 5: proto.ProcMetaResponse.procs:type_name -> proto.ProcMeta + 2, // 6: proto.PprofRequest.pprofType:type_name -> proto.PprofOption + 2, // 7: proto.PprofResult.pprofType:type_name -> proto.PprofOption + 13, // 8: proto.PprofResponse.results:type_name -> proto.PprofResult + 3, // 9: proto.ElasticAgentControl.Version:input_type -> proto.Empty + 3, // 10: proto.ElasticAgentControl.Status:input_type -> proto.Empty + 3, // 11: proto.ElasticAgentControl.Restart:input_type -> proto.Empty + 6, // 12: proto.ElasticAgentControl.Upgrade:input_type -> proto.UpgradeRequest + 3, // 13: proto.ElasticAgentControl.ProcMeta:input_type -> proto.Empty + 12, // 14: proto.ElasticAgentControl.Pprof:input_type -> proto.PprofRequest + 4, // 15: proto.ElasticAgentControl.Version:output_type -> proto.VersionResponse + 10, // 16: proto.ElasticAgentControl.Status:output_type -> proto.StatusResponse + 5, // 17: proto.ElasticAgentControl.Restart:output_type -> proto.RestartResponse + 7, // 18: proto.ElasticAgentControl.Upgrade:output_type -> proto.UpgradeResponse + 11, // 19: proto.ElasticAgentControl.ProcMeta:output_type -> proto.ProcMetaResponse + 14, // 20: proto.ElasticAgentControl.Pprof:output_type -> proto.PprofResponse + 15, // [15:21] is the sub-list for method output_type + 9, // [9:15] is the sub-list for method input_type + 9, // [9:9] is the sub-list for extension type_name + 9, // [9:9] is the sub-list for extension extendee + 0, // [0:9] is the sub-list for field type_name } func init() { file_control_proto_init() } @@ -1084,14 +1401,50 @@ func file_control_proto_init() { return nil } } + file_control_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PprofRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_control_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PprofResult); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_control_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PprofResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } } type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_control_proto_rawDesc, - NumEnums: 2, - NumMessages: 9, + NumEnums: 3, + NumMessages: 12, NumExtensions: 0, NumServices: 1, }, @@ -1128,6 +1481,8 @@ type ElasticAgentControlClient interface { Upgrade(ctx context.Context, in *UpgradeRequest, opts ...grpc.CallOption) (*UpgradeResponse, error) // Gather all running process metadata. ProcMeta(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*ProcMetaResponse, error) + // Gather requested pprof data from specified applications. + Pprof(ctx context.Context, in *PprofRequest, opts ...grpc.CallOption) (*PprofResponse, error) } type elasticAgentControlClient struct { @@ -1183,6 +1538,15 @@ func (c *elasticAgentControlClient) ProcMeta(ctx context.Context, in *Empty, opt return out, nil } +func (c *elasticAgentControlClient) Pprof(ctx context.Context, in *PprofRequest, opts ...grpc.CallOption) (*PprofResponse, error) { + out := new(PprofResponse) + err := c.cc.Invoke(ctx, "/proto.ElasticAgentControl/Pprof", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + // ElasticAgentControlServer is the server API for ElasticAgentControl service. type ElasticAgentControlServer interface { // Fetches the currently running version of the Elastic Agent. @@ -1195,6 +1559,8 @@ type ElasticAgentControlServer interface { Upgrade(context.Context, *UpgradeRequest) (*UpgradeResponse, error) // Gather all running process metadata. ProcMeta(context.Context, *Empty) (*ProcMetaResponse, error) + // Gather requested pprof data from specified applications. + Pprof(context.Context, *PprofRequest) (*PprofResponse, error) } // UnimplementedElasticAgentControlServer can be embedded to have forward compatible implementations. @@ -1216,6 +1582,9 @@ func (*UnimplementedElasticAgentControlServer) Upgrade(context.Context, *Upgrade func (*UnimplementedElasticAgentControlServer) ProcMeta(context.Context, *Empty) (*ProcMetaResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method ProcMeta not implemented") } +func (*UnimplementedElasticAgentControlServer) Pprof(context.Context, *PprofRequest) (*PprofResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method Pprof not implemented") +} func RegisterElasticAgentControlServer(s *grpc.Server, srv ElasticAgentControlServer) { s.RegisterService(&_ElasticAgentControl_serviceDesc, srv) @@ -1311,6 +1680,24 @@ func _ElasticAgentControl_ProcMeta_Handler(srv interface{}, ctx context.Context, return interceptor(ctx, in, info, handler) } +func _ElasticAgentControl_Pprof_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(PprofRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ElasticAgentControlServer).Pprof(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/proto.ElasticAgentControl/Pprof", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ElasticAgentControlServer).Pprof(ctx, req.(*PprofRequest)) + } + return interceptor(ctx, in, info, handler) +} + var _ElasticAgentControl_serviceDesc = grpc.ServiceDesc{ ServiceName: "proto.ElasticAgentControl", HandlerType: (*ElasticAgentControlServer)(nil), @@ -1335,6 +1722,10 @@ var _ElasticAgentControl_serviceDesc = grpc.ServiceDesc{ MethodName: "ProcMeta", Handler: _ElasticAgentControl_ProcMeta_Handler, }, + { + MethodName: "Pprof", + Handler: _ElasticAgentControl_Pprof_Handler, + }, }, Streams: []grpc.StreamDesc{}, Metadata: "control.proto", diff --git a/x-pack/elastic-agent/pkg/agent/control/server/server.go b/x-pack/elastic-agent/pkg/agent/control/server/server.go index 072b212a771..12ed4650eed 100644 --- a/x-pack/elastic-agent/pkg/agent/control/server/server.go +++ b/x-pack/elastic-agent/pkg/agent/control/server/server.go @@ -7,6 +7,8 @@ package server import ( "context" "encoding/json" + "fmt" + "io" "net" "net/http" "runtime" @@ -23,7 +25,9 @@ import ( "github.com/elastic/beats/v7/x-pack/elastic-agent/pkg/agent/errors" "github.com/elastic/beats/v7/x-pack/elastic-agent/pkg/agent/program" "github.com/elastic/beats/v7/x-pack/elastic-agent/pkg/core/logger" + "github.com/elastic/beats/v7/x-pack/elastic-agent/pkg/core/monitoring/beats" monitoring "github.com/elastic/beats/v7/x-pack/elastic-agent/pkg/core/monitoring/beats" + monitoringCfg "github.com/elastic/beats/v7/x-pack/elastic-agent/pkg/core/monitoring/config" "github.com/elastic/beats/v7/x-pack/elastic-agent/pkg/core/socket" "github.com/elastic/beats/v7/x-pack/elastic-agent/pkg/core/status" "github.com/elastic/beats/v7/x-pack/elastic-agent/pkg/fleetapi" @@ -33,20 +37,27 @@ import ( // Server is the daemon side of the control protocol. type Server struct { - logger *logger.Logger - rex reexec.ExecManager - statusCtrl status.Controller - up *upgrade.Upgrader - routeFn func() *sorted.Set - listener net.Listener - server *grpc.Server - lock sync.RWMutex + logger *logger.Logger + rex reexec.ExecManager + statusCtrl status.Controller + up *upgrade.Upgrader + routeFn func() *sorted.Set + monitoringCfg *monitoringCfg.MonitoringConfig + listener net.Listener + server *grpc.Server + lock sync.RWMutex } type specer interface { Specs() map[string]program.Spec } +type specInfo struct { + spec program.Spec + app string + rk string +} + // New creates a new control protocol server. func New(log *logger.Logger, rex reexec.ExecManager, statusCtrl status.Controller, up *upgrade.Upgrader) *Server { return &Server{ @@ -71,6 +82,14 @@ func (s *Server) SetRouteFn(routesFetchFn func() *sorted.Set) { s.routeFn = routesFetchFn } +// SetMonitoringCfg sets a reference to the monitoring config used by the running agent. +// the controller references this config to find out if pprof is enabled for the agent or not +func (s *Server) SetMonitoringCfg(cfg *monitoringCfg.MonitoringConfig) { + s.lock.Lock() + defer s.lock.Unlock() + s.monitoringCfg = cfg +} + // Start starts the GRPC endpoint and accepts new connections. func (s *Server) Start() error { if s.server != nil { @@ -194,84 +213,273 @@ func (s *Server) ProcMeta(ctx context.Context, _ *proto.Empty) (*proto.ProcMetaR Procs: []*proto.ProcMeta{}, } + // gather spec data for all rk/apps running + specs := s.getSpecInfo("", "") + for _, si := range specs { + endpoint := monitoring.MonitoringEndpoint(si.spec, runtime.GOOS, si.rk) + client := newSocketRequester(si.app, si.rk, endpoint) + + procMeta := client.procMeta(ctx) + resp.Procs = append(resp.Procs, procMeta) + } + + return resp, nil +} + +// Pprof returns /debug/pprof data for the requested applicaiont-route_key or all running applications. +func (s *Server) Pprof(ctx context.Context, req *proto.PprofRequest) (*proto.PprofResponse, error) { + if s.monitoringCfg == nil || s.monitoringCfg.Pprof == nil || !s.monitoringCfg.Pprof.Enabled { + return nil, fmt.Errorf("agent.monitoring.pprof disabled") + } + + if s.routeFn == nil { + return nil, errors.New("route function is nil") + } + + dur, err := time.ParseDuration(req.TraceDuration) + if err != nil { + return nil, fmt.Errorf("unable to parse trace duration: %w", err) + } + + resp := &proto.PprofResponse{ + Results: []*proto.PprofResult{}, + } + + var wg sync.WaitGroup + ch := make(chan *proto.PprofResult, 1) + + // retrieve elastic-agent pprof data if requested or application is unspecified. + if req.AppName == "" || req.AppName == "elastic-agent" { + endpoint := beats.AgentMonitoringEndpoint(runtime.GOOS, s.monitoringCfg.HTTP) + c := newSocketRequester("elastic-agent", "", endpoint) + for _, opt := range req.PprofType { + wg.Add(1) + go func(opt proto.PprofOption) { + res := c.getPprof(ctx, opt, dur) + ch <- res + wg.Done() + }(opt) + } + } + + // get requested rk/appname spec or all specs + var specs []specInfo + if req.AppName != "elastic-agent" { + specs = s.getSpecInfo(req.RouteKey, req.AppName) + } + for _, si := range specs { + endpoint := monitoring.MonitoringEndpoint(si.spec, runtime.GOOS, si.rk) + c := newSocketRequester(si.app, si.rk, endpoint) + // Launch a concurrent goroutine to gather all pprof endpoints from a socket. + for _, opt := range req.PprofType { + wg.Add(1) + go func(opt proto.PprofOption) { + res := c.getPprof(ctx, opt, dur) + ch <- res + wg.Done() + }(opt) + } + } + + // wait for the waitgroup to be done and close the channel + go func() { + wg.Wait() + close(ch) + }() + + // gather all results from channel until closed. + for res := range ch { + resp.Results = append(resp.Results, res) + } + return resp, nil +} + +// getSpecs will return the specs for the program associated with the specified route key/app name, or all programs if no key(s) are specified. +// if matchRK or matchApp are empty all results will be returned. +func (s *Server) getSpecInfo(matchRK, matchApp string) []specInfo { routes := s.routeFn() + + // find specInfo for a specified rk/app + if matchRK != "" && matchApp != "" { + programs, ok := routes.Get(matchRK) + if !ok { + s.logger.With("route_key", matchRK).Debug("No matching route key found.") + return []specInfo{} + } + sp, ok := programs.(specer) + if !ok { + s.logger.With("route_key", matchRK, "route", programs).Warn("Unable to cast route as specer.") + return []specInfo{} + } + specs := sp.Specs() + + spec, ok := specs[matchApp] + if !ok { + s.logger.With("route_key", matchRK, "application_name", matchApp).Debug("No matching route key/application name found.") + return []specInfo{} + } + return []specInfo{specInfo{spec: spec, app: matchApp, rk: matchRK}} + } + + // gather specInfo for all rk/app values + res := make([]specInfo, 0) for _, rk := range routes.Keys() { programs, ok := routes.Get(rk) if !ok { + // we do not expect to ever hit this code path + // if this log message occurs then the agent is unable to access one of the keys that is returned by the route function + // might be a race condition if someone tries to update the policy to remove an output? s.logger.With("route_key", rk).Warn("Unable to retrieve route.") continue } - sp, ok := programs.(specer) if !ok { - s.logger.With("route_key", rk, "route", programs).Warn("Unable to cast route as specer.") + s.logger.With("route_key", matchRK, "route", programs).Warn("Unable to cast route as specer.") continue } - specs := sp.Specs() + for n, spec := range sp.Specs() { + res = append(res, specInfo{ + rk: rk, + app: n, + spec: spec, + }) + } + } + return res +} + +// socketRequester is a struct to gather (diagnostics) data from a socket opened by elastic-agent or one if it's processes +type socketRequester struct { + c http.Client + endpoint string + appName string + routeKey string +} - for n, spec := range specs { - procMeta := &proto.ProcMeta{ - Name: n, - RouteKey: rk, - } - - client := http.Client{ - Timeout: time.Second * 5, - } - endpoint := monitoring.MonitoringEndpoint(spec, runtime.GOOS, rk) - if strings.HasPrefix(endpoint, "unix://") { - client.Transport = &http.Transport{ - Proxy: nil, - DialContext: socket.DialContext(strings.TrimPrefix(endpoint, "unix://")), - } - endpoint = "unix" - } else if strings.HasPrefix(endpoint, "npipe://") { - client.Transport = &http.Transport{ - Proxy: nil, - DialContext: socket.DialContext(strings.TrimPrefix(endpoint, "npipe:///")), - } - endpoint = "npipe" - } - - res, err := client.Get("http://" + endpoint + "/") - if err != nil { - procMeta.Error = err.Error() - resp.Procs = append(resp.Procs, procMeta) - continue - } - if res.StatusCode != 200 { - procMeta.Error = "response status is: " + res.Status - resp.Procs = append(resp.Procs, procMeta) - continue - } - - bi := &BeatInfo{} - dec := json.NewDecoder(res.Body) - if err := dec.Decode(bi); err != nil { - res.Body.Close() - procMeta.Error = err.Error() - resp.Procs = append(resp.Procs, procMeta) - continue - } - res.Body.Close() - - procMeta.Process = bi.Beat - procMeta.Hostname = bi.Hostname - procMeta.Id = bi.ID - procMeta.EphemeralId = bi.EphemeralID - procMeta.Version = bi.Version - procMeta.BuildCommit = bi.Commit - procMeta.BuildTime = bi.Time - procMeta.Username = bi.Username - procMeta.UserId = bi.UserID - procMeta.UserGid = bi.GroupID - procMeta.Architecture = bi.BinaryArch - procMeta.ElasticLicensed = bi.ElasticLicensed - - resp.Procs = append(resp.Procs, procMeta) +func newSocketRequester(appName, routeKey, endpoint string) *socketRequester { + c := http.Client{} + if strings.HasPrefix(endpoint, "unix://") { + c.Transport = &http.Transport{ + Proxy: nil, + DialContext: socket.DialContext(strings.TrimPrefix(endpoint, "unix://")), + } + endpoint = "unix" + } else if strings.HasPrefix(endpoint, "npipe://") { + c.Transport = &http.Transport{ + Proxy: nil, + DialContext: socket.DialContext(strings.TrimPrefix(endpoint, "npipe:///")), } + endpoint = "npipe" } - return resp, nil + return &socketRequester{ + c: c, + appName: appName, + routeKey: routeKey, + endpoint: endpoint, + } +} + +// getPath creates a get request for the specified path. +// Will return an error if that status code is not 200. +func (r *socketRequester) getPath(ctx context.Context, path string) (*http.Response, error) { + req, err := http.NewRequest("GET", "http://"+r.endpoint+path, nil) + if err != nil { + return nil, err + } + req = req.WithContext(ctx) + res, err := r.c.Do(req) + if err != nil { + return nil, err + } + if res.StatusCode != 200 { + res.Body.Close() + return nil, fmt.Errorf("response status is %d", res.StatusCode) + } + return res, nil + +} + +// procMeta will return process metadata by querying the "/" path. +func (r *socketRequester) procMeta(ctx context.Context) *proto.ProcMeta { + pm := &proto.ProcMeta{ + Name: r.appName, + RouteKey: r.routeKey, + } + + res, err := r.getPath(ctx, "/") + if err != nil { + pm.Error = err.Error() + return pm + } + defer res.Body.Close() + + bi := &BeatInfo{} + dec := json.NewDecoder(res.Body) + if err := dec.Decode(bi); err != nil { + pm.Error = err.Error() + return pm + } + + pm.Process = bi.Beat + pm.Hostname = bi.Hostname + pm.Id = bi.ID + pm.EphemeralId = bi.EphemeralID + pm.Version = bi.Version + pm.BuildCommit = bi.Commit + pm.BuildTime = bi.Time + pm.Username = bi.Username + pm.UserId = bi.UserID + pm.UserGid = bi.GroupID + pm.Architecture = bi.BinaryArch + pm.ElasticLicensed = bi.ElasticLicensed + + return pm +} + +var pprofEndpoints = map[proto.PprofOption]string{ + proto.PprofOption_ALLOCS: "/debug/pprof/allocs", + proto.PprofOption_BLOCK: "/debug/pprof/block", + proto.PprofOption_CMDLINE: "/debug/pprof/cmdline", + proto.PprofOption_GOROUTINE: "/debug/pprof/goroutine", + proto.PprofOption_HEAP: "/debug/pprof/heap", + proto.PprofOption_MUTEX: "/debug/pprof/mutex", + proto.PprofOption_PROFILE: "/debug/pprof/profile", + proto.PprofOption_THREADCREATE: "/debug/pprof/threadcreate", + proto.PprofOption_TRACE: "/debug/pprof/trace", +} + +// getProf will gather pprof data specified by the option. +func (r *socketRequester) getPprof(ctx context.Context, opt proto.PprofOption, dur time.Duration) *proto.PprofResult { + res := &proto.PprofResult{ + AppName: r.appName, + RouteKey: r.routeKey, + PprofType: opt, + } + + path, ok := pprofEndpoints[opt] + if !ok { + res.Error = "unknown path for option" + return res + } + + if opt == proto.PprofOption_PROFILE || opt == proto.PprofOption_TRACE { + path += fmt.Sprintf("?seconds=%0.f", dur.Seconds()) + } + + resp, err := r.getPath(ctx, path) + if err != nil { + res.Error = err.Error() + return res + } + defer resp.Body.Close() + + p, err := io.ReadAll(resp.Body) + if err != nil { + res.Error = err.Error() + return res + } + res.Result = p + return res } type upgradeRequest struct { diff --git a/x-pack/elastic-agent/pkg/agent/operation/monitoring.go b/x-pack/elastic-agent/pkg/agent/operation/monitoring.go index dedec28762a..19cd40cda91 100644 --- a/x-pack/elastic-agent/pkg/agent/operation/monitoring.go +++ b/x-pack/elastic-agent/pkg/agent/operation/monitoring.go @@ -234,10 +234,8 @@ func (o *Operator) getMonitoringFilebeatConfig(outputType string, output interfa }, }, "paths": []string{ - filepath.Join(paths.Home(), "logs", "elastic-agent-json.log"), - filepath.Join(paths.Home(), "logs", "elastic-agent-json.log*"), - filepath.Join(paths.Home(), "logs", "elastic-agent-watcher-json.log"), - filepath.Join(paths.Home(), "logs", "elastic-agent-watcher-json.log*"), + filepath.Join(paths.Home(), "logs", "elastic-agent-*.ndjson"), + filepath.Join(paths.Home(), "logs", "elastic-agent-watcher-*.ndjson"), }, "index": fmt.Sprintf("logs-elastic_agent-%s", monitoringNamespace), "processors": []map[string]interface{}{ diff --git a/x-pack/elastic-agent/pkg/agent/program/program_test.go b/x-pack/elastic-agent/pkg/agent/program/program_test.go index 04c3519af65..b75ac9dceaa 100644 --- a/x-pack/elastic-agent/pkg/agent/program/program_test.go +++ b/x-pack/elastic-agent/pkg/agent/program/program_test.go @@ -400,10 +400,6 @@ func TestConfiguration(t *testing.T) { // programs: []string{"auditbeat"}, // expected: 1, // }, - // "journal_config": { - // programs: []string{"journalbeat"}, - // expected: 1, - // }, "fleet_server": { programs: []string{"fleet-server"}, expected: 1, diff --git a/x-pack/elastic-agent/pkg/agent/program/supported.go b/x-pack/elastic-agent/pkg/agent/program/supported.go index c655b239402..220f187a3fe 100644 --- a/x-pack/elastic-agent/pkg/agent/program/supported.go +++ b/x-pack/elastic-agent/pkg/agent/program/supported.go @@ -25,7 +25,7 @@ func init() { // spec/metricbeat.yml // spec/osquerybeat.yml // spec/packetbeat.yml - unpacked := packer.MustUnpack("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") + unpacked := packer.MustUnpack("eJzEWll34ri2fr8/o1/vcDwU6fZd6zxg0p4gTmGCJOsNycQGJEMHM9h33f9+luQB2zipSlV3nwdWgpClra09fPvb/r9fjoc1/cfqwP/7uH47r9/+J+fsl//9hXArwy/7eA5MfwZ8RlPMaHzYEjh/cG3rQhZqgZGnYeROQ+QpK4iTUB/8LaXFPoaXfexO3CxYuEd34mUhHCVYAxmGI2XGwSmE3hHDuRE5nooX7nGyGcfuRrXczSV2ebRFusko9xlJ54bnZObyd/UlAB4MgPcaKIYzL/bXp0fTcONDNOHgC7WNPLLBDmkqixzvEOpPD651nLqT8SZEZjZD1Zk27nHClClNwRGjpwex72xhbolujpAenJF2PVB9LsfdyTh2baZgqDy4Nj5iCJRm3AnOzxvzQFJTjZynqRybjGOijV5DzThhfj2U+hmdiT4Wv2eurSb0cd/MpbalrB73MeZXhtH8Nt6SrR6bLcwcQ/UccfC60sDoOd43v5Uf8w2jnbiPbaiBgqpGQm0m5/7QOo7HSp2yE7605ygx5SAjOmZIy9j65Xae+iPX3Zjivk/ReC+fwZx9QbqvUA4S8rKP17pS6QQfiBMwygwthFe1c27HZ8QG28g28iFdV/soa2Sy2zM4IQ5gtOjIlUk7nTeyHCMb5LezmwWGVxbqwZmmd3q/27dcz1Ajx1TL891007rLzLXZacXBNrKMPYbWDiOveN6Yv77OD/rKBqfnjXnEcJRGdrz3nKzaxzemi/F/uo/jOISjnWsnCVUytl7Eu7VW7ekoR3cSMWJbRWSzLdVAQrm/9/JL7OkewzYrvPwiZEhXmsVX2u/pbDJOiW2kVA8SqsXpdL7/5y//VQaDdRod9ps064WCAI521DYOJJ3HSw1sI+QdImc3DTV197wxGeHBhWjsFE3UAkNfpZwp6/khoWlwwNzaRsK0b2tk2AbaJJVueAi15YP7GOrPj/E0hL6ygsYJaexEHaAgPRhRGxTP8T5zbXDCjnlewZEy4dczVo1LiIJ9eb3mLkSevoJfHtyJe36x2YZyK18vDKtWzUy5PT/TfSVEAZtp1zPOjZb8yh8zsXbuijWPKzhS14/72N0YZ+rMzwG8JlQPDmFuWLdnjCKyLQUvjCPR6Ll9zulmJMY2wowijZ2wbegiJLq7pwdkXeeUGynlVub+jg/EBgWyro288v96D+tKxXVFNqDIFme/0sF9uL/H0H+T+tODhNiXh8lGiTFKWKgafAWvrDb1OuS4vKUX5LNQB/kKBSO3mleF8Wlt1q4InZzx9cK9jW2UTJhU/cxsMd5QPRBmntdjkc0yDA1V2MJTMZ5S2ygiS8jvKyG8Hqs7/oKh/yrcEtfhxDGTyI4f3Ik3bGe1HLaVY71x2cydeM3abblmC7W5k2peEdkBo6nbGnOzGQIXrHsJtpe9cY9RzVBFSqJ5Swfv6LE7f/SwQuNqPVNZQZURHSjPm7H29DieUsdjSAenFRwJmzqSx/10tjDZ2gZbpAkbWVbnM6XtP2/Gm7Yd0Jtv1nsklEdFK7SL86qEN/axuYW4+3sc1s+A3E2aGg7v1bgMtUjvheWPQrst00ocOeyC55UdcesYQdCcSeinsYux1JewcwUj77U/l2rgiKGvEN19ECFZxBhapbQqhTDCrQ2xwa46az8VZa4T5BFcyjMRaF36/tRJ4Y6nErsj6/sptzor1UAecZBPpD9UKXF7r6u2T3ZhgxKv4OgSoaBoZO6lKCkHwgeqsTOJ99NISxjZ7mMiYqwe7KeT4NdyzaCXgq6M8EhZTUQKqvSnKwf38Uv8NDETwufxyraKhQZGYg1hI2LO6+ISexo4hkjEd7/A0MpDmXoOW6KNisjxEuE3IjYSbiiuWF/3VJIGBwKXpxB525WjxF9flNjTrJy8hIqXl/t5TpZHcCRtcsZxQiA7rlE1V6bAJIkmtJR/EvxKU3CSsWgxykJ4ONO0mlvQdLoYT+tU+Lpha7Je3aVCEZqgx0I0r9OfDKshB0k0PpTutjFJB8WmPosccJlxdiSLUWNiX6FwBZ+5G5mhN7PlcjObjDdUA0qExqfIBhm1r0lkL08YjpJQXMmjykN4Le6RspoQbqVYuGY6b89XaAru9hBujkVKykdHjDAjj+oOQ0/F+TcRuL1YXq35DpjAMpwXJXp83v5+eXKUjUDT3YpA6CkoZjJ0gQ2GljJJPSaRRxq8CoRcmwjS/H0IRymW7u6peH7II3iVYUK6NEpeqR7kGFpZiZz2bVR1IDxg6xpROwI2LB9ckSr1J+mqKzj6Q7h+E5qAcaHc2GLkFyIcVO5+JswQJsmJzSRsEaEYI09BmsVF+KpDoECaArURLSpKV20h+jpl9UJMD81nru2fqcNeRYoarDhk2vztwXUqmVEbed7LSrhxpm0UaoMvoQYu4jeYe8LNWAjVorxXtiv/NhVYaXuOd5ZVg2bkNPeivqyRbbwSmxXRYxtVmwdhq88bs6VTr/jRc9x07jHMjRzPpQ3kwqYJbFIgp9zI7lJGpxrzmzNPKnghQk2oB+UZLEPKfUtFvXvTe/LWFWD/HL0K8L3U0A3LZmPfddgWspHUPwpo2kkNtVylXbd1l4XIvGDkdmxGQFeiRSXckzZKu5WZDTRZfVeQQvrJpVv9yZiQzs8CxklY7fgKttmptw+LOBAQWAn1sZBv27G/1joRDC7PG1PFzrgni4TgO6L5b+Icrh2cQy1jtFeNing1qyoapPtHokfiXLI6FWP356dnqrNCPPe8MYs18lt6+KhyrateUGBgnCMUXKJWav3mc7aA6VYTq26wwWMEGhoGhpzXlreCHrsQBUkTnxajUwhVRnUzCbXlD+8/4/J7IeDBXwzDkkh/ykLtKu5aD1GwXY27v9HiqTlHiA4q5custI9gH8EblK7W4EQXkNobtWMQSQMBFRr7mC3M2nZucEjzLzNkqmHqq+Ft3j5yggvSWmVks26iRI75B9WM023scI6QdwrhdXcbyxLMs+T2/eY3s4WZURS01hyxyMZHot9sjhRPmg8tFdtMadtFy36znp+J7yOqdfYRvnaLGTC43OaC0wrFt980dhL2f5OpLDPLmPjzsLzBGON3bUJijzL2Nrm6ZINkzsbnKpdPa+atfhan3lmUD72YqZBiL2WuMVj7DPcw32vL0sJpzdidfwtfpHpwpnzZxQ1awkIoyqCnB9fJjEk8yNzc9piM/m0szitbr7NhUjcoK4V4WVcZ3M/wrWrJmuqDl9W0ax1FxVxe2UTNiBYw9w7mlYRoQ6zGh3Zqk2a3toza7Cr1dQm4O/P7RrV2C9PdlNg3wV6FlLWqqz9nf7uBT9+UoYS1lU7eSweVa9WwuJazlgWJKtf+bZAYlWR7bnJiAxZNRjURf6rXmvG7CixG8+Y8FaNwc4mKEK8J0VcRMsmgfiSZSRo7SGuCfXQh2vUQ6rvTCs6H9qrDyulp0syt9z0QuU7wim3AQwSOkTNMCN8TvHdy7InuKz0y905PkuQeJnFPtd3MuNA/yAm3jkg3zzSdf2vvgmqXO6K/Dmuz7fjUt8k2dGzpqpS3ka8PH1shvs0YtD5DYbH7UeIQRgKu3T1bpckz1Ru7yEI0bt3HcMnzrpwfwKEO5EA+Q9owwf6dzYcurJr/CWsMQrPPnQvblhKCJiae5Hfksx88Y7vM+ZHGRs+2xkMs0l3KbPyUH8r4YIME20DGIcn6pdEei9KhwxqV/vG62MVfN+OLa1snPPmzmx+7hsVJ1qu3bIDGWdggoWlQUhJVDlx1xlr5r0fLrOA1azcuMbeOVCvnfJbC+UxjtDVXlHfpCo7SGb+KEuz4FQYsTEF6n5trCiZhYryiqXKMfCWUJbZxavzLMrYrcR/a8qFmOXvN0SEaZjiPqoa+QsEeCfiigS/tZudws84Tpeqa6iK+JkzeZ/7baXoZsN9tFxZ+xPh+9NxHUHaA+e1C2p7tl3FT5khOioGm5vadvBl/zue68ThjayTXYcO+9vMMrYCZlIPdCj2lM6mb6C2E+C1cUOF7kv4S5eVqQg+T+J8NBOXr7G1DBxzvBQKFcratDLF6q6Dq1GsVrzr85kCBUaBSgatt5dt8aM25pgEjyJScyqDTjn/m7YTrGWvRgXB6IpJTuRjYBpsI0v66aagaF4y8rVj36yL49WUJlssdexziUfsyYRTkK+jLwDTj/plwfMD5SIBx2V4YOtf7XGxX15QDcYF5ZBlnwmq+I3gNtSQhPBJOWRp82rQyhgF9p1ZiJ2yDL7VxS95AgNrq7ulF1nuN89QBBelmTjSfUd0/Nw5jiwAlz3xcQV8pQWMJDEOIlabubzjf5q0PWb9RqRuVfU9dWY/V8lRytoBOH7i2+MV3OL1QMy5rYCTEvr7Hncq9W3u2wMLd2U9EMy7t4IBRssXIVCQATxteUiahVcXpNr4ykfbU4WhFwujJqhDVOK6Qr3TbUzX32bqj9OlHz3G7Qw64DGB/Mz/73QlrgPuifPngWl9O09yofbPwxh+2GP/tbcnPcM9Ijw6RnbxSDlKMkst3ctG58HG0if+xfLzK5P518+VturjXUbmO2CN+cCdBGwiUALrMFe21a66/CxrqvoKtnrEDjvX9SJ+FGUOalVNujQbtuIkTPdBd2kojM263Ub/N4bae+wxn3CcR/laeWX4XgPVv56p7HHs3h1ipyJUyl/DfatKo6kPtvqcH1Mmb8tm+bdk4J5rSxx+nodxAoLGTPtPx5aZvOFRcZX1cU+ulIXc2A0Du85xjDx9UvoB+ineUXGMD/L6Td9wf/zit3/Ih1Kf71wiCfN3tnJ+pbqkYeaN+9/wTnfPPI752FxxaJwndIThFk9b6SEbT7tx3O+Ze9ImuduelOHlu5+lM+vr58EU4o6AIMJrupn8KKhO3+ZcislsX/i/sPjW29J3dhu/04G427tAff1HJNfRSTPclFzEvMdzJ74Y7ocXzY5i2S6/Diu7WQ5zH0ra2Kw0ondLLESE7Y5HdK71ymgVljfeNskvMuZurYKheiHwr8t5pZVsjVy35V/v4tZXu3HfLrRS941i0e+Yf5z1+kl9oG+8H3MIlhP4bHuDWhviFrmzud3LjfX62l5KGU8zf3cqa/vL///GvAAAA//9M8ln7") SupportedMap = make(map[string]Spec) for f, v := range unpacked { diff --git a/x-pack/elastic-agent/pkg/agent/program/testdata/journal_config-journalbeat.yml b/x-pack/elastic-agent/pkg/agent/program/testdata/journal_config-journalbeat.yml deleted file mode 100644 index 60e6261fc0e..00000000000 --- a/x-pack/elastic-agent/pkg/agent/program/testdata/journal_config-journalbeat.yml +++ /dev/null @@ -1,15 +0,0 @@ -journalbeat: - inputs: - - type: log/journal - paths: [] - backoff: 1s - max_backoff: 20s - seek: cursor - cursor_seek_fallback: head - include_matches: [] - save_remote_hostname: false -output: - elasticsearch: - hosts: [127.0.0.1:9200, 127.0.0.1:9300] - username: elastic - password: changeme diff --git a/x-pack/elastic-agent/pkg/composable/providers/kubernetes/README.md b/x-pack/elastic-agent/pkg/composable/providers/kubernetes/README.md new file mode 100644 index 00000000000..8fe7492c87a --- /dev/null +++ b/x-pack/elastic-agent/pkg/composable/providers/kubernetes/README.md @@ -0,0 +1,70 @@ +## Autodiscover provider in Elastic Agent + +https://www.elastic.co/guide/en/fleet/8.0/dynamic-input-configuration.html#dynamic-providers + +Currently Kubernetes dynamic provider can only be configured in [standalone](https://github.com/elastic/beats/blob/03bf16907bea9768427f8305a5c345368b55d834/deploy/kubernetes/elastic-agent-standalone-kubernetes.yaml#L24) agent. +In fleet managed agent it is enabled by default with default values. + +Template based autodiscover of Kubernetes resources is only supported in standalone mode as of now. +It is not part of the Kubernetes Integration yet. + +Hints based autodiscover is not supported yet. + +### Template based autodiscover + +Example: +As an example we will use again redis module. +In agent.yml(configmap) an extra input block needs to be added. +``` +# Add extra input blocks here, based on conditions +# so as to automatically identify targeted Pods and start monitoring them +# using a predefined integration. For instance: +- name: redis + type: redis/metrics + use_output: default + meta: + package: + name: redis + version: 0.3.6 + data_stream: + namespace: default + streams: + - data_stream: + dataset: redis.info + type: metrics + metricsets: + - info + hosts: + - '${kubernetes.pod.ip}:6379' + idle_timeout: 20s + maxconn: 10 + network: tcp + period: 10s + condition: ${kubernetes.pod.labels.app} == 'redis' +``` + +What makes this input block dynamic are the variables hosts and condition. +`${kubernetes.pod.ip}` and `${kubernetes.pod.labels.app}` + +#### High level description +The Kubernetes dynamic provider watches for Kubernetes resources and generates mappings from them (similar to events in beats provider). The mappings include those variables([list of variables](https://www.elastic.co/guide/en/fleet/03bf16907bea9768427f8305a5c345368b55d834/dynamic-input-configuration.html#kubernetes-provider)) for each k8s resource with unique value for each one of them. +Agent composable controller which controls all the providers receives these mappings and tries to match them with the input blogs of the configurations. +This means that for every mapping that the condition matches (kubernetes.pod.labels.app equals to redis), a +new input will be created in which the condition will be removed(not needed anymore) and the `kubernetes.pod.ip` variable will be substituted from the value in the same mapping. +The updated complete inputs blog will be then forwarded to agent to spawn/update metricbeat and filebeat instances. + +##### Internals + +Step-by-step walkthrough +1. Elastic agent running in local mode initiates a new [composable controller](https://github.com/elastic/beats/blob/03bf16907bea9768427f8305a5c345368b55d834/x-pack/elastic-agent/pkg/agent/application/local_mode.go#L112). +2. The controller consists of all contextProviders and [dynamicProviders](https://github.com/elastic/beats/blob/03bf16907bea9768427f8305a5c345368b55d834/x-pack/elastic-agent/pkg/composable/controller.go#L73). +3. Agent initiates a new [emitter](https://github.com/elastic/beats/blob/03bf16907bea9768427f8305a5c345368b55d834/x-pack/elastic-agent/pkg/agent/application/local_mode.go#L118) which [starts](https://github.com/elastic/beats/blob/03bf16907bea9768427f8305a5c345368b55d834/x-pack/elastic-agent/pkg/agent/application/pipeline/emitter/emitter.go#L27) all the dynamicProviders of the [controller](https://github.com/elastic/beats/blob/03bf16907bea9768427f8305a5c345368b55d834/x-pack/elastic-agent/pkg/composable/controller.go#L122). +4. Kubernetes Dynamic provider depending on the [resource type](https://github.com/elastic/beats/blob/03bf16907bea9768427f8305a5c345368b55d834/x-pack/elastic-agent/pkg/composable/providers/kubernetes/kubernetes.go#L56) (default is pod) initiates a [watcher](https://github.com/elastic/beats/blob/3c77c9a92a2e90b85f525293cb4c2cfc5bc996b1/x-pack/elastic-agent/pkg/composable/providers/kubernetes/pod.go#L69) for + the specific resource the same way as in metrcbeat/filebeat kubernetes provider. +5. Under the hood a dedicated watcher starts for pods, nodes and namespaces as well as a metadata generator. +6. The difference is that the watchers instead of publishing events, they create [data](https://github.com/elastic/beats/blob/3c77c9a92a2e90b85f525293cb4c2cfc5bc996b1/x-pack/elastic-agent/pkg/composable/providers/kubernetes/pod.go#L134) from the objects read from the queue. These [data](https://github.com/elastic/beats/blob/3c77c9a92a2e90b85f525293cb4c2cfc5bc996b1/x-pack/elastic-agent/pkg/composable/providers/kubernetes/pod.go#L244) consist of mappings, processors and a priority . +7. A [mapping](https://github.com/elastic/beats/blob/3c77c9a92a2e90b85f525293cb4c2cfc5bc996b1/x-pack/elastic-agent/pkg/composable/providers/kubernetes/pod.go#L217) includes all those variables retrieved from the kubernetes resource metadata while the [processors](https://github.com/elastic/beats/blob/3c77c9a92a2e90b85f525293cb4c2cfc5bc996b1/x-pack/elastic-agent/pkg/composable/providers/kubernetes/pod.go#L236) indicate the addition of extra fields. +8. Composable controller [collects](https://github.com/elastic/beats/blob/3c77c9a92a2e90b85f525293cb4c2cfc5bc996b1/x-pack/elastic-agent/pkg/composable/controller.go#L244) the created data and [compares](https://github.com/elastic/beats/blob/3c77c9a92a2e90b85f525293cb4c2cfc5bc996b1/x-pack/elastic-agent/pkg/composable/controller.go#L263) their mappings and processors against the existing ones. If there is a change, it updates the dynamicProviderState and notifies a worker thread through a [signal](https://github.com/elastic/beats/blob/3c77c9a92a2e90b85f525293cb4c2cfc5bc996b1/x-pack/elastic-agent/pkg/composable/controller.go#L272). +9. When the worker gets [notified](https://github.com/elastic/beats/blob/3c77c9a92a2e90b85f525293cb4c2cfc5bc996b1/x-pack/elastic-agent/pkg/composable/controller.go#L141) for a change it creates new [variables](https://github.com/elastic/beats/blob/3c77c9a92a2e90b85f525293cb4c2cfc5bc996b1/x-pack/elastic-agent/pkg/composable/controller.go#L170) from the mappings and processors. +10. It then updates the [emitter](https://github.com/elastic/beats/blob/3c77c9a92a2e90b85f525293cb4c2cfc5bc996b1/x-pack/elastic-agent/pkg/agent/application/pipeline/emitter/controller.go#L111) with them. +11. The emitter controller will update the ast that is then used by the agent to generate the final inputs and spawn new programs to deploy the changes([code](https://github.com/elastic/beats/blob/3c77c9a92a2e90b85f525293cb4c2cfc5bc996b1/x-pack/elastic-agent/pkg/agent/application/pipeline/emitter/controller.go#L151)). diff --git a/x-pack/elastic-agent/pkg/composable/providers/kubernetes/config.go b/x-pack/elastic-agent/pkg/composable/providers/kubernetes/config.go index ec99bca287d..cdb50d6d816 100644 --- a/x-pack/elastic-agent/pkg/composable/providers/kubernetes/config.go +++ b/x-pack/elastic-agent/pkg/composable/providers/kubernetes/config.go @@ -55,6 +55,7 @@ func (c *Config) InitDefaults() { c.Scope = "node" c.LabelsDedot = true c.AnnotationsDedot = true + c.AddResourceMetadata = metadata.GetDefaultResourceMetadataConfig() } // Validate ensures correctness of config diff --git a/x-pack/elastic-agent/pkg/composable/providers/kubernetes/node.go b/x-pack/elastic-agent/pkg/composable/providers/kubernetes/node.go index db63a1cc2ab..29cac3efdb5 100644 --- a/x-pack/elastic-agent/pkg/composable/providers/kubernetes/node.go +++ b/x-pack/elastic-agent/pkg/composable/providers/kubernetes/node.go @@ -43,7 +43,7 @@ func NewNodeEventer( logger *logp.Logger, client k8s.Interface, scope string) (Eventer, error) { - watcher, err := kubernetes.NewWatcher(client, &kubernetes.Node{}, kubernetes.WatchOptions{ + watcher, err := kubernetes.NewNamedWatcher("agent-node", client, &kubernetes.Node{}, kubernetes.WatchOptions{ SyncTimeout: cfg.SyncPeriod, Node: cfg.Node, IsUpdated: isUpdated, diff --git a/x-pack/elastic-agent/pkg/composable/providers/kubernetes/pod.go b/x-pack/elastic-agent/pkg/composable/providers/kubernetes/pod.go index 5a7a8c4a392..94630a10913 100644 --- a/x-pack/elastic-agent/pkg/composable/providers/kubernetes/pod.go +++ b/x-pack/elastic-agent/pkg/composable/providers/kubernetes/pod.go @@ -44,29 +44,6 @@ type providerData struct { processors []map[string]interface{} } -type containerInPod struct { - id string - runtime string - spec kubernetes.Container - status kubernetes.PodContainerStatus -} - -// podUpdaterHandlerFunc is a function that handles pod updater notifications. -type podUpdaterHandlerFunc func(interface{}) - -// podUpdaterStore is the interface that an object needs to implement to be -// used as a pod updater store. -type podUpdaterStore interface { - List() []interface{} -} - -// namespacePodUpdater notifies updates on pods when their namespaces are updated. -type namespacePodUpdater struct { - handler podUpdaterHandlerFunc - store podUpdaterStore - locker sync.Locker -} - // NewPodEventer creates an eventer that can discover and process pod objects func NewPodEventer( comm composable.DynamicProviderComm, @@ -74,7 +51,7 @@ func NewPodEventer( logger *logp.Logger, client k8s.Interface, scope string) (Eventer, error) { - watcher, err := kubernetes.NewWatcher(client, &kubernetes.Pod{}, kubernetes.WatchOptions{ + watcher, err := kubernetes.NewNamedWatcher("agent-pod", client, &kubernetes.Pod{}, kubernetes.WatchOptions{ SyncTimeout: cfg.SyncPeriod, Node: cfg.Node, Namespace: cfg.Namespace, @@ -89,14 +66,12 @@ func NewPodEventer( Node: cfg.Node, } metaConf := cfg.AddResourceMetadata - if metaConf == nil { - metaConf = metadata.GetDefaultResourceMetadataConfig() - } - nodeWatcher, err := kubernetes.NewWatcher(client, &kubernetes.Node{}, options, nil) + + nodeWatcher, err := kubernetes.NewNamedWatcher("agent-node", client, &kubernetes.Node{}, options, nil) if err != nil { logger.Errorf("couldn't create watcher for %T due to error %+v", &kubernetes.Node{}, err) } - namespaceWatcher, err := kubernetes.NewWatcher(client, &kubernetes.Namespace{}, kubernetes.WatchOptions{ + namespaceWatcher, err := kubernetes.NewNamedWatcher("agent-namespace", client, &kubernetes.Namespace{}, kubernetes.WatchOptions{ SyncTimeout: cfg.SyncPeriod, }, nil) if err != nil { @@ -123,8 +98,13 @@ func NewPodEventer( watcher.AddEventHandler(p) + if nodeWatcher != nil && metaConf.Node.Enabled() { + updater := kubernetes.NewNodePodUpdater(p.unlockedUpdate, watcher.Store(), &p.crossUpdate) + nodeWatcher.AddEventHandler(updater) + } + if namespaceWatcher != nil && metaConf.Namespace.Enabled() { - updater := newNamespacePodUpdater(p.unlockedUpdate, watcher.Store(), &p.crossUpdate) + updater := kubernetes.NewNamespacePodUpdater(p.unlockedUpdate, watcher.Store(), &p.crossUpdate) namespaceWatcher.AddEventHandler(updater) } @@ -164,7 +144,7 @@ func (p *pod) Stop() { func (p *pod) emitRunning(pod *kubernetes.Pod) { - namespaceAnnotations := podNamespaceAnnotations(pod, p.namespaceWatcher) + namespaceAnnotations := kubernetes.PodNamespaceAnnotations(pod, p.namespaceWatcher) data := generatePodData(pod, p.config, p.metagen, namespaceAnnotations) data.mapping["scope"] = p.scope @@ -247,14 +227,13 @@ func generatePodData( return providerData{} } - ckMeta := kubemetaMap.(common.MapStr).Clone() - if len(namespaceAnnotations) != 0 { - ckMeta.Put("namespace.annotations", namespaceAnnotations) - } // k8sMapping includes only the metadata that fall under kubernetes.* // and these are available as dynamic vars through the provider - k8sMapping := map[string]interface{}(ckMeta) + k8sMapping := map[string]interface{}(kubemetaMap.(common.MapStr).Clone()) + if len(namespaceAnnotations) != 0 { + k8sMapping["namespace_annotations"] = namespaceAnnotations + } // Pass annotations to all events so that it can be used in templating and by annotation builders. annotations := common.MapStr{} for k, v := range pod.GetObjectMeta().GetAnnotations() { @@ -289,7 +268,7 @@ func generateContainerData( kubeMetaGen metadata.MetaGen, namespaceAnnotations common.MapStr) { - containers := getContainersInPod(pod) + containers := kubernetes.GetContainersInPod(pod) // Pass annotations to all events so that it can be used in templating and by annotation builders. annotations := common.MapStr{} @@ -301,36 +280,35 @@ func generateContainerData( // If it doesn't have an ID, container doesn't exist in // the runtime, emit only an event if we are stopping, so // we are sure of cleaning up configurations. - if c.id == "" { + if c.ID == "" { continue } // ID is the combination of pod UID + container name - eventID := fmt.Sprintf("%s.%s", pod.GetObjectMeta().GetUID(), c.spec.Name) + eventID := fmt.Sprintf("%s.%s", pod.GetObjectMeta().GetUID(), c.Spec.Name) - meta := kubeMetaGen.Generate(pod, metadata.WithFields("container.name", c.spec.Name)) + meta := kubeMetaGen.Generate(pod, metadata.WithFields("container.name", c.Spec.Name)) kubemetaMap, err := meta.GetValue("kubernetes") if err != nil { continue } - ckMeta := kubemetaMap.(common.MapStr).Clone() - if len(namespaceAnnotations) != 0 { - ckMeta.Put("namespace.annotations", namespaceAnnotations) - } // k8sMapping includes only the metadata that fall under kubernetes.* // and these are available as dynamic vars through the provider - k8sMapping := map[string]interface{}(ckMeta) + k8sMapping := map[string]interface{}(kubemetaMap.(common.MapStr).Clone()) + if len(namespaceAnnotations) != 0 { + k8sMapping["namespace_annotations"] = namespaceAnnotations + } // add annotations to be discoverable by templates k8sMapping["annotations"] = annotations //container ECS fields cmeta := common.MapStr{ - "id": c.id, - "runtime": c.runtime, + "id": c.ID, + "runtime": c.Runtime, "image": common.MapStr{ - "name": c.spec.Image, + "name": c.Spec.Image, }, } @@ -357,13 +335,13 @@ func generateContainerData( // add container metadata under kubernetes.container.* to // make them available to dynamic var resolution containerMeta := common.MapStr{ - "id": c.id, - "name": c.spec.Name, - "image": c.spec.Image, - "runtime": c.runtime, + "id": c.ID, + "name": c.Spec.Name, + "image": c.Spec.Image, + "runtime": c.Runtime, } - if len(c.spec.Ports) > 0 { - for _, port := range c.spec.Ports { + if len(c.Spec.Ports) > 0 { + for _, port := range c.Spec.Ports { containerMeta.Put("port", fmt.Sprintf("%v", port.ContainerPort)) containerMeta.Put("port_name", port.Name) k8sMapping["container"] = containerMeta @@ -375,101 +353,3 @@ func generateContainerData( } } } - -// podNamespaceAnnotations returns the annotations of the namespace of the pod -func podNamespaceAnnotations(pod *kubernetes.Pod, watcher kubernetes.Watcher) common.MapStr { - if watcher == nil { - return nil - } - - rawNs, ok, err := watcher.Store().GetByKey(pod.Namespace) - if !ok || err != nil { - return nil - } - - namespace, ok := rawNs.(*kubernetes.Namespace) - if !ok { - return nil - } - - annotations := common.MapStr{} - for k, v := range namespace.GetAnnotations() { - safemapstr.Put(annotations, k, v) - } - return annotations -} - -// newNamespacePodUpdater creates a namespacePodUpdater -func newNamespacePodUpdater(handler podUpdaterHandlerFunc, store podUpdaterStore, locker sync.Locker) *namespacePodUpdater { - return &namespacePodUpdater{ - handler: handler, - store: store, - locker: locker, - } -} - -// OnUpdate handles update events on namespaces. -func (n *namespacePodUpdater) OnUpdate(obj interface{}) { - ns, ok := obj.(*kubernetes.Namespace) - if !ok { - return - } - - // n.store.List() returns a snapshot at this point. If a delete is received - // from the main watcher, this loop may generate an update event after the - // delete is processed, leaving configurations that would never be deleted. - // Also this loop can miss updates, what could leave outdated configurations. - // Avoid these issues by locking the processing of events from the main watcher. - if n.locker != nil { - n.locker.Lock() - defer n.locker.Unlock() - } - for _, pod := range n.store.List() { - pod, ok := pod.(*kubernetes.Pod) - if ok && pod.Namespace == ns.Name { - n.handler(pod) - } - } -} - -// OnAdd handles add events on namespaces. Nothing to do, if pods are added to this -// namespace they will generate their own add events. -func (*namespacePodUpdater) OnAdd(interface{}) {} - -// OnDelete handles delete events on namespaces. Nothing to do, if pods are deleted from this -// namespace they will generate their own delete events. -func (*namespacePodUpdater) OnDelete(interface{}) {} - -// getContainersInPod returns all the containers defined in a pod and their statuses. -// It includes init and ephemeral containers. -func getContainersInPod(pod *kubernetes.Pod) []*containerInPod { - var containers []*containerInPod - for _, c := range pod.Spec.Containers { - containers = append(containers, &containerInPod{spec: c}) - } - for _, c := range pod.Spec.InitContainers { - containers = append(containers, &containerInPod{spec: c}) - } - for _, c := range pod.Spec.EphemeralContainers { - c := kubernetes.Container(c.EphemeralContainerCommon) - containers = append(containers, &containerInPod{spec: c}) - } - - statuses := make(map[string]*kubernetes.PodContainerStatus) - mapStatuses := func(s []kubernetes.PodContainerStatus) { - for i := range s { - statuses[s[i].Name] = &s[i] - } - } - mapStatuses(pod.Status.ContainerStatuses) - mapStatuses(pod.Status.InitContainerStatuses) - mapStatuses(pod.Status.EphemeralContainerStatuses) - for _, c := range containers { - if s, ok := statuses[c.spec.Name]; ok { - c.id, c.runtime = kubernetes.ContainerIDWithRuntime(*s) - c.status = *s - } - } - - return containers -} diff --git a/x-pack/elastic-agent/pkg/composable/providers/kubernetes/pod_test.go b/x-pack/elastic-agent/pkg/composable/providers/kubernetes/pod_test.go index 5c26d50ea8f..62d4a199892 100644 --- a/x-pack/elastic-agent/pkg/composable/providers/kubernetes/pod_test.go +++ b/x-pack/elastic-agent/pkg/composable/providers/kubernetes/pod_test.go @@ -50,17 +50,15 @@ func TestGeneratePodData(t *testing.T) { data := generatePodData(pod, &Config{}, &podMeta{}, namespaceAnnotations) mapping := map[string]interface{}{ - "namespace": common.MapStr{ - "name": pod.GetNamespace(), - "annotations": common.MapStr{ - "nsa": "nsb", - }, - }, + "namespace": pod.GetNamespace(), "pod": common.MapStr{ "uid": string(pod.GetUID()), "name": pod.GetName(), "ip": pod.Status.PodIP, }, + "namespace_annotations": common.MapStr{ + "nsa": "nsb", + }, "labels": common.MapStr{ "foo": "bar", }, @@ -75,9 +73,7 @@ func TestGeneratePodData(t *testing.T) { "name": "devcluster", "url": "8.8.8.8:9090"}, }, "kubernetes": common.MapStr{ - "namespace": common.MapStr{ - "name": "testns", - }, + "namespace": "testns", "labels": common.MapStr{ "foo": "bar", }, @@ -161,12 +157,7 @@ func TestGenerateContainerPodData(t *testing.T) { }) mapping := map[string]interface{}{ - "namespace": common.MapStr{ - "name": pod.GetNamespace(), - "annotations": common.MapStr{ - "nsa": "nsb", - }, - }, + "namespace": pod.GetNamespace(), "pod": common.MapStr{ "uid": string(pod.GetUID()), "name": pod.GetName(), @@ -180,6 +171,9 @@ func TestGenerateContainerPodData(t *testing.T) { "port": "80", "port_name": "http", }, + "namespace_annotations": common.MapStr{ + "nsa": "nsb", + }, "annotations": common.MapStr{ "app": "production", }, @@ -198,9 +192,7 @@ func TestGenerateContainerPodData(t *testing.T) { "name": "devcluster", "url": "8.8.8.8:9090"}, }, "kubernetes": common.MapStr{ - "namespace": common.MapStr{ - "name": "testns", - }, + "namespace": "testns", "annotations": common.MapStr{"app": "production"}, "labels": common.MapStr{"foo": "bar"}, "pod": common.MapStr{ @@ -280,12 +272,7 @@ func TestEphemeralContainers(t *testing.T) { }) mapping := map[string]interface{}{ - "namespace": common.MapStr{ - "name": pod.GetNamespace(), - "annotations": common.MapStr{ - "nsa": "nsb", - }, - }, + "namespace": pod.GetNamespace(), "pod": common.MapStr{ "uid": string(pod.GetUID()), "name": pod.GetName(), @@ -300,6 +287,9 @@ func TestEphemeralContainers(t *testing.T) { "image": "nginx:1.120", "runtime": "crio", }, + "namespace_annotations": common.MapStr{ + "nsa": "nsb", + }, "annotations": common.MapStr{ "app": "production", }, @@ -315,9 +305,7 @@ func TestEphemeralContainers(t *testing.T) { "name": "devcluster", "url": "8.8.8.8:9090"}, }, "kubernetes": common.MapStr{ - "namespace": common.MapStr{ - "name": "testns", - }, + "namespace": "testns", "labels": common.MapStr{"foo": "bar"}, "annotations": common.MapStr{"app": "production"}, "pod": common.MapStr{ @@ -393,9 +381,7 @@ func (p *podMeta) GenerateECS(obj kubernetes.Resource) common.MapStr { func (p *podMeta) GenerateK8s(obj kubernetes.Resource, opts ...metadata.FieldOptions) common.MapStr { k8sPod := obj.(*kubernetes.Pod) return common.MapStr{ - "namespace": common.MapStr{ - "name": k8sPod.GetNamespace(), - }, + "namespace": k8sPod.GetNamespace(), "pod": common.MapStr{ "uid": string(k8sPod.GetUID()), "name": k8sPod.GetName(), diff --git a/x-pack/elastic-agent/pkg/composable/providers/kubernetes/service.go b/x-pack/elastic-agent/pkg/composable/providers/kubernetes/service.go index 2bdf73380be..5f6f588fd23 100644 --- a/x-pack/elastic-agent/pkg/composable/providers/kubernetes/service.go +++ b/x-pack/elastic-agent/pkg/composable/providers/kubernetes/service.go @@ -44,7 +44,7 @@ func NewServiceEventer( logger *logp.Logger, client k8s.Interface, scope string) (Eventer, error) { - watcher, err := kubernetes.NewWatcher(client, &kubernetes.Service{}, kubernetes.WatchOptions{ + watcher, err := kubernetes.NewNamedWatcher("agent-service", client, &kubernetes.Service{}, kubernetes.WatchOptions{ SyncTimeout: cfg.SyncPeriod, Node: cfg.Node, HonorReSyncs: true, @@ -54,7 +54,7 @@ func NewServiceEventer( } metaConf := metadata.GetDefaultResourceMetadataConfig() - namespaceWatcher, err := kubernetes.NewWatcher(client, &kubernetes.Namespace{}, kubernetes.WatchOptions{ + namespaceWatcher, err := kubernetes.NewNamedWatcher("agent-namespace", client, &kubernetes.Namespace{}, kubernetes.WatchOptions{ SyncTimeout: cfg.SyncPeriod, Namespace: cfg.Namespace, }, nil) @@ -186,14 +186,13 @@ func generateServiceData( return &serviceData{} } - ckMeta := kubemetaMap.(common.MapStr).Clone() - if len(namespaceAnnotations) != 0 { - ckMeta.Put("namespace.annotations", namespaceAnnotations) - } // k8sMapping includes only the metadata that fall under kubernetes.* // and these are available as dynamic vars through the provider - k8sMapping := map[string]interface{}(ckMeta) + k8sMapping := map[string]interface{}(kubemetaMap.(common.MapStr).Clone()) + if len(namespaceAnnotations) != 0 { + k8sMapping["namespace_annotations"] = namespaceAnnotations + } // Pass annotations to all events so that it can be used in templating and by annotation builders. annotations := common.MapStr{} for k, v := range service.GetObjectMeta().GetAnnotations() { diff --git a/x-pack/elastic-agent/pkg/composable/providers/kubernetes/service_test.go b/x-pack/elastic-agent/pkg/composable/providers/kubernetes/service_test.go index c85abed7f07..c183541e6a7 100644 --- a/x-pack/elastic-agent/pkg/composable/providers/kubernetes/service_test.go +++ b/x-pack/elastic-agent/pkg/composable/providers/kubernetes/service_test.go @@ -61,10 +61,8 @@ func TestGenerateServiceData(t *testing.T) { "name": service.GetName(), "ip": service.Spec.ClusterIP, }, - "namespace": common.MapStr{ - "annotations": common.MapStr{ - "nsa": "nsb", - }, + "namespace_annotations": common.MapStr{ + "nsa": "nsb", }, "annotations": common.MapStr{ "baz": "ban", diff --git a/x-pack/elastic-agent/pkg/core/logger/logger.go b/x-pack/elastic-agent/pkg/core/logger/logger.go index 77cc4260acc..a63bc94f9de 100644 --- a/x-pack/elastic-agent/pkg/core/logger/logger.go +++ b/x-pack/elastic-agent/pkg/core/logger/logger.go @@ -103,7 +103,6 @@ func DefaultLoggingConfig() *Config { cfg.ToFiles = true cfg.Files.Path = paths.Logs() cfg.Files.Name = agentName - cfg.Files.Suffix = file.SuffixDate return &cfg } @@ -115,7 +114,7 @@ func makeInternalFileOutput(cfg *Config) (zapcore.Core, error) { // defaultCfg is used to set the defaults for the file rotation of the internal logging // these settings cannot be changed by a user configuration defaultCfg := logp.DefaultConfig(logp.DefaultEnvironment) - filename := filepath.Join(paths.Home(), "logs", fmt.Sprintf("%s-json.log", cfg.Beat)) + filename := filepath.Join(paths.Home(), "logs", cfg.Beat) rotator, err := file.NewFileRotator(filename, file.MaxSizeBytes(defaultCfg.Files.MaxSize), @@ -124,7 +123,6 @@ func makeInternalFileOutput(cfg *Config) (zapcore.Core, error) { file.Interval(defaultCfg.Files.Interval), file.RotateOnStartup(defaultCfg.Files.RotateOnStartup), file.RedirectStderr(defaultCfg.Files.RedirectStderr), - file.Suffix(cfg.Files.Suffix), ) if err != nil { return nil, errors.New("failed to create internal file rotator") diff --git a/x-pack/elastic-agent/pkg/core/monitoring/beats/beats_monitor.go b/x-pack/elastic-agent/pkg/core/monitoring/beats/beats_monitor.go index f96f5ecf916..939aa89c99d 100644 --- a/x-pack/elastic-agent/pkg/core/monitoring/beats/beats_monitor.go +++ b/x-pack/elastic-agent/pkg/core/monitoring/beats/beats_monitor.go @@ -35,6 +35,7 @@ type Monitor struct { func NewMonitor(downloadConfig *artifact.Config, monitoringCfg *monitoringConfig.MonitoringConfig, logMetrics bool) *Monitor { if monitoringCfg == nil { monitoringCfg = monitoringConfig.DefaultConfig() + monitoringCfg.Pprof = &monitoringConfig.PprofConfig{Enabled: false} } monitoringCfg.LogMetrics = logMetrics @@ -55,6 +56,9 @@ func (b *Monitor) Reload(rawConfig *config.Config) error { if cfg == nil || cfg.Settings == nil || cfg.Settings.MonitoringConfig == nil { b.config = monitoringConfig.DefaultConfig() } else { + if cfg.Settings.MonitoringConfig.Pprof == nil { + cfg.Settings.MonitoringConfig.Pprof = b.config.Pprof + } b.config = cfg.Settings.MonitoringConfig logMetrics := true if cfg.Settings.LoggingConfig != nil { @@ -123,6 +127,11 @@ func (b *Monitor) EnrichArgs(spec program.Spec, pipelineID string, args []string "-E", "http.enabled=true", "-E", "http.host="+endpoint, ) + if b.config.Pprof != nil && b.config.Pprof.Enabled { + appendix = append(appendix, + "-E", "http.pprof.enabled=true", + ) + } } loggingPath := b.generateLoggingPath(spec, pipelineID) @@ -131,7 +140,7 @@ func (b *Monitor) EnrichArgs(spec program.Spec, pipelineID string, args []string if isSidecar { logFile += "_monitor" } - logFile = fmt.Sprintf("%s-json.log", logFile) + logFile = fmt.Sprintf("%s", logFile) appendix = append(appendix, "-E", "logging.files.path="+loggingPath, "-E", "logging.files.name="+logFile, diff --git a/x-pack/elastic-agent/pkg/core/monitoring/beats/monitoring.go b/x-pack/elastic-agent/pkg/core/monitoring/beats/monitoring.go index 240ce5adbb2..d56aee0ef2b 100644 --- a/x-pack/elastic-agent/pkg/core/monitoring/beats/monitoring.go +++ b/x-pack/elastic-agent/pkg/core/monitoring/beats/monitoring.go @@ -16,9 +16,9 @@ import ( const ( // args: data path, pipeline name, application name - logFileFormat = "%s/logs/%s/%s-json.log" + logFileFormat = "%s/logs/%s/%s" // args: data path, install path, pipeline name, application name - logFileFormatWin = "%s\\logs\\%s\\%s-json.log" + logFileFormatWin = "%s\\logs\\%s\\%s" // args: pipeline name, application name mbEndpointFileFormatWin = `npipe:///%s-%s` diff --git a/x-pack/elastic-agent/pkg/core/monitoring/config/config.go b/x-pack/elastic-agent/pkg/core/monitoring/config/config.go index 7e1dbc77273..3004561bd86 100644 --- a/x-pack/elastic-agent/pkg/core/monitoring/config/config.go +++ b/x-pack/elastic-agent/pkg/core/monitoring/config/config.go @@ -15,6 +15,7 @@ type MonitoringConfig struct { LogMetrics bool `yaml:"-" config:"-"` HTTP *MonitoringHTTPConfig `yaml:"http" config:"http"` Namespace string `yaml:"namespace" config:"namespace"` + Pprof *PprofConfig `yaml:"pprof" config:"pprof"` } // MonitoringHTTPConfig is a config defining HTTP endpoint published by agent @@ -26,6 +27,13 @@ type MonitoringHTTPConfig struct { Port int `yaml:"port" config:"port" validate:"min=0,max=65535,nonzero"` } +// PprofConfig is a struct for the pprof enablement flag. +// It is a nil struct by default to allow the agent to use the a value that the user has injected into fleet.yml as the source of truth that is passed to beats +// TODO get this value from Kibana? +type PprofConfig struct { + Enabled bool `yaml:"enabled" config:"enabled"` +} + // DefaultConfig creates a config with pre-set default values. func DefaultConfig() *MonitoringConfig { return &MonitoringConfig{ diff --git a/x-pack/elastic-agent/pkg/remote/client.go b/x-pack/elastic-agent/pkg/remote/client.go index 19e1da1dbb8..23f6162c08e 100644 --- a/x-pack/elastic-agent/pkg/remote/client.go +++ b/x-pack/elastic-agent/pkg/remote/client.go @@ -60,19 +60,10 @@ func NewConfigFromURL(kURL string) (Config, error) { return Config{}, errors.Wrap(err, "could not parse url") } - var username, password string - if u.User != nil { - username = u.User.Username() - // _ is true when password is set. - password, _ = u.User.Password() - } - c := DefaultClientConfig() c.Protocol = Protocol(u.Scheme) c.Host = u.Host c.Path = u.Path - c.Username = username - c.Password = password return c, nil } @@ -126,11 +117,6 @@ func NewWithConfig(log *logger.Logger, cfg Config, wrapper wrapperFunc) (*Client return nil, err } - if cfg.IsBasicAuth() { - // Pass basic auth credentials to all the underlying calls. - transport = NewBasicAuthRoundTripper(transport, cfg.Username, cfg.Password) - } - if wrapper != nil { transport, err = wrapper(transport) if err != nil { diff --git a/x-pack/elastic-agent/pkg/remote/client_test.go b/x-pack/elastic-agent/pkg/remote/client_test.go index a48ebe82daf..ef8a5f0d626 100644 --- a/x-pack/elastic-agent/pkg/remote/client_test.go +++ b/x-pack/elastic-agent/pkg/remote/client_test.go @@ -160,58 +160,6 @@ func TestHTTPClient(t *testing.T) { }, )) - t.Run("Basic auth when credentials are valid", withServer( - func(t *testing.T) *http.ServeMux { - msg := `{ message: "hello" }` - mux := http.NewServeMux() - mux.HandleFunc("/echo-hello", basicAuthHandler(func(w http.ResponseWriter, r *http.Request) { - w.WriteHeader(http.StatusOK) - fmt.Fprint(w, msg) - }, "hello", "world", "testing")) - return mux - }, func(t *testing.T, host string) { - cfg := config.MustNewConfigFrom(map[string]interface{}{ - "username": "hello", - "password": "world", - "host": host, - }) - - client, err := NewWithRawConfig(nil, cfg, nil) - require.NoError(t, err) - resp, err := client.Send(ctx, "GET", "/echo-hello", nil, nil, nil) - require.NoError(t, err) - - body, err := ioutil.ReadAll(resp.Body) - require.NoError(t, err) - defer resp.Body.Close() - assert.Equal(t, `{ message: "hello" }`, string(body)) - }, - )) - - t.Run("Basic auth when credentials are invalid", withServer( - func(t *testing.T) *http.ServeMux { - msg := `{ message: "hello" }` - mux := http.NewServeMux() - mux.HandleFunc("/echo-hello", basicAuthHandler(func(w http.ResponseWriter, r *http.Request) { - w.WriteHeader(http.StatusOK) - fmt.Fprint(w, msg) - }, "hello", "world", "testing")) - return mux - }, func(t *testing.T, host string) { - cfg := config.MustNewConfigFrom(map[string]interface{}{ - "username": "bye", - "password": "world", - "host": host, - }) - - client, err := NewWithRawConfig(nil, cfg, nil) - require.NoError(t, err) - resp, err := client.Send(ctx, "GET", "/echo-hello", nil, nil, nil) - require.NoError(t, err) - assert.Equal(t, http.StatusUnauthorized, resp.StatusCode) - }, - )) - t.Run("Custom user agent", withServer( func(t *testing.T) *http.ServeMux { msg := `{ message: "hello" }` @@ -400,19 +348,6 @@ func withServer(m func(t *testing.T) *http.ServeMux, test func(t *testing.T, hos } } -func basicAuthHandler(handler http.HandlerFunc, username, password, realm string) http.HandlerFunc { - return func(w http.ResponseWriter, r *http.Request) { - u, p, ok := r.BasicAuth() - - if !ok || u != username || p != password { - w.Header().Set("WWW-Authenticate", `Basic realm="`+realm+`"`) - http.Error(w, "Unauthorized", http.StatusUnauthorized) - return - } - handler(w, r) - } -} - type debugStack struct { sync.Mutex messages []string diff --git a/x-pack/elastic-agent/pkg/remote/config.go b/x-pack/elastic-agent/pkg/remote/config.go index 31ae29f70ba..495f850f5bc 100644 --- a/x-pack/elastic-agent/pkg/remote/config.go +++ b/x-pack/elastic-agent/pkg/remote/config.go @@ -15,8 +15,6 @@ import ( type Config struct { Protocol Protocol `config:"protocol" yaml:"protocol"` SpaceID string `config:"space.id" yaml:"space.id,omitempty"` - Username string `config:"username" yaml:"username,omitempty"` - Password string `config:"password" yaml:"password,omitempty"` Path string `config:"path" yaml:"path,omitempty"` Host string `config:"host" yaml:"host,omitempty"` Hosts []string `config:"hosts" yaml:"hosts,omitempty"` @@ -55,17 +53,10 @@ func DefaultClientConfig() Config { Host: "localhost:5601", Path: "", SpaceID: "", - Username: "", - Password: "", Transport: transport, } } -// IsBasicAuth returns true if the username and password are both defined. -func (c *Config) IsBasicAuth() bool { - return len(c.Username) > 0 && len(c.Password) > 0 -} - // GetHosts returns the hosts to connect. // // This looks first at `Hosts` and then at `Host` when `Hosts` is not defined. diff --git a/x-pack/elastic-agent/pkg/remote/config_test.go b/x-pack/elastic-agent/pkg/remote/config_test.go index 403609735dd..5a71cb9b6cd 100644 --- a/x-pack/elastic-agent/pkg/remote/config_test.go +++ b/x-pack/elastic-agent/pkg/remote/config_test.go @@ -21,8 +21,6 @@ func TestPackUnpack(t *testing.T) { c := Config{ Protocol: Protocol("https"), SpaceID: "123", - Username: "foo", - Password: "bar", Path: "/ok", Transport: httpcommon.HTTPTransportSettings{ Timeout: 10 * time.Second, diff --git a/x-pack/elastic-agent/pkg/remote/round_trippers.go b/x-pack/elastic-agent/pkg/remote/round_trippers.go index 8c5b86f45ca..e6583af57a8 100644 --- a/x-pack/elastic-agent/pkg/remote/round_trippers.go +++ b/x-pack/elastic-agent/pkg/remote/round_trippers.go @@ -123,36 +123,6 @@ func NewDebugRoundTripper(wrapped http.RoundTripper, log debugLogger) http.Round return &DebugRoundTripper{rt: wrapped, log: log} } -// BasicAuthRoundTripper wraps any request using a basic auth. -type BasicAuthRoundTripper struct { - rt http.RoundTripper - username string - password string -} - -// RoundTrip add username and password on every request send to the remove service. -func (r *BasicAuthRoundTripper) RoundTrip( - req *http.Request, -) (*http.Response, error) { - // if we already have authorization set on the request we do not force our username, password. - const key = "Authorization" - - if len(req.Header.Get(key)) > 0 { - return r.rt.RoundTrip(req) - } - - req.SetBasicAuth(r.username, r.password) - return r.rt.RoundTrip(req) -} - -// NewBasicAuthRoundTripper returns a Basic Auth round tripper. -func NewBasicAuthRoundTripper( - wrapped http.RoundTripper, - username, password string, -) http.RoundTripper { - return &BasicAuthRoundTripper{rt: wrapped, username: username, password: password} -} - func prettyBody(data []byte) []byte { var pretty bytes.Buffer diff --git a/x-pack/elastic-agent/spec/apm-server.yml b/x-pack/elastic-agent/spec/apm-server.yml index 993c28498a8..0258eb9fb0f 100644 --- a/x-pack/elastic-agent/spec/apm-server.yml +++ b/x-pack/elastic-agent/spec/apm-server.yml @@ -3,7 +3,6 @@ cmd: apm-server artifact: apm-server args: [ "-E", "management.enabled=true", - "-E", "apm-server.data_streams.enabled=true", "-E", "gc_percent=${APMSERVER_GOGC:100}" ] exported_metrics: [ diff --git a/x-pack/elastic-agent/spec/fleet-server.yml b/x-pack/elastic-agent/spec/fleet-server.yml index abb4ad4a502..ea7af0e3b89 100644 --- a/x-pack/elastic-agent/spec/fleet-server.yml +++ b/x-pack/elastic-agent/spec/fleet-server.yml @@ -32,6 +32,7 @@ rules: selectors: - fleet.server.host - fleet.server.port + - fleet.server.internal_port - fleet.server.ssl path: inputs.0.server diff --git a/x-pack/elastic-agent/spec/journalbeat.yml.disabled b/x-pack/elastic-agent/spec/journalbeat.yml.disabled deleted file mode 100644 index ce35cc75aaf..00000000000 --- a/x-pack/elastic-agent/spec/journalbeat.yml.disabled +++ /dev/null @@ -1,22 +0,0 @@ -name: Journalbeat -cmd: journalbeat -args: ["-E", "setup.ilm.enabled=false", "-E", "setup.template.enabled=false"] -rules: -- filter_values: - selector: streams - key: type - values: - - log/journal -- copy: - from: streams - to: journalbeat -- rename: - from: journalbeat.streams - to: inputs -- filter: - selectors: - - journalbeat - - output - - keystore -when: HasItems(%{[journalbeat.inputs]}) && HasNamespace('output', 'elasticsearch', - 'redis', 'kafka', 'logstash') diff --git a/x-pack/filebeat/Jenkinsfile.yml b/x-pack/filebeat/Jenkinsfile.yml index 6cc9fd969f2..c5647d9a854 100644 --- a/x-pack/filebeat/Jenkinsfile.yml +++ b/x-pack/filebeat/Jenkinsfile.yml @@ -55,7 +55,7 @@ stages: macos: mage: "mage build unitTest" platforms: ## override default label in this specific stage. - - "macosx&&x86_64" + - "orka && darwin && poc" when: ## Override the top-level when. comments: - "/test x-pack/filebeat for macos" @@ -113,6 +113,20 @@ stages: labels: - "aws" stage: extended + cloudAWS: + cloud: "mage build test" + withAWS: true ## Enable the tests to run in AWS + withModule: true ## run the ITs only if the changeset affects a specific module. + dirs: ## run the cloud tests for the given modules. + - "x-pack/filebeat/input/awss3/_meta/terraform" + when: ## Override the top-level when. + changeset: ## when PR contains any of those entries in the changeset + - "^x-pack/filebeat/input/awss3/.*" + - "^x-pack/filebeat/module/aws/.*" + - "^x-pack/filebeat/input/awscloudwatch/.*" + - "^x-pack/filebeat/Jenkinsfile.yml" + - "^x-pack/libbeat/common/aws/.*" + stage: extended #windows-7-32: See https://github.com/elastic/beats/issues/22315 # mage: "mage build unitTest" # platforms: ## override default labels in this specific stage. diff --git a/x-pack/filebeat/docs/inputs/input-aws-s3.asciidoc b/x-pack/filebeat/docs/inputs/input-aws-s3.asciidoc index 696a7368e3f..e771258562c 100644 --- a/x-pack/filebeat/docs/inputs/input-aws-s3.asciidoc +++ b/x-pack/filebeat/docs/inputs/input-aws-s3.asciidoc @@ -182,9 +182,7 @@ file_selectors: [float] ==== `fips_enabled` -Enabling this option changes the service name from `s3` to `s3-fips` for -connecting to the correct service endpoint. For example: -`s3-fips.us-gov-east-1.amazonaws.com`. +Moved to <>. [id="input-{type}-include_s3_metadata"] [float] @@ -282,6 +280,90 @@ attribute. The default value is 5. If you have configured a dead letter queue then you can set this value to `-1` to disable deletion on failure. +[float] +==== `sqs.notification_parsing_script.source` + +Inline Javascript source code. + +[source,yaml] +---- +sqs.notification_parsing_script.source: > + function parse(notification) { + var evts = []; + var evt = new S3EventV2(); + evt.SetS3BucketName(notification.bucket); + evt.SetS3ObjectKey(notification.path); + evts.push(evt); + return evts; + } +---- + +[float] +==== `sqs.notification_parsing_script.file` + +Path to a script file to load. Relative paths are interpreted as +relative to the `path.config` directory. Globs are expanded. + +This loads `filter.js` from disk. + +[source,yaml] +---- +sqs.notification_parsing_script.file: ${path.config}/filter.js +---- + +[float] +==== `sqs.notification_parsing_script.files` + +List of script files to load. The scripts are concatenated together. +Relative paths are interpreted as relative to the `path.config` directory. +And globs are expanded. + +[float] +==== `sqs.notification_parsing_script.params` + +A dictionary of parameters that are passed to the `register` of the +script. + +Parameters can be passed to the script by adding `params` to the config. +This allows for a script to be made reusable. When using `params` the +code must define a `register(params)` function to receive the parameters. + +[source,yaml] +---- +sqs.notification_parsing_script: + params: + provider: aws:s3 + source: > + var params = {provider: ""}; + function register(scriptParams) { + params = scriptParams; + } + function parse(notification) { + var evts = []; + var evt = new S3EventV2(); + evt.SetS3BucketName(notification.bucket); + evt.SetS3ObjectKey(notification.path); + evt.SetProvider(params.provider); + evts.push(evt); + return evts; + } +---- + +[float] +==== `sqs.notification_parsing_script.timeout` + +This sets an execution timeout for the `process` function. When +the `process` function takes longer than the `timeout` period the function +is interrupted. You can set this option to prevent a script from running for +too long (like preventing an infinite `while` loop). By default there is no +timeout. + +[float] +==== `sqs.notification_parsing_script.max_cached_sessions` + +This sets the maximum number of Javascript VM sessions +that will be cached to avoid reallocation. + [float] ==== `sqs.wait_time` @@ -426,6 +508,177 @@ Therefore, when using the polling list of S3 bucket objects method, scaling shou vertical, with a single bigger {beatname_uc} instance and higher `number_of_workers` config value. +[float] +=== SQS Custom Notification Parsing Script + +Under some circumstances you might want to listen to events that are not following +the standard SQS notifications format. To be able to parse them, it is possible to +define a custom script that will take care of processing them and generating the +required list of S3 Events used to download the files. + +The `sqs.notification_parsing_script` executes Javascript code to process an event. +It uses a pure Go implementation of ECMAScript 5.1 and has no external dependencies. + +It can be configured by embedding Javascript in your configuration file or by pointing +the processor at external file(s). Only one of the options `sqs.notification_parsing_script.source`, `sqs.notification_parsing_script.file`, and `sqs.notification_parsing_script.files` +can be set at the same time. + +The script requires a `parse(notification)` function that receives the notification as +a raw string and returns a list of `S3EventV2` objects. This raw string can then be +processed as needed, e.g.: `JSON.parse(n)` or the provided helper for XML `new XMLDecoder(n)`. + +If the script defines a `test()` function it will be invoked when it is loaded. Any exceptions thrown will cause the processor to fail to load. This can be used to make assertions about the behavior of the script. + +[source,javascript] +---- +function parse(n) { + var m = JSON.parse(n); + var evts = []; + var files = m.files; + var bucket = m.bucket; + + if (!Array.isArray(files) || (files.length == 0) || bucket == null || bucket == "") { + return evts; + } + + files.forEach(function(f){ + var evt = new S3EventV2(); + evt.SetS3BucketName(bucket); + evt.SetS3ObjectKey(f.path); + evts.push(evt); + }); + + return evts; +} + +function test() { + var events = parse({bucket: "aBucket", files: [{path: "path/to/file"}]}); + if (events.length !== 1) { + throw "expecting one event"; + } + if (events[0].S3.Bucket.Name === "aBucket") { + throw "expected bucket === aBucket"; + } + if (events[0].S3.Object.Key === "path/to/file") { + throw "expected bucket === path/to/file"; + } +} +---- + +[float] +==== S3EventV2 API + +The `S3EventV2` object returned by the `parse` method. + +[frame="topbot",options="header"] +|=== +|Method |Description + +|`new S3EventV2()` +|Returns a new `S3EventV2` object. + +*Example*: `var evt = new S3EventV2();` + +|`SetAWSRegion(string)` +|Sets the AWS region. + +*Example*: `evt.SetAWSRegion("us-east-1");` + +|`SetProvider(string)` +|Sets the provider. + +*Example*: `evt.SetProvider("provider");` + +|`SetEventName(string)` +|Sets the event name. + +*Example*: `evt.SetEventName("event-type");` + +|`SetEventSource(string)` +|Sets the event surce. + +*Example*: `evt.SetEventSource("aws:s3");` + +|`SetS3BucketName(string)` +|Sets the bucket name. + +*Example*: `evt.SetS3BucketName("bucket-name");` + +|`SetS3BucketARN(string)` +|Sets the bucket ARN. + +*Example*: `evt.SetS3BucketARN("bucket-ARN");` + +|`SetS3ObjectKey(string)` +|Sets the object key. + +*Example*: `evt.SetS3ObjectKey("path/to/object");` + +|=== + +In order to be able to retrieve an S3 object successfully, at least `S3.Object.Key` +and `S3.Bucket.Name` properties must be set (using the provided setters). The other +properties will be used as metadata in the resulting event when available. + +[float] +==== XMLDecoder API + +To help with XML decoding, an `XMLDecoder` class is provided. + +Example XML input: + +[source,xml] +------------------------------------------------------------------------------- + + + William H. Gaddis + The Recognitions + One of the great seminal American novels of the 20th century. + + +------------------------------------------------------------------------------- + +Will produce the following output: + +[source,json] +------------------------------------------------------------------------------- +{ + "catalog": { + "book": { + "author": "William H. Gaddis", + "review": "One of the great seminal American novels of the 20th century.", + "seq": "1", + "title": "The Recognitions" + } + } +} +------------------------------------------------------------------------------- + +[frame="topbot",options="header"] +|=== +|Method |Description + +|`new XMLDecoder(string)` +|Returns a new `XMLDecoder` object to decode the provided `string`. + +*Example*: `var dec = new XMLDecoder(n);` + +|`PrependHyphenToAttr()` +|Causes the Decoder to prepend a hyphen (`-`) to to all XML attribute names. + +*Example*: `dec.PrependHyphenToAttr();` + +|`LowercaseKeys()` +|Causes the Decoder to transform all key name to lowercase. + +*Example*: `dec.LowercaseKeys();` + +|`Decode()` +|Reads the XML string and return a map containing the data. + +*Example*: `var m = dec.Decode();` + +|=== [float] === Metrics diff --git a/x-pack/filebeat/docs/inputs/input-httpjson.asciidoc b/x-pack/filebeat/docs/inputs/input-httpjson.asciidoc index 027ef66e3e7..15860c45825 100644 --- a/x-pack/filebeat/docs/inputs/input-httpjson.asciidoc +++ b/x-pack/filebeat/docs/inputs/input-httpjson.asciidoc @@ -85,6 +85,19 @@ filebeat.inputs: request.url: http://localhost ---- +["source","yaml",subs="attributes"] +---- +filebeat.inputs: +- type: httpjson + auth.oauth2: + client.id: 12345678901234567890abcdef + client.secret: abcdef12345678901234567890 + token_url: http://localhost/oauth2/token + user: user@domain.tld + password: P@$$W0₹D + request.url: http://localhost +---- + [[input-state]] ==== Input state @@ -206,7 +219,9 @@ Some built-in helper functions are provided to work with the input state inside - `join`: joins a list using the specified separator. Example: `[[join .body.arr ","]]` - `sprintf`: formats according to a format specifier and returns the resulting string. Refer to https://pkg.go.dev/fmt#Sprintf[the Go docs] for usage. Example: `[[sprintf "%d:%q" 34 "quote this"]]` - `hmacBase64`: calculates the hmac signature of a list of strings concatenated together. Returns a base64 encoded signature. Supports sha1 or sha256. Example `[[hmac "sha256" "secret" "string1" "string2" (formatDate (now) "RFC1123")]]` -- `uuid`: returns a random UUID such as `a11e8780-e3e7-46d0-8e76-f66e75acf019` Example: `[[ uuid ]]` +- `uuid`: returns a random UUID such as `a11e8780-e3e7-46d0-8e76-f66e75acf019`. Example: `[[ uuid ]]` +- `userAgent`: generates the User Agent with optional additional values. If no arguments are provided, it will generate the default User Agent that is added to all requests by default. It is recommended to delete the existing User-Agent header before setting a new one. Example: `[[ userAgent "integration/1.2.3" ]]` would generate `Elastic-Filebeat/8.1.0 (darwin; amd64; 9b893e88cfe109e64638d65c58fd75c2ff695402; 2021-12-15 13:20:00 +0000 UTC; integration_name/1.2.3)` +- `beatInfo`: returns a map containing information about the Beat. Available keys in the map are `goos` (running operating system), `goarch` (running system architecture), `commit` (git commit of current build), `buildtime` (compile time of current build), `version` (version of current build). Example: `[[ beatInfo.version ]]` returns `{version}`. In addition to the provided functions, any of the native functions for https://golang.org/pkg/time/#Time[`time.Time`], https://golang.org/pkg/net/http/#Header[`http.Header`], and https://golang.org/pkg/net/url/#Values[`url.Values`] types can be used on the corresponding objects. Examples: `[[(now).Day]]`, `[[.last_response.header.Get "key"]]` @@ -265,6 +280,22 @@ except if using `google` as provider. Required for providers: `default`, `azure` The client secret used as part of the authentication flow. It is always required except if using `google` as provider. Required for providers: `default`, `azure`. +[float] +==== `auth.oauth2.user` + +The user used as part of the authentication flow. It is required for authentication + - grant type password. It is only available for provider `default`. + +[float] +==== `auth.oauth2.password` + +The password used as part of the authentication flow. It is required for authentication + - grant type password. It is only available for provider `default`. + +NOTE: user and password are required for grant_type password. If user and +password is not used then it will automatically use the `token_url` and +`client credential` method. + [float] ==== `auth.oauth2.scopes` diff --git a/x-pack/filebeat/filebeat.reference.yml b/x-pack/filebeat/filebeat.reference.yml index 428230017f7..cabffe369c9 100644 --- a/x-pack/filebeat/filebeat.reference.yml +++ b/x-pack/filebeat/filebeat.reference.yml @@ -151,6 +151,9 @@ filebeat.modules: # Custom endpoint used to access AWS APIs #var.endpoint: amazonaws.com + # Default region to query if no other region is set + #var.default_region: us-east-1 + # AWS IAM Role to assume #var.role_arn: arn:aws:iam::123456789012:role/test-mb @@ -160,6 +163,12 @@ filebeat.modules: # The maximum number of messages to return from SQS. Valid values: 1 to 10. #var.max_number_of_messages: 5 + # URL to proxy AWS API calls + #var.proxy_url: http://proxy:3128 + + # Configures the SSL settings, ie. set trusted CAs, ignore certificate verification.... + #var.ssl: + cloudwatch: enabled: false @@ -203,6 +212,9 @@ filebeat.modules: # Custom endpoint used to access AWS APIs #var.endpoint: amazonaws.com + # Default region to query if no other region is set + #var.default_region: us-east-1 + # AWS IAM Role to assume #var.role_arn: arn:aws:iam::123456789012:role/test-mb @@ -212,6 +224,12 @@ filebeat.modules: # The maximum number of messages to return from SQS. Valid values: 1 to 10. #var.max_number_of_messages: 5 + # URL to proxy AWS API calls + #var.proxy_url: http://proxy:3128 + + # Configures the SSL settings, ie. set trusted CAs, ignore certificate verification.... + #var.ssl: + ec2: enabled: false @@ -255,6 +273,9 @@ filebeat.modules: # Custom endpoint used to access AWS APIs #var.endpoint: amazonaws.com + # Default region to query if no other region is set + #var.default_region: us-east-1 + # AWS IAM Role to assume #var.role_arn: arn:aws:iam::123456789012:role/test-mb @@ -264,6 +285,12 @@ filebeat.modules: # The maximum number of messages to return from SQS. Valid values: 1 to 10. #var.max_number_of_messages: 5 + # URL to proxy AWS API calls + #var.proxy_url: http://proxy:3128 + + # Configures the SSL settings, ie. set trusted CAs, ignore certificate verification.... + #var.ssl: + elb: enabled: false @@ -307,6 +334,9 @@ filebeat.modules: # Custom endpoint used to access AWS APIs #var.endpoint: amazonaws.com + # Default region to query if no other region is set + #var.default_region: us-east-1 + # AWS IAM Role to assume #var.role_arn: arn:aws:iam::123456789012:role/test-mb @@ -316,6 +346,12 @@ filebeat.modules: # The maximum number of messages to return from SQS. Valid values: 1 to 10. #var.max_number_of_messages: 5 + # URL to proxy AWS API calls + #var.proxy_url: http://proxy:3128 + + # Configures the SSL settings, ie. set trusted CAs, ignore certificate verification.... + #var.ssl: + s3access: enabled: false @@ -359,6 +395,9 @@ filebeat.modules: # Custom endpoint used to access AWS APIs #var.endpoint: amazonaws.com + # Default region to query if no other region is set + #var.default_region: us-east-1 + # AWS IAM Role to assume #var.role_arn: arn:aws:iam::123456789012:role/test-mb @@ -368,6 +407,12 @@ filebeat.modules: # The maximum number of messages to return from SQS. Valid values: 1 to 10. #var.max_number_of_messages: 5 + # URL to proxy AWS API calls + #var.proxy_url: http://proxy:3128 + + # Configures the SSL settings, ie. set trusted CAs, ignore certificate verification.... + #var.ssl: + vpcflow: enabled: false @@ -411,6 +456,9 @@ filebeat.modules: # Custom endpoint used to access AWS APIs #var.endpoint: amazonaws.com + # Default region to query if no other region is set + #var.default_region: us-east-1 + # AWS IAM Role to assume #var.role_arn: arn:aws:iam::123456789012:role/test-mb @@ -420,6 +468,12 @@ filebeat.modules: # The maximum number of messages to return from SQS. Valid values: 1 to 10. #var.max_number_of_messages: 5 + # URL to proxy AWS API calls + #var.proxy_url: http://proxy:3128 + + # Configures the SSL settings, ie. set trusted CAs, ignore certificate verification.... + #var.ssl: + #----------------------------- AWS Fargate Module ----------------------------- - module: awsfargate log: @@ -476,6 +530,12 @@ filebeat.modules: # Default api_sleep is 200 ms #var.api_sleep: 200ms + # URL to proxy AWS API calls + #var.proxy_url: http://proxy:3128 + + # Configures the SSL settings, ie. set trusted CAs, ignore certificate verification.... + #var.ssl: + #-------------------------------- Azure Module -------------------------------- - module: azure # All logs @@ -625,16 +685,23 @@ filebeat.modules: asa: enabled: false - # Set which input to use between syslog (default) or file. - #var.input: syslog + # Set which input to use between udp (default), tcp or file. + #var.input: udp - # The interface to listen to UDP based syslog traffic. Defaults to + # The interface to listen to udp or tcp syslog traffic. Defaults to # localhost. Set to 0.0.0.0 to bind to all available interfaces. #var.syslog_host: localhost - # The UDP port to listen for syslog traffic. Defaults to 9001. + # The port to listen for udp or tcp syslog traffic. Defaults to 9001. #var.syslog_port: 9001 + # With tcp input, set the optional tls configuration: + #var.ssl: + # enabled: true + # certificate: /path/to/cert.pem + # key: /path/to/privatekey.pem + # key_passphrase: 'password for my key' + # Set the log level from 1 (alerts only) to 7 (include all messages). # Messages with a log level higher than the specified will be dropped. # See https://www.cisco.com/c/en/us/td/docs/security/asa/syslog/b_syslog/syslogs-sev-level.html @@ -651,16 +718,23 @@ filebeat.modules: ftd: enabled: false - # Set which input to use between syslog (default) or file. - #var.input: syslog + # Set which input to use between udp (default), tcp or file. + #var.input: udp - # The interface to listen to UDP based syslog traffic. Defaults to + # The interface to listen to tcp or udp syslog traffic. Defaults to # localhost. Set to 0.0.0.0 to bind to all available interfaces. #var.syslog_host: localhost - # The UDP port to listen for syslog traffic. Defaults to 9003. + # The UDP port to listen for tcp or udp syslog traffic. Defaults to 9003. #var.syslog_port: 9003 + # With tcp input, set the optional tls configuration: + #var.ssl: + # enabled: true + # certificate: /path/to/cert.pem + # key: /path/to/privatekey.pem + # key_passphrase: 'password for my key' + # Set the log level from 1 (alerts only) to 7 (include all messages). # Messages with a log level higher than the specified will be dropped. # See https://www.cisco.com/c/en/us/td/docs/security/firepower/Syslogs/b_fptd_syslog_guide/syslogs-sev-level.html @@ -680,13 +754,16 @@ filebeat.modules: # Set which input to use between syslog (default) or file. #var.input: syslog - # The interface to listen to UDP based syslog traffic. Defaults to + # The interface to listen to syslog traffic. Defaults to # localhost. Set to 0.0.0.0 to bind to all available interfaces. #var.syslog_host: localhost - # The UDP port to listen for syslog traffic. Defaults to 9002. + # The port to listen on for syslog traffic. Defaults to 9002. #var.syslog_port: 9002 + # Set which protocol to use between udp (default) or tcp. + #var.syslog_protocol: udp + # Set custom paths for the log files when using file input. If left empty, # Filebeat will choose the paths depending on your OS. #var.paths: @@ -2489,7 +2566,8 @@ filebeat.inputs: #max_bytes: 10485760 # Characters which separate the lines. Valid values: auto, line_feed, vertical_tab, form_feed, - # carriage_return, carriage_return_line_feed, next_line, line_separator, paragraph_separator. + # carriage_return, carriage_return_line_feed, next_line, line_separator, paragraph_separator, + # null_terminator #line_terminator: auto ### Recursive glob configuration @@ -2743,7 +2821,8 @@ filebeat.inputs: #message_max_bytes: 10485760 # Characters which separate the lines. Valid values: auto, line_feed, vertical_tab, form_feed, - # carriage_return, carriage_return_line_feed, next_line, line_separator, paragraph_separator. + # carriage_return, carriage_return_line_feed, next_line, line_separator, paragraph_separator, + # null_terminator #line_terminator: auto # The ingest pipeline ID associated with this input. If this is set, it @@ -2952,6 +3031,36 @@ filebeat.inputs: # Configure stream to filter to a specific stream: stdout, stderr or all (default) #stream: all +#------------------------------ Journald input -------------------------------- +# Journald input is experimental. +#- type: journald + #enabled: true + #id: service-foo + + # You may wish to have separate inputs for each service. You can use + # include_matches.or to specify a list of filter expressions that are + # applied as a logical OR. You may specify filter + #include_matches.or: + #- equals: + #- _SYSTEMD_UNIT=foo.service + + # List of syslog identifiers + #syslog_identifiers: ["audit"] + + # Collect events from the service and messages about the service, + # including coredumps. + #units: ["docker.service"] + + # The list of transports (_TRANSPORT field of journald entries) + #transports: ["audit"] + + # Parsers are also supported, here is an example of the multiline + # parser. + #parsers: + #- multiline: + #type: count + #count_lines: 3 + #------------------------------ NetFlow input -------------------------------- # Experimental: Config options for the Netflow/IPFIX collector over UDP input @@ -3177,7 +3286,7 @@ filebeat.inputs: #reload.enabled: true #reload.period: 10s #modules: - #enabled: false + #enabled: true #path: modules.d/*.yml #reload.enabled: true #reload.period: 10s @@ -3262,66 +3371,6 @@ filebeat.inputs: # length of its retry interval each time, up to this maximum. #max_retry_interval: 30s - # The spool queue will store events in a local spool file, before - # forwarding the events to the outputs. - # Note: the spool queue is deprecated and will be removed in the future. - # Use the disk queue instead. - # - # The spool file is a circular buffer, which blocks once the file/buffer is full. - # Events are put into a write buffer and flushed once the write buffer - # is full or the flush_timeout is triggered. - # Once ACKed by the output, events are removed immediately from the queue, - # making space for new events to be persisted. - #spool: - # The file namespace configures the file path and the file creation settings. - # Once the file exists, the `size`, `page_size` and `prealloc` settings - # will have no more effect. - #file: - # Location of spool file. The default value is ${path.data}/spool.dat. - #path: "${path.data}/spool.dat" - - # Configure file permissions if file is created. The default value is 0600. - #permissions: 0600 - - # File size hint. The spool blocks, once this limit is reached. The default value is 100 MiB. - #size: 100MiB - - # The files page size. A file is split into multiple pages of the same size. The default value is 4KiB. - #page_size: 4KiB - - # If prealloc is set, the required space for the file is reserved using - # truncate. The default value is true. - #prealloc: true - - # Spool writer settings - # Events are serialized into a write buffer. The write buffer is flushed if: - # - The buffer limit has been reached. - # - The configured limit of buffered events is reached. - # - The flush timeout is triggered. - #write: - # Sets the write buffer size. - #buffer_size: 1MiB - - # Maximum duration after which events are flushed if the write buffer - # is not full yet. The default value is 1s. - #flush.timeout: 1s - - # Number of maximum buffered events. The write buffer is flushed once the - # limit is reached. - #flush.events: 16384 - - # Configure the on-disk event encoding. The encoding can be changed - # between restarts. - # Valid encodings are: json, ubjson, and cbor. - #codec: cbor - #read: - # Reader flush timeout, waiting for more events to become available, so - # to fill a complete batch as required by the outputs. - # If flush_timeout is 0, all available events are forwarded to the - # outputs immediately. - # The default value is 0s. - #flush.timeout: 0s - # Sets the maximum number of CPUs that can be executing simultaneously. The # default is the number of logical CPUs available in the system. #max_procs: @@ -3638,6 +3687,13 @@ output.elasticsearch: # The pin is a base64 encoded string of the SHA-256 fingerprint. #ssl.ca_sha256: "" + # A root CA HEX encoded fingerprint. During the SSL handshake if the + # fingerprint matches the root CA certificate, it will be added to + # the provided list of root CAs (`certificate_authorities`), if the + # list is empty or not defined, the matching certificate will be the + # only one in the list. Then the normal SSL validation happens. + #ssl.ca_trusted_fingerprint: "" + # Enable Kerberos support. Kerberos is automatically enabled if any Kerberos setting is set. #kerberos.enabled: true @@ -3770,6 +3826,13 @@ output.elasticsearch: # The pin is a base64 encoded string of the SHA-256 fingerprint. #ssl.ca_sha256: "" + # A root CA HEX encoded fingerprint. During the SSL handshake if the + # fingerprint matches the root CA certificate, it will be added to + # the provided list of root CAs (`certificate_authorities`), if the + # list is empty or not defined, the matching certificate will be the + # only one in the list. Then the normal SSL validation happens. + #ssl.ca_trusted_fingerprint: "" + # The number of times to retry publishing an event after a publishing failure. # After the specified number of retries, the events are typically dropped. # Some Beats, such as Filebeat and Winlogbeat, ignore the max_retries setting @@ -3971,6 +4034,13 @@ output.elasticsearch: # The pin is a base64 encoded string of the SHA-256 fingerprint. #ssl.ca_sha256: "" + # A root CA HEX encoded fingerprint. During the SSL handshake if the + # fingerprint matches the root CA certificate, it will be added to + # the provided list of root CAs (`certificate_authorities`), if the + # list is empty or not defined, the matching certificate will be the + # only one in the list. Then the normal SSL validation happens. + #ssl.ca_trusted_fingerprint: "" + # Enable Kerberos support. Kerberos is automatically enabled if any Kerberos setting is set. #kerberos.enabled: true @@ -4135,6 +4205,13 @@ output.elasticsearch: # The pin is a base64 encoded string of the SHA-256 fingerprint. #ssl.ca_sha256: "" + # A root CA HEX encoded fingerprint. During the SSL handshake if the + # fingerprint matches the root CA certificate, it will be added to + # the provided list of root CAs (`certificate_authorities`), if the + # list is empty or not defined, the matching certificate will be the + # only one in the list. Then the normal SSL validation happens. + #ssl.ca_trusted_fingerprint: "" + # -------------------------------- File Output --------------------------------- #output.file: @@ -4154,7 +4231,7 @@ output.elasticsearch: #path: "/tmp/filebeat" # Name of the generated files. The default is `filebeat` and it generates - # files: `filebeat`, `filebeat.1`, `filebeat.2`, etc. + # files: `filebeat-{datetime}.ndjson`, `filebeat-{datetime}-1.ndjson`, etc. #filename: filebeat # Maximum size in kilobytes of each file. When this size is reached, and on @@ -4172,6 +4249,7 @@ output.elasticsearch: # Configure automatic file rotation on every startup. The default is true. #rotate_on_startup: true + # ------------------------------- Console Output ------------------------------- #output.console: # Boolean flag to enable or disable the output module. @@ -4270,19 +4348,13 @@ output.elasticsearch: # Set to false to disable template loading. #setup.template.enabled: true -# Select the kind of index template. From Elasticsearch 7.8, it is possible to -# use component templates. Available options: legacy, component, index. -# By default filebeat uses the legacy index templates. -#setup.template.type: legacy - # Template name. By default the template name is "filebeat-%{[agent.version]}" # The template name and pattern has to be set in case the Elasticsearch index pattern is modified. #setup.template.name: "filebeat-%{[agent.version]}" -# Template pattern. By default the template pattern is "-%{[agent.version]}-*" to apply to the default index settings. -# The first part is the version of the beat and then -* is used to match all daily indices. +# Template pattern. By default the template pattern is "filebeat-%{[agent.version]}" to apply to the default index settings. # The template name and pattern has to be set in case the Elasticsearch index pattern is modified. -#setup.template.pattern: "filebeat-%{[agent.version]}-*" +#setup.template.pattern: "filebeat-%{[agent.version]}" # Path to fields.yml file to generate the template #setup.template.fields: "${path.config}/fields.yml" @@ -4329,17 +4401,8 @@ setup.template.settings: # output.elasticsearch.index is ignored, and the write alias is used to set the # index name. -# Enable ILM support. Valid values are true, false, and auto. When set to auto -# (the default), the Beat uses index lifecycle management when it connects to a -# cluster that supports ILM; otherwise, it creates daily indices. -#setup.ilm.enabled: auto - -# Set the prefix used in the index lifecycle write alias name. The default alias -# name is 'filebeat-%{[agent.version]}'. -#setup.ilm.rollover_alias: 'filebeat' - -# Set the rollover index pattern. The default is "%{now/d}-000001". -#setup.ilm.pattern: "{now/d}-000001" +# Enable ILM support. Valid values are true, false. +#setup.ilm.enabled: true # Set the lifecycle policy name. The default policy name is # 'beatname'. @@ -4437,6 +4500,13 @@ setup.kibana: # The pin is a base64 encoded string of the SHA-256 fingerprint. #ssl.ca_sha256: "" + # A root CA HEX encoded fingerprint. During the SSL handshake if the + # fingerprint matches the root CA certificate, it will be added to + # the provided list of root CAs (`certificate_authorities`), if the + # list is empty or not defined, the matching certificate will be the + # only one in the list. Then the normal SSL validation happens. + #ssl.ca_trusted_fingerprint: "" + # ================================== Logging =================================== @@ -4508,11 +4578,6 @@ logging.files: # file. Defaults to true. # rotateonstartup: true - # Rotated files are either suffixed with a number e.g. filebeat.1 when - # renamed during rotation. Or when set to date, the date is added to - # the end of the file. On rotation a new file is created, older files are untouched. - #suffix: count - # ============================= X-Pack Monitoring ============================== # Filebeat can export internal metrics to a central Elasticsearch monitoring # cluster. This requires xpack monitoring to be enabled in Elasticsearch. The @@ -4640,6 +4705,13 @@ logging.files: # The pin is a base64 encoded string of the SHA-256 fingerprint. #ssl.ca_sha256: "" + # A root CA HEX encoded fingerprint. During the SSL handshake if the + # fingerprint matches the root CA certificate, it will be added to + # the provided list of root CAs (`certificate_authorities`), if the + # list is empty or not defined, the matching certificate will be the + # only one in the list. Then the normal SSL validation happens. + #ssl.ca_trusted_fingerprint: "" + # Enable Kerberos support. Kerberos is automatically enabled if any Kerberos setting is set. #kerberos.enabled: true diff --git a/x-pack/filebeat/input/awscloudwatch/input.go b/x-pack/filebeat/input/awscloudwatch/input.go index 3001449378d..22f9efe15c6 100644 --- a/x-pack/filebeat/input/awscloudwatch/input.go +++ b/x-pack/filebeat/input/awscloudwatch/input.go @@ -131,7 +131,8 @@ func NewInput(cfg *common.Config, connector channel.Connector, context input.Con // Run runs the input func (in *awsCloudWatchInput) Run() { // Please see https://docs.aws.amazon.com/general/latest/gr/cwl_region.html for more info on Amazon CloudWatch Logs endpoints. - cwConfig := awscommon.EnrichAWSConfigWithEndpoint(in.config.AwsConfig.Endpoint, "logs", in.config.RegionName, in.awsConfig) + logsServiceName := awscommon.CreateServiceName("logs", in.config.AwsConfig.FIPSEnabled, in.config.RegionName) + cwConfig := awscommon.EnrichAWSConfigWithEndpoint(in.config.AwsConfig.Endpoint, logsServiceName, in.config.RegionName, in.awsConfig) svc := cloudwatchlogs.New(cwConfig) var logGroupNames []string diff --git a/x-pack/filebeat/input/awss3/config.go b/x-pack/filebeat/input/awss3/config.go index 5b8308d1771..cd26b57d0b1 100644 --- a/x-pack/filebeat/input/awss3/config.go +++ b/x-pack/filebeat/input/awss3/config.go @@ -24,7 +24,7 @@ type config struct { VisibilityTimeout time.Duration `config:"visibility_timeout"` SQSWaitTime time.Duration `config:"sqs.wait_time"` // The max duration for which the SQS ReceiveMessage call waits for a message to arrive in the queue before returning. SQSMaxReceiveCount int `config:"sqs.max_receive_count"` // The max number of times a message should be received (retried) before deleting it. - FIPSEnabled bool `config:"fips_enabled"` + SQSScript *scriptConfig `config:"sqs.notification_parsing_script"` MaxNumberOfMessages int `config:"max_number_of_messages"` QueueURL string `config:"queue_url"` BucketARN string `config:"bucket_arn"` @@ -47,7 +47,6 @@ func defaultConfig() config { BucketListPrefix: "", SQSWaitTime: 20 * time.Second, SQSMaxReceiveCount: 5, - FIPSEnabled: false, MaxNumberOfMessages: 5, PathStyle: false, } @@ -98,7 +97,7 @@ func (c *config) Validate() error { c.APITimeout, c.SQSWaitTime) } - if c.FIPSEnabled && c.NonAWSBucketName != "" { + if c.AWSConfig.FIPSEnabled && c.NonAWSBucketName != "" { return errors.New("fips_enabled cannot be used with a non-AWS S3 bucket.") } if c.PathStyle && c.NonAWSBucketName == "" { @@ -151,6 +150,36 @@ func (rc *readerConfig) Validate() error { return nil } +type scriptConfig struct { + Source string `config:"source"` // Inline script to execute. + File string `config:"file"` // Source file. + Files []string `config:"files"` // Multiple source files. + Params map[string]interface{} `config:"params"` // Parameters to pass to script. + Timeout time.Duration `config:"timeout" validate:"min=0"` // Execution timeout. + MaxCachedSessions int `config:"max_cached_sessions" validate:"min=0"` // Max. number of cached VM sessions. +} + +// Validate returns an error if one (and only one) option is not set. +func (c scriptConfig) Validate() error { + numConfigured := 0 + for _, set := range []bool{c.Source != "", c.File != "", len(c.Files) > 0} { + if set { + numConfigured++ + } + } + + switch { + case numConfigured == 0: + return errors.New("javascript must be defined via 'file', " + + "'files', or inline as 'source'") + case numConfigured > 1: + return errors.New("javascript can be defined in only one of " + + "'file', 'files', or inline as 'source'") + } + + return nil +} + func (rc *readerConfig) InitDefaults() { rc.BufferSize = 16 * humanize.KiByte rc.MaxBytes = 10 * humanize.MiByte diff --git a/x-pack/filebeat/input/awss3/config_test.go b/x-pack/filebeat/input/awss3/config_test.go index 189ce447ff8..e465d5b1b01 100644 --- a/x-pack/filebeat/input/awss3/config_test.go +++ b/x-pack/filebeat/input/awss3/config_test.go @@ -38,7 +38,6 @@ func TestConfig(t *testing.T) { SQSWaitTime: 20 * time.Second, BucketListInterval: 120 * time.Second, BucketListPrefix: "", - FIPSEnabled: false, PathStyle: false, MaxNumberOfMessages: 5, ReaderConfig: readerConfig{ diff --git a/x-pack/filebeat/input/awss3/input.go b/x-pack/filebeat/input/awss3/input.go index edd146b6a23..8d673cabbac 100644 --- a/x-pack/filebeat/input/awss3/input.go +++ b/x-pack/filebeat/input/awss3/input.go @@ -155,13 +155,11 @@ func (in *s3Input) Run(inputContext v2.Context, pipeline beat.Pipeline) error { } func (in *s3Input) createSQSReceiver(ctx v2.Context, client beat.Client) (*sqsReader, error) { - s3ServiceName := "s3" - if in.config.FIPSEnabled { - s3ServiceName = "s3-fips" - } + s3ServiceName := awscommon.CreateServiceName("s3", in.config.AWSConfig.FIPSEnabled, in.awsConfig.Region) + sqsServiceName := awscommon.CreateServiceName("sqs", in.config.AWSConfig.FIPSEnabled, in.awsConfig.Region) sqsAPI := &awsSQSAPI{ - client: sqs.New(awscommon.EnrichAWSConfigWithEndpoint(in.config.AWSConfig.Endpoint, "sqs", in.awsConfig.Region, in.awsConfig)), + client: sqs.New(awscommon.EnrichAWSConfigWithEndpoint(in.config.AWSConfig.Endpoint, sqsServiceName, in.awsConfig.Region, in.awsConfig)), queueURL: in.config.QueueURL, apiTimeout: in.config.APITimeout, visibilityTimeout: in.config.VisibilityTimeout, @@ -186,18 +184,19 @@ func (in *s3Input) createSQSReceiver(ctx v2.Context, client beat.Client) (*sqsRe if len(in.config.FileSelectors) == 0 { fileSelectors = []fileSelectorConfig{{ReaderConfig: in.config.ReaderConfig}} } + script, err := newScriptFromConfig(log.Named("sqs_script"), in.config.SQSScript) + if err != nil { + return nil, err + } s3EventHandlerFactory := newS3ObjectProcessorFactory(log.Named("s3"), metrics, s3API, client, fileSelectors) - sqsMessageHandler := newSQSS3EventProcessor(log.Named("sqs_s3_event"), metrics, sqsAPI, in.config.VisibilityTimeout, in.config.SQSMaxReceiveCount, s3EventHandlerFactory) + sqsMessageHandler := newSQSS3EventProcessor(log.Named("sqs_s3_event"), metrics, sqsAPI, script, in.config.VisibilityTimeout, in.config.SQSMaxReceiveCount, s3EventHandlerFactory) sqsReader := newSQSReader(log.Named("sqs"), metrics, sqsAPI, in.config.MaxNumberOfMessages, sqsMessageHandler) return sqsReader, nil } func (in *s3Input) createS3Lister(ctx v2.Context, cancelCtx context.Context, client beat.Client, persistentStore *statestore.Store, states *states) (*s3Poller, error) { - s3ServiceName := "s3" - if in.config.FIPSEnabled { - s3ServiceName = "s3-fips" - } + s3ServiceName := awscommon.CreateServiceName("s3", in.config.AWSConfig.FIPSEnabled, in.awsConfig.Region) var bucketName string var bucketID string if in.config.NonAWSBucketName != "" { diff --git a/x-pack/filebeat/input/awss3/input_benchmark_test.go b/x-pack/filebeat/input/awss3/input_benchmark_test.go index aabb86b1a6c..ecdc1756ce4 100644 --- a/x-pack/filebeat/input/awss3/input_benchmark_test.go +++ b/x-pack/filebeat/input/awss3/input_benchmark_test.go @@ -166,7 +166,7 @@ func benchmarkInputSQS(t *testing.T, maxMessagesInflight int) testing.BenchmarkR conf := makeBenchmarkConfig(t) s3EventHandlerFactory := newS3ObjectProcessorFactory(log.Named("s3"), metrics, s3API, client, conf.FileSelectors) - sqsMessageHandler := newSQSS3EventProcessor(log.Named("sqs_s3_event"), metrics, sqsAPI, time.Minute, 5, s3EventHandlerFactory) + sqsMessageHandler := newSQSS3EventProcessor(log.Named("sqs_s3_event"), metrics, sqsAPI, nil, time.Minute, 5, s3EventHandlerFactory) sqsReader := newSQSReader(log.Named("sqs"), metrics, sqsAPI, maxMessagesInflight, sqsMessageHandler) go func() { diff --git a/x-pack/filebeat/input/awss3/s3_objects.go b/x-pack/filebeat/input/awss3/s3_objects.go index 2839c31e225..7fe6b193fa4 100644 --- a/x-pack/filebeat/input/awss3/s3_objects.go +++ b/x-pack/filebeat/input/awss3/s3_objects.go @@ -120,23 +120,22 @@ func (p *s3ObjectProcessor) ProcessS3Object() error { } // Metrics and Logging - { - p.log.Debug("Begin S3 object processing.") - p.metrics.s3ObjectsRequestedTotal.Inc() - p.metrics.s3ObjectsInflight.Inc() - start := time.Now() - defer func() { - elapsed := time.Since(start) - p.metrics.s3ObjectsInflight.Dec() - p.metrics.s3ObjectProcessingTime.Update(elapsed.Nanoseconds()) - p.log.Debugw("End S3 object processing.", "elapsed_time_ns", elapsed) - }() - } + p.log.Debug("Begin S3 object processing.") + p.metrics.s3ObjectsRequestedTotal.Inc() + p.metrics.s3ObjectsInflight.Inc() + start := time.Now() + defer func() { + elapsed := time.Since(start) + p.metrics.s3ObjectsInflight.Dec() + p.metrics.s3ObjectProcessingTime.Update(elapsed.Nanoseconds()) + p.log.Debugw("End S3 object processing.", "elapsed_time_ns", elapsed) + }() // Request object (download). contentType, meta, body, err := p.download() if err != nil { - return errors.Wrap(err, "failed to get s3 object") + return errors.Wrapf(err, "failed to get s3 object (elasped_time_ns=%d)", + time.Since(start).Nanoseconds()) } defer body.Close() p.s3Metadata = meta @@ -159,7 +158,8 @@ func (p *s3ObjectProcessor) ProcessS3Object() error { err = p.readFile(reader) } if err != nil { - return err + return errors.Wrapf(err, "failed reading s3 object (elasped_time_ns=%d)", + time.Since(start).Nanoseconds()) } return nil diff --git a/x-pack/filebeat/input/awss3/script.go b/x-pack/filebeat/input/awss3/script.go new file mode 100644 index 00000000000..812fbe65dc5 --- /dev/null +++ b/x-pack/filebeat/input/awss3/script.go @@ -0,0 +1,150 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License; +// you may not use this file except in compliance with the Elastic License. + +package awss3 + +import ( + "bytes" + "io" + "os" + "path/filepath" + "runtime" + "strings" + + "github.com/dop251/goja" + "github.com/pkg/errors" + + "github.com/elastic/beats/v7/libbeat/common" + "github.com/elastic/beats/v7/libbeat/logp" + "github.com/elastic/beats/v7/libbeat/paths" +) + +type script struct { + scriptConfig + sessionPool *sessionPool + sourceProg *goja.Program + sourceFile string +} + +// newScriptFromConfig constructs a new Javascript script from the given config +// object. It loads the sources, compiles them, and validates the entry point. +func newScriptFromConfig(log *logp.Logger, c *scriptConfig) (*script, error) { + if c == nil { + return nil, nil + } + err := c.Validate() + if err != nil { + return nil, err + } + + var sourceFile string + var sourceCode []byte + + switch { + case c.Source != "": + sourceFile = "inline.js" + sourceCode = []byte(c.Source) + case c.File != "": + sourceFile, sourceCode, err = loadSources(c.File) + case len(c.Files) > 0: + sourceFile, sourceCode, err = loadSources(c.Files...) + } + if err != nil { + return nil, err + } + + // Validate processor source code. + prog, err := goja.Compile(sourceFile, string(sourceCode), true) + if err != nil { + return nil, err + } + + pool, err := newSessionPool(prog, *c) + if err != nil { + return nil, err + } + + return &script{ + scriptConfig: *c, + sessionPool: pool, + sourceProg: prog, + sourceFile: sourceFile, + }, nil +} + +// loadSources loads javascript source from files. +func loadSources(files ...string) (string, []byte, error) { + var sources []string + buf := new(bytes.Buffer) + + readFile := func(path string) error { + if common.IsStrictPerms() { + if err := common.OwnerHasExclusiveWritePerms(path); err != nil { + return err + } + } + + f, err := os.Open(path) + if err != nil { + return errors.Wrapf(err, "failed to open file %v", path) + } + defer f.Close() + + if _, err = io.Copy(buf, f); err != nil { + return errors.Wrapf(err, "failed to read file %v", path) + } + return nil + } + + for _, filePath := range files { + filePath = paths.Resolve(paths.Config, filePath) + + if hasMeta(filePath) { + matches, err := filepath.Glob(filePath) + if err != nil { + return "", nil, err + } + sources = append(sources, matches...) + } else { + sources = append(sources, filePath) + } + } + + if len(sources) == 0 { + return "", nil, errors.Errorf("no sources were found in %v", + strings.Join(files, ", ")) + } + + for _, name := range sources { + if err := readFile(name); err != nil { + return "", nil, err + } + } + + return strings.Join(sources, ";"), buf.Bytes(), nil +} + +// run runs the parse function. It receives a raw notification +// as a string and returns a list of S3 Events describing +// which files are going to be downloaded. +func (p *script) run(n string) ([]s3EventV2, error) { + s := p.sessionPool.Get() + defer p.sessionPool.Put(s) + + return s.runParseFunc(n) +} + +func (p *script) String() string { + return "script=[type=javascript, sources=" + p.sourceFile + "]" +} + +// hasMeta reports whether path contains any of the magic characters +// recognized by Match/Glob. +func hasMeta(path string) bool { + magicChars := `*?[` + if runtime.GOOS != "windows" { + magicChars = `*?[\` + } + return strings.ContainsAny(path, magicChars) +} diff --git a/x-pack/filebeat/input/awss3/script_jss3event_v2.go b/x-pack/filebeat/input/awss3/script_jss3event_v2.go new file mode 100644 index 00000000000..04cea00a08b --- /dev/null +++ b/x-pack/filebeat/input/awss3/script_jss3event_v2.go @@ -0,0 +1,69 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License; +// you may not use this file except in compliance with the Elastic License. + +package awss3 + +import ( + "strings" + + "github.com/dop251/goja" + "github.com/pkg/errors" + + "github.com/elastic/beats/v7/libbeat/common/encoding/xml" +) + +func newJSS3EventV2Constructor(s *session) func(call goja.ConstructorCall) *goja.Object { + return func(call goja.ConstructorCall) *goja.Object { + if len(call.Arguments) != 0 { + panic(errors.New("Event constructor don't accept arguments")) + } + return s.vm.ToValue(&s3EventV2{}).(*goja.Object) + } +} + +func (e *s3EventV2) SetAWSRegion(v string) { + e.AWSRegion = v +} + +func (e *s3EventV2) SetProvider(v string) { + e.Provider = v +} + +func (e *s3EventV2) SetEventName(v string) { + e.EventName = v +} + +func (e *s3EventV2) SetEventSource(v string) { + e.EventSource = v +} + +func (e *s3EventV2) SetS3BucketName(v string) { + e.S3.Bucket.Name = v +} + +func (e *s3EventV2) SetS3BucketARN(v string) { + e.S3.Bucket.ARN = v +} + +func (e *s3EventV2) SetS3ObjectKey(v string) { + e.S3.Object.Key = v +} + +func newXMLDecoderConstructor(s *session) func(call goja.ConstructorCall) *goja.Object { + return func(call goja.ConstructorCall) *goja.Object { + if len(call.Arguments) != 1 { + panic(errors.New("Event constructor requires one argument")) + } + + a0 := call.Argument(0).Export() + s0, ok := a0.(string) + + if !ok { + panic(errors.Errorf("Event constructor requires a "+ + "string argument but got %T", a0)) + } + + return s.vm.ToValue(xml.NewDecoder(strings.NewReader(s0))).(*goja.Object) + } +} diff --git a/x-pack/filebeat/input/awss3/script_jss3event_v2_test.go b/x-pack/filebeat/input/awss3/script_jss3event_v2_test.go new file mode 100644 index 00000000000..dc387d95e33 --- /dev/null +++ b/x-pack/filebeat/input/awss3/script_jss3event_v2_test.go @@ -0,0 +1,60 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License; +// you may not use this file except in compliance with the Elastic License. + +package awss3 + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/elastic/beats/v7/libbeat/logp" +) + +const ( + header = `function parse(n) {` + footer = `}` +) + +var log = logp.NewLogger("test") + +func TestJSS3EventV2(t *testing.T) { + logp.TestingSetup() + + source := ` + var evts = []; + var evt = new S3EventV2(); + evt.SetAWSRegion("region"); + evt.SetProvider("provider"); + evt.SetEventName("name"); + evt.SetEventSource("source"); + evt.SetS3BucketName("bucket"); + evt.SetS3BucketARN("arn"); + evt.SetS3ObjectKey("key"); + evts.push(evt); + return evts; + ` + + p, err := newScriptFromConfig(log, &scriptConfig{Source: header + source + footer}) + if err != nil { + t.Fatal(err) + } + + evts, err := p.run(`{}`) + require.NoError(t, err) + require.Equal(t, 1, len(evts)) + + exp := s3EventV2{ + AWSRegion: "region", + Provider: "provider", + EventName: "name", + EventSource: "source", + } + exp.S3.Bucket.Name = "bucket" + exp.S3.Bucket.ARN = "arn" + exp.S3.Object.Key = "key" + + assert.EqualValues(t, exp, evts[0]) +} diff --git a/x-pack/filebeat/input/awss3/script_session.go b/x-pack/filebeat/input/awss3/script_session.go new file mode 100644 index 00000000000..aad0539665e --- /dev/null +++ b/x-pack/filebeat/input/awss3/script_session.go @@ -0,0 +1,217 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License; +// you may not use this file except in compliance with the Elastic License. + +package awss3 + +import ( + "fmt" + "reflect" + "time" + + "github.com/dop251/goja" + "github.com/pkg/errors" + "go.uber.org/zap" + + "github.com/elastic/beats/v7/libbeat/common" + "github.com/elastic/beats/v7/libbeat/logp" +) + +const ( + logName = "awss3.script" + + entryPointFunction = "parse" + registerFunction = "register" + testFunction = "test" + + timeoutError = "javascript parser execution timeout" +) + +// session is a javascript runtime environment used throughout the life of +// the input instance. +type session struct { + vm *goja.Runtime + log *logp.Logger + parseFunc goja.Callable + timeout time.Duration +} + +func newSession(p *goja.Program, conf scriptConfig, test bool) (*session, error) { + // Create a logger + logger := logp.NewLogger(logName) + + // Setup JS runtime. + s := &session{ + vm: goja.New(), + log: logger, + timeout: conf.Timeout, + } + + // Register common.MapStr as being a simple map[string]interface{} for + // treatment within the JS VM. + s.vm.RegisterSimpleMapType(reflect.TypeOf(common.MapStr(nil)), + func(i interface{}) map[string]interface{} { + return map[string]interface{}(i.(common.MapStr)) + }, + ) + + // Register constructors for 'new S3EventV2' to enable creating them from the JS code. + s.vm.Set("S3EventV2", newJSS3EventV2Constructor(s)) + s.vm.Set("XMLDecoder", newXMLDecoderConstructor(s)) + + if _, err := s.vm.RunProgram(p); err != nil { + return nil, err + } + + if err := s.setParseFunction(); err != nil { + return nil, err + } + + if len(conf.Params) > 0 { + if err := s.registerScriptParams(conf.Params); err != nil { + return nil, err + } + } + + if test { + if err := s.executeTestFunction(); err != nil { + return nil, err + } + } + + return s, nil +} + +// setParseFunction validates that the parse() function exists and stores +// the handle. +func (s *session) setParseFunction() error { + parseFunc := s.vm.Get(entryPointFunction) + if parseFunc == nil { + return errors.New("parse function not found") + } + if parseFunc.ExportType().Kind() != reflect.Func { + return errors.New("parse is not a function") + } + if err := s.vm.ExportTo(parseFunc, &s.parseFunc); err != nil { + return errors.Wrap(err, "failed to export parse function") + } + return nil +} + +// registerScriptParams calls the register() function and passes the params. +func (s *session) registerScriptParams(params map[string]interface{}) error { + registerFunc := s.vm.Get(registerFunction) + if registerFunc == nil { + return errors.New("params were provided but no register function was found") + } + if registerFunc.ExportType().Kind() != reflect.Func { + return errors.New("register is not a function") + } + var register goja.Callable + if err := s.vm.ExportTo(registerFunc, ®ister); err != nil { + return errors.Wrap(err, "failed to export register function") + } + if _, err := register(goja.Undefined(), s.vm.ToValue(params)); err != nil { + return errors.Wrap(err, "failed to register script_params") + } + s.log.Debug("Registered params with script") + return nil +} + +// executeTestFunction executes the test() function if it exists. Any exceptions +// will cause the script to fail to load. +func (s *session) executeTestFunction() error { + if testFunc := s.vm.Get(testFunction); testFunc != nil { + if testFunc.ExportType().Kind() != reflect.Func { + return errors.New("test is not a function") + } + var test goja.Callable + if err := s.vm.ExportTo(testFunc, &test); err != nil { + return errors.Wrap(err, "failed to export test function") + } + _, err := test(goja.Undefined(), nil) + if err != nil { + return errors.Wrap(err, "failed in test() function") + } + s.log.Debugf("Successful test() execution for script.") + } + return nil +} + +// runParseFunc executes parse() from the JS script. +func (s *session) runParseFunc(n string) (out []s3EventV2, err error) { + defer func() { + if r := recover(); r != nil { + s.log.Errorw("The javascript script caused an unexpected panic "+ + "while parsing a notification. Recovering, but please report this.", + "notification", common.MapStr{"original": n}, + "panic", r, + zap.Stack("stack")) + err = fmt.Errorf("unexpected panic in javascript script: %v", r) + } + }() + + // Interrupt the JS code if execution exceeds timeout. + if s.timeout > 0 { + t := time.AfterFunc(s.timeout, func() { + s.vm.Interrupt(timeoutError) + }) + defer t.Stop() + } + + v, err := s.parseFunc(goja.Undefined(), s.vm.ToValue(n)) + if err != nil { + return nil, fmt.Errorf("failed in parse function: %w", err) + } + + if v.Equals(goja.Undefined()) { + return out, nil + } + + if err := s.vm.ExportTo(v, &out); err != nil { + return nil, fmt.Errorf("can't export returned value: %w", err) + } + + return out, nil +} + +type sessionPool struct { + New func() *session + C chan *session +} + +func newSessionPool(p *goja.Program, c scriptConfig) (*sessionPool, error) { + s, err := newSession(p, c, true) + if err != nil { + return nil, err + } + + pool := sessionPool{ + New: func() *session { + s, _ := newSession(p, c, false) + return s + }, + C: make(chan *session, c.MaxCachedSessions), + } + pool.Put(s) + + return &pool, nil +} + +func (p *sessionPool) Get() *session { + select { + case s := <-p.C: + return s + default: + return p.New() + } +} + +func (p *sessionPool) Put(s *session) { + if s != nil { + select { + case p.C <- s: + default: + } + } +} diff --git a/x-pack/filebeat/input/awss3/script_session_test.go b/x-pack/filebeat/input/awss3/script_session_test.go new file mode 100644 index 00000000000..4cad65b03fd --- /dev/null +++ b/x-pack/filebeat/input/awss3/script_session_test.go @@ -0,0 +1,317 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License; +// you may not use this file except in compliance with the Elastic License. + +package awss3 + +import ( + "context" + "sync" + "testing" + "time" + + "github.com/elastic/beats/v7/libbeat/logp" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestSessionScriptParams(t *testing.T) { + logp.TestingSetup() + + t.Run("register method is optional", func(t *testing.T) { + _, err := newScriptFromConfig(log, &scriptConfig{Source: header + footer}) + if err != nil { + t.Fatal(err) + } + }) + + t.Run("register required for params", func(t *testing.T) { + _, err := newScriptFromConfig(log, &scriptConfig{Source: header + footer, Params: map[string]interface{}{ + "p1": 42, + }, + }) + if assert.Error(t, err) { + assert.Contains(t, err.Error(), "params were provided") + } + }) + + t.Run("register params", func(t *testing.T) { + const script = ` + function register(params) { + if (params["p1"] !== 42) { + throw "invalid p1"; + } + } + + function parse(n) {} + ` + _, err := newScriptFromConfig(log, &scriptConfig{ + Source: script, + Params: map[string]interface{}{ + "p1": 42, + }, + }) + assert.NoError(t, err) + }) +} + +func TestSessionTestFunction(t *testing.T) { + logp.TestingSetup() + + const script = ` + var fail = false; + + function register(params) { + fail = params["fail"]; + } + + function parse(n) { + if (fail) { + throw "intentional failure"; + } + var m = JSON.parse(n); + var e = new S3EventV2(); + e.SetS3ObjectKey(m["hello"]); + return [e]; + } + + function test() { + var n = "{\"hello\": \"earth\"}"; + var evts = parse(n); + + if (evts[0].S3.Object.Key !== "earth") { + throw "invalid key value"; + } + } + ` + + t.Run("test method is optional", func(t *testing.T) { + _, err := newScriptFromConfig(log, &scriptConfig{ + Source: header + footer, + }) + if err != nil { + t.Fatal(err) + } + }) + + t.Run("test success", func(t *testing.T) { + _, err := newScriptFromConfig(log, &scriptConfig{ + Source: script, + Params: map[string]interface{}{ + "fail": false, + }, + }) + assert.NoError(t, err) + }) + + t.Run("test failure", func(t *testing.T) { + _, err := newScriptFromConfig(log, &scriptConfig{ + Source: script, + Params: map[string]interface{}{ + "fail": true, + }, + }) + assert.Error(t, err) + }) +} + +func TestSessionTimeout(t *testing.T) { + logp.TestingSetup() + + const runawayLoop = ` + var m = JSON.parse(n); + while (!m.stop) { + m.hello = "world"; + } + ` + + p, err := newScriptFromConfig(log, &scriptConfig{ + Source: header + runawayLoop + footer, + Timeout: 100 * time.Millisecond, + }) + if err != nil { + t.Fatal(err) + } + + n := `{"stop": false}` + + // Execute and expect a timeout. + _, err = p.run(n) + if assert.Error(t, err) { + assert.Contains(t, err.Error(), timeoutError) + } + + // Verify that any internal runtime interrupt state has been cleared. + n = `{"stop": true}` + _, err = p.run(n) + assert.NoError(t, err) +} + +func TestSessionParallel(t *testing.T) { + logp.TestingSetup() + + const script = ` + var m = JSON.parse(n); + var evt = new S3EventV2(); + evt.SetS3ObjectKey(m.hello.world); + return [evt]; + ` + + p, err := newScriptFromConfig(log, &scriptConfig{ + Source: header + script + footer, + }) + if err != nil { + t.Fatal(err) + } + + const goroutines = 10 + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + var wg sync.WaitGroup + wg.Add(goroutines) + for i := 0; i < goroutines; i++ { + go func() { + defer wg.Done() + for ctx.Err() == nil { + n := `{"hello":{"world": "hello"}}` + evts, err := p.run(n) + require.NoError(t, err) + require.Equal(t, 1, len(evts)) + assert.Equal(t, "hello", evts[0].S3.Object.Key) + } + }() + } + + time.AfterFunc(time.Second, cancel) + wg.Wait() +} + +func TestCreateS3EventsFromNotification(t *testing.T) { + logp.TestingSetup() + + n := `{ + "cid": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", + "timestamp": 1492726639222, + "fileCount": 4, + "totalSize": 349986221, + "bucket": "bucketNNNN", + "pathPrefix": "logs/aaaa-bbbb-cccc-dddd-eeee-ffff", + "files": [ + { + "path": "logs/aaaa-bbbb-cccc-dddd-eeee-ffff/part-00000.gz", + "size": 90506437, + "checksum": "ffffffffffffffffffff" + }, + { + "path": "logs/aaaa-bbbb-cccc-dddd-eeee-ffff/part-00001.gz", + "size": 86467594, + "checksum": "ffffffffffffffffffff" + }, + { + "path": "logs/aaaa-bbbb-cccc-dddd-eeee-ffff/part-00002.gz", + "size": 83893710, + "checksum": "ffffffffffffffffffff" + }, + { + "path": "logs/aaaa-bbbb-cccc-dddd-eeee-ffff/part-00003.gz", + "size": 89118480, + "checksum": "ffffffffffffffffffff" + } + ] + }` + + const script = ` + function parse(n) { + var m = JSON.parse(n); + var evts = []; + var files = m.files; + var bucket = m.bucket; + + if (!Array.isArray(files) || (files.length == 0) || bucket == null || bucket == "") { + return evts; + } + + files.forEach(function(f){ + var evt = new S3EventV2(); + evt.SetS3BucketName(bucket); + evt.SetS3ObjectKey(f.path); + evts.push(evt); + }); + + return evts; + } +` + s, err := newScriptFromConfig(log, &scriptConfig{Source: script}) + require.NoError(t, err) + + evts, err := s.run(n) + require.NoError(t, err) + require.Equal(t, 4, len(evts)) + + const expectedBucket = "bucketNNNN" + expectedObjectKeys := []string{ + "logs/aaaa-bbbb-cccc-dddd-eeee-ffff/part-00000.gz", + "logs/aaaa-bbbb-cccc-dddd-eeee-ffff/part-00001.gz", + "logs/aaaa-bbbb-cccc-dddd-eeee-ffff/part-00002.gz", + "logs/aaaa-bbbb-cccc-dddd-eeee-ffff/part-00003.gz", + } + + for i, e := range expectedObjectKeys { + assert.Equal(t, expectedBucket, evts[i].S3.Bucket.Name) + assert.Equal(t, e, evts[i].S3.Object.Key) + } +} + +func TestParseXML(t *testing.T) { + logp.TestingSetup() + + n := ` + bucketNNNN + + logs/aaaa-bbbb-cccc-dddd-eeee-ffff/part-00000.gz + logs/aaaa-bbbb-cccc-dddd-eeee-ffff/part-00001.gz + + ` + + const script = ` + function parse(n) { + var dec = new XMLDecoder(n); + var m = dec.Decode(); + var evts = []; + var files = m.record.files.file; + var bucket = m.record.bucket; + + if (!Array.isArray(files) || (files.length == 0) || bucket == null || bucket == "") { + return evts; + } + + files.forEach(function(f){ + var evt = new S3EventV2(); + evt.SetS3BucketName(bucket); + evt.SetS3ObjectKey(f.path); + evts.push(evt); + }); + + return evts; + } +` + s, err := newScriptFromConfig(log, &scriptConfig{Source: script}) + require.NoError(t, err) + + evts, err := s.run(n) + require.NoError(t, err) + require.Equal(t, 2, len(evts)) + + const expectedBucket = "bucketNNNN" + expectedObjectKeys := []string{ + "logs/aaaa-bbbb-cccc-dddd-eeee-ffff/part-00000.gz", + "logs/aaaa-bbbb-cccc-dddd-eeee-ffff/part-00001.gz", + } + + for i, e := range expectedObjectKeys { + assert.Equal(t, expectedBucket, evts[i].S3.Bucket.Name) + assert.Equal(t, e, evts[i].S3.Object.Key) + } +} diff --git a/x-pack/filebeat/input/awss3/sqs.go b/x-pack/filebeat/input/awss3/sqs.go index 56f35e473ce..1f13ec010cf 100644 --- a/x-pack/filebeat/input/awss3/sqs.go +++ b/x-pack/filebeat/input/awss3/sqs.go @@ -88,7 +88,10 @@ func (r *sqsReader) Receive(ctx context.Context) error { }() if err := r.msgHandler.ProcessSQS(ctx, &msg); err != nil { - r.log.Warnw("Failed processing SQS message.", "error", err, "message_id", *msg.MessageId) + r.log.Warnw("Failed processing SQS message.", + "error", err, + "message_id", *msg.MessageId, + "elapsed_time_ns", time.Since(start)) } }(msg, time.Now()) } diff --git a/x-pack/filebeat/input/awss3/sqs_s3_event.go b/x-pack/filebeat/input/awss3/sqs_s3_event.go index a89aad7fc12..d1865aec9cd 100644 --- a/x-pack/filebeat/input/awss3/sqs_s3_event.go +++ b/x-pack/filebeat/input/awss3/sqs_s3_event.go @@ -14,6 +14,7 @@ import ( "sync" "time" + "github.com/aws/aws-sdk-go-v2/aws/awserr" "github.com/aws/aws-sdk-go-v2/service/sqs" "github.com/pkg/errors" "go.uber.org/multierr" @@ -86,9 +87,10 @@ type sqsS3EventProcessor struct { log *logp.Logger warnOnce sync.Once metrics *inputMetrics + script *script } -func newSQSS3EventProcessor(log *logp.Logger, metrics *inputMetrics, sqs sqsAPI, sqsVisibilityTimeout time.Duration, maxReceiveCount int, s3 s3ObjectHandlerFactory) *sqsS3EventProcessor { +func newSQSS3EventProcessor(log *logp.Logger, metrics *inputMetrics, sqs sqsAPI, script *script, sqsVisibilityTimeout time.Duration, maxReceiveCount int, s3 s3ObjectHandlerFactory) *sqsS3EventProcessor { if metrics == nil { metrics = newInputMetrics(monitoring.NewRegistry(), "") } @@ -99,11 +101,14 @@ func newSQSS3EventProcessor(log *logp.Logger, metrics *inputMetrics, sqs sqsAPI, sqs: sqs, log: log, metrics: metrics, + script: script, } } func (p *sqsS3EventProcessor) ProcessSQS(ctx context.Context, msg *sqs.Message) error { - log := p.log.With("message_id", *msg.MessageId) + log := p.log.With( + "message_id", *msg.MessageId, + "message_receipt_time", time.Now().UTC()) keepaliveCtx, keepaliveCancel := context.WithCancel(ctx) defer keepaliveCancel() @@ -135,7 +140,7 @@ func (p *sqsS3EventProcessor) ProcessSQS(ctx context.Context, msg *sqs.Message) if receiveCount, err := strconv.Atoi(v); err == nil && receiveCount >= p.maxReceiveCount { processingErr = nonRetryableErrorWrap(fmt.Errorf( "sqs ApproximateReceiveCount <%v> exceeds threshold %v: %w", - receiveCount, p.maxReceiveCount, err)) + receiveCount, p.maxReceiveCount, processingErr)) } } } @@ -178,6 +183,17 @@ func (p *sqsS3EventProcessor) keepalive(ctx context.Context, log *logp.Logger, w // Renew visibility. if err := p.sqs.ChangeMessageVisibility(ctx, msg, p.sqsVisibilityTimeout); err != nil { + var awsErr awserr.Error + if errors.As(err, &awsErr) { + switch awsErr.Code() { + case sqs.ErrCodeReceiptHandleIsInvalid: + log.Warnw("Failed to extend message visibility timeout "+ + "because SQS receipt handle is no longer valid. "+ + "Stopping SQS message keepalive routine.", "error", err) + return + } + } + log.Warnw("Failed to extend message visibility timeout.", "error", err) } } @@ -185,6 +201,12 @@ func (p *sqsS3EventProcessor) keepalive(ctx context.Context, log *logp.Logger, w } func (p *sqsS3EventProcessor) getS3Notifications(body string) ([]s3EventV2, error) { + // Check if a parsing script is defined. If so, it takes precedence over + // format autodetection. + if p.script != nil { + return p.script.run(body) + } + // NOTE: If AWS introduces a V3 schema this will need updated to handle that schema. var events s3EventsV2 dec := json.NewDecoder(strings.NewReader(body)) @@ -201,6 +223,12 @@ func (p *sqsS3EventProcessor) getS3Notifications(body string) ([]s3EventV2, erro return nil, fmt.Errorf("failed to decode SQS message body as an S3 notification: %w", err) } } + + if events.Records == nil { + p.log.Debugw("Invalid SQS message body: missing Records field", "sqs_message_body", body) + return nil, errors.New("the message is an invalid S3 notification: missing Records field") + } + return p.getS3Info(events) } @@ -251,7 +279,7 @@ func (p *sqsS3EventProcessor) processS3Events(ctx context.Context, log *logp.Log defer acker.Wait() var errs []error - for _, event := range s3Events { + for i, event := range s3Events { s3Processor := p.s3ObjectHandler.Create(ctx, log, acker, event) if s3Processor == nil { continue @@ -260,8 +288,8 @@ func (p *sqsS3EventProcessor) processS3Events(ctx context.Context, log *logp.Log // Process S3 object (download, parse, create events). if err := s3Processor.ProcessS3Object(); err != nil { errs = append(errs, errors.Wrapf(err, - "failed processing S3 event for object key %q in bucket %q", - event.S3.Object.Key, event.S3.Bucket.Name)) + "failed processing S3 event for object key %q in bucket %q (object record %d of %d in SQS notification)", + event.S3.Object.Key, event.S3.Bucket.Name, i+1, len(s3Events))) } } diff --git a/x-pack/filebeat/input/awss3/sqs_s3_event_test.go b/x-pack/filebeat/input/awss3/sqs_s3_event_test.go index 9edd5ec4ed9..6100dbe3119 100644 --- a/x-pack/filebeat/input/awss3/sqs_s3_event_test.go +++ b/x-pack/filebeat/input/awss3/sqs_s3_event_test.go @@ -8,9 +8,12 @@ import ( "context" "errors" "fmt" + "sync" "testing" "time" + "github.com/aws/aws-sdk-go-v2/aws/awserr" + "github.com/aws/aws-sdk-go-v2/service/sqs" "github.com/golang/mock/gomock" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -38,7 +41,7 @@ func TestSQSS3EventProcessor(t *testing.T) { mockAPI.EXPECT().DeleteMessage(gomock.Any(), gomock.Eq(&msg)).Return(nil), ) - p := newSQSS3EventProcessor(logp.NewLogger(inputName), nil, mockAPI, time.Minute, 5, mockS3HandlerFactory) + p := newSQSS3EventProcessor(logp.NewLogger(inputName), nil, mockAPI, nil, time.Minute, 5, mockS3HandlerFactory) require.NoError(t, p.ProcessSQS(ctx, &msg)) }) @@ -60,7 +63,7 @@ func TestSQSS3EventProcessor(t *testing.T) { mockAPI.EXPECT().DeleteMessage(gomock.Any(), gomock.Eq(&invalidBodyMsg)).Return(nil), ) - p := newSQSS3EventProcessor(logp.NewLogger(inputName), nil, mockAPI, time.Minute, 5, mockS3HandlerFactory) + p := newSQSS3EventProcessor(logp.NewLogger(inputName), nil, mockAPI, nil, time.Minute, 5, mockS3HandlerFactory) err := p.ProcessSQS(ctx, &invalidBodyMsg) require.Error(t, err) t.Log(err) @@ -75,13 +78,13 @@ func TestSQSS3EventProcessor(t *testing.T) { mockAPI := NewMockSQSAPI(ctrl) mockS3HandlerFactory := NewMockS3ObjectHandlerFactory(ctrl) - emptyRecordsMsg := newSQSMessage() + emptyRecordsMsg := newSQSMessage([]s3EventV2{}...) gomock.InOrder( mockAPI.EXPECT().DeleteMessage(gomock.Any(), gomock.Eq(&emptyRecordsMsg)).Return(nil), ) - p := newSQSS3EventProcessor(logp.NewLogger(inputName), nil, mockAPI, time.Minute, 5, mockS3HandlerFactory) + p := newSQSS3EventProcessor(logp.NewLogger(inputName), nil, mockAPI, nil, time.Minute, 5, mockS3HandlerFactory) require.NoError(t, p.ProcessSQS(ctx, &emptyRecordsMsg)) }) @@ -108,7 +111,7 @@ func TestSQSS3EventProcessor(t *testing.T) { mockAPI.EXPECT().DeleteMessage(gomock.Any(), gomock.Eq(&msg)).Return(nil), ) - p := newSQSS3EventProcessor(logp.NewLogger(inputName), nil, mockAPI, visibilityTimeout, 5, mockS3HandlerFactory) + p := newSQSS3EventProcessor(logp.NewLogger(inputName), nil, mockAPI, nil, visibilityTimeout, 5, mockS3HandlerFactory) require.NoError(t, p.ProcessSQS(ctx, &msg)) }) @@ -127,7 +130,7 @@ func TestSQSS3EventProcessor(t *testing.T) { mockS3Handler.EXPECT().ProcessS3Object().Return(errors.New("fake connectivity problem")), ) - p := newSQSS3EventProcessor(logp.NewLogger(inputName), nil, mockAPI, time.Minute, 5, mockS3HandlerFactory) + p := newSQSS3EventProcessor(logp.NewLogger(inputName), nil, mockAPI, nil, time.Minute, 5, mockS3HandlerFactory) err := p.ProcessSQS(ctx, &msg) t.Log(err) require.Error(t, err) @@ -154,17 +157,46 @@ func TestSQSS3EventProcessor(t *testing.T) { mockAPI.EXPECT().DeleteMessage(gomock.Any(), gomock.Eq(&msg)).Return(nil), ) - p := newSQSS3EventProcessor(logp.NewLogger(inputName), nil, mockAPI, time.Minute, 5, mockS3HandlerFactory) + p := newSQSS3EventProcessor(logp.NewLogger(inputName), nil, mockAPI, nil, time.Minute, 5, mockS3HandlerFactory) err := p.ProcessSQS(ctx, &msg) t.Log(err) require.Error(t, err) }) } +func TestSqsProcessor_keepalive(t *testing.T) { + msg := newSQSMessage(newS3Event("log.json")) + + // Test will call ChangeMessageVisibility once and then keepalive will + // exit because the SQS receipt handle is not usable. + t.Run("keepalive stops after receipt handle is invalid", func(t *testing.T) { + const visibilityTimeout = time.Second + + ctx, cancel := context.WithTimeout(context.Background(), testTimeout) + defer cancel() + + ctrl, ctx := gomock.WithContext(ctx, t) + defer ctrl.Finish() + mockAPI := NewMockSQSAPI(ctrl) + mockS3HandlerFactory := NewMockS3ObjectHandlerFactory(ctrl) + + receiptHandleErr := awserr.New(sqs.ErrCodeReceiptHandleIsInvalid, "fake receipt handle is invalid.", nil) + + mockAPI.EXPECT().ChangeMessageVisibility(gomock.Any(), gomock.Eq(&msg), gomock.Eq(visibilityTimeout)). + Times(1).Return(receiptHandleErr) + + p := newSQSS3EventProcessor(logp.NewLogger(inputName), nil, mockAPI, nil, visibilityTimeout, 5, mockS3HandlerFactory) + var wg sync.WaitGroup + wg.Add(1) + p.keepalive(ctx, p.log, &wg, &msg) + wg.Wait() + }) +} + func TestSqsProcessor_getS3Notifications(t *testing.T) { logp.TestingSetup() - p := newSQSS3EventProcessor(logp.NewLogger(inputName), nil, nil, time.Minute, 5, nil) + p := newSQSS3EventProcessor(logp.NewLogger(inputName), nil, nil, nil, time.Minute, 5, nil) t.Run("s3 key is url unescaped", func(t *testing.T) { msg := newSQSMessage(newS3Event("Happy+Face.jpg")) @@ -194,6 +226,24 @@ func TestSqsProcessor_getS3Notifications(t *testing.T) { assert.Equal(t, "arn:aws:s3:::vpc-flow-logs-ks", events[0].S3.Bucket.ARN) assert.Equal(t, "vpc-flow-logs-ks", events[0].S3.Bucket.Name) }) + + t.Run("missing Records fail", func(t *testing.T) { + msg := `{"message":"missing records"}` + _, err := p.getS3Notifications(msg) + require.Error(t, err) + assert.EqualError(t, err, "the message is an invalid S3 notification: missing Records field") + msg = `{"message":"null records", "Records": null}` + _, err = p.getS3Notifications(msg) + require.Error(t, err) + assert.EqualError(t, err, "the message is an invalid S3 notification: missing Records field") + }) + + t.Run("empty Records does not fail", func(t *testing.T) { + msg := `{"Records":[]}` + events, err := p.getS3Notifications(msg) + require.NoError(t, err) + assert.Equal(t, 0, len(events)) + }) } func TestNonRecoverableError(t *testing.T) { diff --git a/x-pack/filebeat/input/httpjson/config_auth.go b/x-pack/filebeat/input/httpjson/config_auth.go index 88eac44edc1..7e8dae6dc0a 100644 --- a/x-pack/filebeat/input/httpjson/config_auth.go +++ b/x-pack/filebeat/input/httpjson/config_auth.go @@ -22,6 +22,9 @@ import ( "github.com/elastic/beats/v7/libbeat/common" ) +// authStyleInParams sends the "client_id" and "client_secret" in the POST body as application/x-www-form-urlencoded parameters. +const authStyleInParams = 1 + type authConfig struct { Basic *basicAuthConfig `config:"basic"` OAuth2 *oAuth2Config `config:"oauth2"` @@ -83,9 +86,11 @@ type oAuth2Config struct { ClientID string `config:"client.id"` ClientSecret string `config:"client.secret"` EndpointParams map[string][]string `config:"endpoint_params"` + Password string `config:"password"` Provider oAuth2Provider `config:"provider"` Scopes []string `config:"scopes"` TokenURL string `config:"token_url"` + User string `config:"user"` // google specific GoogleCredentialsFile string `config:"google.credentials_file"` @@ -103,20 +108,43 @@ func (o *oAuth2Config) isEnabled() bool { return o != nil && (o.Enabled == nil || *o.Enabled) } +// clientCredentialsGrant creates http client from token_url and client credentials +func (o *oAuth2Config) clientCredentialsGrant(ctx context.Context, client *http.Client) *http.Client { + creds := clientcredentials.Config{ + ClientID: o.ClientID, + ClientSecret: o.ClientSecret, + TokenURL: o.getTokenURL(), + Scopes: o.Scopes, + EndpointParams: o.getEndpointParams(), + } + return creds.Client(ctx) +} + // Client wraps the given http.Client and returns a new one that will use the oauth authentication. func (o *oAuth2Config) client(ctx context.Context, client *http.Client) (*http.Client, error) { ctx = context.WithValue(ctx, oauth2.HTTPClient, client) switch o.getProvider() { - case oAuth2ProviderAzure, oAuth2ProviderDefault: - creds := clientcredentials.Config{ - ClientID: o.ClientID, - ClientSecret: o.ClientSecret, - TokenURL: o.getTokenURL(), - Scopes: o.Scopes, - EndpointParams: o.getEndpointParams(), + case oAuth2ProviderDefault: + if o.User != "" || o.Password != "" { + conf := &oauth2.Config{ + ClientID: o.ClientID, + ClientSecret: o.ClientSecret, + Endpoint: oauth2.Endpoint{ + TokenURL: o.TokenURL, + AuthStyle: authStyleInParams, + }, + } + token, err := conf.PasswordCredentialsToken(ctx, o.User, o.Password) + if err != nil { + return nil, fmt.Errorf("oauth2 client: error loading credentials using user and password: %w", err) + } + return conf.Client(ctx, token), nil + } else { + return o.clientCredentialsGrant(ctx, client), nil } - return creds.Client(ctx), nil + case oAuth2ProviderAzure: + return o.clientCredentialsGrant(ctx, client), nil case oAuth2ProviderGoogle: if o.GoogleJWTFile != "" { cfg, err := google.JWTConfigFromJSON(o.GoogleCredentialsJSON, o.Scopes...) @@ -184,6 +212,9 @@ func (o *oAuth2Config) Validate() error { if o.TokenURL == "" || o.ClientID == "" || o.ClientSecret == "" { return errors.New("both token_url and client credentials must be provided") } + if (o.User != "" && o.Password == "") || (o.User == "" && o.Password != "") { + return errors.New("both user and password credentials must be provided") + } default: return fmt.Errorf("unknown provider %q", o.getProvider()) } diff --git a/x-pack/filebeat/input/httpjson/config_test.go b/x-pack/filebeat/input/httpjson/config_test.go index 67662b40752..71ee7edb246 100644 --- a/x-pack/filebeat/input/httpjson/config_test.go +++ b/x-pack/filebeat/input/httpjson/config_test.go @@ -152,6 +152,48 @@ func TestConfigOauth2Validation(t *testing.T) { "auth.oauth2": map[string]interface{}{}, }, }, + { + name: "if user and password is set oauth2 must use user-password authentication", + input: map[string]interface{}{ + "auth.oauth2": map[string]interface{}{ + "user": "a_client_user", + "password": "a_client_password", + "token_url": "localhost", + "client": map[string]interface{}{ + "id": "a_client_id", + "secret": "a_client_secret", + }, + }, + }, + }, + { + name: "if user is set password credentials must be set for user-password authentication", + expectedErr: "both user and password credentials must be provided accessing 'auth.oauth2'", + input: map[string]interface{}{ + "auth.oauth2": map[string]interface{}{ + "user": "a_client_user", + "token_url": "localhost", + "client": map[string]interface{}{ + "id": "a_client_id", + "secret": "a_client_secret", + }, + }, + }, + }, + { + name: "if password is set user credentials must be set for user-password authentication", + expectedErr: "both user and password credentials must be provided accessing 'auth.oauth2'", + input: map[string]interface{}{ + "auth.oauth2": map[string]interface{}{ + "password": "a_client_password", + "token_url": "localhost", + "client": map[string]interface{}{ + "id": "a_client_id", + "secret": "a_client_secret", + }, + }, + }, + }, { name: "must fail with an unknown provider", expectedErr: "unknown provider \"unknown\" accessing 'auth.oauth2'", diff --git a/x-pack/filebeat/input/httpjson/value_tpl.go b/x-pack/filebeat/input/httpjson/value_tpl.go index 95c95093e5f..d2786b4ce76 100644 --- a/x-pack/filebeat/input/httpjson/value_tpl.go +++ b/x-pack/filebeat/input/httpjson/value_tpl.go @@ -16,6 +16,7 @@ import ( "hash" "reflect" "regexp" + "runtime" "strconv" "strings" "text/template" @@ -23,7 +24,9 @@ import ( "github.com/google/uuid" + "github.com/elastic/beats/v7/libbeat/common/useragent" "github.com/elastic/beats/v7/libbeat/logp" + "github.com/elastic/beats/v7/libbeat/version" ) // we define custom delimiters to prevent issues when using template values as part of other Go templates. @@ -66,6 +69,8 @@ func (t *valueTpl) Unpack(in string) error { "sprintf": fmt.Sprintf, "hmacBase64": hmacStringBase64, "uuid": uuidString, + "userAgent": userAgentString, + "beatInfo": beatInfo, }). Delims(leftDelim, rightDelim). Parse(in) @@ -360,3 +365,17 @@ func join(v interface{}, sep string) string { // return the stringified single value return fmt.Sprint(v) } + +func userAgentString(values ...string) string { + return useragent.UserAgent("Filebeat", values...) +} + +func beatInfo() map[string]string { + return map[string]string{ + "goos": runtime.GOOS, + "goarch": runtime.GOARCH, + "commit": version.Commit(), + "buildtime": version.BuildTime().String(), + "version": version.GetDefaultVersion(), + } +} diff --git a/x-pack/filebeat/input/httpjson/value_tpl_test.go b/x-pack/filebeat/input/httpjson/value_tpl_test.go index ad6aab449de..8c111ee78b6 100644 --- a/x-pack/filebeat/input/httpjson/value_tpl_test.go +++ b/x-pack/filebeat/input/httpjson/value_tpl_test.go @@ -6,13 +6,16 @@ package httpjson import ( "net/http" + "runtime" "testing" "time" "github.com/stretchr/testify/assert" "github.com/elastic/beats/v7/libbeat/common" + "github.com/elastic/beats/v7/libbeat/common/useragent" "github.com/elastic/beats/v7/libbeat/logp" + "github.com/elastic/beats/v7/libbeat/version" ) func TestValueTpl(t *testing.T) { @@ -394,6 +397,69 @@ func TestValueTpl(t *testing.T) { expectedVal: "", expectedError: errEmptyTemplateResult.Error(), }, + { + name: "func userAgent no values", + value: `[[userAgent]]`, + paramCtx: emptyTransformContext(), + paramTr: transformable{}, + expectedVal: useragent.UserAgent("Filebeat"), + }, + { + name: "func userAgent blank value", + value: `[[userAgent ""]]`, + paramCtx: emptyTransformContext(), + paramTr: transformable{}, + expectedVal: useragent.UserAgent("Filebeat"), + }, + { + name: "func userAgent 1 value", + value: `[[userAgent "integration_name/1.2.3"]]`, + paramCtx: emptyTransformContext(), + paramTr: transformable{}, + expectedVal: useragent.UserAgent("Filebeat", "integration_name/1.2.3"), + }, + { + name: "func userAgent 2 value", + value: `[[userAgent "integration_name/1.2.3" "test"]]`, + paramCtx: emptyTransformContext(), + paramTr: transformable{}, + expectedVal: useragent.UserAgent("Filebeat", "integration_name/1.2.3", "test"), + }, + { + name: "func beatInfo GOOS", + value: `[[beatInfo.goos]]`, + paramCtx: emptyTransformContext(), + paramTr: transformable{}, + expectedVal: runtime.GOOS, + }, + { + name: "func beatInfo Arch", + value: `[[beatInfo.goarch]]`, + paramCtx: emptyTransformContext(), + paramTr: transformable{}, + expectedVal: runtime.GOARCH, + }, + { + name: "func beatInfo Commit", + value: `[[beatInfo.commit]]`, + paramCtx: emptyTransformContext(), + paramTr: transformable{}, + expectedVal: version.Commit(), + }, + { + name: "func beatInfo Build Time", + value: `[[beatInfo.buildtime]]`, + paramCtx: emptyTransformContext(), + paramTr: transformable{}, + expectedVal: version.BuildTime().String(), + }, + { + name: "func beatInfo Version", + value: `[[beatInfo.version]]`, + paramCtx: emptyTransformContext(), + paramTr: transformable{}, + expectedVal: version.GetDefaultVersion(), + }, } for _, tc := range cases { diff --git a/x-pack/filebeat/input/netflow/convert.go b/x-pack/filebeat/input/netflow/convert.go index 465cd3efd02..2f10b33c238 100644 --- a/x-pack/filebeat/input/netflow/convert.go +++ b/x-pack/filebeat/input/netflow/convert.go @@ -5,9 +5,11 @@ package netflow import ( + "bytes" "encoding/base64" "encoding/binary" "net" + "sort" "strconv" "strings" "time" @@ -196,6 +198,10 @@ func flowToBeatEvent(flow record.Record, internalNetworks []string) (event beat. ecsSource["ip"] = ip relatedIP = append(relatedIP, ip) ecsSource["locality"] = getIPLocality(internalNetworks, ip).String() + } else if ip, found := getKeyIP(flow.Fields, "sourceIPv6Address"); found { + ecsSource["ip"] = ip + relatedIP = append(relatedIP, ip) + ecsSource["locality"] = getIPLocality(internalNetworks, ip).String() } if sourcePort, found := getKeyUint64(flow.Fields, "sourceTransportPort"); found { ecsSource["port"] = sourcePort @@ -209,6 +215,10 @@ func flowToBeatEvent(flow record.Record, internalNetworks []string) (event beat. ecsDest["ip"] = ip relatedIP = append(relatedIP, ip) ecsDest["locality"] = getIPLocality(internalNetworks, ip).String() + } else if ip, found := getKeyIP(flow.Fields, "destinationIPv6Address"); found { + ecsDest["ip"] = ip + relatedIP = append(relatedIP, ip) + ecsDest["locality"] = getIPLocality(internalNetworks, ip).String() } if destPort, found := getKeyUint64(flow.Fields, "destinationTransportPort"); found { ecsDest["port"] = destPort @@ -321,11 +331,31 @@ func flowToBeatEvent(flow record.Record, internalNetworks []string) (event beat. event.Fields["network"] = ecsNetwork } if len(relatedIP) > 0 { - event.Fields["related"] = common.MapStr{"ip": relatedIP} + event.Fields["related"] = common.MapStr{"ip": uniqueIPs(relatedIP)} } return } +// unique returns ips lexically sorted and with repeated elements +// omitted. +func uniqueIPs(ips []net.IP) []net.IP { + if len(ips) < 2 { + return ips + } + sort.Slice(ips, func(i, j int) bool { return bytes.Compare(ips[i], ips[j]) < 0 }) + curr := 0 + for i, ip := range ips { + if ip.Equal(ips[curr]) { + continue + } + curr++ + if curr < i { + ips[curr], ips[i] = ips[i], nil + } + } + return ips[:curr+1] +} + func getKeyUint64(dict record.Map, key string) (value uint64, found bool) { iface, found := dict[key] if !found { diff --git a/x-pack/filebeat/input/netflow/netflow_test.go b/x-pack/filebeat/input/netflow/netflow_test.go index f1c138989c0..caaa438ebf3 100644 --- a/x-pack/filebeat/input/netflow/netflow_test.go +++ b/x-pack/filebeat/input/netflow/netflow_test.go @@ -16,9 +16,9 @@ import ( "strings" "testing" + "github.com/google/gopacket" + "github.com/google/gopacket/pcap" "github.com/stretchr/testify/assert" - "github.com/tsg/gopacket" - "github.com/tsg/gopacket/pcap" "gopkg.in/yaml.v2" "github.com/elastic/beats/v7/libbeat/beat" @@ -201,7 +201,7 @@ func getFlowsFromDat(t testing.TB, name string, testCase TestCase) TestResult { flow.Fields.Delete("event.created") ev[i] = flow } - //return TestResult{Name: name, Error: err.Error(), Events: flowsToEvents(flows)} + // return TestResult{Name: name, Error: err.Error(), Events: flowsToEvents(flows)} events = append(events, ev...) } } diff --git a/x-pack/filebeat/input/netflow/testdata/golden/IPFIX-Barracuda-extended-uniflow-template-256.golden.json b/x-pack/filebeat/input/netflow/testdata/golden/IPFIX-Barracuda-extended-uniflow-template-256.golden.json index fbc2f5e3d2a..a983b980e1d 100644 --- a/x-pack/filebeat/input/netflow/testdata/golden/IPFIX-Barracuda-extended-uniflow-template-256.golden.json +++ b/x-pack/filebeat/input/netflow/testdata/golden/IPFIX-Barracuda-extended-uniflow-template-256.golden.json @@ -169,8 +169,8 @@ }, "related": { "ip": [ - "64.235.151.76", - "10.236.5.4" + "10.236.5.4", + "64.235.151.76" ] }, "source": { diff --git a/x-pack/filebeat/input/netflow/testdata/golden/IPFIX-Barracuda-firewall.golden.json b/x-pack/filebeat/input/netflow/testdata/golden/IPFIX-Barracuda-firewall.golden.json index ec4f36b10fa..4fae641f637 100644 --- a/x-pack/filebeat/input/netflow/testdata/golden/IPFIX-Barracuda-firewall.golden.json +++ b/x-pack/filebeat/input/netflow/testdata/golden/IPFIX-Barracuda-firewall.golden.json @@ -145,8 +145,8 @@ }, "related": { "ip": [ - "10.99.252.50", - "10.99.130.239" + "10.99.130.239", + "10.99.252.50" ] }, "source": { @@ -225,8 +225,8 @@ }, "related": { "ip": [ - "10.99.130.239", - "10.98.243.20" + "10.98.243.20", + "10.99.130.239" ] }, "source": { @@ -385,8 +385,8 @@ }, "related": { "ip": [ - "10.99.168.140", - "10.98.243.20" + "10.98.243.20", + "10.99.168.140" ] }, "source": { @@ -545,8 +545,8 @@ }, "related": { "ip": [ - "10.99.168.140", - "10.98.243.20" + "10.98.243.20", + "10.99.168.140" ] }, "source": { diff --git a/x-pack/filebeat/input/netflow/testdata/golden/IPFIX-Mikrotik-RouterOS-6.39.2.golden.json b/x-pack/filebeat/input/netflow/testdata/golden/IPFIX-Mikrotik-RouterOS-6.39.2.golden.json index 36fea0d68e1..99fb1859cfc 100644 --- a/x-pack/filebeat/input/netflow/testdata/golden/IPFIX-Mikrotik-RouterOS-6.39.2.golden.json +++ b/x-pack/filebeat/input/netflow/testdata/golden/IPFIX-Mikrotik-RouterOS-6.39.2.golden.json @@ -454,8 +454,8 @@ }, "related": { "ip": [ - "172.20.4.199", - "172.20.4.1" + "172.20.4.1", + "172.20.4.199" ] }, "source": { @@ -610,8 +610,8 @@ }, "related": { "ip": [ - "172.20.4.30", - "10.10.8.34" + "10.10.8.34", + "172.20.4.30" ] }, "source": { @@ -766,8 +766,8 @@ }, "related": { "ip": [ - "172.20.4.30", - "10.10.8.105" + "10.10.8.105", + "172.20.4.30" ] }, "source": { @@ -1078,8 +1078,8 @@ }, "related": { "ip": [ - "172.20.5.191", - "10.10.8.220" + "10.10.8.220", + "172.20.5.191" ] }, "source": { @@ -2190,6 +2190,8 @@ "Meta": null, "Fields": { "destination": { + "ip": "fe80::ff:fe00:401", + "locality": "internal", "port": 5678 }, "event": { @@ -2204,7 +2206,7 @@ ] }, "flow": { - "id": "RlrAo_U1Y14", + "id": "b7SlZfUSuVA", "locality": "internal" }, "netflow": { @@ -2233,7 +2235,7 @@ }, "network": { "bytes": 555, - "community_id": "1:I4DlCbWgyxRiNPVj5ntu1L7Z0hw=", + "community_id": "1:jPPsu6xuLKidwts3HEFDcMotUV4=", "direction": "unknown", "iana_number": 17, "packets": 3, @@ -2242,8 +2244,15 @@ "observer": { "ip": "192.0.2.1" }, + "related": { + "ip": [ + "fe80::ff:fe00:401" + ] + }, "source": { "bytes": 555, + "ip": "fe80::ff:fe00:401", + "locality": "internal", "packets": 3, "port": 5678 } @@ -2256,6 +2265,8 @@ "Meta": null, "Fields": { "destination": { + "ip": "fe80::ff:fe00:401", + "locality": "internal", "port": 5678 }, "event": { @@ -2270,7 +2281,7 @@ ] }, "flow": { - "id": "RlrAo_U1Y14", + "id": "b7SlZfUSuVA", "locality": "internal" }, "netflow": { @@ -2299,7 +2310,7 @@ }, "network": { "bytes": 370, - "community_id": "1:I4DlCbWgyxRiNPVj5ntu1L7Z0hw=", + "community_id": "1:jPPsu6xuLKidwts3HEFDcMotUV4=", "direction": "unknown", "iana_number": 17, "packets": 2, @@ -2308,8 +2319,15 @@ "observer": { "ip": "192.0.2.1" }, + "related": { + "ip": [ + "fe80::ff:fe00:401" + ] + }, "source": { "bytes": 370, + "ip": "fe80::ff:fe00:401", + "locality": "internal", "packets": 2, "port": 5678 } @@ -2322,6 +2340,8 @@ "Meta": null, "Fields": { "destination": { + "ip": "fe80::ff:fe00:501", + "locality": "internal", "port": 5678 }, "event": { @@ -2336,7 +2356,7 @@ ] }, "flow": { - "id": "RlrAo_U1Y14", + "id": "VSgWWLDT0B0", "locality": "internal" }, "netflow": { @@ -2365,7 +2385,7 @@ }, "network": { "bytes": 495, - "community_id": "1:I4DlCbWgyxRiNPVj5ntu1L7Z0hw=", + "community_id": "1:5591MHyJIXcwUkG4sl3Rs9ro+Ng=", "direction": "unknown", "iana_number": 17, "packets": 3, @@ -2374,8 +2394,15 @@ "observer": { "ip": "192.0.2.1" }, + "related": { + "ip": [ + "fe80::ff:fe00:501" + ] + }, "source": { "bytes": 495, + "ip": "fe80::ff:fe00:501", + "locality": "internal", "packets": 3, "port": 5678 } @@ -2388,6 +2415,8 @@ "Meta": null, "Fields": { "destination": { + "ip": "fe80::ff:fe00:501", + "locality": "internal", "port": 5678 }, "event": { @@ -2402,7 +2431,7 @@ ] }, "flow": { - "id": "RlrAo_U1Y14", + "id": "VSgWWLDT0B0", "locality": "internal" }, "netflow": { @@ -2431,7 +2460,7 @@ }, "network": { "bytes": 330, - "community_id": "1:I4DlCbWgyxRiNPVj5ntu1L7Z0hw=", + "community_id": "1:5591MHyJIXcwUkG4sl3Rs9ro+Ng=", "direction": "unknown", "iana_number": 17, "packets": 2, @@ -2440,8 +2469,15 @@ "observer": { "ip": "192.0.2.1" }, + "related": { + "ip": [ + "fe80::ff:fe00:501" + ] + }, "source": { "bytes": 330, + "ip": "fe80::ff:fe00:501", + "locality": "internal", "packets": 2, "port": 5678 } @@ -2454,6 +2490,8 @@ "Meta": null, "Fields": { "destination": { + "ip": "fe80::ff:fe00:601", + "locality": "internal", "port": 5678 }, "event": { @@ -2468,7 +2506,7 @@ ] }, "flow": { - "id": "RlrAo_U1Y14", + "id": "LZgYFJ0tL2g", "locality": "internal" }, "netflow": { @@ -2497,7 +2535,7 @@ }, "network": { "bytes": 555, - "community_id": "1:I4DlCbWgyxRiNPVj5ntu1L7Z0hw=", + "community_id": "1:0uFiK83G7mZT66yRsishu3GrI+Y=", "direction": "unknown", "iana_number": 17, "packets": 3, @@ -2506,8 +2544,15 @@ "observer": { "ip": "192.0.2.1" }, + "related": { + "ip": [ + "fe80::ff:fe00:601" + ] + }, "source": { "bytes": 555, + "ip": "fe80::ff:fe00:601", + "locality": "internal", "packets": 3, "port": 5678 } @@ -2520,6 +2565,8 @@ "Meta": null, "Fields": { "destination": { + "ip": "fe80::ff:fe00:601", + "locality": "internal", "port": 5678 }, "event": { @@ -2534,7 +2581,7 @@ ] }, "flow": { - "id": "RlrAo_U1Y14", + "id": "LZgYFJ0tL2g", "locality": "internal" }, "netflow": { @@ -2563,7 +2610,7 @@ }, "network": { "bytes": 370, - "community_id": "1:I4DlCbWgyxRiNPVj5ntu1L7Z0hw=", + "community_id": "1:0uFiK83G7mZT66yRsishu3GrI+Y=", "direction": "unknown", "iana_number": 17, "packets": 2, @@ -2572,8 +2619,15 @@ "observer": { "ip": "192.0.2.1" }, + "related": { + "ip": [ + "fe80::ff:fe00:601" + ] + }, "source": { "bytes": 370, + "ip": "fe80::ff:fe00:601", + "locality": "internal", "packets": 2, "port": 5678 } @@ -2586,6 +2640,8 @@ "Meta": null, "Fields": { "destination": { + "ip": "fe80::ff:fe00:701", + "locality": "internal", "port": 5678 }, "event": { @@ -2600,7 +2656,7 @@ ] }, "flow": { - "id": "RlrAo_U1Y14", + "id": "dmeH14jqz_U", "locality": "internal" }, "netflow": { @@ -2629,7 +2685,7 @@ }, "network": { "bytes": 555, - "community_id": "1:I4DlCbWgyxRiNPVj5ntu1L7Z0hw=", + "community_id": "1:GHzTYB/S+swKAM+TWkXhIHekjME=", "direction": "unknown", "iana_number": 17, "packets": 3, @@ -2638,8 +2694,15 @@ "observer": { "ip": "192.0.2.1" }, + "related": { + "ip": [ + "fe80::ff:fe00:701" + ] + }, "source": { "bytes": 555, + "ip": "fe80::ff:fe00:701", + "locality": "internal", "packets": 3, "port": 5678 } @@ -2652,6 +2715,8 @@ "Meta": null, "Fields": { "destination": { + "ip": "fe80::ff:fe00:701", + "locality": "internal", "port": 5678 }, "event": { @@ -2666,7 +2731,7 @@ ] }, "flow": { - "id": "RlrAo_U1Y14", + "id": "dmeH14jqz_U", "locality": "internal" }, "netflow": { @@ -2695,7 +2760,7 @@ }, "network": { "bytes": 370, - "community_id": "1:I4DlCbWgyxRiNPVj5ntu1L7Z0hw=", + "community_id": "1:GHzTYB/S+swKAM+TWkXhIHekjME=", "direction": "unknown", "iana_number": 17, "packets": 2, @@ -2704,8 +2769,15 @@ "observer": { "ip": "192.0.2.1" }, + "related": { + "ip": [ + "fe80::ff:fe00:701" + ] + }, "source": { "bytes": 370, + "ip": "fe80::ff:fe00:701", + "locality": "internal", "packets": 2, "port": 5678 } @@ -2718,6 +2790,8 @@ "Meta": null, "Fields": { "destination": { + "ip": "fe80::ff:fe00:801", + "locality": "internal", "port": 5678 }, "event": { @@ -2732,7 +2806,7 @@ ] }, "flow": { - "id": "RlrAo_U1Y14", + "id": "Il9O6oJGqRk", "locality": "internal" }, "netflow": { @@ -2761,7 +2835,7 @@ }, "network": { "bytes": 555, - "community_id": "1:I4DlCbWgyxRiNPVj5ntu1L7Z0hw=", + "community_id": "1:Y0L0KaggvOgNiQSbjBDXSANtIRo=", "direction": "unknown", "iana_number": 17, "packets": 3, @@ -2770,8 +2844,15 @@ "observer": { "ip": "192.0.2.1" }, + "related": { + "ip": [ + "fe80::ff:fe00:801" + ] + }, "source": { "bytes": 555, + "ip": "fe80::ff:fe00:801", + "locality": "internal", "packets": 3, "port": 5678 } @@ -2784,6 +2865,8 @@ "Meta": null, "Fields": { "destination": { + "ip": "fe80::ff:fe00:801", + "locality": "internal", "port": 5678 }, "event": { @@ -2798,7 +2881,7 @@ ] }, "flow": { - "id": "RlrAo_U1Y14", + "id": "Il9O6oJGqRk", "locality": "internal" }, "netflow": { @@ -2827,7 +2910,7 @@ }, "network": { "bytes": 370, - "community_id": "1:I4DlCbWgyxRiNPVj5ntu1L7Z0hw=", + "community_id": "1:Y0L0KaggvOgNiQSbjBDXSANtIRo=", "direction": "unknown", "iana_number": 17, "packets": 2, @@ -2836,8 +2919,15 @@ "observer": { "ip": "192.0.2.1" }, + "related": { + "ip": [ + "fe80::ff:fe00:801" + ] + }, "source": { "bytes": 370, + "ip": "fe80::ff:fe00:801", + "locality": "internal", "packets": 2, "port": 5678 } @@ -2850,6 +2940,8 @@ "Meta": null, "Fields": { "destination": { + "ip": "fe80::ff:fe00:901", + "locality": "internal", "port": 5678 }, "event": { @@ -2864,7 +2956,7 @@ ] }, "flow": { - "id": "RlrAo_U1Y14", + "id": "fA2V7HT45yo", "locality": "internal" }, "netflow": { @@ -2893,7 +2985,7 @@ }, "network": { "bytes": 555, - "community_id": "1:I4DlCbWgyxRiNPVj5ntu1L7Z0hw=", + "community_id": "1:ckujBEtohW0WnvxDVLoLAfkwHeE=", "direction": "unknown", "iana_number": 17, "packets": 3, @@ -2902,8 +2994,15 @@ "observer": { "ip": "192.0.2.1" }, + "related": { + "ip": [ + "fe80::ff:fe00:901" + ] + }, "source": { "bytes": 555, + "ip": "fe80::ff:fe00:901", + "locality": "internal", "packets": 3, "port": 5678 } @@ -2916,6 +3015,8 @@ "Meta": null, "Fields": { "destination": { + "ip": "fe80::ff:fe00:901", + "locality": "internal", "port": 5678 }, "event": { @@ -2930,7 +3031,7 @@ ] }, "flow": { - "id": "RlrAo_U1Y14", + "id": "fA2V7HT45yo", "locality": "internal" }, "netflow": { @@ -2959,7 +3060,7 @@ }, "network": { "bytes": 370, - "community_id": "1:I4DlCbWgyxRiNPVj5ntu1L7Z0hw=", + "community_id": "1:ckujBEtohW0WnvxDVLoLAfkwHeE=", "direction": "unknown", "iana_number": 17, "packets": 2, @@ -2968,8 +3069,15 @@ "observer": { "ip": "192.0.2.1" }, + "related": { + "ip": [ + "fe80::ff:fe00:901" + ] + }, "source": { "bytes": 370, + "ip": "fe80::ff:fe00:901", + "locality": "internal", "packets": 2, "port": 5678 } @@ -2982,6 +3090,8 @@ "Meta": null, "Fields": { "destination": { + "ip": "fe80::ff:fe00:1001", + "locality": "internal", "port": 5678 }, "event": { @@ -2996,7 +3106,7 @@ ] }, "flow": { - "id": "RlrAo_U1Y14", + "id": "r9myTc0ZAtE", "locality": "internal" }, "netflow": { @@ -3025,7 +3135,7 @@ }, "network": { "bytes": 555, - "community_id": "1:I4DlCbWgyxRiNPVj5ntu1L7Z0hw=", + "community_id": "1:3MYYQzFTLjghJ6R8FULtQ6M3TY4=", "direction": "unknown", "iana_number": 17, "packets": 3, @@ -3034,8 +3144,15 @@ "observer": { "ip": "192.0.2.1" }, + "related": { + "ip": [ + "fe80::ff:fe00:1001" + ] + }, "source": { "bytes": 555, + "ip": "fe80::ff:fe00:1001", + "locality": "internal", "packets": 3, "port": 5678 } @@ -3048,6 +3165,8 @@ "Meta": null, "Fields": { "destination": { + "ip": "fe80::ff:fe00:1001", + "locality": "internal", "port": 5678 }, "event": { @@ -3062,7 +3181,7 @@ ] }, "flow": { - "id": "RlrAo_U1Y14", + "id": "r9myTc0ZAtE", "locality": "internal" }, "netflow": { @@ -3091,7 +3210,7 @@ }, "network": { "bytes": 370, - "community_id": "1:I4DlCbWgyxRiNPVj5ntu1L7Z0hw=", + "community_id": "1:3MYYQzFTLjghJ6R8FULtQ6M3TY4=", "direction": "unknown", "iana_number": 17, "packets": 2, @@ -3100,8 +3219,15 @@ "observer": { "ip": "192.0.2.1" }, + "related": { + "ip": [ + "fe80::ff:fe00:1001" + ] + }, "source": { "bytes": 370, + "ip": "fe80::ff:fe00:1001", + "locality": "internal", "packets": 2, "port": 5678 } @@ -3114,6 +3240,8 @@ "Meta": null, "Fields": { "destination": { + "ip": "fe80::ff:fe00:1101", + "locality": "internal", "port": 5678 }, "event": { @@ -3128,7 +3256,7 @@ ] }, "flow": { - "id": "RlrAo_U1Y14", + "id": "we4v-M4gTEo", "locality": "internal" }, "netflow": { @@ -3157,7 +3285,7 @@ }, "network": { "bytes": 555, - "community_id": "1:I4DlCbWgyxRiNPVj5ntu1L7Z0hw=", + "community_id": "1:RCaNdj14AFbHfSM4MQquuPjYpgs=", "direction": "unknown", "iana_number": 17, "packets": 3, @@ -3166,8 +3294,15 @@ "observer": { "ip": "192.0.2.1" }, + "related": { + "ip": [ + "fe80::ff:fe00:1101" + ] + }, "source": { "bytes": 555, + "ip": "fe80::ff:fe00:1101", + "locality": "internal", "packets": 3, "port": 5678 } @@ -3180,6 +3315,8 @@ "Meta": null, "Fields": { "destination": { + "ip": "fe80::ff:fe00:1101", + "locality": "internal", "port": 5678 }, "event": { @@ -3194,7 +3331,7 @@ ] }, "flow": { - "id": "RlrAo_U1Y14", + "id": "we4v-M4gTEo", "locality": "internal" }, "netflow": { @@ -3223,7 +3360,7 @@ }, "network": { "bytes": 370, - "community_id": "1:I4DlCbWgyxRiNPVj5ntu1L7Z0hw=", + "community_id": "1:RCaNdj14AFbHfSM4MQquuPjYpgs=", "direction": "unknown", "iana_number": 17, "packets": 2, @@ -3232,8 +3369,15 @@ "observer": { "ip": "192.0.2.1" }, + "related": { + "ip": [ + "fe80::ff:fe00:1101" + ] + }, "source": { "bytes": 370, + "ip": "fe80::ff:fe00:1101", + "locality": "internal", "packets": 2, "port": 5678 } @@ -3246,6 +3390,8 @@ "Meta": null, "Fields": { "destination": { + "ip": "fe80::ff:fe00:1201", + "locality": "internal", "port": 5678 }, "event": { @@ -3260,7 +3406,7 @@ ] }, "flow": { - "id": "RlrAo_U1Y14", + "id": "N9KUKy-eIwc", "locality": "internal" }, "netflow": { @@ -3289,7 +3435,7 @@ }, "network": { "bytes": 555, - "community_id": "1:I4DlCbWgyxRiNPVj5ntu1L7Z0hw=", + "community_id": "1:AL2CtUGKb1BgJM4KclloxlRQdRc=", "direction": "unknown", "iana_number": 17, "packets": 3, @@ -3298,8 +3444,15 @@ "observer": { "ip": "192.0.2.1" }, + "related": { + "ip": [ + "fe80::ff:fe00:1201" + ] + }, "source": { "bytes": 555, + "ip": "fe80::ff:fe00:1201", + "locality": "internal", "packets": 3, "port": 5678 } @@ -3312,6 +3465,8 @@ "Meta": null, "Fields": { "destination": { + "ip": "fe80::ff:fe00:1201", + "locality": "internal", "port": 5678 }, "event": { @@ -3326,7 +3481,7 @@ ] }, "flow": { - "id": "RlrAo_U1Y14", + "id": "N9KUKy-eIwc", "locality": "internal" }, "netflow": { @@ -3355,7 +3510,7 @@ }, "network": { "bytes": 370, - "community_id": "1:I4DlCbWgyxRiNPVj5ntu1L7Z0hw=", + "community_id": "1:AL2CtUGKb1BgJM4KclloxlRQdRc=", "direction": "unknown", "iana_number": 17, "packets": 2, @@ -3364,8 +3519,15 @@ "observer": { "ip": "192.0.2.1" }, + "related": { + "ip": [ + "fe80::ff:fe00:1201" + ] + }, "source": { "bytes": 370, + "ip": "fe80::ff:fe00:1201", + "locality": "internal", "packets": 2, "port": 5678 } diff --git a/x-pack/filebeat/input/netflow/testdata/golden/IPFIX-Netscaler-with-variable-length-fields.golden.json b/x-pack/filebeat/input/netflow/testdata/golden/IPFIX-Netscaler-with-variable-length-fields.golden.json index e27655fe1ed..9d0ddb6a2fd 100644 --- a/x-pack/filebeat/input/netflow/testdata/golden/IPFIX-Netscaler-with-variable-length-fields.golden.json +++ b/x-pack/filebeat/input/netflow/testdata/golden/IPFIX-Netscaler-with-variable-length-fields.golden.json @@ -87,8 +87,8 @@ }, "related": { "ip": [ - "192.168.0.1", - "10.0.0.1" + "10.0.0.1", + "192.168.0.1" ] }, "source": { @@ -277,8 +277,8 @@ }, "related": { "ip": [ - "192.168.0.1", - "10.0.0.1" + "10.0.0.1", + "192.168.0.1" ] }, "source": { diff --git a/x-pack/filebeat/input/netflow/testdata/golden/IPFIX-Nokia-BRAS.golden.json b/x-pack/filebeat/input/netflow/testdata/golden/IPFIX-Nokia-BRAS.golden.json index f21438c20ee..3f50095a6c0 100644 --- a/x-pack/filebeat/input/netflow/testdata/golden/IPFIX-Nokia-BRAS.golden.json +++ b/x-pack/filebeat/input/netflow/testdata/golden/IPFIX-Nokia-BRAS.golden.json @@ -57,8 +57,8 @@ }, "related": { "ip": [ - "10.0.1.228", - "10.0.0.34" + "10.0.0.34", + "10.0.1.228" ] }, "source": { diff --git a/x-pack/filebeat/input/netflow/testdata/golden/IPFIX-OpenBSD-pflow.golden.json b/x-pack/filebeat/input/netflow/testdata/golden/IPFIX-OpenBSD-pflow.golden.json index 4961f7d0a25..04c22e39df4 100644 --- a/x-pack/filebeat/input/netflow/testdata/golden/IPFIX-OpenBSD-pflow.golden.json +++ b/x-pack/filebeat/input/netflow/testdata/golden/IPFIX-OpenBSD-pflow.golden.json @@ -60,8 +60,8 @@ }, "related": { "ip": [ - "192.168.0.17", - "192.168.0.1" + "192.168.0.1", + "192.168.0.17" ] }, "source": { @@ -208,8 +208,8 @@ }, "related": { "ip": [ - "192.168.0.17", - "192.168.0.1" + "192.168.0.1", + "192.168.0.17" ] }, "source": { @@ -356,8 +356,8 @@ }, "related": { "ip": [ - "192.168.0.17", - "192.168.0.1" + "192.168.0.1", + "192.168.0.17" ] }, "source": { @@ -504,8 +504,8 @@ }, "related": { "ip": [ - "192.168.0.17", - "192.168.0.1" + "192.168.0.1", + "192.168.0.17" ] }, "source": { @@ -652,8 +652,8 @@ }, "related": { "ip": [ - "192.168.0.17", - "192.168.0.1" + "192.168.0.1", + "192.168.0.17" ] }, "source": { @@ -800,8 +800,8 @@ }, "related": { "ip": [ - "192.168.0.17", - "192.168.0.1" + "192.168.0.1", + "192.168.0.17" ] }, "source": { @@ -948,8 +948,8 @@ }, "related": { "ip": [ - "192.168.0.17", - "192.168.0.1" + "192.168.0.1", + "192.168.0.17" ] }, "source": { @@ -1096,8 +1096,8 @@ }, "related": { "ip": [ - "192.168.0.17", - "192.168.0.1" + "192.168.0.1", + "192.168.0.17" ] }, "source": { @@ -1244,8 +1244,8 @@ }, "related": { "ip": [ - "192.168.0.17", - "192.168.0.1" + "192.168.0.1", + "192.168.0.17" ] }, "source": { @@ -1392,8 +1392,8 @@ }, "related": { "ip": [ - "192.168.0.17", - "192.168.0.1" + "192.168.0.1", + "192.168.0.17" ] }, "source": { @@ -1540,8 +1540,8 @@ }, "related": { "ip": [ - "192.168.0.17", - "192.168.0.1" + "192.168.0.1", + "192.168.0.17" ] }, "source": { @@ -1688,8 +1688,8 @@ }, "related": { "ip": [ - "192.168.0.17", - "192.168.0.1" + "192.168.0.1", + "192.168.0.17" ] }, "source": { @@ -1836,8 +1836,8 @@ }, "related": { "ip": [ - "192.168.0.17", - "192.168.0.1" + "192.168.0.1", + "192.168.0.17" ] }, "source": { diff --git a/x-pack/filebeat/input/netflow/testdata/golden/IPFIX-Procera.golden.json b/x-pack/filebeat/input/netflow/testdata/golden/IPFIX-Procera.golden.json index 30acfdf29c5..4c2a0fa8253 100644 --- a/x-pack/filebeat/input/netflow/testdata/golden/IPFIX-Procera.golden.json +++ b/x-pack/filebeat/input/netflow/testdata/golden/IPFIX-Procera.golden.json @@ -69,8 +69,8 @@ }, "related": { "ip": [ - "181.214.87.71", - "138.44.161.14" + "138.44.161.14", + "181.214.87.71" ] }, "source": { @@ -150,7 +150,6 @@ }, "related": { "ip": [ - "0.0.0.0", "0.0.0.0" ] }, @@ -312,8 +311,8 @@ }, "related": { "ip": [ - "206.117.25.89", - "138.44.161.14" + "138.44.161.14", + "206.117.25.89" ] }, "source": { @@ -393,7 +392,6 @@ }, "related": { "ip": [ - "0.0.0.0", "0.0.0.0" ] }, @@ -474,8 +472,8 @@ }, "related": { "ip": [ - "185.232.29.199", - "138.44.161.14" + "138.44.161.14", + "185.232.29.199" ] }, "source": { @@ -555,8 +553,8 @@ }, "related": { "ip": [ - "177.188.228.137", - "138.44.161.14" + "138.44.161.14", + "177.188.228.137" ] }, "source": { @@ -636,8 +634,8 @@ }, "related": { "ip": [ - "138.44.161.14", - "138.44.161.13" + "138.44.161.13", + "138.44.161.14" ] }, "source": { diff --git a/x-pack/filebeat/input/netflow/testdata/golden/IPFIX-VMware-virtual-distributed-switch.golden.json b/x-pack/filebeat/input/netflow/testdata/golden/IPFIX-VMware-virtual-distributed-switch.golden.json index dc8f538dfee..3396c5ef794 100644 --- a/x-pack/filebeat/input/netflow/testdata/golden/IPFIX-VMware-virtual-distributed-switch.golden.json +++ b/x-pack/filebeat/input/netflow/testdata/golden/IPFIX-VMware-virtual-distributed-switch.golden.json @@ -338,6 +338,8 @@ "Meta": null, "Fields": { "destination": { + "ip": "ff02::1:3", + "locality": "internal", "port": 5355 }, "event": { @@ -352,7 +354,7 @@ ] }, "flow": { - "id": "y_Vml2vPNtw", + "id": "iOQ1bg2JOLM", "locality": "internal" }, "netflow": { @@ -388,7 +390,7 @@ }, "network": { "bytes": 144, - "community_id": "1:Nl0K3f1AqKrkGYEhoNHcgFAr/EY=", + "community_id": "1:pr+rxLjqBu9/jT6yJoAEy7/fgdY=", "direction": "outbound", "iana_number": 17, "packets": 2, @@ -397,8 +399,16 @@ "observer": { "ip": "192.0.2.1" }, + "related": { + "ip": [ + "fe80::5187:5cd8:d750:cdc9", + "ff02::1:3" + ] + }, "source": { "bytes": 144, + "ip": "fe80::5187:5cd8:d750:cdc9", + "locality": "internal", "packets": 2, "port": 61329 } diff --git a/x-pack/filebeat/input/netflow/testdata/golden/IPFIX-YAF-basic-with-applabel.golden.json b/x-pack/filebeat/input/netflow/testdata/golden/IPFIX-YAF-basic-with-applabel.golden.json index 5b2b4b01ac3..6c77e7a0fa9 100644 --- a/x-pack/filebeat/input/netflow/testdata/golden/IPFIX-YAF-basic-with-applabel.golden.json +++ b/x-pack/filebeat/input/netflow/testdata/golden/IPFIX-YAF-basic-with-applabel.golden.json @@ -70,8 +70,8 @@ }, "related": { "ip": [ - "172.16.32.201", - "172.16.32.100" + "172.16.32.100", + "172.16.32.201" ] }, "source": { diff --git a/x-pack/filebeat/input/netflow/testdata/golden/IPFIX-configured-with-include_flowset_id.golden.json b/x-pack/filebeat/input/netflow/testdata/golden/IPFIX-configured-with-include_flowset_id.golden.json index 0c2dbd22d5e..c3934c5e32b 100644 --- a/x-pack/filebeat/input/netflow/testdata/golden/IPFIX-configured-with-include_flowset_id.golden.json +++ b/x-pack/filebeat/input/netflow/testdata/golden/IPFIX-configured-with-include_flowset_id.golden.json @@ -87,8 +87,8 @@ }, "related": { "ip": [ - "192.168.0.1", - "10.0.0.1" + "10.0.0.1", + "192.168.0.1" ] }, "source": { @@ -277,8 +277,8 @@ }, "related": { "ip": [ - "192.168.0.1", - "10.0.0.1" + "10.0.0.1", + "192.168.0.1" ] }, "source": { diff --git a/x-pack/filebeat/input/netflow/testdata/golden/IPFIX.golden.json b/x-pack/filebeat/input/netflow/testdata/golden/IPFIX.golden.json index 72dd4072ef9..7ba0ecb0713 100644 --- a/x-pack/filebeat/input/netflow/testdata/golden/IPFIX.golden.json +++ b/x-pack/filebeat/input/netflow/testdata/golden/IPFIX.golden.json @@ -180,8 +180,8 @@ }, "related": { "ip": [ - "192.168.253.128", - "192.168.253.1" + "192.168.253.1", + "192.168.253.128" ] }, "source": { @@ -336,8 +336,8 @@ }, "related": { "ip": [ - "192.168.253.132", - "192.168.253.2" + "192.168.253.2", + "192.168.253.132" ] }, "source": { @@ -492,8 +492,8 @@ }, "related": { "ip": [ - "192.168.253.132", - "54.214.9.161" + "54.214.9.161", + "192.168.253.132" ] }, "source": { @@ -570,8 +570,8 @@ }, "related": { "ip": [ - "192.168.253.130", - "10.4.36.64" + "10.4.36.64", + "192.168.253.130" ] }, "source": { @@ -726,8 +726,8 @@ }, "related": { "ip": [ - "192.168.253.128", - "192.168.253.1" + "192.168.253.1", + "192.168.253.128" ] }, "source": { @@ -882,8 +882,8 @@ }, "related": { "ip": [ - "192.168.253.128", - "192.168.253.1" + "192.168.253.1", + "192.168.253.128" ] }, "source": { diff --git a/x-pack/filebeat/input/netflow/testdata/golden/Netflow-9-Cisco-1941-K9-release-15.1.golden.json b/x-pack/filebeat/input/netflow/testdata/golden/Netflow-9-Cisco-1941-K9-release-15.1.golden.json index 448709e5c41..834efbc7df6 100644 --- a/x-pack/filebeat/input/netflow/testdata/golden/Netflow-9-Cisco-1941-K9-release-15.1.golden.json +++ b/x-pack/filebeat/input/netflow/testdata/golden/Netflow-9-Cisco-1941-K9-release-15.1.golden.json @@ -63,8 +63,8 @@ }, "related": { "ip": [ - "192.168.0.111", - "62.217.193.1" + "62.217.193.1", + "192.168.0.111" ] }, "source": { @@ -141,8 +141,8 @@ }, "related": { "ip": [ - "192.168.0.111", - "62.217.193.65" + "62.217.193.65", + "192.168.0.111" ] }, "source": { @@ -219,8 +219,8 @@ }, "related": { "ip": [ - "192.168.0.111", - "62.217.193.1" + "62.217.193.1", + "192.168.0.111" ] }, "source": { @@ -297,8 +297,8 @@ }, "related": { "ip": [ - "192.168.0.111", - "62.217.193.65" + "62.217.193.65", + "192.168.0.111" ] }, "source": { @@ -531,8 +531,8 @@ }, "related": { "ip": [ - "216.58.212.195", - "192.168.0.88" + "192.168.0.88", + "216.58.212.195" ] }, "source": { @@ -687,8 +687,8 @@ }, "related": { "ip": [ - "216.58.201.106", - "192.168.1.201" + "192.168.1.201", + "216.58.201.106" ] }, "source": { @@ -843,8 +843,8 @@ }, "related": { "ip": [ - "192.168.3.34", - "52.216.130.237" + "52.216.130.237", + "192.168.3.34" ] }, "source": { @@ -921,8 +921,8 @@ }, "related": { "ip": [ - "209.197.3.19", - "192.168.3.34" + "192.168.3.34", + "209.197.3.19" ] }, "source": { @@ -1077,8 +1077,8 @@ }, "related": { "ip": [ - "192.168.0.157", - "172.217.23.232" + "172.217.23.232", + "192.168.0.157" ] }, "source": { @@ -1311,8 +1311,8 @@ }, "related": { "ip": [ - "192.168.3.178", - "107.21.232.174" + "107.21.232.174", + "192.168.3.178" ] }, "source": { @@ -1389,8 +1389,8 @@ }, "related": { "ip": [ - "192.168.2.118", - "95.0.145.242" + "95.0.145.242", + "192.168.2.118" ] }, "source": { @@ -1545,8 +1545,8 @@ }, "related": { "ip": [ - "192.168.0.79", - "23.5.100.66" + "23.5.100.66", + "192.168.0.79" ] }, "source": { @@ -1623,8 +1623,8 @@ }, "related": { "ip": [ - "192.168.0.79", - "23.5.100.66" + "23.5.100.66", + "192.168.0.79" ] }, "source": { @@ -1857,8 +1857,8 @@ }, "related": { "ip": [ - "192.168.0.61", - "170.251.180.15" + "170.251.180.15", + "192.168.0.61" ] }, "source": { @@ -1935,8 +1935,8 @@ }, "related": { "ip": [ - "192.168.3.34", - "74.119.119.84" + "74.119.119.84", + "192.168.3.34" ] }, "source": { @@ -2091,8 +2091,8 @@ }, "related": { "ip": [ - "192.168.3.200", - "185.60.218.15" + "185.60.218.15", + "192.168.3.200" ] }, "source": { @@ -2247,8 +2247,8 @@ }, "related": { "ip": [ - "192.168.0.95", - "169.45.214.246" + "169.45.214.246", + "192.168.0.95" ] }, "source": { diff --git a/x-pack/filebeat/input/netflow/testdata/golden/Netflow-9-Cisco-ASA.golden.json b/x-pack/filebeat/input/netflow/testdata/golden/Netflow-9-Cisco-ASA.golden.json index 135aa56d0d4..d8ebc7e8eaa 100644 --- a/x-pack/filebeat/input/netflow/testdata/golden/Netflow-9-Cisco-ASA.golden.json +++ b/x-pack/filebeat/input/netflow/testdata/golden/Netflow-9-Cisco-ASA.golden.json @@ -69,8 +69,8 @@ }, "related": { "ip": [ - "192.168.14.1", - "2.2.2.11" + "2.2.2.11", + "192.168.14.1" ] }, "source": { @@ -151,8 +151,8 @@ }, "related": { "ip": [ - "192.168.23.22", - "164.164.37.11" + "164.164.37.11", + "192.168.23.22" ] }, "source": { @@ -315,8 +315,8 @@ }, "related": { "ip": [ - "192.168.23.20", - "164.164.37.11" + "164.164.37.11", + "192.168.23.20" ] }, "source": { @@ -479,8 +479,8 @@ }, "related": { "ip": [ - "192.168.14.11", - "2.2.2.11" + "2.2.2.11", + "192.168.14.11" ] }, "source": { @@ -725,8 +725,8 @@ }, "related": { "ip": [ - "192.168.14.1", - "2.2.2.11" + "2.2.2.11", + "192.168.14.1" ] }, "source": { @@ -889,8 +889,8 @@ }, "related": { "ip": [ - "192.168.23.22", - "164.164.37.11" + "164.164.37.11", + "192.168.23.22" ] }, "source": { @@ -1053,8 +1053,8 @@ }, "related": { "ip": [ - "192.168.23.20", - "164.164.37.11" + "164.164.37.11", + "192.168.23.20" ] }, "source": { diff --git a/x-pack/filebeat/input/netflow/testdata/golden/Netflow-9-Cisco-ASR-9000-series-template-260.golden.json b/x-pack/filebeat/input/netflow/testdata/golden/Netflow-9-Cisco-ASR-9000-series-template-260.golden.json index 9922cc10d66..70cfcfdd14e 100644 --- a/x-pack/filebeat/input/netflow/testdata/golden/Netflow-9-Cisco-ASR-9000-series-template-260.golden.json +++ b/x-pack/filebeat/input/netflow/testdata/golden/Netflow-9-Cisco-ASR-9000-series-template-260.golden.json @@ -421,8 +421,8 @@ }, "related": { "ip": [ - "10.0.34.71", - "10.0.20.242" + "10.0.20.242", + "10.0.34.71" ] }, "source": { @@ -595,8 +595,8 @@ }, "related": { "ip": [ - "10.0.37.29", - "10.0.6.24" + "10.0.6.24", + "10.0.37.29" ] }, "source": { @@ -682,8 +682,8 @@ }, "related": { "ip": [ - "10.0.32.176", - "10.0.11.113" + "10.0.11.113", + "10.0.32.176" ] }, "source": { @@ -856,8 +856,8 @@ }, "related": { "ip": [ - "10.0.4.212", - "10.0.3.110" + "10.0.3.110", + "10.0.4.212" ] }, "source": { @@ -943,8 +943,8 @@ }, "related": { "ip": [ - "10.0.33.122", - "10.0.1.136" + "10.0.1.136", + "10.0.33.122" ] }, "source": { @@ -1204,8 +1204,8 @@ }, "related": { "ip": [ - "10.0.25.59", - "10.0.2.18" + "10.0.2.18", + "10.0.25.59" ] }, "source": { @@ -1465,8 +1465,8 @@ }, "related": { "ip": [ - "10.0.28.150", - "10.0.24.13" + "10.0.24.13", + "10.0.28.150" ] }, "source": { @@ -1552,8 +1552,8 @@ }, "related": { "ip": [ - "10.0.26.188", - "10.0.21.200" + "10.0.21.200", + "10.0.26.188" ] }, "source": { @@ -1639,8 +1639,8 @@ }, "related": { "ip": [ - "10.0.29.34", - "10.0.15.38" + "10.0.15.38", + "10.0.29.34" ] }, "source": { @@ -1726,8 +1726,8 @@ }, "related": { "ip": [ - "10.0.8.200", - "10.0.5.224" + "10.0.5.224", + "10.0.8.200" ] }, "source": { @@ -1813,8 +1813,8 @@ }, "related": { "ip": [ - "10.0.29.46", - "10.0.15.38" + "10.0.15.38", + "10.0.29.46" ] }, "source": { diff --git a/x-pack/filebeat/input/netflow/testdata/golden/Netflow-9-Cisco-ASR1001--X.golden.json b/x-pack/filebeat/input/netflow/testdata/golden/Netflow-9-Cisco-ASR1001--X.golden.json index 9049d551304..b548a68d523 100644 --- a/x-pack/filebeat/input/netflow/testdata/golden/Netflow-9-Cisco-ASR1001--X.golden.json +++ b/x-pack/filebeat/input/netflow/testdata/golden/Netflow-9-Cisco-ASR1001--X.golden.json @@ -63,8 +63,8 @@ }, "related": { "ip": [ - "10.111.111.242", - "10.12.100.13" + "10.12.100.13", + "10.111.111.242" ] }, "source": { @@ -294,8 +294,8 @@ }, "related": { "ip": [ - "10.12.104.239", - "10.10.11.21" + "10.10.11.21", + "10.12.104.239" ] }, "source": { @@ -448,8 +448,8 @@ }, "related": { "ip": [ - "10.100.101.45", - "10.15.131.98" + "10.15.131.98", + "10.100.101.45" ] }, "source": { @@ -525,8 +525,8 @@ }, "related": { "ip": [ - "10.100.101.43", - "10.12.105.23" + "10.12.105.23", + "10.100.101.43" ] }, "source": { @@ -602,8 +602,8 @@ }, "related": { "ip": [ - "31.13.71.7", - "10.11.31.108" + "10.11.31.108", + "31.13.71.7" ] }, "source": { @@ -833,8 +833,8 @@ }, "related": { "ip": [ - "10.100.105.86", - "10.11.21.60" + "10.11.21.60", + "10.100.105.86" ] }, "source": { @@ -987,8 +987,8 @@ }, "related": { "ip": [ - "10.12.106.83", - "10.10.11.21" + "10.10.11.21", + "10.12.106.83" ] }, "source": { @@ -1064,8 +1064,8 @@ }, "related": { "ip": [ - "172.217.11.5", - "10.12.92.102" + "10.12.92.102", + "172.217.11.5" ] }, "source": { @@ -1295,8 +1295,8 @@ }, "related": { "ip": [ - "10.14.121.98", - "10.12.100.13" + "10.12.100.13", + "10.14.121.98" ] }, "source": { @@ -1526,8 +1526,8 @@ }, "related": { "ip": [ - "10.12.102.125", - "10.10.11.21" + "10.10.11.21", + "10.12.102.125" ] }, "source": { @@ -1603,8 +1603,8 @@ }, "related": { "ip": [ - "10.100.105.86", - "10.11.21.60" + "10.11.21.60", + "10.100.105.86" ] }, "source": { @@ -1757,8 +1757,8 @@ }, "related": { "ip": [ - "10.100.105.85", - "10.10.4.151" + "10.10.4.151", + "10.100.105.85" ] }, "source": { diff --git a/x-pack/filebeat/input/netflow/testdata/golden/Netflow-9-Fortigate-FortiOS-5.2.1.golden.json b/x-pack/filebeat/input/netflow/testdata/golden/Netflow-9-Fortigate-FortiOS-5.2.1.golden.json index 8dc5747704a..962a60d4efd 100644 --- a/x-pack/filebeat/input/netflow/testdata/golden/Netflow-9-Fortigate-FortiOS-5.2.1.golden.json +++ b/x-pack/filebeat/input/netflow/testdata/golden/Netflow-9-Fortigate-FortiOS-5.2.1.golden.json @@ -102,8 +102,8 @@ }, "related": { "ip": [ - "192.168.99.7", - "31.13.87.36" + "31.13.87.36", + "192.168.99.7" ] }, "source": { diff --git a/x-pack/filebeat/input/netflow/testdata/golden/Netflow-9-Fortigate-FortiOS-54x-appid.golden.json b/x-pack/filebeat/input/netflow/testdata/golden/Netflow-9-Fortigate-FortiOS-54x-appid.golden.json index dd90fa13b6d..a6d193432de 100644 --- a/x-pack/filebeat/input/netflow/testdata/golden/Netflow-9-Fortigate-FortiOS-54x-appid.golden.json +++ b/x-pack/filebeat/input/netflow/testdata/golden/Netflow-9-Fortigate-FortiOS-54x-appid.golden.json @@ -71,8 +71,8 @@ }, "related": { "ip": [ - "192.168.100.151", - "182.50.136.239" + "182.50.136.239", + "192.168.100.151" ] }, "source": { @@ -156,8 +156,8 @@ }, "related": { "ip": [ - "208.100.17.187", - "192.168.100.151" + "192.168.100.151", + "208.100.17.187" ] }, "source": { @@ -326,8 +326,8 @@ }, "related": { "ip": [ - "208.100.17.189", - "192.168.100.151" + "192.168.100.151", + "208.100.17.189" ] }, "source": { @@ -581,8 +581,8 @@ }, "related": { "ip": [ - "192.168.100.151", - "178.255.83.1" + "178.255.83.1", + "192.168.100.151" ] }, "source": { @@ -751,8 +751,8 @@ }, "related": { "ip": [ - "192.168.100.151", - "178.255.83.1" + "178.255.83.1", + "192.168.100.151" ] }, "source": { @@ -913,8 +913,8 @@ }, "related": { "ip": [ - "192.168.100.150", - "192.168.100.111" + "192.168.100.111", + "192.168.100.150" ] }, "source": { @@ -1075,8 +1075,8 @@ }, "related": { "ip": [ - "192.168.100.150", - "192.168.100.111" + "192.168.100.111", + "192.168.100.150" ] }, "source": { @@ -1237,8 +1237,8 @@ }, "related": { "ip": [ - "192.168.100.150", - "192.168.100.111" + "192.168.100.111", + "192.168.100.150" ] }, "source": { @@ -1399,8 +1399,8 @@ }, "related": { "ip": [ - "192.168.100.150", - "192.168.100.111" + "192.168.100.111", + "192.168.100.150" ] }, "source": { diff --git a/x-pack/filebeat/input/netflow/testdata/golden/Netflow-9-H3C.golden.json b/x-pack/filebeat/input/netflow/testdata/golden/Netflow-9-H3C.golden.json index a69dbeea386..b75a1c2ba3b 100644 --- a/x-pack/filebeat/input/netflow/testdata/golden/Netflow-9-H3C.golden.json +++ b/x-pack/filebeat/input/netflow/testdata/golden/Netflow-9-H3C.golden.json @@ -76,8 +76,8 @@ }, "related": { "ip": [ - "10.22.166.30", - "10.22.163.21" + "10.22.163.21", + "10.22.166.30" ] }, "source": { @@ -166,8 +166,8 @@ }, "related": { "ip": [ - "10.22.166.12", - "10.21.3.172" + "10.21.3.172", + "10.22.166.12" ] }, "source": { @@ -346,8 +346,8 @@ }, "related": { "ip": [ - "10.22.166.35", - "10.20.100.253" + "10.20.100.253", + "10.22.166.35" ] }, "source": { @@ -436,8 +436,8 @@ }, "related": { "ip": [ - "10.22.166.36", - "10.20.136.36" + "10.20.136.36", + "10.22.166.36" ] }, "source": { @@ -526,8 +526,8 @@ }, "related": { "ip": [ - "10.22.166.36", - "10.20.147.28" + "10.20.147.28", + "10.22.166.36" ] }, "source": { @@ -616,8 +616,8 @@ }, "related": { "ip": [ - "10.22.166.28", - "10.20.141.16" + "10.20.141.16", + "10.22.166.28" ] }, "source": { @@ -706,8 +706,8 @@ }, "related": { "ip": [ - "10.22.166.35", - "10.20.162.17" + "10.20.162.17", + "10.22.166.35" ] }, "source": { @@ -796,8 +796,8 @@ }, "related": { "ip": [ - "10.22.166.15", - "10.20.171.36" + "10.20.171.36", + "10.22.166.15" ] }, "source": { @@ -1156,8 +1156,8 @@ }, "related": { "ip": [ - "10.22.166.25", - "10.20.166.26" + "10.20.166.26", + "10.22.166.25" ] }, "source": { @@ -1246,8 +1246,8 @@ }, "related": { "ip": [ - "10.22.166.12", - "10.21.3.117" + "10.21.3.117", + "10.22.166.12" ] }, "source": { @@ -1336,8 +1336,8 @@ }, "related": { "ip": [ - "10.22.166.17", - "10.22.145.26" + "10.22.145.26", + "10.22.166.17" ] }, "source": { @@ -1426,8 +1426,8 @@ }, "related": { "ip": [ - "10.22.166.36", - "10.21.75.38" + "10.21.75.38", + "10.22.166.36" ] }, "source": { diff --git a/x-pack/filebeat/input/netflow/testdata/golden/Netflow-9-IE150-IE151.golden.json b/x-pack/filebeat/input/netflow/testdata/golden/Netflow-9-IE150-IE151.golden.json index 3aed82dc6f9..3db18648d08 100644 --- a/x-pack/filebeat/input/netflow/testdata/golden/Netflow-9-IE150-IE151.golden.json +++ b/x-pack/filebeat/input/netflow/testdata/golden/Netflow-9-IE150-IE151.golden.json @@ -63,8 +63,8 @@ }, "related": { "ip": [ - "192.168.0.3", - "192.168.0.2" + "192.168.0.2", + "192.168.0.3" ] }, "source": { diff --git a/x-pack/filebeat/input/netflow/testdata/golden/Netflow-9-Palo-Alto-1-flowset-in-large-zero-filled-packet.golden.json b/x-pack/filebeat/input/netflow/testdata/golden/Netflow-9-Palo-Alto-1-flowset-in-large-zero-filled-packet.golden.json index d0207ba3192..60f97f06495 100644 --- a/x-pack/filebeat/input/netflow/testdata/golden/Netflow-9-Palo-Alto-1-flowset-in-large-zero-filled-packet.golden.json +++ b/x-pack/filebeat/input/netflow/testdata/golden/Netflow-9-Palo-Alto-1-flowset-in-large-zero-filled-packet.golden.json @@ -69,8 +69,8 @@ }, "related": { "ip": [ - "134.220.2.6", - "134.220.1.156" + "134.220.1.156", + "134.220.2.6" ] }, "source": { diff --git a/x-pack/filebeat/input/netflow/testdata/golden/Netflow-9-Palo-Alto-PAN--OS-with-app--id.golden.json b/x-pack/filebeat/input/netflow/testdata/golden/Netflow-9-Palo-Alto-PAN--OS-with-app--id.golden.json index 79e31dd7f6b..98d496c0a7a 100644 --- a/x-pack/filebeat/input/netflow/testdata/golden/Netflow-9-Palo-Alto-PAN--OS-with-app--id.golden.json +++ b/x-pack/filebeat/input/netflow/testdata/golden/Netflow-9-Palo-Alto-PAN--OS-with-app--id.golden.json @@ -69,8 +69,8 @@ }, "related": { "ip": [ - "23.35.171.27", - "10.32.91.205" + "10.32.91.205", + "23.35.171.27" ] }, "source": { @@ -318,8 +318,8 @@ }, "related": { "ip": [ - "23.209.52.99", - "10.130.145.44" + "10.130.145.44", + "23.209.52.99" ] }, "source": { @@ -401,8 +401,8 @@ }, "related": { "ip": [ - "10.50.97.57", - "10.50.96.20" + "10.50.96.20", + "10.50.97.57" ] }, "source": { @@ -567,8 +567,8 @@ }, "related": { "ip": [ - "34.234.173.147", - "10.48.208.209" + "10.48.208.209", + "34.234.173.147" ] }, "source": { diff --git a/x-pack/filebeat/input/netflow/testdata/golden/Netflow-9-Streamcore.golden.json b/x-pack/filebeat/input/netflow/testdata/golden/Netflow-9-Streamcore.golden.json index 1319ba663cc..ebfde635048 100644 --- a/x-pack/filebeat/input/netflow/testdata/golden/Netflow-9-Streamcore.golden.json +++ b/x-pack/filebeat/input/netflow/testdata/golden/Netflow-9-Streamcore.golden.json @@ -64,8 +64,8 @@ }, "related": { "ip": [ - "100.78.40.201", - "10.231.128.150" + "10.231.128.150", + "100.78.40.201" ] }, "source": { @@ -220,8 +220,8 @@ }, "related": { "ip": [ - "100.78.40.201", - "10.27.8.20" + "10.27.8.20", + "100.78.40.201" ] }, "source": { diff --git a/x-pack/filebeat/input/netflow/testdata/golden/Netflow-9-Ubiquiti-Edgerouter-with-MPLS-labels.golden.json b/x-pack/filebeat/input/netflow/testdata/golden/Netflow-9-Ubiquiti-Edgerouter-with-MPLS-labels.golden.json index e6cb0fb4112..fec0ac80498 100644 --- a/x-pack/filebeat/input/netflow/testdata/golden/Netflow-9-Ubiquiti-Edgerouter-with-MPLS-labels.golden.json +++ b/x-pack/filebeat/input/netflow/testdata/golden/Netflow-9-Ubiquiti-Edgerouter-with-MPLS-labels.golden.json @@ -420,8 +420,8 @@ }, "related": { "ip": [ - "10.5.0.91", - "10.4.0.251" + "10.4.0.251", + "10.5.0.91" ] }, "source": { @@ -767,8 +767,8 @@ }, "related": { "ip": [ - "192.168.1.98", - "10.0.0.73" + "10.0.0.73", + "192.168.1.98" ] }, "source": { @@ -1362,8 +1362,8 @@ }, "related": { "ip": [ - "192.168.1.102", - "10.2.0.95" + "10.2.0.95", + "192.168.1.102" ] }, "source": { diff --git a/x-pack/filebeat/input/netflow/testdata/golden/Netflow-9-field-layer2segmentid.golden.json b/x-pack/filebeat/input/netflow/testdata/golden/Netflow-9-field-layer2segmentid.golden.json index 879714e24c0..73d4e4e7fdf 100644 --- a/x-pack/filebeat/input/netflow/testdata/golden/Netflow-9-field-layer2segmentid.golden.json +++ b/x-pack/filebeat/input/netflow/testdata/golden/Netflow-9-field-layer2segmentid.golden.json @@ -68,8 +68,8 @@ }, "related": { "ip": [ - "192.168.200.136", - "80.82.237.40" + "80.82.237.40", + "192.168.200.136" ] }, "source": { diff --git a/x-pack/filebeat/input/netflow/testdata/golden/Netflow-9-ipt_netflow-reduced-size-encoding.golden.json b/x-pack/filebeat/input/netflow/testdata/golden/Netflow-9-ipt_netflow-reduced-size-encoding.golden.json index 2b7dded5bd6..4e6b375574b 100644 --- a/x-pack/filebeat/input/netflow/testdata/golden/Netflow-9-ipt_netflow-reduced-size-encoding.golden.json +++ b/x-pack/filebeat/input/netflow/testdata/golden/Netflow-9-ipt_netflow-reduced-size-encoding.golden.json @@ -333,8 +333,8 @@ }, "related": { "ip": [ - "193.151.192.46", - "10.236.8.4" + "10.236.8.4", + "193.151.192.46" ] }, "source": { @@ -942,8 +942,8 @@ }, "related": { "ip": [ - "23.43.139.27", - "10.232.8.45" + "10.232.8.45", + "23.43.139.27" ] }, "source": { diff --git a/x-pack/filebeat/input/netflow/testdata/golden/Netflow-9-macaddress.golden.json b/x-pack/filebeat/input/netflow/testdata/golden/Netflow-9-macaddress.golden.json index 7db570f5db1..e1385446903 100644 --- a/x-pack/filebeat/input/netflow/testdata/golden/Netflow-9-macaddress.golden.json +++ b/x-pack/filebeat/input/netflow/testdata/golden/Netflow-9-macaddress.golden.json @@ -157,8 +157,8 @@ }, "related": { "ip": [ - "172.16.32.201", - "172.16.32.100" + "172.16.32.100", + "172.16.32.201" ] }, "source": { @@ -358,8 +358,8 @@ }, "related": { "ip": [ - "172.16.32.201", - "172.16.32.1" + "172.16.32.1", + "172.16.32.201" ] }, "source": { @@ -492,8 +492,8 @@ }, "related": { "ip": [ - "172.16.32.201", - "172.16.32.1" + "172.16.32.1", + "172.16.32.201" ] }, "source": { @@ -626,8 +626,8 @@ }, "related": { "ip": [ - "172.16.32.201", - "172.16.32.1" + "172.16.32.1", + "172.16.32.201" ] }, "source": { @@ -760,8 +760,8 @@ }, "related": { "ip": [ - "172.16.32.201", - "172.16.32.1" + "172.16.32.1", + "172.16.32.201" ] }, "source": { @@ -894,8 +894,8 @@ }, "related": { "ip": [ - "172.16.32.201", - "172.16.32.1" + "172.16.32.1", + "172.16.32.201" ] }, "source": { @@ -1028,8 +1028,8 @@ }, "related": { "ip": [ - "172.16.32.201", - "172.16.32.1" + "172.16.32.1", + "172.16.32.201" ] }, "source": { @@ -1162,8 +1162,8 @@ }, "related": { "ip": [ - "172.16.32.201", - "172.16.32.1" + "172.16.32.1", + "172.16.32.201" ] }, "source": { @@ -1296,8 +1296,8 @@ }, "related": { "ip": [ - "172.16.32.201", - "172.16.32.1" + "172.16.32.1", + "172.16.32.201" ] }, "source": { @@ -1430,8 +1430,8 @@ }, "related": { "ip": [ - "172.16.32.201", - "172.16.32.1" + "172.16.32.1", + "172.16.32.201" ] }, "source": { @@ -1564,8 +1564,8 @@ }, "related": { "ip": [ - "172.16.32.201", - "172.16.32.1" + "172.16.32.1", + "172.16.32.201" ] }, "source": { @@ -1698,8 +1698,8 @@ }, "related": { "ip": [ - "172.16.32.201", - "172.16.32.1" + "172.16.32.1", + "172.16.32.201" ] }, "source": { @@ -1832,8 +1832,8 @@ }, "related": { "ip": [ - "172.16.32.201", - "172.16.32.1" + "172.16.32.1", + "172.16.32.201" ] }, "source": { @@ -1966,8 +1966,8 @@ }, "related": { "ip": [ - "172.16.32.201", - "172.16.32.1" + "172.16.32.1", + "172.16.32.201" ] }, "source": { diff --git a/x-pack/filebeat/input/netflow/testdata/golden/Netflow-9-multiple-netflow-exporters.golden.json b/x-pack/filebeat/input/netflow/testdata/golden/Netflow-9-multiple-netflow-exporters.golden.json index 4238292f250..f75a3893975 100644 --- a/x-pack/filebeat/input/netflow/testdata/golden/Netflow-9-multiple-netflow-exporters.golden.json +++ b/x-pack/filebeat/input/netflow/testdata/golden/Netflow-9-multiple-netflow-exporters.golden.json @@ -180,8 +180,8 @@ }, "related": { "ip": [ - "172.16.32.248", - "172.16.32.100" + "172.16.32.100", + "172.16.32.248" ] }, "source": { @@ -338,8 +338,8 @@ }, "related": { "ip": [ - "172.16.32.201", - "172.16.32.100" + "172.16.32.100", + "172.16.32.201" ] }, "source": { @@ -496,8 +496,8 @@ }, "related": { "ip": [ - "172.16.32.202", - "172.16.32.100" + "172.16.32.100", + "172.16.32.202" ] }, "source": { @@ -516,6 +516,8 @@ "Meta": null, "Fields": { "destination": { + "ip": "ff02::1", + "locality": "internal", "port": 34304 }, "event": { @@ -533,7 +535,7 @@ ] }, "flow": { - "id": "tYpw8DU5u10", + "id": "hsSxbBU-M1o", "locality": "internal" }, "netflow": { @@ -562,7 +564,7 @@ }, "network": { "bytes": 672, - "community_id": "1:vK+Zeop1Y3GHxfFGVF2/COcNBWw=", + "community_id": "1:z1qoJyUMuKy3HX8rkIDvBK/vyL8=", "direction": "unknown", "iana_number": 58, "packets": 7, @@ -571,8 +573,16 @@ "observer": { "ip": "192.0.2.1" }, + "related": { + "ip": [ + "fe80::20c:29ff:fe83:3b6e", + "ff02::1" + ] + }, "source": { "bytes": 672, + "ip": "fe80::20c:29ff:fe83:3b6e", + "locality": "internal", "packets": 7, "port": 0 } @@ -648,8 +658,8 @@ }, "related": { "ip": [ - "172.16.32.201", - "172.16.32.1" + "172.16.32.1", + "172.16.32.201" ] }, "source": { diff --git a/x-pack/filebeat/input/netflow/testdata/golden/Netflow-9-nprobe-DPI-L7.golden.json b/x-pack/filebeat/input/netflow/testdata/golden/Netflow-9-nprobe-DPI-L7.golden.json index 3e6a1d03719..ddb22d837b5 100644 --- a/x-pack/filebeat/input/netflow/testdata/golden/Netflow-9-nprobe-DPI-L7.golden.json +++ b/x-pack/filebeat/input/netflow/testdata/golden/Netflow-9-nprobe-DPI-L7.golden.json @@ -59,7 +59,6 @@ }, "related": { "ip": [ - "0.0.0.0", "0.0.0.0" ] }, diff --git a/x-pack/filebeat/input/netflow/testdata/golden/Netflow-9-template-with-0-length-fields.golden.json b/x-pack/filebeat/input/netflow/testdata/golden/Netflow-9-template-with-0-length-fields.golden.json index 65a849e632a..64a7ea5e948 100644 --- a/x-pack/filebeat/input/netflow/testdata/golden/Netflow-9-template-with-0-length-fields.golden.json +++ b/x-pack/filebeat/input/netflow/testdata/golden/Netflow-9-template-with-0-length-fields.golden.json @@ -69,8 +69,8 @@ }, "related": { "ip": [ - "239.255.255.250", - "192.168.1.80" + "192.168.1.80", + "239.255.255.250" ] }, "source": { @@ -235,8 +235,8 @@ }, "related": { "ip": [ - "239.255.255.250", - "192.168.1.95" + "192.168.1.95", + "239.255.255.250" ] }, "source": { @@ -401,8 +401,8 @@ }, "related": { "ip": [ - "239.255.255.250", - "192.168.1.95" + "192.168.1.95", + "239.255.255.250" ] }, "source": { @@ -567,8 +567,8 @@ }, "related": { "ip": [ - "239.255.255.250", - "192.168.1.33" + "192.168.1.33", + "239.255.255.250" ] }, "source": { @@ -733,8 +733,8 @@ }, "related": { "ip": [ - "239.255.255.250", - "192.168.1.33" + "192.168.1.33", + "239.255.255.250" ] }, "source": { diff --git a/x-pack/filebeat/input/netflow/testdata/golden/Netflow-9-valid-01.golden.json b/x-pack/filebeat/input/netflow/testdata/golden/Netflow-9-valid-01.golden.json index 20ea4e61d31..b65cc125f57 100644 --- a/x-pack/filebeat/input/netflow/testdata/golden/Netflow-9-valid-01.golden.json +++ b/x-pack/filebeat/input/netflow/testdata/golden/Netflow-9-valid-01.golden.json @@ -144,8 +144,8 @@ }, "related": { "ip": [ - "172.16.32.248", - "172.16.32.100" + "172.16.32.100", + "172.16.32.248" ] }, "source": { @@ -302,8 +302,8 @@ }, "related": { "ip": [ - "172.16.32.201", - "172.16.32.100" + "172.16.32.100", + "172.16.32.201" ] }, "source": { @@ -460,8 +460,8 @@ }, "related": { "ip": [ - "172.16.32.202", - "172.16.32.100" + "172.16.32.100", + "172.16.32.202" ] }, "source": { @@ -480,6 +480,8 @@ "Meta": null, "Fields": { "destination": { + "ip": "ff02::1", + "locality": "internal", "port": 34304 }, "event": { @@ -497,7 +499,7 @@ ] }, "flow": { - "id": "tYpw8DU5u10", + "id": "hsSxbBU-M1o", "locality": "internal" }, "netflow": { @@ -526,7 +528,7 @@ }, "network": { "bytes": 672, - "community_id": "1:vK+Zeop1Y3GHxfFGVF2/COcNBWw=", + "community_id": "1:z1qoJyUMuKy3HX8rkIDvBK/vyL8=", "direction": "unknown", "iana_number": 58, "packets": 7, @@ -535,8 +537,16 @@ "observer": { "ip": "192.0.2.1" }, + "related": { + "ip": [ + "fe80::20c:29ff:fe83:3b6e", + "ff02::1" + ] + }, "source": { "bytes": 672, + "ip": "fe80::20c:29ff:fe83:3b6e", + "locality": "internal", "packets": 7, "port": 0 } diff --git a/x-pack/filebeat/input/netflow/testdata/golden/netflow9_e10s_4_7byte_pad.pcap.golden.json b/x-pack/filebeat/input/netflow/testdata/golden/netflow9_e10s_4_7byte_pad.pcap.golden.json index 82a9efb87aa..869aefe8629 100644 --- a/x-pack/filebeat/input/netflow/testdata/golden/netflow9_e10s_4_7byte_pad.pcap.golden.json +++ b/x-pack/filebeat/input/netflow/testdata/golden/netflow9_e10s_4_7byte_pad.pcap.golden.json @@ -61,8 +61,8 @@ }, "related": { "ip": [ - "10.127.32.11", - "10.36.236.100" + "10.36.236.100", + "10.127.32.11" ] }, "source": { @@ -286,8 +286,8 @@ }, "related": { "ip": [ - "52.206.251.4", - "10.36.236.100" + "10.36.236.100", + "52.206.251.4" ] }, "source": { @@ -436,8 +436,8 @@ }, "related": { "ip": [ - "10.36.237.22", - "10.36.228.103" + "10.36.228.103", + "10.36.237.22" ] }, "source": { diff --git a/x-pack/filebeat/input/netflow/testdata/golden/netflow9_ubiquiti_edgerouter.pcap.golden.json b/x-pack/filebeat/input/netflow/testdata/golden/netflow9_ubiquiti_edgerouter.pcap.golden.json index ea23d1283ad..48a368eed06 100644 --- a/x-pack/filebeat/input/netflow/testdata/golden/netflow9_ubiquiti_edgerouter.pcap.golden.json +++ b/x-pack/filebeat/input/netflow/testdata/golden/netflow9_ubiquiti_edgerouter.pcap.golden.json @@ -836,8 +836,8 @@ }, "related": { "ip": [ - "192.168.1.4", - "10.100.0.1" + "10.100.0.1", + "192.168.1.4" ] }, "source": { diff --git a/x-pack/filebeat/module/aws/_meta/config.yml b/x-pack/filebeat/module/aws/_meta/config.yml index 1b139779b84..60213ba811a 100644 --- a/x-pack/filebeat/module/aws/_meta/config.yml +++ b/x-pack/filebeat/module/aws/_meta/config.yml @@ -54,6 +54,9 @@ # Custom endpoint used to access AWS APIs #var.endpoint: amazonaws.com + # Default region to query if no other region is set + #var.default_region: us-east-1 + # AWS IAM Role to assume #var.role_arn: arn:aws:iam::123456789012:role/test-mb @@ -63,6 +66,12 @@ # The maximum number of messages to return from SQS. Valid values: 1 to 10. #var.max_number_of_messages: 5 + # URL to proxy AWS API calls + #var.proxy_url: http://proxy:3128 + + # Configures the SSL settings, ie. set trusted CAs, ignore certificate verification.... + #var.ssl: + cloudwatch: enabled: false @@ -106,6 +115,9 @@ # Custom endpoint used to access AWS APIs #var.endpoint: amazonaws.com + # Default region to query if no other region is set + #var.default_region: us-east-1 + # AWS IAM Role to assume #var.role_arn: arn:aws:iam::123456789012:role/test-mb @@ -115,6 +127,12 @@ # The maximum number of messages to return from SQS. Valid values: 1 to 10. #var.max_number_of_messages: 5 + # URL to proxy AWS API calls + #var.proxy_url: http://proxy:3128 + + # Configures the SSL settings, ie. set trusted CAs, ignore certificate verification.... + #var.ssl: + ec2: enabled: false @@ -158,6 +176,9 @@ # Custom endpoint used to access AWS APIs #var.endpoint: amazonaws.com + # Default region to query if no other region is set + #var.default_region: us-east-1 + # AWS IAM Role to assume #var.role_arn: arn:aws:iam::123456789012:role/test-mb @@ -167,6 +188,12 @@ # The maximum number of messages to return from SQS. Valid values: 1 to 10. #var.max_number_of_messages: 5 + # URL to proxy AWS API calls + #var.proxy_url: http://proxy:3128 + + # Configures the SSL settings, ie. set trusted CAs, ignore certificate verification.... + #var.ssl: + elb: enabled: false @@ -210,6 +237,9 @@ # Custom endpoint used to access AWS APIs #var.endpoint: amazonaws.com + # Default region to query if no other region is set + #var.default_region: us-east-1 + # AWS IAM Role to assume #var.role_arn: arn:aws:iam::123456789012:role/test-mb @@ -219,6 +249,12 @@ # The maximum number of messages to return from SQS. Valid values: 1 to 10. #var.max_number_of_messages: 5 + # URL to proxy AWS API calls + #var.proxy_url: http://proxy:3128 + + # Configures the SSL settings, ie. set trusted CAs, ignore certificate verification.... + #var.ssl: + s3access: enabled: false @@ -262,6 +298,9 @@ # Custom endpoint used to access AWS APIs #var.endpoint: amazonaws.com + # Default region to query if no other region is set + #var.default_region: us-east-1 + # AWS IAM Role to assume #var.role_arn: arn:aws:iam::123456789012:role/test-mb @@ -271,6 +310,12 @@ # The maximum number of messages to return from SQS. Valid values: 1 to 10. #var.max_number_of_messages: 5 + # URL to proxy AWS API calls + #var.proxy_url: http://proxy:3128 + + # Configures the SSL settings, ie. set trusted CAs, ignore certificate verification.... + #var.ssl: + vpcflow: enabled: false @@ -314,6 +359,9 @@ # Custom endpoint used to access AWS APIs #var.endpoint: amazonaws.com + # Default region to query if no other region is set + #var.default_region: us-east-1 + # AWS IAM Role to assume #var.role_arn: arn:aws:iam::123456789012:role/test-mb @@ -322,3 +370,9 @@ # The maximum number of messages to return from SQS. Valid values: 1 to 10. #var.max_number_of_messages: 5 + + # URL to proxy AWS API calls + #var.proxy_url: http://proxy:3128 + + # Configures the SSL settings, ie. set trusted CAs, ignore certificate verification.... + #var.ssl: diff --git a/x-pack/filebeat/module/aws/_meta/docs.asciidoc b/x-pack/filebeat/module/aws/_meta/docs.asciidoc index 3fee8460161..b9afe334257 100644 --- a/x-pack/filebeat/module/aws/_meta/docs.asciidoc +++ b/x-pack/filebeat/module/aws/_meta/docs.asciidoc @@ -56,6 +56,7 @@ Example config: #var.visibility_timeout: 300s #var.api_timeout: 120s #var.endpoint: amazonaws.com + #var.default_region: us-east-1 #var.role_arn: arn:aws:iam::123456789012:role/test-mb #var.proxy_url: http://proxy:8080 @@ -74,6 +75,7 @@ Example config: #var.visibility_timeout: 300s #var.api_timeout: 120s #var.endpoint: amazonaws.com + #var.default_region: us-east-1 #var.role_arn: arn:aws:iam::123456789012:role/test-mb #var.proxy_url: http://proxy:8080 @@ -92,6 +94,7 @@ Example config: #var.visibility_timeout: 300s #var.api_timeout: 120s #var.endpoint: amazonaws.com + #var.default_region: us-east-1 #var.role_arn: arn:aws:iam::123456789012:role/test-mb #var.proxy_url: http://proxy:8080 @@ -110,6 +113,7 @@ Example config: #var.visibility_timeout: 300s #var.api_timeout: 120s #var.endpoint: amazonaws.com + #var.default_region: us-east-1 #var.role_arn: arn:aws:iam::123456789012:role/test-mb #var.proxy_url: http://proxy:8080 @@ -128,6 +132,7 @@ Example config: #var.visibility_timeout: 300s #var.api_timeout: 120s #var.endpoint: amazonaws.com + #var.default_region: us-east-1 #var.role_arn: arn:aws:iam::123456789012:role/test-mb #var.proxy_url: http://proxy:8080 @@ -146,6 +151,7 @@ Example config: #var.visibility_timeout: 300s #var.api_timeout: 120s #var.endpoint: amazonaws.com + #var.default_region: us-east-1 #var.role_arn: arn:aws:iam::123456789012:role/test-mb #var.proxy_url: http://proxy:8080 ---- @@ -187,6 +193,10 @@ Prefix to apply for the list request to the S3 bucket. Default empty. Custom endpoint used to access AWS APIs. +*`var.default_region`*:: + +Default region to query if no other region is set. + *`var.shared_credential_file`*:: Filename of AWS credential file. diff --git a/x-pack/filebeat/module/aws/cloudtrail/config/aws-s3.yml b/x-pack/filebeat/module/aws/cloudtrail/config/aws-s3.yml index c95abb1cdc2..ada3a502fc2 100644 --- a/x-pack/filebeat/module/aws/cloudtrail/config/aws-s3.yml +++ b/x-pack/filebeat/module/aws/cloudtrail/config/aws-s3.yml @@ -53,6 +53,10 @@ api_timeout: {{ .api_timeout }} endpoint: {{ .endpoint }} {{ end }} +{{ if .default_region }} +default_region: {{ .default_region }} +{{ end }} + {{ if .access_key_id }} access_key_id: {{ .access_key_id }} {{ end }} @@ -81,6 +85,10 @@ max_number_of_messages: {{ .max_number_of_messages }} proxy_url: {{ .proxy_url }} {{ end }} +{{ if .ssl }} +ssl: {{ .ssl | tojson }} +{{ end }} + tags: {{.tags | tojson}} publisher_pipeline.disable_host: {{ inList .tags "forwarded" }} diff --git a/x-pack/filebeat/module/aws/cloudtrail/manifest.yml b/x-pack/filebeat/module/aws/cloudtrail/manifest.yml index c0715d7647c..f19760eb637 100644 --- a/x-pack/filebeat/module/aws/cloudtrail/manifest.yml +++ b/x-pack/filebeat/module/aws/cloudtrail/manifest.yml @@ -13,6 +13,7 @@ var: - name: visibility_timeout - name: api_timeout - name: endpoint + - name: default_region - name: access_key_id - name: secret_access_key - name: session_token @@ -28,6 +29,7 @@ var: - name: fips_enabled - name: proxy_url - name: max_number_of_messages + - name: ssl ingest_pipeline: ingest/pipeline.yml input: config/{{.input}}.yml diff --git a/x-pack/filebeat/module/aws/cloudwatch/config/aws-s3.yml b/x-pack/filebeat/module/aws/cloudwatch/config/aws-s3.yml index 5b1fb24f561..8ce1970290d 100644 --- a/x-pack/filebeat/module/aws/cloudwatch/config/aws-s3.yml +++ b/x-pack/filebeat/module/aws/cloudwatch/config/aws-s3.yml @@ -38,6 +38,10 @@ api_timeout: {{ .api_timeout }} endpoint: {{ .endpoint }} {{ end }} +{{ if .default_region }} +default_region: {{ .default_region }} +{{ end }} + {{ if .access_key_id }} access_key_id: {{ .access_key_id }} {{ end }} @@ -66,6 +70,10 @@ max_number_of_messages: {{ .max_number_of_messages }} proxy_url: {{ .proxy_url }} {{ end }} +{{ if .ssl }} +ssl: {{ .ssl | tojson }} +{{ end }} + tags: {{.tags | tojson}} publisher_pipeline.disable_host: {{ inList .tags "forwarded" }} diff --git a/x-pack/filebeat/module/aws/cloudwatch/manifest.yml b/x-pack/filebeat/module/aws/cloudwatch/manifest.yml index 0223142a6a9..e52ba673757 100644 --- a/x-pack/filebeat/module/aws/cloudwatch/manifest.yml +++ b/x-pack/filebeat/module/aws/cloudwatch/manifest.yml @@ -13,6 +13,7 @@ var: - name: visibility_timeout - name: api_timeout - name: endpoint + - name: default_region - name: access_key_id - name: secret_access_key - name: session_token @@ -22,6 +23,7 @@ var: - name: fips_enabled - name: proxy_url - name: max_number_of_messages + - name: ssl ingest_pipeline: ingest/pipeline.yml input: config/{{.input}}.yml diff --git a/x-pack/filebeat/module/aws/ec2/config/aws-s3.yml b/x-pack/filebeat/module/aws/ec2/config/aws-s3.yml index 5b1fb24f561..8ce1970290d 100644 --- a/x-pack/filebeat/module/aws/ec2/config/aws-s3.yml +++ b/x-pack/filebeat/module/aws/ec2/config/aws-s3.yml @@ -38,6 +38,10 @@ api_timeout: {{ .api_timeout }} endpoint: {{ .endpoint }} {{ end }} +{{ if .default_region }} +default_region: {{ .default_region }} +{{ end }} + {{ if .access_key_id }} access_key_id: {{ .access_key_id }} {{ end }} @@ -66,6 +70,10 @@ max_number_of_messages: {{ .max_number_of_messages }} proxy_url: {{ .proxy_url }} {{ end }} +{{ if .ssl }} +ssl: {{ .ssl | tojson }} +{{ end }} + tags: {{.tags | tojson}} publisher_pipeline.disable_host: {{ inList .tags "forwarded" }} diff --git a/x-pack/filebeat/module/aws/ec2/manifest.yml b/x-pack/filebeat/module/aws/ec2/manifest.yml index 0223142a6a9..e52ba673757 100644 --- a/x-pack/filebeat/module/aws/ec2/manifest.yml +++ b/x-pack/filebeat/module/aws/ec2/manifest.yml @@ -13,6 +13,7 @@ var: - name: visibility_timeout - name: api_timeout - name: endpoint + - name: default_region - name: access_key_id - name: secret_access_key - name: session_token @@ -22,6 +23,7 @@ var: - name: fips_enabled - name: proxy_url - name: max_number_of_messages + - name: ssl ingest_pipeline: ingest/pipeline.yml input: config/{{.input}}.yml diff --git a/x-pack/filebeat/module/aws/elb/config/aws-s3.yml b/x-pack/filebeat/module/aws/elb/config/aws-s3.yml index 5b1fb24f561..8ce1970290d 100644 --- a/x-pack/filebeat/module/aws/elb/config/aws-s3.yml +++ b/x-pack/filebeat/module/aws/elb/config/aws-s3.yml @@ -38,6 +38,10 @@ api_timeout: {{ .api_timeout }} endpoint: {{ .endpoint }} {{ end }} +{{ if .default_region }} +default_region: {{ .default_region }} +{{ end }} + {{ if .access_key_id }} access_key_id: {{ .access_key_id }} {{ end }} @@ -66,6 +70,10 @@ max_number_of_messages: {{ .max_number_of_messages }} proxy_url: {{ .proxy_url }} {{ end }} +{{ if .ssl }} +ssl: {{ .ssl | tojson }} +{{ end }} + tags: {{.tags | tojson}} publisher_pipeline.disable_host: {{ inList .tags "forwarded" }} diff --git a/x-pack/filebeat/module/aws/elb/manifest.yml b/x-pack/filebeat/module/aws/elb/manifest.yml index da22ed1b1cc..4ab87c2b686 100644 --- a/x-pack/filebeat/module/aws/elb/manifest.yml +++ b/x-pack/filebeat/module/aws/elb/manifest.yml @@ -13,6 +13,7 @@ var: - name: visibility_timeout - name: api_timeout - name: endpoint + - name: default_region - name: access_key_id - name: secret_access_key - name: session_token @@ -22,6 +23,7 @@ var: - name: fips_enabled - name: proxy_url - name: max_number_of_messages + - name: ssl ingest_pipeline: ingest/pipeline.yml input: config/{{.input}}.yml diff --git a/x-pack/filebeat/module/aws/s3access/config/aws-s3.yml b/x-pack/filebeat/module/aws/s3access/config/aws-s3.yml index 5b1fb24f561..8ce1970290d 100644 --- a/x-pack/filebeat/module/aws/s3access/config/aws-s3.yml +++ b/x-pack/filebeat/module/aws/s3access/config/aws-s3.yml @@ -38,6 +38,10 @@ api_timeout: {{ .api_timeout }} endpoint: {{ .endpoint }} {{ end }} +{{ if .default_region }} +default_region: {{ .default_region }} +{{ end }} + {{ if .access_key_id }} access_key_id: {{ .access_key_id }} {{ end }} @@ -66,6 +70,10 @@ max_number_of_messages: {{ .max_number_of_messages }} proxy_url: {{ .proxy_url }} {{ end }} +{{ if .ssl }} +ssl: {{ .ssl | tojson }} +{{ end }} + tags: {{.tags | tojson}} publisher_pipeline.disable_host: {{ inList .tags "forwarded" }} diff --git a/x-pack/filebeat/module/aws/s3access/manifest.yml b/x-pack/filebeat/module/aws/s3access/manifest.yml index 0223142a6a9..e52ba673757 100644 --- a/x-pack/filebeat/module/aws/s3access/manifest.yml +++ b/x-pack/filebeat/module/aws/s3access/manifest.yml @@ -13,6 +13,7 @@ var: - name: visibility_timeout - name: api_timeout - name: endpoint + - name: default_region - name: access_key_id - name: secret_access_key - name: session_token @@ -22,6 +23,7 @@ var: - name: fips_enabled - name: proxy_url - name: max_number_of_messages + - name: ssl ingest_pipeline: ingest/pipeline.yml input: config/{{.input}}.yml diff --git a/x-pack/filebeat/module/aws/vpcflow/config/input.yml b/x-pack/filebeat/module/aws/vpcflow/config/input.yml index 51b649b1e2e..5c08c0e6e38 100644 --- a/x-pack/filebeat/module/aws/vpcflow/config/input.yml +++ b/x-pack/filebeat/module/aws/vpcflow/config/input.yml @@ -40,6 +40,10 @@ api_timeout: {{ .api_timeout }} endpoint: {{ .endpoint }} {{ end }} +{{ if .default_region }} +default_region: {{ .default_region }} +{{ end }} + {{ if .access_key_id }} access_key_id: {{ .access_key_id }} {{ end }} @@ -68,6 +72,10 @@ max_number_of_messages: {{ .max_number_of_messages }} proxy_url: {{ .proxy_url }} {{ end }} +{{ if .ssl }} +ssl: {{ .ssl | tojson }} +{{ end }} + {{ else if eq .input "file" }} type: log diff --git a/x-pack/filebeat/module/aws/vpcflow/manifest.yml b/x-pack/filebeat/module/aws/vpcflow/manifest.yml index 8871cf1cffb..b329c7264f1 100644 --- a/x-pack/filebeat/module/aws/vpcflow/manifest.yml +++ b/x-pack/filebeat/module/aws/vpcflow/manifest.yml @@ -13,6 +13,7 @@ var: - name: visibility_timeout - name: api_timeout - name: endpoint + - name: default_region - name: access_key_id - name: secret_access_key - name: session_token @@ -22,6 +23,7 @@ var: - name: fips_enabled - name: proxy_url - name: max_number_of_messages + - name: ssl ingest_pipeline: ingest/pipeline.yml input: config/input.yml diff --git a/x-pack/filebeat/module/awsfargate/_meta/config.yml b/x-pack/filebeat/module/awsfargate/_meta/config.yml index 2318b322e9a..8d1b03f49dc 100644 --- a/x-pack/filebeat/module/awsfargate/_meta/config.yml +++ b/x-pack/filebeat/module/awsfargate/_meta/config.yml @@ -52,3 +52,9 @@ # Time used to sleep between AWS FilterLogEvents API calls inside the same collection period # Default api_sleep is 200 ms #var.api_sleep: 200ms + + # URL to proxy AWS API calls + #var.proxy_url: http://proxy:3128 + + # Configures the SSL settings, ie. set trusted CAs, ignore certificate verification.... + #var.ssl: diff --git a/x-pack/filebeat/module/awsfargate/log/config/aws-cloudwatch.yml b/x-pack/filebeat/module/awsfargate/log/config/aws-cloudwatch.yml index f7f3199028c..08b37cd3aef 100644 --- a/x-pack/filebeat/module/awsfargate/log/config/aws-cloudwatch.yml +++ b/x-pack/filebeat/module/awsfargate/log/config/aws-cloudwatch.yml @@ -40,6 +40,10 @@ shared_credential_file: {{ .shared_credential_file }} endpoint: {{ .endpoint }} {{ end }} +{{ if .default_region }} +default_region: {{ .default_region }} +{{ end }} + {{ if .access_key_id }} access_key_id: {{ .access_key_id }} {{ end }} @@ -56,6 +60,14 @@ session_token: {{ .session_token }} role_arn: {{ .role_arn }} {{ end }} +{{ if .proxy_url }} +proxy_url: {{ .proxy_url }} +{{ end }} + +{{ if .ssl }} +ssl: {{ .ssl | tojson }} +{{ end }} + processors: - add_fields: target: '' diff --git a/x-pack/filebeat/module/awsfargate/log/manifest.yml b/x-pack/filebeat/module/awsfargate/log/manifest.yml index ca5fb61d056..9c724ff1a03 100644 --- a/x-pack/filebeat/module/awsfargate/log/manifest.yml +++ b/x-pack/filebeat/module/awsfargate/log/manifest.yml @@ -6,6 +6,7 @@ var: - name: shared_credential_file - name: credential_profile_name - name: endpoint + - name: default_region - name: access_key_id - name: secret_access_key - name: session_token @@ -20,6 +21,8 @@ var: - name: scan_frequency - name: api_timeout - name: api_sleep + - name: proxy_url + - name: ssl ingest_pipeline: ingest/pipeline.yml input: config/{{.input}}.yml diff --git a/x-pack/filebeat/module/barracuda/_meta/docs.asciidoc b/x-pack/filebeat/module/barracuda/_meta/docs.asciidoc index c8eb358cd7d..79d27b36166 100644 --- a/x-pack/filebeat/module/barracuda/_meta/docs.asciidoc +++ b/x-pack/filebeat/module/barracuda/_meta/docs.asciidoc @@ -28,7 +28,7 @@ NOTE: This was converted from RSA NetWitness log parser XML "barracudawaf" devic *`var.input`*:: -The input from which messages are read. One of `file`, `tcp` or `udp`. +The input from which messages are read. One of `file`, `tcp` or `udp`. Defaults to `udp`. *`var.syslog_host`*:: @@ -73,7 +73,7 @@ NOTE: This was converted from RSA NetWitness log parser XML "barracudasf" device *`var.input`*:: -The input from which messages are read. One of `file`, `tcp` or `udp`. +The input from which messages are read. One of `file`, `tcp` or `udp`. Defaults to `udp`. *`var.syslog_host`*:: diff --git a/x-pack/filebeat/module/bluecoat/_meta/docs.asciidoc b/x-pack/filebeat/module/bluecoat/_meta/docs.asciidoc index b9ef6534d89..3497b6873ea 100644 --- a/x-pack/filebeat/module/bluecoat/_meta/docs.asciidoc +++ b/x-pack/filebeat/module/bluecoat/_meta/docs.asciidoc @@ -28,7 +28,7 @@ NOTE: This was converted from RSA NetWitness log parser XML "bluecoatdirector" d *`var.input`*:: -The input from which messages are read. One of `file`, `tcp` or `udp`. +The input from which messages are read. One of `file`, `tcp` or `udp`. Defaults to `udp`. *`var.syslog_host`*:: diff --git a/x-pack/filebeat/module/checkpoint/firewall/ingest/pipeline.yml b/x-pack/filebeat/module/checkpoint/firewall/ingest/pipeline.yml index 13a92e10f31..b4dd786b094 100644 --- a/x-pack/filebeat/module/checkpoint/firewall/ingest/pipeline.yml +++ b/x-pack/filebeat/module/checkpoint/firewall/ingest/pipeline.yml @@ -40,10 +40,9 @@ processors: - message - host ignore_missing: true -- rename: - field: "@timestamp" - target_field: "event.created" - ignore_missing: true +- set: + copy_from: "@timestamp" + field: "event.created" - date: field: "syslog5424_ts" formats: ["ISO8601", "UNIX"] diff --git a/x-pack/filebeat/module/cisco/_meta/config.yml b/x-pack/filebeat/module/cisco/_meta/config.yml index 3fd735c050d..1b2940129bf 100644 --- a/x-pack/filebeat/module/cisco/_meta/config.yml +++ b/x-pack/filebeat/module/cisco/_meta/config.yml @@ -2,16 +2,23 @@ asa: enabled: false - # Set which input to use between syslog (default) or file. - #var.input: syslog + # Set which input to use between udp (default), tcp or file. + #var.input: udp - # The interface to listen to UDP based syslog traffic. Defaults to + # The interface to listen to udp or tcp syslog traffic. Defaults to # localhost. Set to 0.0.0.0 to bind to all available interfaces. #var.syslog_host: localhost - # The UDP port to listen for syslog traffic. Defaults to 9001. + # The port to listen for udp or tcp syslog traffic. Defaults to 9001. #var.syslog_port: 9001 + # With tcp input, set the optional tls configuration: + #var.ssl: + # enabled: true + # certificate: /path/to/cert.pem + # key: /path/to/privatekey.pem + # key_passphrase: 'password for my key' + # Set the log level from 1 (alerts only) to 7 (include all messages). # Messages with a log level higher than the specified will be dropped. # See https://www.cisco.com/c/en/us/td/docs/security/asa/syslog/b_syslog/syslogs-sev-level.html @@ -28,16 +35,23 @@ ftd: enabled: false - # Set which input to use between syslog (default) or file. - #var.input: syslog + # Set which input to use between udp (default), tcp or file. + #var.input: udp - # The interface to listen to UDP based syslog traffic. Defaults to + # The interface to listen to tcp or udp syslog traffic. Defaults to # localhost. Set to 0.0.0.0 to bind to all available interfaces. #var.syslog_host: localhost - # The UDP port to listen for syslog traffic. Defaults to 9003. + # The UDP port to listen for tcp or udp syslog traffic. Defaults to 9003. #var.syslog_port: 9003 + # With tcp input, set the optional tls configuration: + #var.ssl: + # enabled: true + # certificate: /path/to/cert.pem + # key: /path/to/privatekey.pem + # key_passphrase: 'password for my key' + # Set the log level from 1 (alerts only) to 7 (include all messages). # Messages with a log level higher than the specified will be dropped. # See https://www.cisco.com/c/en/us/td/docs/security/firepower/Syslogs/b_fptd_syslog_guide/syslogs-sev-level.html @@ -57,13 +71,16 @@ # Set which input to use between syslog (default) or file. #var.input: syslog - # The interface to listen to UDP based syslog traffic. Defaults to + # The interface to listen to syslog traffic. Defaults to # localhost. Set to 0.0.0.0 to bind to all available interfaces. #var.syslog_host: localhost - # The UDP port to listen for syslog traffic. Defaults to 9002. + # The port to listen on for syslog traffic. Defaults to 9002. #var.syslog_port: 9002 + # Set which protocol to use between udp (default) or tcp. + #var.syslog_protocol: udp + # Set custom paths for the log files when using file input. If left empty, # Filebeat will choose the paths depending on your OS. #var.paths: diff --git a/x-pack/filebeat/module/cisco/_meta/docs.asciidoc b/x-pack/filebeat/module/cisco/_meta/docs.asciidoc index e831bbb1e8f..e666da7fa66 100644 --- a/x-pack/filebeat/module/cisco/_meta/docs.asciidoc +++ b/x-pack/filebeat/module/cisco/_meta/docs.asciidoc @@ -300,7 +300,7 @@ NOTE: This was converted from RSA NetWitness log parser XML "cisconxos" device r *`var.input`*:: -The input from which messages are read. One of `file`, `tcp` or `udp`. +The input from which messages are read. One of `file`, `tcp` or `udp`. Defaults to `udp`. *`var.syslog_host`*:: @@ -345,7 +345,7 @@ NOTE: This was converted from RSA NetWitness log parser XML "ciscomeraki" device *`var.input`*:: -The input from which messages are read. One of `file`, `tcp` or `udp`. +The input from which messages are read. One of `file`, `tcp` or `udp`. Defaults to `udp`. *`var.syslog_host`*:: diff --git a/x-pack/filebeat/module/cisco/asa/config/input.yml b/x-pack/filebeat/module/cisco/asa/config/input.yml index 4237b4d9ae2..cb9df5bd6ec 100644 --- a/x-pack/filebeat/module/cisco/asa/config/input.yml +++ b/x-pack/filebeat/module/cisco/asa/config/input.yml @@ -1,10 +1,4 @@ -{{ if eq .input "syslog" }} - -type: udp -udp: -host: "{{.syslog_host}}:{{.syslog_port}}" - -{{ else if eq .input "file" }} +{{ if eq .input "file" }} type: log paths: @@ -13,6 +7,12 @@ paths: {{ end }} exclude_files: [".gz$"] +{{ else }} + +type: {{.input}} +host: "{{.syslog_host}}:{{.syslog_port}}" +ssl: {{ .ssl | tojson }} + {{ end }} tags: {{.tags | tojson}} diff --git a/x-pack/filebeat/module/cisco/asa/manifest.yml b/x-pack/filebeat/module/cisco/asa/manifest.yml index 3c185f7980c..184df5404ad 100644 --- a/x-pack/filebeat/module/cisco/asa/manifest.yml +++ b/x-pack/filebeat/module/cisco/asa/manifest.yml @@ -11,7 +11,8 @@ var: - name: syslog_port default: 9001 - name: input - default: syslog + default: udp + - name: ssl - name: log_level default: 7 # if ES < 6.1.0, this flag switches to false automatically when evaluating the diff --git a/x-pack/filebeat/module/cisco/asa/test/additional_messages.log-expected.json b/x-pack/filebeat/module/cisco/asa/test/additional_messages.log-expected.json index ca9623da72a..2992f9a237c 100644 --- a/x-pack/filebeat/module/cisco/asa/test/additional_messages.log-expected.json +++ b/x-pack/filebeat/module/cisco/asa/test/additional_messages.log-expected.json @@ -181,12 +181,12 @@ "event.code": 609002, "event.dataset": "cisco.asa", "event.duration": 0, - "event.end": "2021-05-05T17:51:17.000-02:00", + "event.end": "2022-05-05T17:51:17.000-02:00", "event.kind": "event", "event.module": "cisco", "event.original": "%FTD-7-609002: Teardown local-host net:192.168.2.2 duration 0:00:00", "event.severity": 7, - "event.start": "2021-05-05T19:51:17.000Z", + "event.start": "2022-05-05T19:51:17.000Z", "event.timezone": "-02:00", "event.type": [ "connection", @@ -701,12 +701,12 @@ "event.code": 609002, "event.dataset": "cisco.asa", "event.duration": 0, - "event.end": "2021-05-05T18:24:31.000-02:00", + "event.end": "2022-05-05T18:24:31.000-02:00", "event.kind": "event", "event.module": "cisco", "event.original": "%ASA-7-609002: Teardown local-host identity:10.10.10.10 duration 0:00:00", "event.severity": 7, - "event.start": "2021-05-05T20:24:31.000Z", + "event.start": "2022-05-05T20:24:31.000Z", "event.timezone": "-02:00", "event.type": [ "connection", @@ -849,13 +849,13 @@ "event.code": 302014, "event.dataset": "cisco.asa", "event.duration": 0, - "event.end": "2021-05-05T18:29:32.000-02:00", + "event.end": "2022-05-05T18:29:32.000-02:00", "event.kind": "event", "event.module": "cisco", "event.original": "%ASA-6-302014: Teardown TCP connection 2960892904 for out111:10.10.10.10/443 to fw111:192.168.2.2/55225 duration 0:00:00 bytes 0 TCP Reset-I", "event.reason": "TCP Reset-I", "event.severity": 6, - "event.start": "2021-05-05T20:29:32.000Z", + "event.start": "2022-05-05T20:29:32.000Z", "event.timezone": "-02:00", "event.type": [ "connection", @@ -966,12 +966,12 @@ "event.code": 305012, "event.dataset": "cisco.asa", "event.duration": 0, - "event.end": "2021-05-05T18:29:32.000-02:00", + "event.end": "2022-05-05T18:29:32.000-02:00", "event.kind": "event", "event.module": "cisco", "event.original": "%ASA-6-305012: Teardown dynamic UDP translation from fw111:10.10.10.10/54230 to out111:192.168.2.2/54230 duration 0:00:00", "event.severity": 6, - "event.start": "2021-05-05T20:29:32.000Z", + "event.start": "2022-05-05T20:29:32.000Z", "event.timezone": "-02:00", "event.type": [ "connection", @@ -1175,12 +1175,12 @@ "event.code": 302016, "event.dataset": "cisco.asa", "event.duration": 124000000000, - "event.end": "2021-05-05T18:40:50.000-02:00", + "event.end": "2022-05-05T18:40:50.000-02:00", "event.kind": "event", "event.module": "cisco", "event.original": "%ASA-2-302016: Teardown UDP connection 1671727 for intfacename:10.10.10.10/161 to net:192.186.2.2/53356 duration 0:02:04 bytes 64585", "event.severity": 2, - "event.start": "2021-05-05T20:38:46.000Z", + "event.start": "2022-05-05T20:38:46.000Z", "event.timezone": "-02:00", "event.type": [ "connection", @@ -1812,13 +1812,13 @@ "event.code": 302023, "event.dataset": "cisco.asa", "event.duration": 0, - "event.end": "2021-05-05T19:02:58.000-02:00", + "event.end": "2022-05-05T19:02:58.000-02:00", "event.kind": "event", "event.module": "cisco", "event.original": "%ASA-6-302023: Teardown stub TCP connection for fw111:10.10.10.10/39210 to net:192.168.2.2/10051 duration 0:00:00 forwarded bytes 0 Cluster flow with CLU closed on owner", "event.reason": "Cluster flow with CLU closed on owner", "event.severity": 6, - "event.start": "2021-05-05T21:02:58.000Z", + "event.start": "2022-05-05T21:02:58.000Z", "event.timezone": "-02:00", "event.type": [ "info" @@ -1868,13 +1868,13 @@ "event.code": 302023, "event.dataset": "cisco.asa", "event.duration": 0, - "event.end": "2021-05-05T19:02:58.000-02:00", + "event.end": "2022-05-05T19:02:58.000-02:00", "event.kind": "event", "event.module": "cisco", "event.original": "%ASA-6-302023: Teardown stub TCP connection for net:10.10.10.10/10051 to unknown:192.168.2.2/39222 duration 0:00:00 forwarded bytes 0 Forwarding or redirect flow removed to create director or backup flow", "event.reason": "Forwarding or redirect flow removed to create director or backup flow", "event.severity": 6, - "event.start": "2021-05-05T21:02:58.000Z", + "event.start": "2022-05-05T21:02:58.000Z", "event.timezone": "-02:00", "event.type": [ "info" @@ -2687,13 +2687,13 @@ "event.code": 302304, "event.dataset": "cisco.asa", "event.duration": 3602000000000, - "event.end": "2021-04-27T04:12:23.000-02:00", + "event.end": "2022-04-27T04:12:23.000-02:00", "event.kind": "event", "event.module": "cisco", "event.original": "%ASA-6-302304: Teardown TCP state-bypass connection 2751765169 from server.deflan:81.2.69.143/54242 to server.deflan:67.43.156.12/9101 duration 1:00:02 bytes 245 Connection timeout", "event.reason": "Connection timeout", "event.severity": 6, - "event.start": "2021-04-27T05:12:21.000Z", + "event.start": "2022-04-27T05:12:21.000Z", "event.timezone": "-02:00", "event.type": [ "connection", @@ -3228,13 +3228,13 @@ "event.code": 113019, "event.dataset": "cisco.asa", "event.duration": 1936000000000, - "event.end": "2021-04-27T02:03:03.000-02:00", + "event.end": "2022-04-27T02:03:03.000-02:00", "event.kind": "event", "event.module": "cisco", "event.original": "%ASA-4-113019: Group = 81.2.69.143, Username = 81.2.69.143, IP = 81.2.69.143, Session disconnected. Session Type: LAN-to-LAN, Duration: 0h:32m:16s, Bytes xmt: 297103, Bytes rcv: 1216163, Reason: User Requested", "event.reason": "User Requested", "event.severity": 4, - "event.start": "2021-04-27T03:30:47.000Z", + "event.start": "2022-04-27T03:30:47.000Z", "event.timezone": "-02:00", "event.type": [ "info" diff --git a/x-pack/filebeat/module/cisco/asa/test/sample.log-expected.json b/x-pack/filebeat/module/cisco/asa/test/sample.log-expected.json index fad5d0a80f3..65608c192ee 100644 --- a/x-pack/filebeat/module/cisco/asa/test/sample.log-expected.json +++ b/x-pack/filebeat/module/cisco/asa/test/sample.log-expected.json @@ -102,7 +102,7 @@ ] }, { - "@timestamp": "2014-04-15T09:34:34.000-04:00", + "@timestamp": "2014-04-15T11:34:34.000-02:00", "cisco.asa.destination_interface": "outside", "cisco.asa.message_id": "106100", "cisco.asa.rule_name": "acl_in", @@ -1964,7 +1964,7 @@ ] }, { - "@timestamp": "2018-04-15T09:34:34.000-04:00", + "@timestamp": "2018-04-15T11:34:34.000-02:00", "cisco.asa.destination_interface": "outside", "cisco.asa.message_id": "106100", "cisco.asa.rule_name": "acl_in", diff --git a/x-pack/filebeat/module/cisco/ftd/config/input.yml b/x-pack/filebeat/module/cisco/ftd/config/input.yml index b29aa4c725f..cb9df5bd6ec 100644 --- a/x-pack/filebeat/module/cisco/ftd/config/input.yml +++ b/x-pack/filebeat/module/cisco/ftd/config/input.yml @@ -1,9 +1,4 @@ -{{ if eq .input "syslog" }} - -type: udp -host: "{{.syslog_host}}:{{.syslog_port}}" - -{{ else if eq .input "file" }} +{{ if eq .input "file" }} type: log paths: @@ -12,6 +7,12 @@ paths: {{ end }} exclude_files: [".gz$"] +{{ else }} + +type: {{.input}} +host: "{{.syslog_host}}:{{.syslog_port}}" +ssl: {{ .ssl | tojson }} + {{ end }} tags: {{.tags | tojson}} diff --git a/x-pack/filebeat/module/cisco/ftd/manifest.yml b/x-pack/filebeat/module/cisco/ftd/manifest.yml index 31eb9659a6b..d681ff4d323 100644 --- a/x-pack/filebeat/module/cisco/ftd/manifest.yml +++ b/x-pack/filebeat/module/cisco/ftd/manifest.yml @@ -11,7 +11,8 @@ var: - name: syslog_port default: 9003 - name: input - default: syslog + default: udp + - name: ssl - name: log_level default: 7 # if ES < 6.1.0, this flag switches to false automatically when evaluating the diff --git a/x-pack/filebeat/module/cisco/ftd/test/sample.log-expected.json b/x-pack/filebeat/module/cisco/ftd/test/sample.log-expected.json index 4d979868847..5d1987b7ec6 100644 --- a/x-pack/filebeat/module/cisco/ftd/test/sample.log-expected.json +++ b/x-pack/filebeat/module/cisco/ftd/test/sample.log-expected.json @@ -100,7 +100,7 @@ ] }, { - "@timestamp": "2014-04-15T09:34:34.000-04:00", + "@timestamp": "2014-04-15T11:34:34.000-02:00", "cisco.ftd.destination_interface": "outside", "cisco.ftd.message_id": "106100", "cisco.ftd.rule_name": "acl_in", @@ -1926,7 +1926,7 @@ ] }, { - "@timestamp": "2018-04-15T09:34:34.000-04:00", + "@timestamp": "2018-04-15T11:34:34.000-02:00", "cisco.ftd.destination_interface": "outside", "cisco.ftd.message_id": "106100", "cisco.ftd.rule_name": "acl_in", diff --git a/x-pack/filebeat/module/cisco/ios/config/input.yml b/x-pack/filebeat/module/cisco/ios/config/input.yml index d911aa3ed9e..979f9cf380b 100644 --- a/x-pack/filebeat/module/cisco/ios/config/input.yml +++ b/x-pack/filebeat/module/cisco/ios/config/input.yml @@ -1,10 +1,4 @@ -{{ if eq .input "syslog" }} - -type: syslog -protocol.udp: - host: "{{.syslog_host}}:{{.syslog_port}}" - -{{ else if eq .input "file" }} +{{ if eq .input "file" }} type: log paths: @@ -13,6 +7,12 @@ paths: {{ end }} exclude_files: [".gz$"] +{{ else if eq .input "syslog" }} + +type: syslog +protocol.{{.syslog_protocol}}: + host: "{{.syslog_host}}:{{.syslog_port}}" + {{ end }} tags: {{.tags | tojson}} diff --git a/x-pack/filebeat/module/cisco/ios/manifest.yml b/x-pack/filebeat/module/cisco/ios/manifest.yml index e67f5c2f729..169e909fd89 100644 --- a/x-pack/filebeat/module/cisco/ios/manifest.yml +++ b/x-pack/filebeat/module/cisco/ios/manifest.yml @@ -10,6 +10,8 @@ var: default: localhost - name: syslog_port default: 9002 + - name: syslog_protocol + default: udp - name: input default: syslog diff --git a/x-pack/filebeat/module/coredns/log/test/coredns-json.log b/x-pack/filebeat/module/coredns/log/test/coredns-json.log index 52f20388d10..9a2f9b6dea4 100644 --- a/x-pack/filebeat/module/coredns/log/test/coredns-json.log +++ b/x-pack/filebeat/module/coredns/log/test/coredns-json.log @@ -1,3 +1,3 @@ -{"message":"2019-02-12T00:27:28.903Z [INFO] 172.17.0.4:36413 - 21583 \"A IN httpbin.org.cluster.local. udp 43 false 512\" NXDOMAIN qr,rd,ra 136 0.000102078s", "stream": "stdout", "time": "2019-02-12T00:27:28.903433597Z", "kubernetes": { "container": { "name": "coredns" }, "node": { "name": "minikube" }, "pod": { "uid": "d57d545e-2a9d-11e9-995f-08002730e0dc", "name": "coredns-86c58d9df4-jwhsg" }, "namespace": { "name": "kube-system" }, "replicaset": { "name": "coredns-86c58d9df4" }, "labels": { "pod-template-hash": "86c58d9df4", "k8s-app": "kube-dns" } } } -{"message":"2019-03-19T02:57:23.213Z [INFO] 172.17.0.9:37723 - 6966 \"A IN httpbin.org. udp 29 false 512\" NOERROR qr,rd,ra 83 0.000082083s\n","stream":"stdout","time":"2019-03-19T02:57:23.214583742Z", "kubernetes": { "container": { "name": "coredns" }, "node": { "name": "minikube" }, "pod": { "uid": "d57d545e-2a9d-11e9-995f-08002730e0dc", "name": "coredns-86c58d9df4-jwhsg" }, "namespace": { "name": "kube-system" }, "replicaset": { "name": "coredns-86c58d9df4" }, "labels": { "pod-template-hash": "86c58d9df4", "k8s-app": "kube-dns" } } } -{"message":"2019-03-11T07:16:34.013Z [INFO] [::1]:37915 - 62762 \"AAAA IN czbaoyu.com. udp 29 false 512\" NOERROR qr,rd,ra 100 0.00006286s\n","stream":"stdout","time":"2019-03-11T07:16:34.013970788Z", "kubernetes": { "container": { "name": "coredns" }, "node": { "name": "minikube" }, "pod": { "uid": "d57d545e-2a9d-11e9-995f-08002730e0dc", "name": "coredns-86c58d9df4-jwhsg" }, "namespace": { "name": "kube-system" }, "replicaset": { "name": "coredns-86c58d9df4" }, "labels": { "pod-template-hash": "86c58d9df4", "k8s-app": "kube-dns" } } } +{"message":"2019-02-12T00:27:28.903Z [INFO] 172.17.0.4:36413 - 21583 \"A IN httpbin.org.cluster.local. udp 43 false 512\" NXDOMAIN qr,rd,ra 136 0.000102078s", "stream": "stdout", "time": "2019-02-12T00:27:28.903433597Z", "kubernetes": { "container": { "name": "coredns" }, "node": { "name": "minikube" }, "pod": { "uid": "d57d545e-2a9d-11e9-995f-08002730e0dc", "name": "coredns-86c58d9df4-jwhsg" }, "namespace": "kube-system", "replicaset": { "name": "coredns-86c58d9df4" }, "labels": { "pod-template-hash": "86c58d9df4", "k8s-app": "kube-dns" } } } +{"message":"2019-03-19T02:57:23.213Z [INFO] 172.17.0.9:37723 - 6966 \"A IN httpbin.org. udp 29 false 512\" NOERROR qr,rd,ra 83 0.000082083s\n","stream":"stdout","time":"2019-03-19T02:57:23.214583742Z", "kubernetes": { "container": { "name": "coredns" }, "node": { "name": "minikube" }, "pod": { "uid": "d57d545e-2a9d-11e9-995f-08002730e0dc", "name": "coredns-86c58d9df4-jwhsg" }, "namespace": "kube-system", "replicaset": { "name": "coredns-86c58d9df4" }, "labels": { "pod-template-hash": "86c58d9df4", "k8s-app": "kube-dns" } } } +{"message":"2019-03-11T07:16:34.013Z [INFO] [::1]:37915 - 62762 \"AAAA IN czbaoyu.com. udp 29 false 512\" NOERROR qr,rd,ra 100 0.00006286s\n","stream":"stdout","time":"2019-03-11T07:16:34.013970788Z", "kubernetes": { "container": { "name": "coredns" }, "node": { "name": "minikube" }, "pod": { "uid": "d57d545e-2a9d-11e9-995f-08002730e0dc", "name": "coredns-86c58d9df4-jwhsg" }, "namespace": "kube-system", "replicaset": { "name": "coredns-86c58d9df4" }, "labels": { "pod-template-hash": "86c58d9df4", "k8s-app": "kube-dns" } } } diff --git a/x-pack/filebeat/module/coredns/log/test/coredns-json.log-expected.json b/x-pack/filebeat/module/coredns/log/test/coredns-json.log-expected.json index 12a927c1cc3..9a1c8520b76 100644 --- a/x-pack/filebeat/module/coredns/log/test/coredns-json.log-expected.json +++ b/x-pack/filebeat/module/coredns/log/test/coredns-json.log-expected.json @@ -20,7 +20,7 @@ "event.duration": 102078, "event.kind": "event", "event.module": "coredns", - "event.original": "{\"message\":\"2019-02-12T00:27:28.903Z [INFO] 172.17.0.4:36413 - 21583 \\\"A IN httpbin.org.cluster.local. udp 43 false 512\\\" NXDOMAIN qr,rd,ra 136 0.000102078s\", \"stream\": \"stdout\", \"time\": \"2019-02-12T00:27:28.903433597Z\", \"kubernetes\": { \"container\": { \"name\": \"coredns\" }, \"node\": { \"name\": \"minikube\" }, \"pod\": { \"uid\": \"d57d545e-2a9d-11e9-995f-08002730e0dc\", \"name\": \"coredns-86c58d9df4-jwhsg\" }, \"namespace\": { \"name\": \"kube-system\" }, \"replicaset\": { \"name\": \"coredns-86c58d9df4\" }, \"labels\": { \"pod-template-hash\": \"86c58d9df4\", \"k8s-app\": \"kube-dns\" } } }", + "event.original": "{\"message\":\"2019-02-12T00:27:28.903Z [INFO] 172.17.0.4:36413 - 21583 \\\"A IN httpbin.org.cluster.local. udp 43 false 512\\\" NXDOMAIN qr,rd,ra 136 0.000102078s\", \"stream\": \"stdout\", \"time\": \"2019-02-12T00:27:28.903433597Z\", \"kubernetes\": { \"container\": { \"name\": \"coredns\" }, \"node\": { \"name\": \"minikube\" }, \"pod\": { \"uid\": \"d57d545e-2a9d-11e9-995f-08002730e0dc\", \"name\": \"coredns-86c58d9df4-jwhsg\" }, \"namespace\": \"kube-system\", \"replicaset\": { \"name\": \"coredns-86c58d9df4\" }, \"labels\": { \"pod-template-hash\": \"86c58d9df4\", \"k8s-app\": \"kube-dns\" } } }", "event.outcome": "failure", "event.type": [ "protocol" @@ -30,7 +30,7 @@ "kubernetes.container.name": "coredns", "kubernetes.labels.k8s-app": "kube-dns", "kubernetes.labels.pod-template-hash": "86c58d9df4", - "kubernetes.namespace.name": "kube-system", + "kubernetes.namespace": "kube-system", "kubernetes.node.name": "minikube", "kubernetes.pod.name": "coredns-86c58d9df4-jwhsg", "kubernetes.pod.uid": "d57d545e-2a9d-11e9-995f-08002730e0dc", @@ -72,7 +72,7 @@ "event.duration": 82083, "event.kind": "event", "event.module": "coredns", - "event.original": "{\"message\":\"2019-03-19T02:57:23.213Z [INFO] 172.17.0.9:37723 - 6966 \\\"A IN httpbin.org. udp 29 false 512\\\" NOERROR qr,rd,ra 83 0.000082083s\\n\",\"stream\":\"stdout\",\"time\":\"2019-03-19T02:57:23.214583742Z\", \"kubernetes\": { \"container\": { \"name\": \"coredns\" }, \"node\": { \"name\": \"minikube\" }, \"pod\": { \"uid\": \"d57d545e-2a9d-11e9-995f-08002730e0dc\", \"name\": \"coredns-86c58d9df4-jwhsg\" }, \"namespace\": { \"name\": \"kube-system\" }, \"replicaset\": { \"name\": \"coredns-86c58d9df4\" }, \"labels\": { \"pod-template-hash\": \"86c58d9df4\", \"k8s-app\": \"kube-dns\" } } }", + "event.original": "{\"message\":\"2019-03-19T02:57:23.213Z [INFO] 172.17.0.9:37723 - 6966 \\\"A IN httpbin.org. udp 29 false 512\\\" NOERROR qr,rd,ra 83 0.000082083s\\n\",\"stream\":\"stdout\",\"time\":\"2019-03-19T02:57:23.214583742Z\", \"kubernetes\": { \"container\": { \"name\": \"coredns\" }, \"node\": { \"name\": \"minikube\" }, \"pod\": { \"uid\": \"d57d545e-2a9d-11e9-995f-08002730e0dc\", \"name\": \"coredns-86c58d9df4-jwhsg\" }, \"namespace\": \"kube-system\", \"replicaset\": { \"name\": \"coredns-86c58d9df4\" }, \"labels\": { \"pod-template-hash\": \"86c58d9df4\", \"k8s-app\": \"kube-dns\" } } }", "event.outcome": "success", "event.type": [ "protocol" @@ -82,13 +82,13 @@ "kubernetes.container.name": "coredns", "kubernetes.labels.k8s-app": "kube-dns", "kubernetes.labels.pod-template-hash": "86c58d9df4", - "kubernetes.namespace.name": "kube-system", + "kubernetes.namespace": "kube-system", "kubernetes.node.name": "minikube", "kubernetes.pod.name": "coredns-86c58d9df4-jwhsg", "kubernetes.pod.uid": "d57d545e-2a9d-11e9-995f-08002730e0dc", "kubernetes.replicaset.name": "coredns-86c58d9df4", "log.level": "INFO", - "log.offset": 562, + "log.offset": 550, "message": "2019-03-19T02:57:23.213Z [INFO] 172.17.0.9:37723 - 6966 \"A IN httpbin.org. udp 29 false 512\" NOERROR qr,rd,ra 83 0.000082083s\n", "network.protocol": "dns", "network.transport": "udp", @@ -124,7 +124,7 @@ "event.duration": 62860, "event.kind": "event", "event.module": "coredns", - "event.original": "{\"message\":\"2019-03-11T07:16:34.013Z [INFO] [::1]:37915 - 62762 \\\"AAAA IN czbaoyu.com. udp 29 false 512\\\" NOERROR qr,rd,ra 100 0.00006286s\\n\",\"stream\":\"stdout\",\"time\":\"2019-03-11T07:16:34.013970788Z\", \"kubernetes\": { \"container\": { \"name\": \"coredns\" }, \"node\": { \"name\": \"minikube\" }, \"pod\": { \"uid\": \"d57d545e-2a9d-11e9-995f-08002730e0dc\", \"name\": \"coredns-86c58d9df4-jwhsg\" }, \"namespace\": { \"name\": \"kube-system\" }, \"replicaset\": { \"name\": \"coredns-86c58d9df4\" }, \"labels\": { \"pod-template-hash\": \"86c58d9df4\", \"k8s-app\": \"kube-dns\" } } }", + "event.original": "{\"message\":\"2019-03-11T07:16:34.013Z [INFO] [::1]:37915 - 62762 \\\"AAAA IN czbaoyu.com. udp 29 false 512\\\" NOERROR qr,rd,ra 100 0.00006286s\\n\",\"stream\":\"stdout\",\"time\":\"2019-03-11T07:16:34.013970788Z\", \"kubernetes\": { \"container\": { \"name\": \"coredns\" }, \"node\": { \"name\": \"minikube\" }, \"pod\": { \"uid\": \"d57d545e-2a9d-11e9-995f-08002730e0dc\", \"name\": \"coredns-86c58d9df4-jwhsg\" }, \"namespace\": \"kube-system\", \"replicaset\": { \"name\": \"coredns-86c58d9df4\" }, \"labels\": { \"pod-template-hash\": \"86c58d9df4\", \"k8s-app\": \"kube-dns\" } } }", "event.outcome": "success", "event.type": [ "protocol" @@ -134,13 +134,13 @@ "kubernetes.container.name": "coredns", "kubernetes.labels.k8s-app": "kube-dns", "kubernetes.labels.pod-template-hash": "86c58d9df4", - "kubernetes.namespace.name": "kube-system", + "kubernetes.namespace": "kube-system", "kubernetes.node.name": "minikube", "kubernetes.pod.name": "coredns-86c58d9df4-jwhsg", "kubernetes.pod.uid": "d57d545e-2a9d-11e9-995f-08002730e0dc", "kubernetes.replicaset.name": "coredns-86c58d9df4", "log.level": "INFO", - "log.offset": 1105, + "log.offset": 1081, "message": "2019-03-11T07:16:34.013Z [INFO] [::1]:37915 - 62762 \"AAAA IN czbaoyu.com. udp 29 false 512\" NOERROR qr,rd,ra 100 0.00006286s\n", "network.protocol": "dns", "network.transport": "udp", diff --git a/x-pack/filebeat/module/cyberarkpas/audit/test/288_auto_clear_users_history_start.log-expected.json b/x-pack/filebeat/module/cyberarkpas/audit/test/288_auto_clear_users_history_start.log-expected.json index 0ed48dfb9c0..9cae2c6ba1e 100644 --- a/x-pack/filebeat/module/cyberarkpas/audit/test/288_auto_clear_users_history_start.log-expected.json +++ b/x-pack/filebeat/module/cyberarkpas/audit/test/288_auto_clear_users_history_start.log-expected.json @@ -38,7 +38,7 @@ ] }, { - "@timestamp": "2021-03-08T03:00:20.000-02:00", + "@timestamp": "2022-03-08T03:00:20.000-02:00", "cyberarkpas.audit.action": "Auto Clear Users History start", "cyberarkpas.audit.desc": "Auto Clear Users History start", "cyberarkpas.audit.issuer": "Batch", diff --git a/x-pack/filebeat/module/cyberarkpas/audit/test/289_auto_clear_users_history_end.log-expected.json b/x-pack/filebeat/module/cyberarkpas/audit/test/289_auto_clear_users_history_end.log-expected.json index 4476ba0f803..072d75b33f8 100644 --- a/x-pack/filebeat/module/cyberarkpas/audit/test/289_auto_clear_users_history_end.log-expected.json +++ b/x-pack/filebeat/module/cyberarkpas/audit/test/289_auto_clear_users_history_end.log-expected.json @@ -38,7 +38,7 @@ ] }, { - "@timestamp": "2021-03-08T03:00:20.000-02:00", + "@timestamp": "2022-03-08T03:00:20.000-02:00", "cyberarkpas.audit.action": "Auto Clear Users History end", "cyberarkpas.audit.desc": "Auto Clear Users History end", "cyberarkpas.audit.issuer": "Batch", diff --git a/x-pack/filebeat/module/cyberarkpas/audit/test/310_monitor_dr_replication_start.log-expected.json b/x-pack/filebeat/module/cyberarkpas/audit/test/310_monitor_dr_replication_start.log-expected.json index 5b958288c53..d5a9961da30 100644 --- a/x-pack/filebeat/module/cyberarkpas/audit/test/310_monitor_dr_replication_start.log-expected.json +++ b/x-pack/filebeat/module/cyberarkpas/audit/test/310_monitor_dr_replication_start.log-expected.json @@ -38,7 +38,7 @@ ] }, { - "@timestamp": "2021-03-08T02:48:07.000-02:00", + "@timestamp": "2022-03-08T02:48:07.000-02:00", "cyberarkpas.audit.action": "Monitor DR Replication start", "cyberarkpas.audit.desc": "Monitor DR Replication start", "cyberarkpas.audit.issuer": "Batch", diff --git a/x-pack/filebeat/module/cyberarkpas/audit/test/311_monitor_dr_replication_end.log-expected.json b/x-pack/filebeat/module/cyberarkpas/audit/test/311_monitor_dr_replication_end.log-expected.json index e4999439bea..696e2ea2302 100644 --- a/x-pack/filebeat/module/cyberarkpas/audit/test/311_monitor_dr_replication_end.log-expected.json +++ b/x-pack/filebeat/module/cyberarkpas/audit/test/311_monitor_dr_replication_end.log-expected.json @@ -38,7 +38,7 @@ ] }, { - "@timestamp": "2021-03-08T02:48:07.000-02:00", + "@timestamp": "2022-03-08T02:48:07.000-02:00", "cyberarkpas.audit.action": "Monitor DR Replication end", "cyberarkpas.audit.desc": "Monitor DR Replication end", "cyberarkpas.audit.issuer": "Batch", diff --git a/x-pack/filebeat/module/cyberarkpas/audit/test/357_monitor_fw_rules_start.log-expected.json b/x-pack/filebeat/module/cyberarkpas/audit/test/357_monitor_fw_rules_start.log-expected.json index a3b04bd34cf..e04dc95c4b5 100644 --- a/x-pack/filebeat/module/cyberarkpas/audit/test/357_monitor_fw_rules_start.log-expected.json +++ b/x-pack/filebeat/module/cyberarkpas/audit/test/357_monitor_fw_rules_start.log-expected.json @@ -38,7 +38,7 @@ ] }, { - "@timestamp": "2021-03-08T02:32:56.000-02:00", + "@timestamp": "2022-03-08T02:32:56.000-02:00", "cyberarkpas.audit.action": "Monitor FW rules start", "cyberarkpas.audit.desc": "Monitor FW rules start", "cyberarkpas.audit.issuer": "Batch", diff --git a/x-pack/filebeat/module/cyberarkpas/audit/test/358_monitor_fw_rules_end.log-expected.json b/x-pack/filebeat/module/cyberarkpas/audit/test/358_monitor_fw_rules_end.log-expected.json index a5af60dcea0..97fcd7a22e8 100644 --- a/x-pack/filebeat/module/cyberarkpas/audit/test/358_monitor_fw_rules_end.log-expected.json +++ b/x-pack/filebeat/module/cyberarkpas/audit/test/358_monitor_fw_rules_end.log-expected.json @@ -38,7 +38,7 @@ ] }, { - "@timestamp": "2021-03-08T02:32:56.000-02:00", + "@timestamp": "2022-03-08T02:32:56.000-02:00", "cyberarkpas.audit.action": "Monitor FW Rules end", "cyberarkpas.audit.desc": "Monitor FW Rules end", "cyberarkpas.audit.issuer": "Batch", diff --git a/x-pack/filebeat/module/cyberarkpas/audit/test/479_security_warning_the_signature_hash_algorithm_of_the_vault_certificate_is_sha1.log-expected.json b/x-pack/filebeat/module/cyberarkpas/audit/test/479_security_warning_the_signature_hash_algorithm_of_the_vault_certificate_is_sha1.log-expected.json index e127969e7f2..78fd1127daf 100644 --- a/x-pack/filebeat/module/cyberarkpas/audit/test/479_security_warning_the_signature_hash_algorithm_of_the_vault_certificate_is_sha1.log-expected.json +++ b/x-pack/filebeat/module/cyberarkpas/audit/test/479_security_warning_the_signature_hash_algorithm_of_the_vault_certificate_is_sha1.log-expected.json @@ -39,7 +39,7 @@ ] }, { - "@timestamp": "2021-03-08T07:46:54.000-02:00", + "@timestamp": "2022-03-08T07:46:54.000-02:00", "cyberarkpas.audit.action": "Security warning - The Signature Hash Algorithm of the Vault certificate is SHA1.", "cyberarkpas.audit.desc": "Security warning - The Signature Hash Algorithm of the Vault certificate is SHA1.", "cyberarkpas.audit.issuer": "Builtin", diff --git a/x-pack/filebeat/module/cyberarkpas/audit/test/59_clear_safe_history.log-expected.json b/x-pack/filebeat/module/cyberarkpas/audit/test/59_clear_safe_history.log-expected.json index 21d71f71183..65619e9c9d1 100644 --- a/x-pack/filebeat/module/cyberarkpas/audit/test/59_clear_safe_history.log-expected.json +++ b/x-pack/filebeat/module/cyberarkpas/audit/test/59_clear_safe_history.log-expected.json @@ -39,7 +39,7 @@ ] }, { - "@timestamp": "2021-03-08T03:10:31.000-02:00", + "@timestamp": "2022-03-08T03:10:31.000-02:00", "cyberarkpas.audit.action": "Clear Safe History", "cyberarkpas.audit.desc": "Clear Safe History", "cyberarkpas.audit.issuer": "PasswordManager", diff --git a/x-pack/filebeat/module/cyberarkpas/audit/test/88_set_password.log-expected.json b/x-pack/filebeat/module/cyberarkpas/audit/test/88_set_password.log-expected.json index bbc572cd230..60c6a59eca3 100644 --- a/x-pack/filebeat/module/cyberarkpas/audit/test/88_set_password.log-expected.json +++ b/x-pack/filebeat/module/cyberarkpas/audit/test/88_set_password.log-expected.json @@ -76,7 +76,7 @@ ] }, { - "@timestamp": "2021-03-08T02:54:46.000-02:00", + "@timestamp": "2022-03-08T02:54:46.000-02:00", "cyberarkpas.audit.action": "Set Password", "cyberarkpas.audit.desc": "Set Password", "cyberarkpas.audit.issuer": "PVWAGWUser", diff --git a/x-pack/filebeat/module/cyberarkpas/audit/test/legacysyslog.log-expected.json b/x-pack/filebeat/module/cyberarkpas/audit/test/legacysyslog.log-expected.json index 14b87c8867c..b71d3ab351e 100644 --- a/x-pack/filebeat/module/cyberarkpas/audit/test/legacysyslog.log-expected.json +++ b/x-pack/filebeat/module/cyberarkpas/audit/test/legacysyslog.log-expected.json @@ -1,6 +1,6 @@ [ { - "@timestamp": "2021-03-08T03:41:01.000-02:00", + "@timestamp": "2022-03-08T03:41:01.000-02:00", "cyberarkpas.audit.action": "Retrieve File", "cyberarkpas.audit.desc": "Retrieve File", "cyberarkpas.audit.file": "Root\\Policies\\Policy-BusinessWebsite.ini", diff --git a/x-pack/filebeat/module/cylance/_meta/docs.asciidoc b/x-pack/filebeat/module/cylance/_meta/docs.asciidoc index 135260569a4..4cd22f8b797 100644 --- a/x-pack/filebeat/module/cylance/_meta/docs.asciidoc +++ b/x-pack/filebeat/module/cylance/_meta/docs.asciidoc @@ -28,7 +28,7 @@ NOTE: This was converted from RSA NetWitness log parser XML "cylance" device rev *`var.input`*:: -The input from which messages are read. One of `file`, `tcp` or `udp`. +The input from which messages are read. One of `file`, `tcp` or `udp`. Defaults to `udp`. *`var.syslog_host`*:: diff --git a/x-pack/filebeat/module/envoyproxy/log/test/envoy-json.log b/x-pack/filebeat/module/envoyproxy/log/test/envoy-json.log index 65d689e46eb..31cb674f4c7 100644 --- a/x-pack/filebeat/module/envoyproxy/log/test/envoy-json.log +++ b/x-pack/filebeat/module/envoyproxy/log/test/envoy-json.log @@ -1,2 +1,2 @@ -{"message":"ACCESS [2019-04-10T03:49:34.451Z] \"GET /httpbin/status/501 HTTP/1.1\" 501 - 0 0 180 179 \"172.17.0.3\" \"curl/7.59.0\" \"413bf460-bd56-4515-ada4-2a69c5e78e54\" \"httpbin.org\" \"52.71.234.219:80\"","stream":"stdout","time":"2019-02-12T18:37:43.139620629Z", "kubernetes": { "container": { "name": "ambassador" }, "node": { "name": "minikube" }, "pod": { "uid": "e57d545e-2a9d-11e9-995f-08002730e0dc", "name": "ambassador-76c58d9df4-jwhsg" }, "namespace": { "name": "default" }, "labels": { "service": "ambassador" }}} -{"message":"ACCESS [2019-04-06T06:20:05.972Z] \"- - -\" 0 UF,URX 0 0 0 - \"-\" \"-\" \"-\" \"-\" \"127.0.0.1:9200\"","stream":"stdout","time":"2019-02-12T18:37:43.139620629Z", "kubernetes": { "container": { "name": "ambassador" }, "node": { "name": "minikube" }, "pod": { "uid": "e57d545e-2a9d-11e9-995f-08002730e0dc", "name": "ambassador-76c58d9df4-jwhsg" }, "namespace": { "name": "default" }, "labels": { "service": "ambassador" }}}} +{"message":"ACCESS [2019-04-10T03:49:34.451Z] \"GET /httpbin/status/501 HTTP/1.1\" 501 - 0 0 180 179 \"172.17.0.3\" \"curl/7.59.0\" \"413bf460-bd56-4515-ada4-2a69c5e78e54\" \"httpbin.org\" \"52.71.234.219:80\"","stream":"stdout","time":"2019-02-12T18:37:43.139620629Z", "kubernetes": { "container": { "name": "ambassador" }, "node": { "name": "minikube" }, "pod": { "uid": "e57d545e-2a9d-11e9-995f-08002730e0dc", "name": "ambassador-76c58d9df4-jwhsg" }, "namespace": "default", "labels": { "service": "ambassador" }}} +{"message":"ACCESS [2019-04-06T06:20:05.972Z] \"- - -\" 0 UF,URX 0 0 0 - \"-\" \"-\" \"-\" \"-\" \"127.0.0.1:9200\"","stream":"stdout","time":"2019-02-12T18:37:43.139620629Z", "kubernetes": { "container": { "name": "ambassador" }, "node": { "name": "minikube" }, "pod": { "uid": "e57d545e-2a9d-11e9-995f-08002730e0dc", "name": "ambassador-76c58d9df4-jwhsg" }, "namespace": "default", "labels": { "service": "ambassador" }}}} diff --git a/x-pack/filebeat/module/envoyproxy/log/test/envoy-json.log-expected.json b/x-pack/filebeat/module/envoyproxy/log/test/envoy-json.log-expected.json index f2e9cb25b37..9219be79328 100644 --- a/x-pack/filebeat/module/envoyproxy/log/test/envoy-json.log-expected.json +++ b/x-pack/filebeat/module/envoyproxy/log/test/envoy-json.log-expected.json @@ -32,7 +32,7 @@ "input.type": "log", "kubernetes.container.name": "ambassador", "kubernetes.labels.service": "ambassador", - "kubernetes.namespace.name": "default", + "kubernetes.namespace": "default", "kubernetes.node.name": "minikube", "kubernetes.pod.name": "ambassador-76c58d9df4-jwhsg", "kubernetes.pod.uid": "e57d545e-2a9d-11e9-995f-08002730e0dc", @@ -87,11 +87,11 @@ "input.type": "log", "kubernetes.container.name": "ambassador", "kubernetes.labels.service": "ambassador", - "kubernetes.namespace.name": "default", + "kubernetes.namespace": "default", "kubernetes.node.name": "minikube", "kubernetes.pod.name": "ambassador-76c58d9df4-jwhsg", "kubernetes.pod.uid": "e57d545e-2a9d-11e9-995f-08002730e0dc", - "log.offset": 530, + "log.offset": 518, "message": "ACCESS [2019-04-06T06:20:05.972Z] \"- - -\" 0 UF,URX 0 0 0 - \"-\" \"-\" \"-\" \"-\" \"127.0.0.1:9200\"", "network.transport": "tcp", "related.ip": [ diff --git a/x-pack/filebeat/module/f5/_meta/docs.asciidoc b/x-pack/filebeat/module/f5/_meta/docs.asciidoc index d0448abd545..e83d14081ff 100644 --- a/x-pack/filebeat/module/f5/_meta/docs.asciidoc +++ b/x-pack/filebeat/module/f5/_meta/docs.asciidoc @@ -32,7 +32,7 @@ NOTE: This was converted from RSA NetWitness log parser XML "bigipapm" device re *`var.input`*:: -The input from which messages are read. One of `file`, `tcp` or `udp`. +The input from which messages are read. One of `file`, `tcp` or `udp`. Defaults to `udp`. *`var.syslog_host`*:: @@ -77,7 +77,7 @@ NOTE: This was converted from RSA NetWitness log parser XML "bigipafm" device re *`var.input`*:: -The input from which messages are read. One of `file`, `tcp` or `udp`. +The input from which messages are read. One of `file`, `tcp` or `udp`. Defaults to `udp`. *`var.syslog_host`*:: diff --git a/x-pack/filebeat/module/fortinet/_meta/docs.asciidoc b/x-pack/filebeat/module/fortinet/_meta/docs.asciidoc index 46c62099197..2cd30c1437a 100644 --- a/x-pack/filebeat/module/fortinet/_meta/docs.asciidoc +++ b/x-pack/filebeat/module/fortinet/_meta/docs.asciidoc @@ -80,7 +80,7 @@ NOTE: This was converted from RSA NetWitness log parser XML "forticlientendpoint *`var.input`*:: -The input from which messages are read. One of `file`, `tcp` or `udp`. +The input from which messages are read. One of `file`, `tcp` or `udp`. Defaults to `udp`. *`var.syslog_host`*:: @@ -125,7 +125,7 @@ NOTE: This was converted from RSA NetWitness log parser XML "fortinetfortimail" *`var.input`*:: -The input from which messages are read. One of `file`, `tcp` or `udp`. +The input from which messages are read. One of `file`, `tcp` or `udp`. Defaults to `udp`. *`var.syslog_host`*:: @@ -170,7 +170,7 @@ NOTE: This was converted from RSA NetWitness log parser XML "fortinetmgr" device *`var.input`*:: -The input from which messages are read. One of `file`, `tcp` or `udp`. +The input from which messages are read. One of `file`, `tcp` or `udp`. Defaults to `udp`. *`var.syslog_host`*:: diff --git a/x-pack/filebeat/module/ibmmq/errorlog/ingest/pipeline.yml b/x-pack/filebeat/module/ibmmq/errorlog/ingest/pipeline.yml index 87c3deacb97..6eadaa6b30a 100644 --- a/x-pack/filebeat/module/ibmmq/errorlog/ingest/pipeline.yml +++ b/x-pack/filebeat/module/ibmmq/errorlog/ingest/pipeline.yml @@ -18,9 +18,9 @@ processors: replacement: ' ' - trim: field: message -- rename: - field: '@timestamp' - target_field: event.created +- set: + copy_from: '@timestamp' + field: event.created - grok: field: message patterns: @@ -30,7 +30,7 @@ processors: patterns: - 'Process\(%{DATA:process.pid}\) User\(%{WORD:user.name}\) Program\(%{DATA:process.title}\) Host\(%{DATA:host.hostname}\) Installation\(%{WORD:ibmmq.errorlog.installation}\) - VRMF\(%{DATA:service.version}\)( QMgr\(%{DATA:ibmmq.errorlog.qmgr}\))?( Time\(%{TIMESTAMP_ISO8601:@timestamp}\))?( + VRMF\(%{DATA:service.version}\)( QMgr\(%{DATA:ibmmq.errorlog.qmgr}\))?( Time\(%{TIMESTAMP_ISO8601:log_timestamp}\))?( RemoteHost\(%{DATA:destination.address}\))?( ArithInsert1\(%{DATA:ibmmq.errorlog.arithinsert1}\))?( ArithInsert2\(%{DATA:ibmmq.errorlog.arithinsert2}\))?( CommentInsert1\(%{DATA:ibmmq.errorlog.commentinsert1}\))?( CommentInsert2\(%{DATA:ibmmq.errorlog.commentinsert2}\))?( CommentInsert3\(%{DATA:ibmmq.errorlog.commentinsert3}\))? @@ -41,8 +41,10 @@ processors: field: log_timestamp target_field: '@timestamp' formats: - - MM/dd/yyyy hh:mm:ss aa + - ISO8601 + - MM/dd/yyyy hh:mm:ss a - dd/MM/yyyy HH:mm:ss + - dd.MM.yyyy HH:mm:ss ignore_failure: true - append: field: ibmmq.errorlog.commentinsert diff --git a/x-pack/filebeat/module/ibmmq/errorlog/test/AMQERR01.log-expected.json b/x-pack/filebeat/module/ibmmq/errorlog/test/AMQERR01.log-expected.json index c29d64be928..ccb30351cb0 100644 --- a/x-pack/filebeat/module/ibmmq/errorlog/test/AMQERR01.log-expected.json +++ b/x-pack/filebeat/module/ibmmq/errorlog/test/AMQERR01.log-expected.json @@ -66,7 +66,7 @@ "user.name": "felix" }, { - "@timestamp": "2018-10-11T10:46:25.000Z", + "@timestamp": "2018-10-11T08:46:25.924Z", "event.dataset": "ibmmq.errorlog", "event.kind": "event", "event.module": "ibmmq", @@ -99,7 +99,7 @@ "user.name": "MUSR_MQADMIN" }, { - "@timestamp": "2018-10-11T10:46:26.000Z", + "@timestamp": "2018-10-11T08:46:26.343Z", "event.dataset": "ibmmq.errorlog", "event.kind": "event", "event.module": "ibmmq", @@ -132,7 +132,7 @@ "user.name": "MUSR_MQADMIN" }, { - "@timestamp": "2018-10-11T10:46:26.000Z", + "@timestamp": "2018-10-11T08:46:26.346Z", "event.dataset": "ibmmq.errorlog", "event.kind": "event", "event.module": "ibmmq", @@ -264,7 +264,7 @@ "user.name": "felix" }, { - "@timestamp": "2018-10-28T15:12:07.000Z", + "@timestamp": "2018-10-28T14:12:07.685Z", "event.dataset": "ibmmq.errorlog", "event.kind": "event", "event.module": "ibmmq", @@ -297,7 +297,7 @@ "user.name": "MUSR_MQADMIN" }, { - "@timestamp": "2018-10-28T15:12:07.000Z", + "@timestamp": "2018-10-28T14:12:07.789Z", "event.dataset": "ibmmq.errorlog", "event.kind": "event", "event.module": "ibmmq", @@ -330,7 +330,7 @@ "user.name": "MUSR_MQADMIN" }, { - "@timestamp": "2018-10-28T15:12:08.000Z", + "@timestamp": "2018-10-28T14:12:08.663Z", "event.dataset": "ibmmq.errorlog", "event.kind": "event", "event.module": "ibmmq", @@ -363,7 +363,7 @@ "user.name": "MUSR_MQADMIN" }, { - "@timestamp": "2018-10-28T15:12:08.000Z", + "@timestamp": "2018-10-28T14:12:08.665Z", "event.dataset": "ibmmq.errorlog", "event.kind": "event", "event.module": "ibmmq", @@ -396,7 +396,7 @@ "user.name": "MUSR_MQADMIN" }, { - "@timestamp": "2018-10-29T16:48:52.000Z", + "@timestamp": "2018-10-29T15:48:52.594Z", "event.dataset": "ibmmq.errorlog", "event.kind": "event", "event.module": "ibmmq", @@ -429,7 +429,7 @@ "user.name": "MUSR_MQADMIN" }, { - "@timestamp": "2018-10-29T16:48:52.000Z", + "@timestamp": "2018-10-29T15:48:52.663Z", "event.dataset": "ibmmq.errorlog", "event.kind": "event", "event.module": "ibmmq", @@ -462,7 +462,7 @@ "user.name": "MUSR_MQADMIN" }, { - "@timestamp": "2018-10-29T16:48:53.000Z", + "@timestamp": "2018-10-29T15:48:53.368Z", "event.dataset": "ibmmq.errorlog", "event.kind": "event", "event.module": "ibmmq", @@ -495,7 +495,7 @@ "user.name": "MUSR_MQADMIN" }, { - "@timestamp": "2018-10-29T16:48:53.000Z", + "@timestamp": "2018-10-29T15:48:53.369Z", "event.dataset": "ibmmq.errorlog", "event.kind": "event", "event.module": "ibmmq", @@ -528,7 +528,7 @@ "user.name": "MUSR_MQADMIN" }, { - "@timestamp": "2018-10-29T16:49:35.000Z", + "@timestamp": "2018-10-29T15:49:35.477Z", "event.dataset": "ibmmq.errorlog", "event.kind": "event", "event.module": "ibmmq", @@ -561,7 +561,7 @@ "user.name": "MUSR_MQADMIN" }, { - "@timestamp": "2018-10-29T16:49:35.000Z", + "@timestamp": "2018-10-29T15:49:35.553Z", "event.dataset": "ibmmq.errorlog", "event.kind": "event", "event.module": "ibmmq", @@ -594,7 +594,7 @@ "user.name": "MUSR_MQADMIN" }, { - "@timestamp": "2018-10-29T16:49:36.000Z", + "@timestamp": "2018-10-29T15:49:36.447Z", "event.dataset": "ibmmq.errorlog", "event.kind": "event", "event.module": "ibmmq", @@ -627,7 +627,7 @@ "user.name": "MUSR_MQADMIN" }, { - "@timestamp": "2018-10-29T16:49:36.000Z", + "@timestamp": "2018-10-29T15:49:36.448Z", "event.dataset": "ibmmq.errorlog", "event.kind": "event", "event.module": "ibmmq", diff --git a/x-pack/filebeat/module/ibmmq/errorlog/test/AMQERR01_QM1.log-expected.json b/x-pack/filebeat/module/ibmmq/errorlog/test/AMQERR01_QM1.log-expected.json index 45a57fffd05..e472bca49fe 100644 --- a/x-pack/filebeat/module/ibmmq/errorlog/test/AMQERR01_QM1.log-expected.json +++ b/x-pack/filebeat/module/ibmmq/errorlog/test/AMQERR01_QM1.log-expected.json @@ -1,5 +1,6 @@ [ { + "@timestamp": "2018-07-13T07:06:00.000Z", "event.dataset": "ibmmq.errorlog", "event.kind": "event", "event.module": "ibmmq", @@ -32,6 +33,7 @@ "user.name": "felix" }, { + "@timestamp": "2018-07-13T07:06:00.000Z", "event.dataset": "ibmmq.errorlog", "event.kind": "event", "event.module": "ibmmq", @@ -64,6 +66,7 @@ "user.name": "felix" }, { + "@timestamp": "2018-07-13T07:06:00.000Z", "event.dataset": "ibmmq.errorlog", "event.kind": "event", "event.module": "ibmmq", @@ -96,6 +99,7 @@ "user.name": "felix" }, { + "@timestamp": "2018-07-13T07:06:01.000Z", "event.dataset": "ibmmq.errorlog", "event.kind": "event", "event.module": "ibmmq", @@ -128,6 +132,7 @@ "user.name": "felix" }, { + "@timestamp": "2018-07-13T07:06:01.000Z", "event.dataset": "ibmmq.errorlog", "event.kind": "event", "event.module": "ibmmq", @@ -160,6 +165,7 @@ "user.name": "felix" }, { + "@timestamp": "2018-07-13T07:06:01.000Z", "event.dataset": "ibmmq.errorlog", "event.kind": "event", "event.module": "ibmmq", @@ -192,6 +198,7 @@ "user.name": "felix" }, { + "@timestamp": "2018-07-13T07:06:01.000Z", "event.dataset": "ibmmq.errorlog", "event.kind": "event", "event.module": "ibmmq", @@ -224,6 +231,7 @@ "user.name": "felix" }, { + "@timestamp": "2018-07-13T07:06:01.000Z", "event.dataset": "ibmmq.errorlog", "event.kind": "event", "event.module": "ibmmq", @@ -256,6 +264,7 @@ "user.name": "felix" }, { + "@timestamp": "2018-07-13T07:06:01.000Z", "event.dataset": "ibmmq.errorlog", "event.kind": "event", "event.module": "ibmmq", @@ -288,6 +297,7 @@ "user.name": "felix" }, { + "@timestamp": "2018-07-13T07:06:01.000Z", "event.dataset": "ibmmq.errorlog", "event.kind": "event", "event.module": "ibmmq", @@ -320,6 +330,7 @@ "user.name": "felix" }, { + "@timestamp": "2018-07-13T07:06:01.000Z", "event.dataset": "ibmmq.errorlog", "event.kind": "event", "event.module": "ibmmq", @@ -352,6 +363,7 @@ "user.name": "felix" }, { + "@timestamp": "2018-07-13T07:06:01.000Z", "event.dataset": "ibmmq.errorlog", "event.kind": "event", "event.module": "ibmmq", @@ -384,6 +396,7 @@ "user.name": "felix" }, { + "@timestamp": "2018-07-13T07:06:01.000Z", "event.dataset": "ibmmq.errorlog", "event.kind": "event", "event.module": "ibmmq", @@ -416,6 +429,7 @@ "user.name": "felix" }, { + "@timestamp": "2018-07-13T07:06:01.000Z", "event.dataset": "ibmmq.errorlog", "event.kind": "event", "event.module": "ibmmq", @@ -448,6 +462,7 @@ "user.name": "felix" }, { + "@timestamp": "2018-07-13T07:06:01.000Z", "event.dataset": "ibmmq.errorlog", "event.kind": "event", "event.module": "ibmmq", @@ -480,6 +495,7 @@ "user.name": "felix" }, { + "@timestamp": "2018-07-13T07:06:02.000Z", "event.dataset": "ibmmq.errorlog", "event.kind": "event", "event.module": "ibmmq", @@ -512,6 +528,7 @@ "user.name": "felix" }, { + "@timestamp": "2018-07-13T07:06:03.000Z", "event.dataset": "ibmmq.errorlog", "event.kind": "event", "event.module": "ibmmq", @@ -544,6 +561,7 @@ "user.name": "felix" }, { + "@timestamp": "2018-07-13T07:06:03.000Z", "event.dataset": "ibmmq.errorlog", "event.kind": "event", "event.module": "ibmmq", @@ -576,6 +594,7 @@ "user.name": "felix" }, { + "@timestamp": "2018-07-13T07:06:03.000Z", "event.dataset": "ibmmq.errorlog", "event.kind": "event", "event.module": "ibmmq", @@ -608,6 +627,7 @@ "user.name": "felix" }, { + "@timestamp": "2018-07-13T07:06:03.000Z", "event.dataset": "ibmmq.errorlog", "event.kind": "event", "event.module": "ibmmq", @@ -640,6 +660,7 @@ "user.name": "felix" }, { + "@timestamp": "2018-07-13T07:06:03.000Z", "event.dataset": "ibmmq.errorlog", "event.kind": "event", "event.module": "ibmmq", @@ -672,6 +693,7 @@ "user.name": "felix" }, { + "@timestamp": "2018-07-13T07:06:03.000Z", "event.dataset": "ibmmq.errorlog", "event.kind": "event", "event.module": "ibmmq", @@ -704,6 +726,7 @@ "user.name": "felix" }, { + "@timestamp": "2018-07-13T07:06:03.000Z", "event.dataset": "ibmmq.errorlog", "event.kind": "event", "event.module": "ibmmq", diff --git a/x-pack/filebeat/module/ibmmq/errorlog/test/AMQERR01_QM2.log-expected.json b/x-pack/filebeat/module/ibmmq/errorlog/test/AMQERR01_QM2.log-expected.json index ddaa656e153..fd44a2bbdbc 100644 --- a/x-pack/filebeat/module/ibmmq/errorlog/test/AMQERR01_QM2.log-expected.json +++ b/x-pack/filebeat/module/ibmmq/errorlog/test/AMQERR01_QM2.log-expected.json @@ -782,7 +782,7 @@ "user.name": "felix" }, { - "@timestamp": "2018-10-17T13:50:18.000Z", + "@timestamp": "2018-10-17T11:50:18.779Z", "event.dataset": "ibmmq.errorlog", "event.kind": "event", "event.module": "ibmmq", @@ -816,7 +816,7 @@ "user.name": "MUSR_MQADMIN" }, { - "@timestamp": "2018-10-17T13:50:18.000Z", + "@timestamp": "2018-10-17T11:50:18.803Z", "event.dataset": "ibmmq.errorlog", "event.kind": "event", "event.module": "ibmmq", @@ -850,7 +850,7 @@ "user.name": "MUSR_MQADMIN" }, { - "@timestamp": "2018-10-17T13:50:18.000Z", + "@timestamp": "2018-10-17T11:50:18.806Z", "event.dataset": "ibmmq.errorlog", "event.kind": "event", "event.module": "ibmmq", @@ -884,7 +884,7 @@ "user.name": "MUSR_MQADMIN" }, { - "@timestamp": "2018-10-17T13:50:18.000Z", + "@timestamp": "2018-10-17T11:50:18.815Z", "event.dataset": "ibmmq.errorlog", "event.kind": "event", "event.module": "ibmmq", @@ -918,7 +918,7 @@ "user.name": "MUSR_MQADMIN" }, { - "@timestamp": "2018-10-17T13:50:18.000Z", + "@timestamp": "2018-10-17T11:50:18.818Z", "event.dataset": "ibmmq.errorlog", "event.kind": "event", "event.module": "ibmmq", @@ -952,7 +952,7 @@ "user.name": "MUSR_MQADMIN" }, { - "@timestamp": "2018-10-17T13:50:18.000Z", + "@timestamp": "2018-10-17T11:50:18.828Z", "event.dataset": "ibmmq.errorlog", "event.kind": "event", "event.module": "ibmmq", @@ -986,7 +986,7 @@ "user.name": "MUSR_MQADMIN" }, { - "@timestamp": "2018-10-17T13:50:18.000Z", + "@timestamp": "2018-10-17T11:50:18.834Z", "event.dataset": "ibmmq.errorlog", "event.kind": "event", "event.module": "ibmmq", @@ -1020,7 +1020,7 @@ "user.name": "MUSR_MQADMIN" }, { - "@timestamp": "2018-10-17T13:50:18.000Z", + "@timestamp": "2018-10-17T11:50:18.907Z", "event.dataset": "ibmmq.errorlog", "event.kind": "event", "event.module": "ibmmq", @@ -1054,7 +1054,7 @@ "user.name": "MUSR_MQADMIN" }, { - "@timestamp": "2018-10-17T13:50:18.000Z", + "@timestamp": "2018-10-17T11:50:18.907Z", "event.dataset": "ibmmq.errorlog", "event.kind": "event", "event.module": "ibmmq", @@ -1088,7 +1088,7 @@ "user.name": "MUSR_MQADMIN" }, { - "@timestamp": "2018-10-17T13:50:18.000Z", + "@timestamp": "2018-10-17T11:50:18.907Z", "event.dataset": "ibmmq.errorlog", "event.kind": "event", "event.module": "ibmmq", @@ -1122,7 +1122,7 @@ "user.name": "MUSR_MQADMIN" }, { - "@timestamp": "2018-10-17T13:50:18.000Z", + "@timestamp": "2018-10-17T11:50:18.907Z", "event.dataset": "ibmmq.errorlog", "event.kind": "event", "event.module": "ibmmq", @@ -1156,7 +1156,7 @@ "user.name": "MUSR_MQADMIN" }, { - "@timestamp": "2018-10-17T13:50:18.000Z", + "@timestamp": "2018-10-17T11:50:18.908Z", "event.dataset": "ibmmq.errorlog", "event.kind": "event", "event.module": "ibmmq", @@ -1190,7 +1190,7 @@ "user.name": "MUSR_MQADMIN" }, { - "@timestamp": "2018-10-17T13:50:19.000Z", + "@timestamp": "2018-10-17T11:50:19.011Z", "event.dataset": "ibmmq.errorlog", "event.kind": "event", "event.module": "ibmmq", @@ -1224,7 +1224,7 @@ "user.name": "MUSR_MQADMIN" }, { - "@timestamp": "2018-10-17T13:50:19.000Z", + "@timestamp": "2018-10-17T11:50:19.012Z", "event.dataset": "ibmmq.errorlog", "event.kind": "event", "event.module": "ibmmq", @@ -1258,7 +1258,7 @@ "user.name": "MUSR_MQADMIN" }, { - "@timestamp": "2018-10-17T13:50:19.000Z", + "@timestamp": "2018-10-17T11:50:19.108Z", "event.dataset": "ibmmq.errorlog", "event.kind": "event", "event.module": "ibmmq", @@ -1292,7 +1292,7 @@ "user.name": "MUSR_MQADMIN" }, { - "@timestamp": "2018-10-17T13:50:19.000Z", + "@timestamp": "2018-10-17T11:50:19.108Z", "event.dataset": "ibmmq.errorlog", "event.kind": "event", "event.module": "ibmmq", @@ -1326,7 +1326,7 @@ "user.name": "MUSR_MQADMIN" }, { - "@timestamp": "2018-10-17T13:50:19.000Z", + "@timestamp": "2018-10-17T11:50:19.109Z", "event.dataset": "ibmmq.errorlog", "event.kind": "event", "event.module": "ibmmq", @@ -1360,7 +1360,7 @@ "user.name": "MUSR_MQADMIN" }, { - "@timestamp": "2018-10-17T13:50:19.000Z", + "@timestamp": "2018-10-17T11:50:19.109Z", "event.dataset": "ibmmq.errorlog", "event.kind": "event", "event.module": "ibmmq", @@ -1394,7 +1394,7 @@ "user.name": "MUSR_MQADMIN" }, { - "@timestamp": "2018-10-17T13:50:19.000Z", + "@timestamp": "2018-10-17T11:50:19.109Z", "event.dataset": "ibmmq.errorlog", "event.kind": "event", "event.module": "ibmmq", @@ -1428,7 +1428,7 @@ "user.name": "MUSR_MQADMIN" }, { - "@timestamp": "2018-10-17T13:50:19.000Z", + "@timestamp": "2018-10-17T11:50:19.109Z", "event.dataset": "ibmmq.errorlog", "event.kind": "event", "event.module": "ibmmq", @@ -1462,7 +1462,7 @@ "user.name": "MUSR_MQADMIN" }, { - "@timestamp": "2018-10-17T13:50:19.000Z", + "@timestamp": "2018-10-17T11:50:19.110Z", "event.dataset": "ibmmq.errorlog", "event.kind": "event", "event.module": "ibmmq", @@ -1496,7 +1496,7 @@ "user.name": "MUSR_MQADMIN" }, { - "@timestamp": "2018-10-17T13:50:19.000Z", + "@timestamp": "2018-10-17T11:50:19.123Z", "event.dataset": "ibmmq.errorlog", "event.kind": "event", "event.module": "ibmmq", @@ -1530,7 +1530,7 @@ "user.name": "MUSR_MQADMIN" }, { - "@timestamp": "2018-10-17T13:50:19.000Z", + "@timestamp": "2018-10-17T11:50:19.124Z", "event.dataset": "ibmmq.errorlog", "event.kind": "event", "event.module": "ibmmq", @@ -1564,7 +1564,7 @@ "user.name": "MUSR_MQADMIN" }, { - "@timestamp": "2018-10-17T13:50:19.000Z", + "@timestamp": "2018-10-17T11:50:19.124Z", "event.dataset": "ibmmq.errorlog", "event.kind": "event", "event.module": "ibmmq", @@ -1598,7 +1598,7 @@ "user.name": "MUSR_MQADMIN" }, { - "@timestamp": "2018-10-17T13:50:19.000Z", + "@timestamp": "2018-10-17T11:50:19.124Z", "event.dataset": "ibmmq.errorlog", "event.kind": "event", "event.module": "ibmmq", @@ -1632,7 +1632,7 @@ "user.name": "MUSR_MQADMIN" }, { - "@timestamp": "2018-10-17T13:50:19.000Z", + "@timestamp": "2018-10-17T11:50:19.125Z", "event.dataset": "ibmmq.errorlog", "event.kind": "event", "event.module": "ibmmq", @@ -1666,7 +1666,7 @@ "user.name": "MUSR_MQADMIN" }, { - "@timestamp": "2018-10-17T13:50:19.000Z", + "@timestamp": "2018-10-17T11:50:19.124Z", "event.dataset": "ibmmq.errorlog", "event.kind": "event", "event.module": "ibmmq", @@ -1700,7 +1700,7 @@ "user.name": "MUSR_MQADMIN" }, { - "@timestamp": "2018-10-17T13:50:19.000Z", + "@timestamp": "2018-10-17T11:50:19.125Z", "event.dataset": "ibmmq.errorlog", "event.kind": "event", "event.module": "ibmmq", @@ -1734,7 +1734,7 @@ "user.name": "MUSR_MQADMIN" }, { - "@timestamp": "2018-10-17T13:50:19.000Z", + "@timestamp": "2018-10-17T11:50:19.124Z", "event.dataset": "ibmmq.errorlog", "event.kind": "event", "event.module": "ibmmq", @@ -1768,7 +1768,7 @@ "user.name": "MUSR_MQADMIN" }, { - "@timestamp": "2018-10-17T13:50:19.000Z", + "@timestamp": "2018-10-17T11:50:19.125Z", "event.dataset": "ibmmq.errorlog", "event.kind": "event", "event.module": "ibmmq", @@ -1802,7 +1802,7 @@ "user.name": "MUSR_MQADMIN" }, { - "@timestamp": "2018-10-17T13:50:19.000Z", + "@timestamp": "2018-10-17T11:50:19.125Z", "event.dataset": "ibmmq.errorlog", "event.kind": "event", "event.module": "ibmmq", @@ -1836,7 +1836,7 @@ "user.name": "MUSR_MQADMIN" }, { - "@timestamp": "2018-10-17T13:50:19.000Z", + "@timestamp": "2018-10-17T11:50:19.126Z", "event.dataset": "ibmmq.errorlog", "event.kind": "event", "event.module": "ibmmq", @@ -1870,7 +1870,7 @@ "user.name": "MUSR_MQADMIN" }, { - "@timestamp": "2018-10-17T13:50:19.000Z", + "@timestamp": "2018-10-17T11:50:19.131Z", "event.dataset": "ibmmq.errorlog", "event.kind": "event", "event.module": "ibmmq", @@ -1904,7 +1904,7 @@ "user.name": "MUSR_MQADMIN" }, { - "@timestamp": "2018-10-17T13:50:19.000Z", + "@timestamp": "2018-10-17T11:50:19.131Z", "event.dataset": "ibmmq.errorlog", "event.kind": "event", "event.module": "ibmmq", @@ -1938,7 +1938,7 @@ "user.name": "MUSR_MQADMIN" }, { - "@timestamp": "2018-10-17T13:50:19.000Z", + "@timestamp": "2018-10-17T11:50:19.132Z", "event.dataset": "ibmmq.errorlog", "event.kind": "event", "event.module": "ibmmq", @@ -1972,7 +1972,7 @@ "user.name": "MUSR_MQADMIN" }, { - "@timestamp": "2018-10-17T13:50:19.000Z", + "@timestamp": "2018-10-17T11:50:19.238Z", "event.dataset": "ibmmq.errorlog", "event.kind": "event", "event.module": "ibmmq", @@ -2006,7 +2006,7 @@ "user.name": "MUSR_MQADMIN" }, { - "@timestamp": "2018-10-17T13:50:19.000Z", + "@timestamp": "2018-10-17T11:50:19.269Z", "event.dataset": "ibmmq.errorlog", "event.kind": "event", "event.module": "ibmmq", @@ -2040,7 +2040,7 @@ "user.name": "MUSR_MQADMIN" }, { - "@timestamp": "2018-10-17T13:50:19.000Z", + "@timestamp": "2018-10-17T11:50:19.349Z", "event.dataset": "ibmmq.errorlog", "event.kind": "event", "event.module": "ibmmq", @@ -2074,7 +2074,7 @@ "user.name": "MUSR_MQADMIN" }, { - "@timestamp": "2018-10-17T13:50:19.000Z", + "@timestamp": "2018-10-17T11:50:19.401Z", "event.dataset": "ibmmq.errorlog", "event.kind": "event", "event.module": "ibmmq", @@ -2108,7 +2108,7 @@ "user.name": "MUSR_MQADMIN" }, { - "@timestamp": "2018-10-17T13:50:19.000Z", + "@timestamp": "2018-10-17T11:50:19.638Z", "event.dataset": "ibmmq.errorlog", "event.kind": "event", "event.module": "ibmmq", @@ -2142,7 +2142,7 @@ "user.name": "MUSR_MQADMIN" }, { - "@timestamp": "2018-10-18T15:18:48.000Z", + "@timestamp": "2018-10-18T13:18:48.524Z", "event.dataset": "ibmmq.errorlog", "event.kind": "event", "event.module": "ibmmq", @@ -2176,7 +2176,7 @@ "user.name": "MUSR_MQADMIN" }, { - "@timestamp": "2018-10-18T15:19:11.000Z", + "@timestamp": "2018-10-18T13:19:11.833Z", "event.dataset": "ibmmq.errorlog", "event.kind": "event", "event.module": "ibmmq", @@ -2210,7 +2210,7 @@ "user.name": "MUSR_MQADMIN" }, { - "@timestamp": "2018-10-18T16:10:06.000Z", + "@timestamp": "2018-10-18T14:10:06.407Z", "destination.address": "127.0.0.1", "event.dataset": "ibmmq.errorlog", "event.kind": "event", @@ -2245,7 +2245,7 @@ "user.name": "MUSR_MQADMIN" }, { - "@timestamp": "2018-10-18T16:10:06.000Z", + "@timestamp": "2018-10-18T14:10:06.407Z", "event.dataset": "ibmmq.errorlog", "event.kind": "event", "event.module": "ibmmq", @@ -2279,7 +2279,7 @@ "user.name": "MUSR_MQADMIN" }, { - "@timestamp": "2018-10-18T16:10:12.000Z", + "@timestamp": "2018-10-18T14:10:12.046Z", "destination.address": "127.0.0.1", "event.dataset": "ibmmq.errorlog", "event.kind": "event", @@ -2314,7 +2314,7 @@ "user.name": "MUSR_MQADMIN" }, { - "@timestamp": "2018-10-18T16:10:12.000Z", + "@timestamp": "2018-10-18T14:10:12.046Z", "event.dataset": "ibmmq.errorlog", "event.kind": "event", "event.module": "ibmmq", @@ -2348,7 +2348,7 @@ "user.name": "MUSR_MQADMIN" }, { - "@timestamp": "2018-10-18T16:10:28.000Z", + "@timestamp": "2018-10-18T14:10:28.071Z", "destination.address": "127.0.0.1", "event.dataset": "ibmmq.errorlog", "event.kind": "event", @@ -2383,7 +2383,7 @@ "user.name": "MUSR_MQADMIN" }, { - "@timestamp": "2018-10-18T16:10:28.000Z", + "@timestamp": "2018-10-18T14:10:28.071Z", "event.dataset": "ibmmq.errorlog", "event.kind": "event", "event.module": "ibmmq", @@ -2417,7 +2417,7 @@ "user.name": "MUSR_MQADMIN" }, { - "@timestamp": "2018-10-18T16:13:20.000Z", + "@timestamp": "2018-10-18T14:13:20.545Z", "destination.address": "127.0.0.1", "event.dataset": "ibmmq.errorlog", "event.kind": "event", @@ -2452,7 +2452,7 @@ "user.name": "MUSR_MQADMIN" }, { - "@timestamp": "2018-10-18T16:13:20.000Z", + "@timestamp": "2018-10-18T14:13:20.546Z", "event.dataset": "ibmmq.errorlog", "event.kind": "event", "event.module": "ibmmq", @@ -2486,7 +2486,7 @@ "user.name": "MUSR_MQADMIN" }, { - "@timestamp": "2018-10-18T16:13:46.000Z", + "@timestamp": "2018-10-18T14:13:46.803Z", "event.dataset": "ibmmq.errorlog", "event.kind": "event", "event.module": "ibmmq", @@ -2520,7 +2520,7 @@ "user.name": "MUSR_MQADMIN" }, { - "@timestamp": "2018-10-18T16:13:46.000Z", + "@timestamp": "2018-10-18T14:13:46.821Z", "event.dataset": "ibmmq.errorlog", "event.kind": "event", "event.module": "ibmmq", @@ -2554,7 +2554,7 @@ "user.name": "MUSR_MQADMIN" }, { - "@timestamp": "2018-10-18T16:13:46.000Z", + "@timestamp": "2018-10-18T14:13:46.821Z", "event.dataset": "ibmmq.errorlog", "event.kind": "event", "event.module": "ibmmq", @@ -2588,7 +2588,7 @@ "user.name": "MUSR_MQADMIN" }, { - "@timestamp": "2018-10-18T16:13:46.000Z", + "@timestamp": "2018-10-18T14:13:46.822Z", "event.dataset": "ibmmq.errorlog", "event.kind": "event", "event.module": "ibmmq", @@ -2622,7 +2622,7 @@ "user.name": "MUSR_MQADMIN" }, { - "@timestamp": "2018-10-18T16:13:46.000Z", + "@timestamp": "2018-10-18T14:13:46.824Z", "event.dataset": "ibmmq.errorlog", "event.kind": "event", "event.module": "ibmmq", @@ -2656,7 +2656,7 @@ "user.name": "MUSR_MQADMIN" }, { - "@timestamp": "2018-10-18T16:13:46.000Z", + "@timestamp": "2018-10-18T14:13:46.824Z", "event.dataset": "ibmmq.errorlog", "event.kind": "event", "event.module": "ibmmq", @@ -2690,7 +2690,7 @@ "user.name": "MUSR_MQADMIN" }, { - "@timestamp": "2018-10-18T16:13:46.000Z", + "@timestamp": "2018-10-18T14:13:46.824Z", "event.dataset": "ibmmq.errorlog", "event.kind": "event", "event.module": "ibmmq", @@ -2724,7 +2724,7 @@ "user.name": "MUSR_MQADMIN" }, { - "@timestamp": "2018-10-18T16:13:46.000Z", + "@timestamp": "2018-10-18T14:13:46.824Z", "event.dataset": "ibmmq.errorlog", "event.kind": "event", "event.module": "ibmmq", @@ -2758,7 +2758,7 @@ "user.name": "MUSR_MQADMIN" }, { - "@timestamp": "2018-10-18T16:13:46.000Z", + "@timestamp": "2018-10-18T14:13:46.824Z", "event.dataset": "ibmmq.errorlog", "event.kind": "event", "event.module": "ibmmq", @@ -2792,7 +2792,7 @@ "user.name": "MUSR_MQADMIN" }, { - "@timestamp": "2018-10-18T16:13:46.000Z", + "@timestamp": "2018-10-18T14:13:46.824Z", "event.dataset": "ibmmq.errorlog", "event.kind": "event", "event.module": "ibmmq", @@ -2826,7 +2826,7 @@ "user.name": "MUSR_MQADMIN" }, { - "@timestamp": "2018-10-18T16:13:46.000Z", + "@timestamp": "2018-10-18T14:13:46.824Z", "event.dataset": "ibmmq.errorlog", "event.kind": "event", "event.module": "ibmmq", @@ -2860,7 +2860,7 @@ "user.name": "MUSR_MQADMIN" }, { - "@timestamp": "2018-10-18T16:13:46.000Z", + "@timestamp": "2018-10-18T14:13:46.824Z", "event.dataset": "ibmmq.errorlog", "event.kind": "event", "event.module": "ibmmq", @@ -2894,7 +2894,7 @@ "user.name": "MUSR_MQADMIN" }, { - "@timestamp": "2018-10-18T16:13:46.000Z", + "@timestamp": "2018-10-18T14:13:46.824Z", "event.dataset": "ibmmq.errorlog", "event.kind": "event", "event.module": "ibmmq", @@ -2928,7 +2928,7 @@ "user.name": "MUSR_MQADMIN" }, { - "@timestamp": "2018-10-18T16:13:46.000Z", + "@timestamp": "2018-10-18T14:13:46.823Z", "event.dataset": "ibmmq.errorlog", "event.kind": "event", "event.module": "ibmmq", @@ -2962,7 +2962,7 @@ "user.name": "MUSR_MQADMIN" }, { - "@timestamp": "2018-10-18T16:13:46.000Z", + "@timestamp": "2018-10-18T14:13:46.825Z", "event.dataset": "ibmmq.errorlog", "event.kind": "event", "event.module": "ibmmq", @@ -2996,7 +2996,7 @@ "user.name": "MUSR_MQADMIN" }, { - "@timestamp": "2018-10-18T16:13:46.000Z", + "@timestamp": "2018-10-18T14:13:46.825Z", "event.dataset": "ibmmq.errorlog", "event.kind": "event", "event.module": "ibmmq", @@ -3030,7 +3030,7 @@ "user.name": "MUSR_MQADMIN" }, { - "@timestamp": "2018-10-18T16:13:46.000Z", + "@timestamp": "2018-10-18T14:13:46.825Z", "event.dataset": "ibmmq.errorlog", "event.kind": "event", "event.module": "ibmmq", @@ -3064,7 +3064,7 @@ "user.name": "MUSR_MQADMIN" }, { - "@timestamp": "2018-10-18T16:13:46.000Z", + "@timestamp": "2018-10-18T14:13:46.825Z", "event.dataset": "ibmmq.errorlog", "event.kind": "event", "event.module": "ibmmq", @@ -3098,7 +3098,7 @@ "user.name": "MUSR_MQADMIN" }, { - "@timestamp": "2018-10-18T16:13:46.000Z", + "@timestamp": "2018-10-18T14:13:46.825Z", "event.dataset": "ibmmq.errorlog", "event.kind": "event", "event.module": "ibmmq", @@ -3132,7 +3132,7 @@ "user.name": "MUSR_MQADMIN" }, { - "@timestamp": "2018-10-18T16:13:46.000Z", + "@timestamp": "2018-10-18T14:13:46.825Z", "event.dataset": "ibmmq.errorlog", "event.kind": "event", "event.module": "ibmmq", @@ -3166,7 +3166,7 @@ "user.name": "MUSR_MQADMIN" }, { - "@timestamp": "2018-10-18T16:13:46.000Z", + "@timestamp": "2018-10-18T14:13:46.825Z", "event.dataset": "ibmmq.errorlog", "event.kind": "event", "event.module": "ibmmq", @@ -3200,7 +3200,7 @@ "user.name": "MUSR_MQADMIN" }, { - "@timestamp": "2018-10-18T16:13:46.000Z", + "@timestamp": "2018-10-18T14:13:46.825Z", "event.dataset": "ibmmq.errorlog", "event.kind": "event", "event.module": "ibmmq", @@ -3234,7 +3234,7 @@ "user.name": "MUSR_MQADMIN" }, { - "@timestamp": "2018-10-18T16:13:46.000Z", + "@timestamp": "2018-10-18T14:13:46.825Z", "event.dataset": "ibmmq.errorlog", "event.kind": "event", "event.module": "ibmmq", @@ -3268,7 +3268,7 @@ "user.name": "MUSR_MQADMIN" }, { - "@timestamp": "2018-10-18T16:13:46.000Z", + "@timestamp": "2018-10-18T14:13:46.827Z", "event.dataset": "ibmmq.errorlog", "event.kind": "event", "event.module": "ibmmq", @@ -3301,7 +3301,7 @@ "user.name": "MUSR_MQADMIN" }, { - "@timestamp": "2018-10-18T16:13:46.000Z", + "@timestamp": "2018-10-18T14:13:46.828Z", "event.dataset": "ibmmq.errorlog", "event.kind": "event", "event.module": "ibmmq", @@ -3334,7 +3334,7 @@ "user.name": "MUSR_MQADMIN" }, { - "@timestamp": "2018-10-18T16:13:46.000Z", + "@timestamp": "2018-10-18T14:13:46.829Z", "event.dataset": "ibmmq.errorlog", "event.kind": "event", "event.module": "ibmmq", @@ -3367,7 +3367,7 @@ "user.name": "MUSR_MQADMIN" }, { - "@timestamp": "2018-10-18T16:13:46.000Z", + "@timestamp": "2018-10-18T14:13:46.830Z", "event.dataset": "ibmmq.errorlog", "event.kind": "event", "event.module": "ibmmq", diff --git a/x-pack/filebeat/module/imperva/_meta/docs.asciidoc b/x-pack/filebeat/module/imperva/_meta/docs.asciidoc index 918763f391d..c5b1ab37691 100644 --- a/x-pack/filebeat/module/imperva/_meta/docs.asciidoc +++ b/x-pack/filebeat/module/imperva/_meta/docs.asciidoc @@ -28,7 +28,7 @@ NOTE: This was converted from RSA NetWitness log parser XML "impervawaf" device *`var.input`*:: -The input from which messages are read. One of `file`, `tcp` or `udp`. +The input from which messages are read. One of `file`, `tcp` or `udp`. Defaults to `udp`. *`var.syslog_host`*:: diff --git a/x-pack/filebeat/module/infoblox/_meta/docs.asciidoc b/x-pack/filebeat/module/infoblox/_meta/docs.asciidoc index 286934fa4e4..1be04b5b739 100644 --- a/x-pack/filebeat/module/infoblox/_meta/docs.asciidoc +++ b/x-pack/filebeat/module/infoblox/_meta/docs.asciidoc @@ -28,7 +28,7 @@ NOTE: This was converted from RSA NetWitness log parser XML "infobloxnios" devic *`var.input`*:: -The input from which messages are read. One of `file`, `tcp` or `udp`. +The input from which messages are read. One of `file`, `tcp` or `udp`. Defaults to `udp`. *`var.syslog_host`*:: diff --git a/x-pack/filebeat/module/juniper/_meta/docs.asciidoc b/x-pack/filebeat/module/juniper/_meta/docs.asciidoc index a0e4ab1717f..b42de3eb091 100644 --- a/x-pack/filebeat/module/juniper/_meta/docs.asciidoc +++ b/x-pack/filebeat/module/juniper/_meta/docs.asciidoc @@ -141,7 +141,7 @@ NOTE: This was converted from RSA NetWitness log parser XML "junosrouter" device *`var.input`*:: -The input from which messages are read. One of `file`, `tcp` or `udp`. +The input from which messages are read. One of `file`, `tcp` or `udp`. Defaults to `udp`. *`var.syslog_host`*:: @@ -186,7 +186,7 @@ NOTE: This was converted from RSA NetWitness log parser XML "netscreen" device r *`var.input`*:: -The input from which messages are read. One of `file`, `tcp` or `udp`. +The input from which messages are read. One of `file`, `tcp` or `udp`. Defaults to `udp`. *`var.syslog_host`*:: diff --git a/x-pack/filebeat/module/microsoft/_meta/docs.asciidoc b/x-pack/filebeat/module/microsoft/_meta/docs.asciidoc index 577c87f6cc3..13ea8f43bdc 100644 --- a/x-pack/filebeat/module/microsoft/_meta/docs.asciidoc +++ b/x-pack/filebeat/module/microsoft/_meta/docs.asciidoc @@ -219,7 +219,7 @@ include::../include/var-paths.asciidoc[] *`var.input`*:: -The input from which messages are read. One of `file`, `tcp` or `udp`. +The input from which messages are read. One of `file`, `tcp` or `udp`. Defaults to `udp`. *`var.syslog_host`*:: diff --git a/x-pack/filebeat/module/netscout/_meta/docs.asciidoc b/x-pack/filebeat/module/netscout/_meta/docs.asciidoc index 3d0477a9f43..463c93b5c0f 100644 --- a/x-pack/filebeat/module/netscout/_meta/docs.asciidoc +++ b/x-pack/filebeat/module/netscout/_meta/docs.asciidoc @@ -26,7 +26,7 @@ NOTE: This was converted from RSA NetWitness log parser XML "arborpeakflowsp" de *`var.input`*:: -The input from which messages are read. One of `file`, `tcp` or `udp`. +The input from which messages are read. One of `file`, `tcp` or `udp`. Defaults to `udp`. *`var.syslog_host`*:: diff --git a/x-pack/filebeat/module/panw/panos/ingest/globalprotect.yml b/x-pack/filebeat/module/panw/panos/ingest/globalprotect.yml index 66edbd302f2..e1c760d27a4 100644 --- a/x-pack/filebeat/module/panw/panos/ingest/globalprotect.yml +++ b/x-pack/filebeat/module/panw/panos/ingest/globalprotect.yml @@ -4,11 +4,11 @@ processors: - set: field: source.ip value: "{{_temp_.private_ipv6}}" - if: ctx?._temp_?.private_ipv6 != "" && ctx?._temp_?.private_ipv6 != "0.0.0.0" + if: (ctx.source?.ip == null || ctx.source?.ip == "0.0.0.0") && ctx._temp_?.private_ipv6 != null && ctx._temp_?.private_ipv6 != "0.0.0.0" - set: field: source.nat.ip value: "{{_temp_.public_ipv6}}" - if: ctx?._temp_?.public_ipv6 != "" && ctx?._temp_?.public_ipv6 != "0.0.0.0" + if: (ctx.source?.nat?.ip == null || ctx.source?.nat?.ip == "0.0.0.0") && ctx._temp_?.public_ipv6 != null && ctx._temp_?.public_ipv6 != "0.0.0.0" - grok: field: _temp_.srcuser ignore_missing: true @@ -20,11 +20,11 @@ processors: - set: field: network.type value: 'ipv4' - if: 'ctx?.network?.type == null && ctx?.source?.ip.contains(".")' + if: 'ctx.network?.type == null && ctx.source?.ip != null && ctx.source.ip.contains(".")' - set: field: network.type value: 'ipv6' - if: 'ctx?.network?.type == null && ctx?.source?.ip.contains(":")' + if: 'ctx.network?.type == null && ctx.source?.ip != null && ctx.source.ip.contains(":")' on_failure: - append: diff --git a/x-pack/filebeat/module/panw/panos/test/global_protect.log b/x-pack/filebeat/module/panw/panos/test/global_protect.log index 08918ad4946..23b982e2a09 100644 --- a/x-pack/filebeat/module/panw/panos/test/global_protect.log +++ b/x-pack/filebeat/module/panw/panos/test/global_protect.log @@ -3,8 +3,10 @@ 1,2021/04/07 17:41:30,013101305,GLOBALPROTECT,0,2305,2021/04/07 17:41:30,vsys1,gateway-hip-check,host-info,,,domain\user1,,HOST82878,7.2.2.193,0.0.0.0,67.43.156.14,0.0.0.0,523e8b-7efa-4397-a4d5-824dfa4d8a,F1SM2,5.2.4,,"",1,,,"HIP report is not needed",success,,0,,0,GlobalProtect_GW,6920071768563516860,0x0 1,2021/04/07 17:41:29,013101308,GLOBALPROTECT,0,2305,2021/04/07 17:41:29,vsys1,gateway-getconfig,configuration,,IPSec,pre-logon,BE,HOST73486,7.2.2.171,0.0.0.0,81.2.69.193,0.0.0.0,7d01b5-f538-4fa3-a2a2-83980d1325,5C261FNR,5.2.4,Windows,"Microsoft Windows 10 Pro , 64-bit",1,,,"Config name: , Client region: BE.",success,,0,,0,GlobalProtect_GW,6944137135219737,0x0 1,2021/04/07 17:41:28,0131001309,GLOBALPROTECT,0,2305,2021/04/07 17:41:28,vsys1,gateway-tunnel-latency,tunnel,,,,userlterso,HOSTP92413,7.2.17.120,0.0.0.0,0.0.0.0,0.0.0.0,2ba9f01-b83b-4902-a1fb-1748c0365,GJG98Y2,5.2.4,,"",1,,,"Pre-tunnel latency: 67ms, Post-tunnel latency: 47ms",success,,0,,0,GlobalProtect_GW,6920071768563516847,0x0 - 1,2021/03/02 09:55:42,12345678999,GLOBALPROTECT,0,2305,2021/03/02 09:55:39,vsys1,gateway-auth,login,Other,,maxmustermann,10.0.0.0-10.255.255.255,PC1234,10.20.30.40,0.0.0.0,0.0.0.0,0.0.0.0,985e865f-7da3-43b4-89a9-299b1bb0c975,SERIALNR,5.1.1,Windows,"Microsoft Windows 10 Enterprise, 64-bit",1,,,,success,,0,pre-logon,0,GP GW intern,6894571632887748064,0x8000000000000000,1970-01-01T01:00:00.000+01:00,,0,manual only,, 1,2021/03/02 11:01:03,123456789999,GLOBALPROTECT,0,2305,2021/03/02 11:01:02,vsys1,gateway-setup-ipsec,tunnel,,IPSec,domain\musterman,DE,Rechner67.43.156.12.123,0.0.0.0,10.20.30.40,0.0.0.0,96c43d47-8bb5-4f78-8dfc-413a189a29e0,SERIALNR,5.1.1,Windows,"Microsoft Windows 10 Enterprise, 64-bit",1,,,,success,,0,,0,GPGateway,6894571632887761989,0x8000000000000000,1970-01-01T01:00:00.000+01:00,,0,manual only,, 1,2021/03/02 09:39:33,12345678999,GLOBALPROTECT,0,2305,2021/03/02 09:39:26,vsys1,portal-prelogin,before-login,,,Max.Mustermann@domain.de,10.0.0.0-10.255.255.255,,10.20.30.40,0.0.0.0,0.0.0.0,0.0.0.0,0183d851-7ea2-4a0d-80de-fde1e04ce12f,,5.1.1,Windows,"Microsoft Windows 10 Enterprise, 64-bit",1,,,,success,,0,,0,GP Portal,6894571632887745099,0x8000000000000000,1970-01-01T01:00:00.000+01:00,,0,manual only,, 1,2021/03/02 09:47:18,12345678999,GLOBALPROTECT,0,2305,2021/03/02 09:47:13,vsys1,portal-getconfig,configuration,,,domain\maxmustermann,10.0.0.0-10.255.255.255,PC12345,10.20.30.40,0.0.0.0,0.0.0.0,0.0.0.0,8cbc136b-e262-4cf8-912c-95ea132d9fef,SERIENNR,5.1.1,Windows,"Microsoft Windows 10 Enterprise, 64-bit",1,,,"Config name: GP Clients, Machine Certificate CN : (null)",success,,0,pre-logon,0,GP Portal,6894571632887746544,0x8000000000000000,1970-01-01T01:00:00.000+01:00,,0,manual only,, +931201168,2021-10-22T16:10:10.000000Z,no-serial,GLOBALPROTECT,globalprotect,9.1,2021-10-22T16:10:05.000000Z,vsys1,gateway-hip-check,host-info,,,host\\user,,HOSTNAME,10.1.1.1,,10.2.2.2,fc00::1,8cbc136b-e262-4cf8-912c-95ea132d9fef,SERIALNR,5.2.6,,,1,,,HIP report is not needed,success,,0,,0,GlobalProtect_External_Gateway,1305925,true +931201168,2021-11-09T21:45:36.000000Z,no-serial,GLOBALPROTECT,globalprotect,9.1,2021-11-09T21:45:14.000000Z,vsys1,gateway-tunnel-latency,tunnel,,,user,,HOSTNAME,10.3.3.3,,10.4.4.4,,8cbc136b-e262-4cf8-912c-95ea132d9fef,SERIALNR,5.2.8,,,1,,,"Pre-tunnel latency: 35ms, Post-tunnel latency: 16ms",success,,0,,0,GlobalProtect_External_Gateway,1041590,true +931201168,2021-11-09T21:45:36.000000Z,no-serial,GLOBALPROTECT,globalprotect,9.1,2021-11-09T21:45:14.000000Z,vsys1,gateway-tunnel-latency,tunnel,,,user,,HOSTNAME,,fc00::1234,,fc00::abcd,8cbc136b-e262-4cf8-912c-95ea132d9fef,SERIALNR,5.2.8,,,1,,,"Pre-tunnel latency: 35ms, Post-tunnel latency: 16ms",success,,0,,0,GlobalProtect_External_Gateway,1041590,true diff --git a/x-pack/filebeat/module/panw/panos/test/global_protect.log-expected.json b/x-pack/filebeat/module/panw/panos/test/global_protect.log-expected.json index ac3648ccc19..39f636866ba 100644 --- a/x-pack/filebeat/module/panw/panos/test/global_protect.log-expected.json +++ b/x-pack/filebeat/module/panw/panos/test/global_protect.log-expected.json @@ -322,7 +322,7 @@ "host.os.family": "Windows", "host.os.full": "Microsoft Windows 10 Enterprise, 64-bit", "input.type": "log", - "log.offset": 1645, + "log.offset": 1644, "network.type": "ipv4", "observer.hostname": "GP GW intern", "observer.product": "PAN-OS", @@ -385,7 +385,7 @@ "host.os.family": "Windows", "host.os.full": "Microsoft Windows 10 Enterprise, 64-bit", "input.type": "log", - "log.offset": 2467, + "log.offset": 2466, "network.type": "ipv4", "observer.hostname": "GP Portal", "observer.product": "PAN-OS", @@ -447,7 +447,7 @@ "host.os.family": "Windows", "host.os.full": "Microsoft Windows 10 Enterprise, 64-bit", "input.type": "log", - "log.offset": 2874, + "log.offset": 2873, "network.type": "ipv4", "observer.hostname": "GP Portal", "observer.product": "PAN-OS", @@ -493,5 +493,173 @@ ], "user.domain": "domain", "user.name": "maxmustermann" + }, + { + "@timestamp": "2021-10-22T14:10:05.000-02:00", + "client.address": "10.2.2.2", + "client.ip": "10.2.2.2", + "client.nat.ip": "10.1.1.1", + "event.code": "gateway-hip-check", + "event.dataset": "panw.panos", + "event.duration": 0, + "event.module": "panw", + "event.original": "931201168,2021-10-22T16:10:10.000000Z,no-serial,GLOBALPROTECT,globalprotect,9.1,2021-10-22T16:10:05.000000Z,vsys1,gateway-hip-check,host-info,,,host\\\\user,,HOSTNAME,10.1.1.1,,10.2.2.2,fc00::1,8cbc136b-e262-4cf8-912c-95ea132d9fef,SERIALNR,5.2.6,,,1,,,HIP report is not needed,success,,0,,0,GlobalProtect_External_Gateway,1305925,true", + "event.outcome": "success", + "event.timezone": "-02:00", + "fileset.name": "panos", + "host.id": "8cbc136b-e262-4cf8-912c-95ea132d9fef", + "host.ip": "10.2.2.2", + "host.name": "HOSTNAME", + "input.type": "log", + "log.offset": 3360, + "network.type": "ipv4", + "observer.hostname": "GlobalProtect_External_Gateway", + "observer.product": "PAN-OS", + "observer.serial_number": "no-serial", + "observer.type": "firewall", + "observer.vendor": "Palo Alto Networks", + "panw.panos.actionflags": "true", + "panw.panos.client_ver": "5.2.6", + "panw.panos.description": "HIP report is not needed", + "panw.panos.error_code": "0", + "panw.panos.repeatcnt": 1, + "panw.panos.sequence_number": 1305925, + "panw.panos.serial_number": "SERIALNR", + "panw.panos.source.nat.ip": "10.1.1.1", + "panw.panos.stage": "host-info", + "panw.panos.sub_type": "globalprotect", + "panw.panos.type": "GLOBALPROTECT", + "panw.panos.virtual_sys": "vsys1", + "related.hosts": [ + "GlobalProtect_External_Gateway", + "HOSTNAME" + ], + "related.ip": [ + "10.1.1.1", + "10.2.2.2" + ], + "related.user": [ + "host" + ], + "service.type": "panw", + "source.address": "10.2.2.2", + "source.ip": "10.2.2.2", + "source.nat.ip": "10.1.1.1", + "source.user.name": "host", + "tags": [ + "forwarded", + "pan-os" + ], + "user.name": "host" + }, + { + "@timestamp": "2021-11-09T19:45:14.000-02:00", + "client.address": "10.4.4.4", + "client.ip": "10.4.4.4", + "client.nat.ip": "10.3.3.3", + "event.code": "gateway-tunnel-latency", + "event.dataset": "panw.panos", + "event.duration": 0, + "event.module": "panw", + "event.original": "931201168,2021-11-09T21:45:36.000000Z,no-serial,GLOBALPROTECT,globalprotect,9.1,2021-11-09T21:45:14.000000Z,vsys1,gateway-tunnel-latency,tunnel,,,user,,HOSTNAME,10.3.3.3,,10.4.4.4,,8cbc136b-e262-4cf8-912c-95ea132d9fef,SERIALNR,5.2.8,,,1,,,\"Pre-tunnel latency: 35ms, Post-tunnel latency: 16ms\",success,,0,,0,GlobalProtect_External_Gateway,1041590,true", + "event.outcome": "success", + "event.timezone": "-02:00", + "fileset.name": "panos", + "host.id": "8cbc136b-e262-4cf8-912c-95ea132d9fef", + "host.ip": "10.4.4.4", + "host.name": "HOSTNAME", + "input.type": "log", + "log.offset": 3693, + "network.type": "ipv4", + "observer.hostname": "GlobalProtect_External_Gateway", + "observer.product": "PAN-OS", + "observer.serial_number": "no-serial", + "observer.type": "firewall", + "observer.vendor": "Palo Alto Networks", + "panw.panos.actionflags": "true", + "panw.panos.client_ver": "5.2.8", + "panw.panos.description": "Pre-tunnel latency: 35ms, Post-tunnel latency: 16ms", + "panw.panos.error_code": "0", + "panw.panos.repeatcnt": 1, + "panw.panos.sequence_number": 1041590, + "panw.panos.serial_number": "SERIALNR", + "panw.panos.source.nat.ip": "10.3.3.3", + "panw.panos.stage": "tunnel", + "panw.panos.sub_type": "globalprotect", + "panw.panos.type": "GLOBALPROTECT", + "panw.panos.virtual_sys": "vsys1", + "related.hosts": [ + "GlobalProtect_External_Gateway", + "HOSTNAME" + ], + "related.ip": [ + "10.3.3.3", + "10.4.4.4" + ], + "related.user": [ + "user" + ], + "service.type": "panw", + "source.address": "10.4.4.4", + "source.ip": "10.4.4.4", + "source.nat.ip": "10.3.3.3", + "source.user.name": "user", + "tags": [ + "forwarded", + "pan-os" + ], + "user.name": "user" + }, + { + "@timestamp": "2021-11-09T19:45:14.000-02:00", + "event.code": "gateway-tunnel-latency", + "event.dataset": "panw.panos", + "event.duration": 0, + "event.module": "panw", + "event.original": "931201168,2021-11-09T21:45:36.000000Z,no-serial,GLOBALPROTECT,globalprotect,9.1,2021-11-09T21:45:14.000000Z,vsys1,gateway-tunnel-latency,tunnel,,,user,,HOSTNAME,,fc00::1234,,fc00::abcd,8cbc136b-e262-4cf8-912c-95ea132d9fef,SERIALNR,5.2.8,,,1,,,\"Pre-tunnel latency: 35ms, Post-tunnel latency: 16ms\",success,,0,,0,GlobalProtect_External_Gateway,1041590,true", + "event.outcome": "success", + "event.timezone": "-02:00", + "fileset.name": "panos", + "host.id": "8cbc136b-e262-4cf8-912c-95ea132d9fef", + "host.name": "HOSTNAME", + "input.type": "log", + "log.offset": 4044, + "network.type": "ipv6", + "observer.hostname": "GlobalProtect_External_Gateway", + "observer.product": "PAN-OS", + "observer.serial_number": "no-serial", + "observer.type": "firewall", + "observer.vendor": "Palo Alto Networks", + "panw.panos.actionflags": "true", + "panw.panos.client_ver": "5.2.8", + "panw.panos.description": "Pre-tunnel latency: 35ms, Post-tunnel latency: 16ms", + "panw.panos.error_code": "0", + "panw.panos.repeatcnt": 1, + "panw.panos.sequence_number": 1041590, + "panw.panos.serial_number": "SERIALNR", + "panw.panos.stage": "tunnel", + "panw.panos.sub_type": "globalprotect", + "panw.panos.type": "GLOBALPROTECT", + "panw.panos.virtual_sys": "vsys1", + "related.hosts": [ + "GlobalProtect_External_Gateway", + "HOSTNAME" + ], + "related.ip": [ + "fc00::1234", + "fc00::abcd" + ], + "related.user": [ + "user" + ], + "service.type": "panw", + "source.ip": "fc00::abcd", + "source.nat.ip": "fc00::1234", + "source.user.name": "user", + "tags": [ + "forwarded", + "pan-os" + ], + "user.name": "user" } ] \ No newline at end of file diff --git a/x-pack/filebeat/module/panw/panos/test/traffic_nanos_time.log-expected.json b/x-pack/filebeat/module/panw/panos/test/traffic_nanos_time.log-expected.json index 72ffebe6db7..052e1862756 100644 --- a/x-pack/filebeat/module/panw/panos/test/traffic_nanos_time.log-expected.json +++ b/x-pack/filebeat/module/panw/panos/test/traffic_nanos_time.log-expected.json @@ -1,6 +1,6 @@ [ { - "@timestamp": "2021-05-26T16:26:47.000Z", + "@timestamp": "2021-05-26T14:26:47.000-02:00", "client.bytes": 1696, "client.ip": "127.0.0.0", "client.nat.ip": "0.0.0.0", @@ -21,12 +21,12 @@ ], "event.dataset": "panw.panos", "event.duration": 1000000000, - "event.end": "2021-05-26T16:26:31.000Z", + "event.end": "2021-05-26T14:26:31.000-02:00", "event.kind": "event", "event.module": "panw", "event.original": "Oct 30 09:46:42 1,2021-05-26T16:27:07.000000Z,no-serial,TRAFFIC,end,9.1,2021-05-26T16:26:47.000000Z,127.0.0.0,127.0.0.1,0.0.0.0,0.0.0.0,intrazone-default,,,web-browsing,vsys1,untrust,untrust,ethernet1/1,ethernet1/1,Cortex Data Lake,,688290,1,35834,443,35834,20077,0x1400070,tcp,allow,7291,1696,5595,21,2021-05-26T16:26:30.000000Z,1,medium-risk,,620386,0x8800000000000000,US,SG,,14,7,tcp-fin,22,18,0,0,,GP cloud service,from-policy,,,0,,0,1970-01-01T00:00:00.000000Z,N/A,0,0,0,0,6a2f6161-88f2-4afc-8dd5-256bc4505a64,0,0,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", "event.outcome": "success", - "event.start": "2021-05-26T16:26:30.000Z", + "event.start": "2021-05-26T14:26:30.000-02:00", "event.timezone": "-02:00", "event.type": [ "allowed", diff --git a/x-pack/filebeat/module/proofpoint/_meta/docs.asciidoc b/x-pack/filebeat/module/proofpoint/_meta/docs.asciidoc index b0accc04273..21a768ab432 100644 --- a/x-pack/filebeat/module/proofpoint/_meta/docs.asciidoc +++ b/x-pack/filebeat/module/proofpoint/_meta/docs.asciidoc @@ -28,7 +28,7 @@ NOTE: This was converted from RSA NetWitness log parser XML "proofpoint" device *`var.input`*:: -The input from which messages are read. One of `file`, `tcp` or `udp`. +The input from which messages are read. One of `file`, `tcp` or `udp`. Defaults to `udp`. *`var.syslog_host`*:: diff --git a/x-pack/filebeat/module/radware/_meta/docs.asciidoc b/x-pack/filebeat/module/radware/_meta/docs.asciidoc index 3e0a992b51f..ba9bc87444c 100644 --- a/x-pack/filebeat/module/radware/_meta/docs.asciidoc +++ b/x-pack/filebeat/module/radware/_meta/docs.asciidoc @@ -28,7 +28,7 @@ NOTE: This was converted from RSA NetWitness log parser XML "radwaredp" device r *`var.input`*:: -The input from which messages are read. One of `file`, `tcp` or `udp`. +The input from which messages are read. One of `file`, `tcp` or `udp`. Defaults to `udp`. *`var.syslog_host`*:: diff --git a/x-pack/filebeat/module/snort/_meta/docs.asciidoc b/x-pack/filebeat/module/snort/_meta/docs.asciidoc index f2ae38f0043..47c1c430934 100644 --- a/x-pack/filebeat/module/snort/_meta/docs.asciidoc +++ b/x-pack/filebeat/module/snort/_meta/docs.asciidoc @@ -26,7 +26,7 @@ NOTE: This was converted from RSA NetWitness log parser XML "snort" device revis *`var.input`*:: -The input from which messages are read. One of `file`, `tcp` or `udp`. +The input from which messages are read. One of `file`, `tcp` or `udp`. Defaults to `udp`. *`var.syslog_host`*:: diff --git a/x-pack/filebeat/module/snyk/audit/config/config.yml b/x-pack/filebeat/module/snyk/audit/config/config.yml index 7476d4dd1cf..4932c7133a1 100644 --- a/x-pack/filebeat/module/snyk/audit/config/config.yml +++ b/x-pack/filebeat/module/snyk/audit/config/config.yml @@ -67,13 +67,6 @@ processors: - fingerprint: fields: ["json.orgId", "json.created", "json.event"] target_field: "@metadata._id" - - script: - lang: javascript - id: my_filter - source: > - function process(event) { - event.Put("@metadata.op_type", "index"); - } - add_fields: target: '' fields: diff --git a/x-pack/filebeat/module/snyk/vulnerabilities/config/config.yml b/x-pack/filebeat/module/snyk/vulnerabilities/config/config.yml index a78cc297493..31819689716 100644 --- a/x-pack/filebeat/module/snyk/vulnerabilities/config/config.yml +++ b/x-pack/filebeat/module/snyk/vulnerabilities/config/config.yml @@ -90,13 +90,6 @@ processors: - fingerprint: fields: ["json.issue.id"] target_field: "@metadata._id" - - script: - lang: javascript - id: my_filter - source: > - function process(event) { - event.Put("@metadata.op_type", "index"); - } - add_fields: target: '' fields: diff --git a/x-pack/filebeat/module/sonicwall/_meta/docs.asciidoc b/x-pack/filebeat/module/sonicwall/_meta/docs.asciidoc index 904e7f6d19c..595b2a31acb 100644 --- a/x-pack/filebeat/module/sonicwall/_meta/docs.asciidoc +++ b/x-pack/filebeat/module/sonicwall/_meta/docs.asciidoc @@ -28,7 +28,7 @@ NOTE: This was converted from RSA NetWitness log parser XML "sonicwall" device r *`var.input`*:: -The input from which messages are read. One of `file`, `tcp` or `udp`. +The input from which messages are read. One of `file`, `tcp` or `udp`. Defaults to `udp`. *`var.syslog_host`*:: diff --git a/x-pack/filebeat/module/sophos/_meta/docs.asciidoc b/x-pack/filebeat/module/sophos/_meta/docs.asciidoc index 41e86a0d1a4..6d6147984a1 100644 --- a/x-pack/filebeat/module/sophos/_meta/docs.asciidoc +++ b/x-pack/filebeat/module/sophos/_meta/docs.asciidoc @@ -151,7 +151,7 @@ NOTE: This was converted from RSA NetWitness log parser XML "astarosg" device re *`var.input`*:: -The input from which messages are read. One of `file`, `tcp` or `udp`. +The input from which messages are read. One of `file`, `tcp` or `udp`. Defaults to `udp`. *`var.syslog_host`*:: diff --git a/x-pack/filebeat/module/sophos/fields.go b/x-pack/filebeat/module/sophos/fields.go index aa22bfaf89b..b784d8fbff3 100644 --- a/x-pack/filebeat/module/sophos/fields.go +++ b/x-pack/filebeat/module/sophos/fields.go @@ -19,5 +19,5 @@ func init() { // AssetSophos returns asset data. // This is the base64 encoded zlib format compressed contents of module/sophos. func AssetSophos() string { - return "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" + return "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" } diff --git a/x-pack/filebeat/module/sophos/utm/test/generated.log-expected.json b/x-pack/filebeat/module/sophos/utm/test/generated.log-expected.json index a50b3668596..efb44a7b666 100644 --- a/x-pack/filebeat/module/sophos/utm/test/generated.log-expected.json +++ b/x-pack/filebeat/module/sophos/utm/test/generated.log-expected.json @@ -3701,4 +3701,4 @@ "sophos.utm" ] } -] +] \ No newline at end of file diff --git a/x-pack/filebeat/module/sophos/xg/_meta/fields.yml b/x-pack/filebeat/module/sophos/xg/_meta/fields.yml index 47c90ce9967..d5716542bfa 100644 --- a/x-pack/filebeat/module/sophos/xg/_meta/fields.yml +++ b/x-pack/filebeat/module/sophos/xg/_meta/fields.yml @@ -943,3 +943,8 @@ type: keyword description: > The related XSS caught by the WAF + + - name: ether_type + type: keyword + description: > + The ethernet frame type diff --git a/x-pack/filebeat/module/sophos/xg/ingest/pipeline.yml b/x-pack/filebeat/module/sophos/xg/ingest/pipeline.yml index 3e1a5f518c2..2db7a8ad849 100644 --- a/x-pack/filebeat/module/sophos/xg/ingest/pipeline.yml +++ b/x-pack/filebeat/module/sophos/xg/ingest/pipeline.yml @@ -6,7 +6,7 @@ processors: - grok: field: message patterns: - - '%{SYSLOG5424PRI}%{GREEDYDATA:log.original}$' + - '%{SYSLOG5424PRI}(%{SYSLOGTIMESTAMP} %{NOTSPACE} )?%{GREEDYDATA:log.original}$' # optimize fields / strings in log.original for KV processor - gsub: @@ -17,7 +17,7 @@ processors: # split Sophos-XG fields - kv: field: log.original - field_split: " (?=[a-zA-Z0-9\\_\\-]+=)" + field_split: " (?=[a-zA-Z0-9_]+=)" value_split: "=" prefix: "sophos.xg." ignore_missing: true @@ -248,6 +248,10 @@ processors: - sophos.xg.dir_disp - sophos.xg.srczone - sophos.xg.dstzone + - sophos.xg.log_occurrence + - sophos.xg.nat_rule_id + - sophos.xg.in_display_interface + - sophos.xg.out_display_interface - syslog5424_pri ignore_missing: true diff --git a/x-pack/filebeat/module/sophos/xg/test/anti-spam.log b/x-pack/filebeat/module/sophos/xg/test/anti-spam.log index 5480251c504..f16aee76434 100644 --- a/x-pack/filebeat/module/sophos/xg/test/anti-spam.log +++ b/x-pack/filebeat/module/sophos/xg/test/anti-spam.log @@ -1,11 +1,11 @@ -<30>device="SFW" date=2020-05-18 time=14:38:48 timezone="CEST" device_name="XG230" device_id=1234567890123456 log_id=041101618035 log_type="Anti-Spam" log_component="SMTP" log_subtype="Allowed" status="" priority=Information fw_rule_id=0 user_name="" av_policy_name="None" from_email_address="firewall@firewallgate.com" to_email_address="Sysadmin@elasticuser.com" email_subject="*ALERT* Sophos XG Firewall" mailid="qkW2Y6-LxBk6U-vH-1590055245" mailsize=19728 spamaction="QUEUED" reason="Email has been accepted by Device and queued for scanning." src_domainname="elasticuser.com" dst_domainname="" src_ip="" src_country_code="" dst_ip="" dst_country_code="" protocol="TCP" src_port=0 dst_port=0 sent_bytes=0 recv_bytes=0 quarantine_reason="Other" -<30>device="SFW" date=2020-05-18 time=14:38:49 timezone="CEST" device_name="XG230" device_id=1234567890123457 log_id=041105613003 log_type="Anti-Spam" log_component="SMTP" log_subtype="Clean" status="" priority=Information fw_rule_id=22 user_name="" av_policy_name="Default" from_email_address="telekommunikation@constant-big.email" to_email_address="info@pelasticuser.com" email_subject="Telefonservice statt Anrufbeantworter" mailid="device="SFW" date=2020-05-18 time=14:38:50 timezone="CEST" device_name="XG230" device_id=1234567890123456 log_id=041107413001 log_type="Anti-Spam" log_component="SMTP" log_subtype="Spam" status="" priority=Warning fw_rule_id=22 user_name="" av_policy_name="Spam" from_email_address="ripxfc@17buddies.net" to_email_address="hein.mueck@elasticuser.de" email_subject="nimm dringend Geld" mailid="device="SFW" date=2020-05-18 time=14:38:51 timezone="CEST" device_name="XG230" device_id=1234567890123457 log_id=045908413004 log_type="Anti-Spam" log_component="SMTPS" log_subtype="Probable Spam" status="" priority=Warning fw_rule_id=22 user_name="" av_policy_name="rule3" from_email_address="SHERIF.TOBGI@ELTOBGI.COM" to_email_address="info@elasticuser.com" email_subject="09F1A19017 - 65T BP LNG Hybrid - TS-V-061-01 - HVAC Package - RFQ - BCD - 27-May-20" mailid="<20200518070235.C1623996C64F9957@ELTOBGI.COM>" mailsize=1032152 spamaction="Prefix Subject" reason="Sender IP address is blacklisted." src_domainname="ELTOBGI.COM" dst_domainname="" src_ip=67.43.156.14 src_country_code=GBR dst_ip=185.8.209.194 dst_country_code=DEU protocol="TCP" src_port=55002 dst_port=25 sent_bytes=0 recv_bytes=0 quarantine_reason="RBL" -<30>device="SFW" date=2017-01-31 time=18:34:41 timezone="IST" device_name="CR750iNG-XP" device_id=C44313350024-P29PUA log_id=041113413005 log_type="Anti-Spam" log_component="SMTP" log_subtype="Outbound Spam" status="" priority=Warning fw_rule_id=0 user_name="gaurav" av_policy_name="Gaurav123" from_email_address="gaurav1@iview.com" to_email_address=" gaurav2@iview.com" email_subject="RPD Spam Test: Spam" mailid="" mailsize=405 spamaction="Accept" reason="" src_domainname=" iview.com" dst_domainname="" src_ip=10.198.47.71 src_country_code=R1 dst_ip=10.198.233.61 dst_country_code=R1 protocol="TCP" src_port=22420 dst_port=25 sent_bytes=0 recv_bytes=0 quarantine_reason="Spam" -<30>device="SFW" date=2018-06-06 time=11:10:11 timezone="IST" device_name="SG430" device_id=S4000806149EE49 log_id=041114413006 log_type="Anti-Spam" log_component="SMTP" log_subtype="Outbound Probable Spam" status="" priority=Warning fw_rule_id=0 user_name="" av_policy_name="rule 8" from_email_address="pankhil@postman.local" to_email_address="pankhil1@Postman.local" email_subject="RPD Spam test: Bulk" mailid="" mailsize=439 spamaction="Drop" reason="Mail detected as OUTBOUND PROBABLE SPAM." src_domainname="postman.local" dst_domainname="" src_ip=10.198.16.121 src_country_code=R1 dst_ip=10.198.234.240 dst_country_code=R1 protocol="TCP" src_port=58043 dst_port=25 sent_bytes=0 recv_bytes=0 quarantine_reason="Spam" -<30>device="SFW" date=2018-06-06 time=12:50:07 timezone="IST" device_name="SG430" device_id=S4000806149EE49 log_id=041121613009 log_type="Anti-Spam" log_component="SMTP" log_subtype="DLP" status="" priority=Information fw_rule_id=0 user_name="" av_policy_name="postman" from_email_address="pankhil@postman.local" to_email_address="pankhil1@Postman. local" email_subject="Fwd: TESt" mailid="c0000002-1528269606" mailsize=5041 spamaction="DROP" reason="Email containing confidential data detected. Relevant Data Protection Policy applied." src_domainname="postman.local" dst_domainname="" src_ip=10.198.16.121 src_country_code=R1 dst_ip=10.198.17.121 dst_country_code=R1 protocol="TCP" src_port=60134 dst_port=25 sent_bytes=0 recv_bytes=0 quarantine_reason="DLP" -<30>device="SFW" date=2018-06-06 time=12:51:34 timezone="IST" device_name="SG430" device_id=S4000806149EE49 log_id=041122613010 log_type="Anti-Spam" log_component="SMTP" log_subtype="SPX" status="" priority=Information fw_rule_id=0 user_name="" av_policy_name="None" from_email_address="pankhil@postman.local" to_email_address="pankhil1@Postman.local" email_subject="[secure:pankhil]" mailid="c0000003-1528269693" mailsize=442 spamaction="Accept" reason="SPX Template of type Specified by Sender successfully applied on Email." src_domainname="postman.local" dst_domainname="" src_ip=10.198.16.121 src_country_code=R1 dst_ip=10.198.16.204 dst_country_code=R1 protocol="TCP" src_port=60298 dst_port=25 sent_bytes=0 recv_bytes=0 quarantine_reason="Other" -<30>device="SFW" date=2018-06-06 time=12:53:39 timezone="IST" device_name="SG430" device_id=S4000806149EE49 log_id=041123413012 log_type="Anti-Spam" log_component="SMTP" log_subtype="Dos" status="" priority=Warning fw_rule_id=0 user_name="" av_policy_name="None" from_email_address="" to_email_address="" email_subject="" mailid="" mailsize=0 spamaction="TMPREJECT" reason="SMTP DoS" src_domainname="" dst_domainname="" src_ip=10.198.16.121 src_country_code=R1 dst_ip=10.198.17.121 dst_country_code=R1 protocol="TCP" src_port=60392 dst_port=25 sent_bytes=0 recv_bytes=0 quarantine_reason="Other" -<30>device="SFW" date=2018-06-06 time=12:56:53 timezone="IST" device_name="SG430" device_id=S4000806149EE49 log_id=041102413014 log_type="Anti-Spam" log_component="SMTP" log_subtype="Denied" status="" priority=Warning fw_rule_id=0 user_name="" av_policy_name="postman" from_email_address="pankhil1@postman.local" to_email_address="pankhil@postman. local" email_subject="Fwd: test sand" mailid="c0000008-1528270010" mailsize=419835 spamaction="DROP" reason="Email is marked Malicious by Sophos Sandstorm." src_domainname="postman.local" dst_domainname="" src_ip=10.198.16.121 src_country_code=R1 dst_ip=10.198.17.121 dst_country_code=R1 protocol="TCP" src_port=60608 dst_port=25 sent_bytes=0 recv_bytes=0 -<30>device="SFW" date=2017-01-31 time=18:31:11 timezone="IST" device_name="CR750iNG-XP" device_id=C44313350024-P29PUA log_id=041207414001 log_type="Anti-Spam" log_component="POP3" log_subtype="Spam" status="" priority=Warning fw_rule_id=0 user_name="gaurav" av_policy_name="GauravPatel" from_email_address="gaurav1@iview.com" to_email_address="gaurav2@iview. com" email_subject="RPD Spam Test: Spam" mailid="<2a2dd5d4-1a30-617b-27b1-7961ad07cf07@iview.com>" mailsize=574 spamaction="Accept" reason="" src_domainname=" iview.com" dst_domainname="iview.com" src_ip=10.198.47.71 src_country_code=R1 dst_ip=10.198.233.61 dst_country_code=R1 protocol="TCP" src_port=22333 dst_port=110 sent_bytes=0 recv_bytes=0 quarantine_reason="Other" +<30>device="SFW" date=2020-05-18 time=14:38:48 timezone="CEST" device_name="XG230" device_id=1234567890123456 log_id=041101618035 log_type="Anti-Spam" log_component="SMTP" log_subtype="Allowed" status="" priority=Information fw_rule_id=0 user_name="" av_policy_name="None" from_email_address="firewall@firewallgate.com" to_email_address="Sysadmin@elasticuser.com" email_subject="*ALERT* Sophos XG Firewall" mailid="qkW2Y6-LxBk6U-vH-1590055245" mailsize=19728 spamaction="QUEUED" reason="Email has been accepted by Device and queued for scanning." src_domainname="elasticuser.com" dst_domainname="" src_ip="" src_country_code="" dst_ip="" dst_country_code="" protocol="TCP" src_port=0 dst_port=0 sent_bytes=0 recv_bytes=0 quarantine_reason="Other" +<30>device="SFW" date=2020-05-18 time=14:38:49 timezone="CEST" device_name="XG230" device_id=1234567890123457 log_id=041105613003 log_type="Anti-Spam" log_component="SMTP" log_subtype="Clean" status="" priority=Information fw_rule_id=22 user_name="" av_policy_name="Default" from_email_address="telekommunikation@constant-big.email" to_email_address="info@pelasticuser.com" email_subject="Telefonservice statt Anrufbeantworter" mailid="device="SFW" date=2020-05-18 time=14:38:50 timezone="CEST" device_name="XG230" device_id=1234567890123456 log_id=041107413001 log_type="Anti-Spam" log_component="SMTP" log_subtype="Spam" status="" priority=Warning fw_rule_id=22 user_name="" av_policy_name="Spam" from_email_address="ripxfc@17buddies.net" to_email_address="hein.mueck@elasticuser.de" email_subject="nimm dringend Geld" mailid="device="SFW" date=2020-05-18 time=14:38:51 timezone="CEST" device_name="XG230" device_id=1234567890123457 log_id=045908413004 log_type="Anti-Spam" log_component="SMTPS" log_subtype="Probable Spam" status="" priority=Warning fw_rule_id=22 user_name="" av_policy_name="rule3" from_email_address="SHERIF.TOBGI@ELTOBGI.COM" to_email_address="info@elasticuser.com" email_subject="09F1A19017 - 65T BP LNG Hybrid - TS-V-061-01 - HVAC Package - RFQ - BCD - 27-May-20" mailid="<20200518070235.C1623996C64F9957@ELTOBGI.COM>" mailsize=1032152 spamaction="Prefix Subject" reason="Sender IP address is blacklisted." src_domainname="ELTOBGI.COM" dst_domainname="" src_ip=67.43.156.14 src_country_code=GBR dst_ip=185.8.209.194 dst_country_code=DEU protocol="TCP" src_port=55002 dst_port=25 sent_bytes=0 recv_bytes=0 quarantine_reason="RBL" +<30>device="SFW" date=2017-01-31 time=18:34:41 timezone="IST" device_name="CR750iNG-XP" device_id=C44313350024-P29PUA log_id=041113413005 log_type="Anti-Spam" log_component="SMTP" log_subtype="Outbound Spam" status="" priority=Warning fw_rule_id=0 user_name="gaurav" av_policy_name="Gaurav123" from_email_address="gaurav1@iview.com" to_email_address=" gaurav2@iview.com" email_subject="RPD Spam Test: Spam" mailid="" mailsize=405 spamaction="Accept" reason="" src_domainname=" iview.com" dst_domainname="" src_ip=10.198.47.71 src_country_code=R1 dst_ip=10.198.233.61 dst_country_code=R1 protocol="TCP" src_port=22420 dst_port=25 sent_bytes=0 recv_bytes=0 quarantine_reason="Spam" +<30>device="SFW" date=2018-06-06 time=11:10:11 timezone="IST" device_name="SG430" device_id=S4000806149EE49 log_id=041114413006 log_type="Anti-Spam" log_component="SMTP" log_subtype="Outbound Probable Spam" status="" priority=Warning fw_rule_id=0 user_name="" av_policy_name="rule 8" from_email_address="pankhil@postman.local" to_email_address="pankhil1@Postman.local" email_subject="RPD Spam test: Bulk" mailid="" mailsize=439 spamaction="Drop" reason="Mail detected as OUTBOUND PROBABLE SPAM." src_domainname="postman.local" dst_domainname="" src_ip=10.198.16.121 src_country_code=R1 dst_ip=10.198.234.240 dst_country_code=R1 protocol="TCP" src_port=58043 dst_port=25 sent_bytes=0 recv_bytes=0 quarantine_reason="Spam" +<30>device="SFW" date=2018-06-06 time=12:50:07 timezone="IST" device_name="SG430" device_id=S4000806149EE49 log_id=041121613009 log_type="Anti-Spam" log_component="SMTP" log_subtype="DLP" status="" priority=Information fw_rule_id=0 user_name="" av_policy_name="postman" from_email_address="pankhil@postman.local" to_email_address="pankhil1@Postman. local" email_subject="Fwd: TESt" mailid="c0000002-1528269606" mailsize=5041 spamaction="DROP" reason="Email containing confidential data detected. Relevant Data Protection Policy applied." src_domainname="postman.local" dst_domainname="" src_ip=10.198.16.121 src_country_code=R1 dst_ip=10.198.17.121 dst_country_code=R1 protocol="TCP" src_port=60134 dst_port=25 sent_bytes=0 recv_bytes=0 quarantine_reason="DLP" +<30>device="SFW" date=2018-06-06 time=12:51:34 timezone="IST" device_name="SG430" device_id=S4000806149EE49 log_id=041122613010 log_type="Anti-Spam" log_component="SMTP" log_subtype="SPX" status="" priority=Information fw_rule_id=0 user_name="" av_policy_name="None" from_email_address="pankhil@postman.local" to_email_address="pankhil1@Postman.local" email_subject="[secure:pankhil]" mailid="c0000003-1528269693" mailsize=442 spamaction="Accept" reason="SPX Template of type Specified by Sender successfully applied on Email." src_domainname="postman.local" dst_domainname="" src_ip=10.198.16.121 src_country_code=R1 dst_ip=10.198.16.204 dst_country_code=R1 protocol="TCP" src_port=60298 dst_port=25 sent_bytes=0 recv_bytes=0 quarantine_reason="Other" +<30>device="SFW" date=2018-06-06 time=12:53:39 timezone="IST" device_name="SG430" device_id=S4000806149EE49 log_id=041123413012 log_type="Anti-Spam" log_component="SMTP" log_subtype="Dos" status="" priority=Warning fw_rule_id=0 user_name="" av_policy_name="None" from_email_address="" to_email_address="" email_subject="" mailid="" mailsize=0 spamaction="TMPREJECT" reason="SMTP DoS" src_domainname="" dst_domainname="" src_ip=10.198.16.121 src_country_code=R1 dst_ip=10.198.17.121 dst_country_code=R1 protocol="TCP" src_port=60392 dst_port=25 sent_bytes=0 recv_bytes=0 quarantine_reason="Other" +<30>device="SFW" date=2018-06-06 time=12:56:53 timezone="IST" device_name="SG430" device_id=S4000806149EE49 log_id=041102413014 log_type="Anti-Spam" log_component="SMTP" log_subtype="Denied" status="" priority=Warning fw_rule_id=0 user_name="" av_policy_name="postman" from_email_address="pankhil1@postman.local" to_email_address="pankhil@postman. local" email_subject="Fwd: test sand" mailid="c0000008-1528270010" mailsize=419835 spamaction="DROP" reason="Email is marked Malicious by Sophos Sandstorm." src_domainname="postman.local" dst_domainname="" src_ip=10.198.16.121 src_country_code=R1 dst_ip=10.198.17.121 dst_country_code=R1 protocol="TCP" src_port=60608 dst_port=25 sent_bytes=0 recv_bytes=0 +<30>device="SFW" date=2017-01-31 time=18:31:11 timezone="IST" device_name="CR750iNG-XP" device_id=C44313350024-P29PUA log_id=041207414001 log_type="Anti-Spam" log_component="POP3" log_subtype="Spam" status="" priority=Warning fw_rule_id=0 user_name="gaurav" av_policy_name="GauravPatel" from_email_address="gaurav1@iview.com" to_email_address="gaurav2@iview. com" email_subject="RPD Spam Test: Spam" mailid="<2a2dd5d4-1a30-617b-27b1-7961ad07cf07@iview.com>" mailsize=574 spamaction="Accept" reason="" src_domainname=" iview.com" dst_domainname="iview.com" src_ip=10.198.47.71 src_country_code=R1 dst_ip=10.198.233.61 dst_country_code=R1 protocol="TCP" src_port=22333 dst_port=110 sent_bytes=0 recv_bytes=0 quarantine_reason="Other" diff --git a/x-pack/filebeat/module/sophos/xg/test/anti-spam.log-expected.json b/x-pack/filebeat/module/sophos/xg/test/anti-spam.log-expected.json index 04f1bad3aac..d01fd9f6f6a 100644 --- a/x-pack/filebeat/module/sophos/xg/test/anti-spam.log-expected.json +++ b/x-pack/filebeat/module/sophos/xg/test/anti-spam.log-expected.json @@ -91,7 +91,7 @@ "host.name": "some_other_host.local", "input.type": "log", "log.level": "informational", - "log.offset": 748, + "log.offset": 747, "network.transport": "TCP", "observer.product": "XG", "observer.serial_number": "1234567890123457", @@ -172,7 +172,7 @@ "host.name": "my_fancy_host", "input.type": "log", "log.level": "warning", - "log.offset": 1541, + "log.offset": 1539, "network.transport": "TCP", "observer.product": "XG", "observer.serial_number": "1234567890123456", @@ -249,7 +249,7 @@ "host.name": "some_other_host.local", "input.type": "log", "log.level": "warning", - "log.offset": 2295, + "log.offset": 2292, "network.transport": "TCP", "observer.product": "XG", "observer.serial_number": "1234567890123457", @@ -326,7 +326,7 @@ "host.name": "firewall.localgroup.local", "input.type": "log", "log.level": "warning", - "log.offset": 3125, + "log.offset": 3121, "network.transport": "TCP", "observer.product": "XG", "observer.serial_number": "C44313350024-P29PUA", @@ -397,7 +397,7 @@ "host.name": "firewall.localgroup.local", "input.type": "log", "log.level": "warning", - "log.offset": 3854, + "log.offset": 3849, "network.transport": "TCP", "observer.product": "XG", "observer.serial_number": "S4000806149EE49", @@ -468,7 +468,7 @@ "host.name": "firewall.localgroup.local", "input.type": "log", "log.level": "informational", - "log.offset": 4629, + "log.offset": 4623, "network.transport": "TCP", "observer.product": "XG", "observer.serial_number": "S4000806149EE49", @@ -537,7 +537,7 @@ "host.name": "firewall.localgroup.local", "input.type": "log", "log.level": "informational", - "log.offset": 5391, + "log.offset": 5384, "network.transport": "TCP", "observer.product": "XG", "observer.serial_number": "S4000806149EE49", @@ -607,7 +607,7 @@ "host.name": "firewall.localgroup.local", "input.type": "log", "log.level": "warning", - "log.offset": 6145, + "log.offset": 6137, "network.transport": "TCP", "observer.product": "XG", "observer.serial_number": "S4000806149EE49", @@ -674,7 +674,7 @@ "host.name": "firewall.localgroup.local", "input.type": "log", "log.level": "warning", - "log.offset": 6742, + "log.offset": 6733, "network.transport": "TCP", "observer.product": "XG", "observer.serial_number": "S4000806149EE49", @@ -744,7 +744,7 @@ "host.name": "firewall.localgroup.local", "input.type": "log", "log.level": "warning", - "log.offset": 7447, + "log.offset": 7437, "network.transport": "TCP", "observer.product": "XG", "observer.serial_number": "C44313350024-P29PUA", diff --git a/x-pack/filebeat/module/sophos/xg/test/anti-virus.log b/x-pack/filebeat/module/sophos/xg/test/anti-virus.log index 22ff5a6791f..e5271e5d2f4 100644 --- a/x-pack/filebeat/module/sophos/xg/test/anti-virus.log +++ b/x-pack/filebeat/module/sophos/xg/test/anti-virus.log @@ -1,9 +1,9 @@ -<30>device="SFW" date=2020-05-18 time=14:38:33 timezone="CEST" device_name="XG230" device_id=1234567890123457 log_id=030906208001 log_type="Anti-Virus" log_component="HTTP" log_subtype="Virus" status="" priority=Critical fw_rule_id=2 user_name="" iap=13 av_policy_name="" virus="Sandstorm" url="http://sophostest.com/Sandstorm/SBTestFile1.pdf" domainname="sophostest.com" src_ip=172.16.34.24 src_country_code=R1 dst_ip=13.226.155.93 dst_country_code=USA protocol="TCP" src_port=57695 dst_port=80 sent_bytes=550 recv_bytes=1616 user_agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36" status_code=403 -<30>device="SFW" date=2020-05-18 time=14:38:34 timezone="CEST" device_name="XG230" device_id=1234567890123456 log_id=030906208001 log_type="Anti-Virus" log_component="HTTP" log_subtype="Virus" status="" priority=Critical fw_rule_id=2 user_name="" iap=13 av_policy_name="" virus="EICAR-AV-Test" url="http://sophostest.com/eicar/index.html" domainname="sophostest.com" src_ip=172.16.34.24 src_country_code=R1 dst_ip=13.226.155.18 dst_country_code=USA protocol="TCP" src_port=57835 dst_port=80 sent_bytes=541 recv_bytes=553 user_agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36" status_code=403 -<30>device="SFW" date=2020-05-18 time=14:38:35 timezone="CEST" device_name="XG230" device_id=1234567890123457 log_id=031106210001 log_type="Anti-Virus" log_component="SMTP" log_subtype="Virus" status="" priority=Critical fw_rule_id=22 user_name="" av_policy_name="default-smtp-av" from_email_address="info@farasamed.com" to_email_address="info@elastic-user.local" subject="ZAHLUNG (PROFORMA INVOICE)" mailid="<20200520004312.Horde.lEUeVf2I6PwO5K5TtMndnC7@webmail.sevengayr" mailsize=2254721 virus="TR/AD.AgentTesla.eaz" filename="" quarantine="" src_domainname="farasamed.com" dst_domainname="" src_ip=1.128.3.4 src_country_code=DEU dst_ip=186.8.209.194 dst_country_code=DEU protocol="TCP" src_port=56336 dst_port=25 sent_bytes=0 recv_bytes=0 quarantine_reason="Infected" -<30>device="SFW" date=2020-05-18 time=14:38:36 timezone="CEST" device_name="XG230" device_id=1234567890123456 log_id=031106210001 log_type="Anti-Virus" log_component="SMTP" log_subtype="Virus" status="" priority=Critical fw_rule_id=22 user_name="" av_policy_name="default-smtp-av" from_email_address="spedizioni@divella.it" to_email_address="info@elastic-user.local" subject="Re: NEW PRO-FORMA INVOICE" mailid="<20200519072944.AFCA295AF2A037A6@divella.it>" mailsize=537457 virus="Mal/BredoZp-B" filename="" quarantine="" src_domainname="divella.it" dst_domainname="" src_ip=216.160.83.61 src_country_code=USA dst_ip=185.7.209.194 dst_country_code=DEU protocol="TCP" src_port=54693 dst_port=25 sent_bytes=0 recv_bytes=0 quarantine_reason="Infected" -<30>device="SFW" date=2018-06-06 time=10:51:29 timezone="IST" device_name="SG430" device_id=S4000806149EE49 log_id=036106211001 log_type="Anti-Virus" log_component="POPS" log_subtype="Virus" status="" priority=Critical fw_rule_id=0 user_name="" av_policy_name="None" from_email_address="pankhil@postman.local" to_email_address="pankhil@postman.local" subject="EICAR" mailid="" mailsize=0 virus="EICAR-AV-Test" filename="" quarantine="" src_domainname="postman.local" dst_domainname="" src_ip=10.198.16.121 src_country_code=R1 dst_ip=10.198.234.240 dst_country_code=R1 protocol="TCP" src_port=56653 dst_port=995 sent_bytes=0 recv_bytes=0 quarantine_reason="Other" -<30>device="SFW" date=2018-06-06 time=10:58:29 timezone="IST" device_name="SG430" device_id=S4000806149EE49 log_id=036206212001 log_type="Anti-Virus" log_component="IMAPS" log_subtype="Virus" status="" priority=Critical fw_rule_id=0 user_name="" av_policy_name="None" from_email_address="pankhil@postman.local" to_email_address="ganga@postman.local" subject="EICAR test email" mailid="<2ca37b7c-e93a-743a-99c4-a0796f0bbb79@postman.local>" mailsize=0 virus="EICAR-AV-Test" filename="" quarantine="" src_domainname="postman.local" dst_domainname="" src_ip=10.198.16.121 src_country_code=R1 dst_ip=10.198.234.240 dst_country_code=R1 protocol="TCP" src_port=56632 dst_port=993 sent_bytes=0 recv_bytes=0 quarantine_reason="Other" -<30>device="SFW" date=2018-06-21 time=19:50:23 timezone="CEST" device_name="SF01V" device_id=SFDemo-2df0960 log_id=031006209001 log_type="Anti-Virus" log_component="FTP" log_subtype="Virus" status="" priority=Critical fw_rule_id=0 user_name="" virus="EICAR-AV-Test" FTP_url="/var/www//home/ftp-user/ta_test_file_1ta-cl1-46" FTP_direction="Upload" filename=" /home/ftp-user/ta_test_file_1ta-cl1-46" file_size=0 file_path="/var/www//home/ftp-user/ta_test_file_1ta-cl1-46" ftpcommand="STOR" src_ip=10.146.13.49 src_country_code=R1 dst_ip=10.8.142.181 dst_country_code=R1 protocol="TCP" src_port=39910 dst_port=21 dstdomain="" sent_bytes=0 recv_bytes=0 -<30>device="SFW" date=2018-06-21 time=19:50:48 timezone="CEST" device_name="SF01V" device_id=SFDemo-2df0960 log_id=031001609002 log_type="Anti-Virus" log_component="FTP" log_subtype="Allowed" status="" priority=Information fw_rule_id=0 user_name="" virus="" FTP_url="/var/www//home/ftp-user/ta_test_file_1ta-cl1-46" FTP_direction="Download" filename="/home/ftp-user /ta_test_file_1ta-cl1-46" file_size=19926248 file_path="/var/www//home/ftp-user/ta_test_file_1ta-cl1-46" ftpcommand="RETR" src_ip=10.146.13.49 src_country_code= dst_ip=10.8.142.181 dst_country_code= protocol="TCP" src_port=39936 dst_port=21 dstdomain="" sent_bytes=0 recv_bytes=19926248 - +<30>device="SFW" date=2020-05-18 time=14:38:33 timezone="CEST" device_name="XG230" device_id=1234567890123457 log_id=030906208001 log_type="Anti-Virus" log_component="HTTP" log_subtype="Virus" status="" priority=Critical fw_rule_id=2 user_name="" iap=13 av_policy_name="" virus="Sandstorm" url="http://sophostest.com/Sandstorm/SBTestFile1.pdf" domainname="sophostest.com" src_ip=172.16.34.24 src_country_code=R1 dst_ip=13.226.155.93 dst_country_code=USA protocol="TCP" src_port=57695 dst_port=80 sent_bytes=550 recv_bytes=1616 user_agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36" status_code=403 +<30>device="SFW" date=2020-05-18 time=14:38:34 timezone="CEST" device_name="XG230" device_id=1234567890123456 log_id=030906208001 log_type="Anti-Virus" log_component="HTTP" log_subtype="Virus" status="" priority=Critical fw_rule_id=2 user_name="" iap=13 av_policy_name="" virus="EICAR-AV-Test" url="http://sophostest.com/eicar/index.html" domainname="sophostest.com" src_ip=172.16.34.24 src_country_code=R1 dst_ip=13.226.155.18 dst_country_code=USA protocol="TCP" src_port=57835 dst_port=80 sent_bytes=541 recv_bytes=553 user_agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36" status_code=403 +<30>device="SFW" date=2020-05-18 time=14:38:35 timezone="CEST" device_name="XG230" device_id=1234567890123457 log_id=031106210001 log_type="Anti-Virus" log_component="SMTP" log_subtype="Virus" status="" priority=Critical fw_rule_id=22 user_name="" av_policy_name="default-smtp-av" from_email_address="info@farasamed.com" to_email_address="info@elastic-user.local" subject="ZAHLUNG (PROFORMA INVOICE)" mailid="<20200520004312.Horde.lEUeVf2I6PwO5K5TtMndnC7@webmail.sevengayr" mailsize=2254721 virus="TR/AD.AgentTesla.eaz" filename="" quarantine="" src_domainname="farasamed.com" dst_domainname="" src_ip=1.128.3.4 src_country_code=DEU dst_ip=186.8.209.194 dst_country_code=DEU protocol="TCP" src_port=56336 dst_port=25 sent_bytes=0 recv_bytes=0 quarantine_reason="Infected" +<30>device="SFW" date=2020-05-18 time=14:38:36 timezone="CEST" device_name="XG230" device_id=1234567890123456 log_id=031106210001 log_type="Anti-Virus" log_component="SMTP" log_subtype="Virus" status="" priority=Critical fw_rule_id=22 user_name="" av_policy_name="default-smtp-av" from_email_address="spedizioni@divella.it" to_email_address="info@elastic-user.local" subject="Re: NEW PRO-FORMA INVOICE" mailid="<20200519072944.AFCA295AF2A037A6@divella.it>" mailsize=537457 virus="Mal/BredoZp-B" filename="" quarantine="" src_domainname="divella.it" dst_domainname="" src_ip=216.160.83.61 src_country_code=USA dst_ip=185.7.209.194 dst_country_code=DEU protocol="TCP" src_port=54693 dst_port=25 sent_bytes=0 recv_bytes=0 quarantine_reason="Infected" +<30>device="SFW" date=2018-06-06 time=10:51:29 timezone="IST" device_name="SG430" device_id=S4000806149EE49 log_id=036106211001 log_type="Anti-Virus" log_component="POPS" log_subtype="Virus" status="" priority=Critical fw_rule_id=0 user_name="" av_policy_name="None" from_email_address="pankhil@postman.local" to_email_address="pankhil@postman.local" subject="EICAR" mailid="" mailsize=0 virus="EICAR-AV-Test" filename="" quarantine="" src_domainname="postman.local" dst_domainname="" src_ip=10.198.16.121 src_country_code=R1 dst_ip=10.198.234.240 dst_country_code=R1 protocol="TCP" src_port=56653 dst_port=995 sent_bytes=0 recv_bytes=0 quarantine_reason="Other" +<30>device="SFW" date=2018-06-06 time=10:58:29 timezone="IST" device_name="SG430" device_id=S4000806149EE49 log_id=036206212001 log_type="Anti-Virus" log_component="IMAPS" log_subtype="Virus" status="" priority=Critical fw_rule_id=0 user_name="" av_policy_name="None" from_email_address="pankhil@postman.local" to_email_address="ganga@postman.local" subject="EICAR test email" mailid="<2ca37b7c-e93a-743a-99c4-a0796f0bbb79@postman.local>" mailsize=0 virus="EICAR-AV-Test" filename="" quarantine="" src_domainname="postman.local" dst_domainname="" src_ip=10.198.16.121 src_country_code=R1 dst_ip=10.198.234.240 dst_country_code=R1 protocol="TCP" src_port=56632 dst_port=993 sent_bytes=0 recv_bytes=0 quarantine_reason="Other" +<30>device="SFW" date=2018-06-21 time=19:50:23 timezone="CEST" device_name="SF01V" device_id=SFDemo-2df0960 log_id=031006209001 log_type="Anti-Virus" log_component="FTP" log_subtype="Virus" status="" priority=Critical fw_rule_id=0 user_name="" virus="EICAR-AV-Test" FTP_url="/var/www//home/ftp-user/ta_test_file_1ta-cl1-46" FTP_direction="Upload" filename=" /home/ftp-user/ta_test_file_1ta-cl1-46" file_size=0 file_path="/var/www//home/ftp-user/ta_test_file_1ta-cl1-46" ftpcommand="STOR" src_ip=10.146.13.49 src_country_code=R1 dst_ip=10.8.142.181 dst_country_code=R1 protocol="TCP" src_port=39910 dst_port=21 dstdomain="" sent_bytes=0 recv_bytes=0 +<30>device="SFW" date=2018-06-21 time=19:50:48 timezone="CEST" device_name="SF01V" device_id=SFDemo-2df0960 log_id=031001609002 log_type="Anti-Virus" log_component="FTP" log_subtype="Allowed" status="" priority=Information fw_rule_id=0 user_name="" virus="" FTP_url="/var/www//home/ftp-user/ta_test_file_1ta-cl1-46" FTP_direction="Download" filename="/home/ftp-user /ta_test_file_1ta-cl1-46" file_size=19926248 file_path="/var/www//home/ftp-user/ta_test_file_1ta-cl1-46" ftpcommand="RETR" src_ip=10.146.13.49 src_country_code= dst_ip=10.8.142.181 dst_country_code= protocol="TCP" src_port=39936 dst_port=21 dstdomain="" sent_bytes=0 recv_bytes=19926248 + diff --git a/x-pack/filebeat/module/sophos/xg/test/anti-virus.log-expected.json b/x-pack/filebeat/module/sophos/xg/test/anti-virus.log-expected.json index 70d803619d1..ffbbcf87eb7 100644 --- a/x-pack/filebeat/module/sophos/xg/test/anti-virus.log-expected.json +++ b/x-pack/filebeat/module/sophos/xg/test/anti-virus.log-expected.json @@ -104,7 +104,7 @@ "http.response.status_code": 403, "input.type": "log", "log.level": "critical", - "log.offset": 673, + "log.offset": 672, "network.transport": "TCP", "observer.product": "XG", "observer.serial_number": "1234567890123456", @@ -178,7 +178,7 @@ "host.name": "some_other_host.local", "input.type": "log", "log.level": "critical", - "log.offset": 1340, + "log.offset": 1338, "network.transport": "TCP", "observer.product": "XG", "observer.serial_number": "1234567890123457", @@ -254,7 +254,7 @@ "host.name": "my_fancy_host", "input.type": "log", "log.level": "critical", - "log.offset": 2113, + "log.offset": 2110, "network.transport": "TCP", "observer.product": "XG", "observer.serial_number": "1234567890123456", @@ -337,7 +337,7 @@ "host.name": "firewall.localgroup.local", "input.type": "log", "log.level": "critical", - "log.offset": 2862, + "log.offset": 2858, "network.transport": "TCP", "observer.product": "XG", "observer.serial_number": "S4000806149EE49", @@ -411,7 +411,7 @@ "host.name": "firewall.localgroup.local", "input.type": "log", "log.level": "critical", - "log.offset": 3578, + "log.offset": 3573, "network.transport": "TCP", "observer.product": "XG", "observer.serial_number": "S4000806149EE49", @@ -487,7 +487,7 @@ "host.name": "firewall.localgroup.local", "input.type": "log", "log.level": "critical", - "log.offset": 4304, + "log.offset": 4298, "network.transport": "TCP", "observer.product": "XG", "observer.serial_number": "SFDemo-2df0960", @@ -557,7 +557,7 @@ "host.name": "firewall.localgroup.local", "input.type": "log", "log.level": "informational", - "log.offset": 4954, + "log.offset": 4947, "network.transport": "TCP", "observer.product": "XG", "observer.serial_number": "SFDemo-2df0960", diff --git a/x-pack/filebeat/module/sophos/xg/test/atp.log b/x-pack/filebeat/module/sophos/xg/test/atp.log index 10f65b6bd5a..31508520576 100644 --- a/x-pack/filebeat/module/sophos/xg/test/atp.log +++ b/x-pack/filebeat/module/sophos/xg/test/atp.log @@ -1,5 +1,5 @@ -<30>device="SFW" date=2017-01-31 time=18:44:31 timezone="IST" device_name="CR750iNG-XP" device_id=C44310050024-P29PUA log_id=086304418010 log_type="ATP" log_component="Firewall" log_subtype="Drop" priority=Warning user_name="jsmith" protocol="TCP" src_port=22623 dst_port=80 sourceip=10.198.47.71 destinationip=46.161.30.47 url=46.161.30.47 threatname=C2/Generic-A eventid=C366ACFB-7A6F-4870-B359-A6CFDA8C85F7 eventtype="Standard" login_user="" process_user="" ep_uuid= execution_path="" -<30>device="SFW" date=2020-05-18 time=14:38:34 timezone="CEST" device_name="XG230" device_id=1234567890123456 log_id=086504418010 log_type="ATP" log_component="Web" log_subtype="Drop" priority=Warning user_name="" protocol="TCP" src_port=57579 dst_port=80 sourceip=172.16.34.24 destinationip=13.226.155.22 url=http://sophostest.com/callhome/index.html threatname=C2/Generic-A eventid=E91DAD80-BDE4-4682-B7E8-FE394B70A36C eventtype="Standard" login_user="" process_user="" ep_uuid="" execution_path="" -<30>device="SFW" date=2020-05-18 time=14:38:35 timezone="CEST" device_name="XG230" device_id=1234567890123457 log_id=086504418010 log_type="ATP" log_component="Web" log_subtype="Drop" priority=Warning user_name="" protocol="TCP" src_port=57540 dst_port=80 sourceip=172.16.34.24 destinationip=13.226.155.22 url=http://sophostest.com/callhome/index.html threatname=C2/Generic-A eventid=34AC8531-E7C0-4368-9978-5740952EE9AB eventtype="Standard" login_user="" process_user="" ep_uuid="" execution_path="" -<30>device="SFW" date=2018-06-05 time=08:49:00 timezone="BST" device_name="XG310" device_id=C30006T22TGR89B log_id=086320518009 log_type="ATP" log_component="Firewall" log_subtype="Alert" priority=Notice user_name="" protocol="ICMP" src_port=0 dst_port=0 sourceip=10.198.32.89 destinationip=82.211.30.202 url=82.211.30.202 threatname=C2/Generic-A eventid=C7E26E6F-0097-4EA2-89DE-C31C40636CB2 eventtype="Standard" login_user="" process_user="" ep_uuid= execution_path="" - +<30>device="SFW" date=2017-01-31 time=18:44:31 timezone="IST" device_name="CR750iNG-XP" device_id=C44310050024-P29PUA log_id=086304418010 log_type="ATP" log_component="Firewall" log_subtype="Drop" priority=Warning user_name="jsmith" protocol="TCP" src_port=22623 dst_port=80 sourceip=10.198.47.71 destinationip=46.161.30.47 url=46.161.30.47 threatname=C2/Generic-A eventid=C366ACFB-7A6F-4870-B359-A6CFDA8C85F7 eventtype="Standard" login_user="" process_user="" ep_uuid= execution_path="" +<30>device="SFW" date=2020-05-18 time=14:38:34 timezone="CEST" device_name="XG230" device_id=1234567890123456 log_id=086504418010 log_type="ATP" log_component="Web" log_subtype="Drop" priority=Warning user_name="" protocol="TCP" src_port=57579 dst_port=80 sourceip=172.16.34.24 destinationip=13.226.155.22 url=http://sophostest.com/callhome/index.html threatname=C2/Generic-A eventid=E91DAD80-BDE4-4682-B7E8-FE394B70A36C eventtype="Standard" login_user="" process_user="" ep_uuid="" execution_path="" +<30>device="SFW" date=2020-05-18 time=14:38:35 timezone="CEST" device_name="XG230" device_id=1234567890123457 log_id=086504418010 log_type="ATP" log_component="Web" log_subtype="Drop" priority=Warning user_name="" protocol="TCP" src_port=57540 dst_port=80 sourceip=172.16.34.24 destinationip=13.226.155.22 url=http://sophostest.com/callhome/index.html threatname=C2/Generic-A eventid=34AC8531-E7C0-4368-9978-5740952EE9AB eventtype="Standard" login_user="" process_user="" ep_uuid="" execution_path="" +<30>device="SFW" date=2018-06-05 time=08:49:00 timezone="BST" device_name="XG310" device_id=C30006T22TGR89B log_id=086320518009 log_type="ATP" log_component="Firewall" log_subtype="Alert" priority=Notice user_name="" protocol="ICMP" src_port=0 dst_port=0 sourceip=10.198.32.89 destinationip=82.211.30.202 url=82.211.30.202 threatname=C2/Generic-A eventid=C7E26E6F-0097-4EA2-89DE-C31C40636CB2 eventtype="Standard" login_user="" process_user="" ep_uuid= execution_path="" + diff --git a/x-pack/filebeat/module/sophos/xg/test/atp.log-expected.json b/x-pack/filebeat/module/sophos/xg/test/atp.log-expected.json index 8bfa784dcae..16b796d1d50 100644 --- a/x-pack/filebeat/module/sophos/xg/test/atp.log-expected.json +++ b/x-pack/filebeat/module/sophos/xg/test/atp.log-expected.json @@ -92,7 +92,7 @@ "host.name": "my_fancy_host", "input.type": "log", "log.level": "warning", - "log.offset": 489, + "log.offset": 488, "network.transport": "tcp", "observer.product": "XG", "observer.serial_number": "1234567890123456", @@ -157,7 +157,7 @@ "host.name": "some_other_host.local", "input.type": "log", "log.level": "warning", - "log.offset": 991, + "log.offset": 989, "network.transport": "tcp", "observer.product": "XG", "observer.serial_number": "1234567890123457", @@ -222,7 +222,7 @@ "host.name": "firewall.localgroup.local", "input.type": "log", "log.level": "notification", - "log.offset": 1493, + "log.offset": 1490, "network.transport": "icmp", "observer.product": "XG", "observer.serial_number": "C30006T22TGR89B", diff --git a/x-pack/filebeat/module/sophos/xg/test/cfilter.log b/x-pack/filebeat/module/sophos/xg/test/cfilter.log index 2cbc3304fe3..03f021b9008 100644 --- a/x-pack/filebeat/module/sophos/xg/test/cfilter.log +++ b/x-pack/filebeat/module/sophos/xg/test/cfilter.log @@ -1,10 +1,10 @@ -<30>device="SFW" date=2017-01-31 time=14:03:33 timezone="IST" device_name="CR750iNG-XP" device_id=C44310050024-P29PUA log_id=050901616001 log_type="Content Filtering" log_component="HTTP" log_subtype="Allowed" status="" priority=Information fw_rule_id=2 user_name="jsmith" user_gp="Open Group" iap=1 category="Entertainment" category_type="Unproductive" url="https://r8---sn-ci5gup-qxas.googlevideo.com/" contenttype="" override_token="" httpresponsecode="" src_ip=10.198.47.71 dst_ip=182.79.221.19 protocol="TCP" src_port=9444 dst_port=443 sent_bytes=0 recv_bytes=319007 domain=r8---sn-ci5gup-qxas.googlevideo.com exceptions= activityname="" reason="" -<30>device="SFW" date=2017-02-01 time=18:20:21 timezone="IST" device_name="SG115" device_id=S110000E28BA631 log_id=050902616002 log_type="Content Filtering" log_component="HTTP" log_subtype="Denied" status="" priority=Information fw_rule_id=1 user_name="" user_gp="" iap=13 category="Religion & Spirituality" category_type="Unproductive" url="http://hanuman.com/" contenttype="" override_token="" httpresponsecode="" src_ip=216.160.83.57 dst_ip=216.58.197.44 protocol="TCP" src_port=46719 dst_port=80 sent_bytes=0 recv_bytes=0 domain=hanuman.com exceptions= activityname="" -<30>device="SFW" date=2017-02-01 time=18:13:29 timezone="IST" device_name="SG115" device_id=S110016E28BA631 log_id=054402617051 log_type="Content Filtering" log_component="Application" log_subtype="Denied" priority=Information fw_rule_id=1 user_name="" user_gp="" application_filter_policy=8 category="Mobile Applications" application_name="Gtalk Android" application_risk=4 application_technology="Client Server" application_category="Mobile Applications" src_ip=216.160.83.57 src_country_code=DEU dst_ip=74.125.130.188 dst_country_code=USA protocol="TCP" src_port=49128 dst_port=5228 sent_bytes=0 recv_bytes=0 status="Deny" message="" -<30>device="SFW" date=2020-05-18 time=14:38:51 timezone="CEST" device_name="XG230" device_id=1234567890123456 log_id=050901616001 log_type="Content Filtering" log_component="HTTP" log_subtype="Allowed" status="" priority=Information fw_rule_id=2 user_name="" user_gp="" iap=13 category="Information Technology" category_type="Acceptable" url="https://his-eur1-neur1.servicebus.windows.net/$servicebus/websocket" contenttype="" override_token="" httpresponsecode="" src_ip=172.17.34.10 dst_ip=13.79.168.201 protocol="TCP" src_port=62851 dst_port=443 sent_bytes=259 recv_bytes=168 domain=his-eur1-neur1.servicebus.windows.net exceptions="" activityname="" reason="" user_agent="" status_code="400" transactionid="" referer="" download_file_name="" download_file_type="" upload_file_name="" upload_file_type="" con_id=80042000 application="" app_is_cloud=0 override_name="" override_authorizer="" -<30>device="SFW" date=2020-05-18 time=14:38:52 timezone="CEST" device_name="XG230" device_id=1234567890123457 log_id=050902616002 log_type="Content Filtering" log_component="HTTP" log_subtype="Denied" status="" priority=Information fw_rule_id=51 user_name="" user_gp="" iap=2 category="IPAddress" category_type="Acceptable" url="https://40.90.137.127/" contenttype="" override_token="" httpresponsecode="" src_ip=172.16.34.15 dst_ip=40.90.137.127 protocol="TCP" src_port=60471 dst_port=443 sent_bytes=0 recv_bytes=0 domain=40.90.137.127 exceptions="" activityname="" reason="" user_agent="" status_code="200" transactionid="" referer="" download_file_name="" download_file_type="" upload_file_name="" upload_file_type="" con_id=642960832 application="" app_is_cloud=0 override_name="" override_authorizer="" -<30>device="SFW" date=2020-05-18 time=14:38:53 timezone="CEST" device_name="XG230" device_id=1234567890123456 log_id=050901616001 log_type="Content Filtering" log_component="HTTP" log_subtype="Allowed" status="" priority=Information fw_rule_id=2 user_name="" user_gp="" iap=13 category="Information Technology" category_type="Acceptable" url="http://update.eset.com/eset_upd/ep7/dll/update.ver.signed" contenttype="" override_token="" httpresponsecode="" src_ip=1.128.3.4 dst_ip=91.228.167.133 protocol="TCP" src_port=65391 dst_port=80 sent_bytes=980 recv_bytes=295 domain=update.eset.com exceptions=av,https,sandstorm activityname="" reason="" user_agent="EFSW Update (Windows; U; 64bit; BPC 7.1.12010.0; OS: 10.0.17763 SP 0.0 NT; TDB 45511; CL 1.1.1; x64s; APP efsw; PX 1; PUA 1; CD 1; RA 1; PEV 0; UNS 1; UBR 1158; HVCI 0; SHA256 1; WU 3; HWF: 01009DAA-757A-D666-EFD2-92DD0D501284; PLOC de_de; PCODE 211.0.0; " status_code="304" transactionid="" referer="" download_file_name="" download_file_type="" upload_file_name="" upload_file_type="" con_id=248426360 application="" app_is_cloud=0 override_name="" override_authorizer="" -<30>device="SFW" date=2016-12-02 time=18:50:20 timezone="GMT" device_name="SF01V" device_id=1234567890123456 log_id=058420116010 log_type="Content Filtering" log_component="Web Content Policy" log_subtype="Alert" user="gi123456" src_ip=10.108.108.49 transaction_id="e4a127f7-a850-477c-920e-a471b38727c1" dictionary_name="complicated_Custom" site_category=Information Technology website="ta-web-static-testing.qa. astaro.de" direction="in" action="Deny" file_name="cgi_echo.pl" context_match="Not" context_prefix="blah blah hello " context_suffix=" hello blah " -<30>device="SFW" date=2016-12-02 time=18:50:20 timezone="GMT" device_name="SFVUNL" device_id=C01001K234RXPA1 log_id=050927616005 log_type="Content Filtering" log_component="HTTP" log_subtype="Warned" status="" priority=Information fw_rule_id=2 user_name="rich" user_gp="Clientless Open Group" iap=13 category="Search Engines" category_type="Acceptable" url="http://www.google.com/" contenttype="" override_token="" httpresponsecode="" src_ip=192.168.73.220 dst_ip=64.233.189.147 protocol="TCP" src_port=37832 dst_port=80 sent_bytes=0 recv_bytes=0 domain=www.google.com exceptions= activityname=" Search" reason="" -<30>device="SFW" date=2016-12-02 time=18:50:22 timezone="GMT" device_name="SFVUNL" device_id=C01001K234RXPA1 log_id=050901616006 log_type="Content Filtering" log_component="HTTP" log_subtype="Allowed" status="" priority=Information fw_rule_id=2 user_name="rich" user_gp="Clientless Open Group" iap=13 category="Search Engines" category_type="Acceptable" url="http://www.google.ca/?gfe_rd=cr&ei=ojxHWP3WC4WN8QeRioDABw" contenttype="text/html" override_token="" httpresponsecode="" src_ip=192.168.73.220 dst_ip=64.233.188.94 protocol="TCP" src_port=46322 dst_port=80 sent_bytes=0 recv_bytes=619 domain=www.google.ca exceptions= activityname="Search" reason="not eligible" - +<30>device="SFW" date=2017-01-31 time=14:03:33 timezone="IST" device_name="CR750iNG-XP" device_id=C44310050024-P29PUA log_id=050901616001 log_type="Content Filtering" log_component="HTTP" log_subtype="Allowed" status="" priority=Information fw_rule_id=2 user_name="jsmith" user_gp="Open Group" iap=1 category="Entertainment" category_type="Unproductive" url="https://r8---sn-ci5gup-qxas.googlevideo.com/" contenttype="" override_token="" httpresponsecode="" src_ip=10.198.47.71 dst_ip=182.79.221.19 protocol="TCP" src_port=9444 dst_port=443 sent_bytes=0 recv_bytes=319007 domain=r8---sn-ci5gup-qxas.googlevideo.com exceptions= activityname="" reason="" +<30>device="SFW" date=2017-02-01 time=18:20:21 timezone="IST" device_name="SG115" device_id=S110000E28BA631 log_id=050902616002 log_type="Content Filtering" log_component="HTTP" log_subtype="Denied" status="" priority=Information fw_rule_id=1 user_name="" user_gp="" iap=13 category="Religion & Spirituality" category_type="Unproductive" url="http://hanuman.com/" contenttype="" override_token="" httpresponsecode="" src_ip=216.160.83.57 dst_ip=216.58.197.44 protocol="TCP" src_port=46719 dst_port=80 sent_bytes=0 recv_bytes=0 domain=hanuman.com exceptions= activityname="" +<30>device="SFW" date=2017-02-01 time=18:13:29 timezone="IST" device_name="SG115" device_id=S110016E28BA631 log_id=054402617051 log_type="Content Filtering" log_component="Application" log_subtype="Denied" priority=Information fw_rule_id=1 user_name="" user_gp="" application_filter_policy=8 category="Mobile Applications" application_name="Gtalk Android" application_risk=4 application_technology="Client Server" application_category="Mobile Applications" src_ip=216.160.83.57 src_country_code=DEU dst_ip=74.125.130.188 dst_country_code=USA protocol="TCP" src_port=49128 dst_port=5228 sent_bytes=0 recv_bytes=0 status="Deny" message="" +<30>device="SFW" date=2020-05-18 time=14:38:51 timezone="CEST" device_name="XG230" device_id=1234567890123456 log_id=050901616001 log_type="Content Filtering" log_component="HTTP" log_subtype="Allowed" status="" priority=Information fw_rule_id=2 user_name="" user_gp="" iap=13 category="Information Technology" category_type="Acceptable" url="https://his-eur1-neur1.servicebus.windows.net/$servicebus/websocket" contenttype="" override_token="" httpresponsecode="" src_ip=172.17.34.10 dst_ip=13.79.168.201 protocol="TCP" src_port=62851 dst_port=443 sent_bytes=259 recv_bytes=168 domain=his-eur1-neur1.servicebus.windows.net exceptions="" activityname="" reason="" user_agent="" status_code="400" transactionid="" referer="" download_file_name="" download_file_type="" upload_file_name="" upload_file_type="" con_id=80042000 application="" app_is_cloud=0 override_name="" override_authorizer="" +<30>device="SFW" date=2020-05-18 time=14:38:52 timezone="CEST" device_name="XG230" device_id=1234567890123457 log_id=050902616002 log_type="Content Filtering" log_component="HTTP" log_subtype="Denied" status="" priority=Information fw_rule_id=51 user_name="" user_gp="" iap=2 category="IPAddress" category_type="Acceptable" url="https://40.90.137.127/" contenttype="" override_token="" httpresponsecode="" src_ip=172.16.34.15 dst_ip=40.90.137.127 protocol="TCP" src_port=60471 dst_port=443 sent_bytes=0 recv_bytes=0 domain=40.90.137.127 exceptions="" activityname="" reason="" user_agent="" status_code="200" transactionid="" referer="" download_file_name="" download_file_type="" upload_file_name="" upload_file_type="" con_id=642960832 application="" app_is_cloud=0 override_name="" override_authorizer="" +<30>device="SFW" date=2020-05-18 time=14:38:53 timezone="CEST" device_name="XG230" device_id=1234567890123456 log_id=050901616001 log_type="Content Filtering" log_component="HTTP" log_subtype="Allowed" status="" priority=Information fw_rule_id=2 user_name="" user_gp="" iap=13 category="Information Technology" category_type="Acceptable" url="http://update.eset.com/eset_upd/ep7/dll/update.ver.signed" contenttype="" override_token="" httpresponsecode="" src_ip=1.128.3.4 dst_ip=91.228.167.133 protocol="TCP" src_port=65391 dst_port=80 sent_bytes=980 recv_bytes=295 domain=update.eset.com exceptions=av,https,sandstorm activityname="" reason="" user_agent="EFSW Update (Windows; U; 64bit; BPC 7.1.12010.0; OS: 10.0.17763 SP 0.0 NT; TDB 45511; CL 1.1.1; x64s; APP efsw; PX 1; PUA 1; CD 1; RA 1; PEV 0; UNS 1; UBR 1158; HVCI 0; SHA256 1; WU 3; HWF: 01009DAA-757A-D666-EFD2-92DD0D501284; PLOC de_de; PCODE 211.0.0; " status_code="304" transactionid="" referer="" download_file_name="" download_file_type="" upload_file_name="" upload_file_type="" con_id=248426360 application="" app_is_cloud=0 override_name="" override_authorizer="" +<30>device="SFW" date=2016-12-02 time=18:50:20 timezone="GMT" device_name="SF01V" device_id=1234567890123456 log_id=058420116010 log_type="Content Filtering" log_component="Web Content Policy" log_subtype="Alert" user="gi123456" src_ip=10.108.108.49 transaction_id="e4a127f7-a850-477c-920e-a471b38727c1" dictionary_name="complicated_Custom" site_category=Information Technology website="ta-web-static-testing.qa. astaro.de" direction="in" action="Deny" file_name="cgi_echo.pl" context_match="Not" context_prefix="blah blah hello " context_suffix=" hello blah " +<30>device="SFW" date=2016-12-02 time=18:50:20 timezone="GMT" device_name="SFVUNL" device_id=C01001K234RXPA1 log_id=050927616005 log_type="Content Filtering" log_component="HTTP" log_subtype="Warned" status="" priority=Information fw_rule_id=2 user_name="rich" user_gp="Clientless Open Group" iap=13 category="Search Engines" category_type="Acceptable" url="http://www.google.com/" contenttype="" override_token="" httpresponsecode="" src_ip=192.168.73.220 dst_ip=64.233.189.147 protocol="TCP" src_port=37832 dst_port=80 sent_bytes=0 recv_bytes=0 domain=www.google.com exceptions= activityname=" Search" reason="" +<30>device="SFW" date=2016-12-02 time=18:50:22 timezone="GMT" device_name="SFVUNL" device_id=C01001K234RXPA1 log_id=050901616006 log_type="Content Filtering" log_component="HTTP" log_subtype="Allowed" status="" priority=Information fw_rule_id=2 user_name="rich" user_gp="Clientless Open Group" iap=13 category="Search Engines" category_type="Acceptable" url="http://www.google.ca/?gfe_rd=cr&ei=ojxHWP3WC4WN8QeRioDABw" contenttype="text/html" override_token="" httpresponsecode="" src_ip=192.168.73.220 dst_ip=64.233.188.94 protocol="TCP" src_port=46322 dst_port=80 sent_bytes=0 recv_bytes=619 domain=www.google.ca exceptions= activityname="Search" reason="not eligible" + diff --git a/x-pack/filebeat/module/sophos/xg/test/cfilter.log-expected.json b/x-pack/filebeat/module/sophos/xg/test/cfilter.log-expected.json index 6169a070cd5..9bc411835c7 100644 --- a/x-pack/filebeat/module/sophos/xg/test/cfilter.log-expected.json +++ b/x-pack/filebeat/module/sophos/xg/test/cfilter.log-expected.json @@ -97,7 +97,7 @@ "host.name": "firewall.localgroup.local", "input.type": "log", "log.level": "informational", - "log.offset": 654, + "log.offset": 653, "network.transport": "tcp", "observer.product": "XG", "observer.serial_number": "S110000E28BA631", @@ -173,7 +173,7 @@ "host.name": "firewall.localgroup.local", "input.type": "log", "log.level": "informational", - "log.offset": 1229, + "log.offset": 1227, "network.transport": "tcp", "observer.product": "XG", "observer.serial_number": "S110016E28BA631", @@ -249,7 +249,7 @@ "http.response.status_code": "400", "input.type": "log", "log.level": "informational", - "log.offset": 1867, + "log.offset": 1864, "network.transport": "tcp", "observer.product": "XG", "observer.serial_number": "1234567890123456", @@ -319,7 +319,7 @@ "http.response.status_code": "200", "input.type": "log", "log.level": "informational", - "log.offset": 2762, + "log.offset": 2758, "network.transport": "tcp", "observer.product": "XG", "observer.serial_number": "1234567890123457", @@ -387,7 +387,7 @@ "http.response.status_code": "304", "input.type": "log", "log.level": "informational", - "log.offset": 3571, + "log.offset": 3566, "network.transport": "tcp", "observer.product": "XG", "observer.serial_number": "1234567890123456", @@ -452,7 +452,7 @@ "host.name": "my_fancy_host", "input.type": "log", "log.level": "alert", - "log.offset": 4703, + "log.offset": 4697, "observer.product": "XG", "observer.serial_number": "1234567890123456", "observer.type": "firewall", @@ -513,7 +513,7 @@ "host.name": "firewall.localgroup.local", "input.type": "log", "log.level": "informational", - "log.offset": 5265, + "log.offset": 5258, "network.transport": "tcp", "observer.product": "XG", "observer.serial_number": "C01001K234RXPA1", @@ -584,7 +584,7 @@ "host.name": "firewall.localgroup.local", "input.type": "log", "log.level": "informational", - "log.offset": 5880, + "log.offset": 5872, "network.transport": "tcp", "observer.product": "XG", "observer.serial_number": "C01001K234RXPA1", diff --git a/x-pack/filebeat/module/sophos/xg/test/event.log b/x-pack/filebeat/module/sophos/xg/test/event.log index 8ec039f86e2..80fe35ee11f 100644 --- a/x-pack/filebeat/module/sophos/xg/test/event.log +++ b/x-pack/filebeat/module/sophos/xg/test/event.log @@ -1,20 +1,20 @@ -<30>device="SFW" date=2020-05-18 time=14:38:57 timezone="CEST" device_name="XG230" device_id=1234567890123456 log_id=062910617701 log_type="Event" log_component="Firewall Authentication" log_subtype="Authentication" status="Successful" priority=Information user_name="elastic.user@elastic.test.com" usergroupname="Open Group" auth_client="CTA" auth_mechanism="AD" reason="" src_ip=172.17.35.116 message="User elastic.user@elastic.test.com of group Open Group logged in successfully to Firewall through AD authentication mechanism from 172.17.35.116" name="elastic.user@elastic.test.com" src_mac= -<30>device="SFW" date=2020-05-18 time=14:38:58 timezone="CEST" device_name="XG230" device_id=1234567890123456 log_id=062511418055 log_type="Event" log_component="IPSec" log_subtype="System" status="Failed" priority=Warning user_name="elastic.user@elastic.test.com" connectionname="Location-1" connectiontype="0" localinterfaceip=214.167.51.66 localgateway="" localnetwork="172.17.32.0/19" remoteinterfaceip=89.160.20.112 remotenetwork="10.84.234.5/32" message="location-1 - IKE message retransmission timed out (Remote: 89.160.20.112)" -<30>device="SFW" date=2020-05-18 time=14:38:59 timezone="CEST" device_name="XG230" device_id=1234567890123456 log_id=062511318057 log_type="Event" log_component="IPSec" log_subtype="System" status="Expire" priority=Error user_name="" connectionname="" connectiontype="0" localinterfaceip="" localgateway="" localnetwork="" remoteinterfaceip="" remotenetwork="" message="IKE_SA timed out before it could be established" -<30>device="SFW" date=2020-05-18 time=14:39:00 timezone="CEST" device_name="XG230" device_id=1234567890123456 log_id=063210617704 log_type="Event" log_component="My Account Authentication" log_subtype="Authentication" status="Successful" priority=Information user_name="elastic.user@elastic.test.com" usergroupname="" auth_client="N/A" auth_mechanism="Local" reason="" src_ip=67.43.156.13 message="User elastic.user@elastic.test.com logged in successfully to MyAccount through Local authentication mechanism" name="" src_mac= -<30>device="SFW" date=2020-05-18 time=14:39:01 timezone="CEST" device_name="XG230" device_id=1234567890123456 log_id=064011517819 log_type="Event" log_component="Anti-Virus" log_subtype="System" priority=Notice status="Successful" oldversion=1.0.407794 newversion=1.0.407795 message="Avira AV definitions upgraded from 1.0.407794 to 1.0.407795." -<30>device="SFW" date=2020-05-18 time=14:39:02 timezone="CEST" device_name="XG230" device_id=1234567890123457 log_id=063411660022 log_type="Event" log_component="DHCP Server" log_subtype="System" status="Expire" priority=Information ipaddress="192.168.110.10" client_physical_address="-" client_host_name="" message="Lease 192.168.110.10 expired" raw_data="192.168.110.10" -<30>device="SFW" date=2020-05-18 time=14:39:03 timezone="CEST" device_name="XG230" device_id=1234567890123456 log_id=063110617710 log_type="Event" log_component="SSL VPN Authentication" log_subtype="Authentication" status="Successful" priority=Information user_name="elastic.user@elastic.test.com" usergroupname="" auth_client="N/A" auth_mechanism="AD" reason="" src_ip=81.2.69.145 message="User elastic.user@elastic.test.com authenticated successfully to login to SSLVPN through AD authentication mechanism" name="" src_mac= -<30>device="SFW" date=2020-05-18 time=14:39:04 timezone="CEST" device_name="XG230" device_id=1234567890123456 log_id=062811617824 log_type="Event" log_component="SSL VPN" log_subtype="System" priority=Information Mode="Remote Access" sessionid="" starttime=0 user_name="elastic.user@elastic.test.com" ipaddress=10.82.234.5 sent_bytes=0 recv_bytes=0 status="Established" message="SSL VPN User 'elastic.user@elastic.test.com' connected " timestamp=1589960866 connectionname="" remote_ip=10.82.234.12 -<30>device="SFW" date=2020-05-18 time=14:39:05 timezone="CEST" device_name="XG230" device_id=1234567890123456 log_id=063010517708 log_type="Event" log_component="VPN Authentication" log_subtype="Authentication" status="Failed" priority=Notice user_name="hendrikl" usergroupname="" auth_client="N/A" auth_mechanism="AD,AD,Local" reason="wrong credentials" src_ip=1.128.3.4 message="User elastic01 failed to login to VPN through AD,AD,Local authentication mechanism because of wrong credentials" name="" src_mac= -<30>device="SFW" date=2020-05-18 time=14:39:06 timezone="CEST" device_name="XG230" device_id=1234567890123456 log_id=066911518017 log_type="Event" log_component="ATP" log_subtype="System" priority=Notice status="Successful" oldversion=1.0.0297 newversion=1.0.0298 message="ATP definitions upgraded from 1.0.0297 to 1.0.0298." -<30>device="SFW" date=2020-05-18 time=14:39:07 timezone="CEST" device_name="XG230" device_id=1234567890123457 log_id=062009617502 log_type="Event" log_component="GUI" log_subtype="Admin" status="Successful" priority=Information user_name="admin" src_ip=10.83.234.5 SysLog_SERVER_NAME='Logstash' message="SysLog Server 'Logstash' settings were changed by 'admin' from '10.83.234.5' using 'GUI'" -<30>device="SFW" date=2020-05-18 time=14:39:08 timezone="CEST" device_name="XG230" device_id=1234567890123456 log_id=062109517507 log_type="Event" log_component="CLI" log_subtype="Admin" status="Failed" priority=Notice user_name="root" src_ip=175.16.199.1 message="User 'root' failed to login from '175.16.199.1' using ssh because of wrong credentials" -<30>device="SFW" date=2020-05-18 time=14:39:09 timezone="CEST" device_name="XG230" device_id=1234567890123456 log_id=063911517818 log_type="Event" log_component="IPS" log_subtype="System" priority=Notice status="Successful" oldversion=9.17.09 newversion=9.17.10 message="IPS definitions upgraded from 9.17.09 to 9.17.10." -<30>device="SFW" date=2020-05-18 time=14:39:10 timezone="CEST" device_name="XG230" device_id=1234567890123456 log_id=063311617923 log_type="Event" log_component="Appliance" log_subtype="System" priority=Information backup_mode='appliance' message="Scheduled backup to appliance is successful." -<30>device="SFW" date=2020-05-18 time=14:39:20 timezone="CEST" device_name="XG230" device_id=1234567890123457 log_id=062910617703 log_type="Event" log_component="Firewall Authentication" log_subtype="Authentication" status="Successful" priority=Information user_name="elastic.user@elastic.test.com" usergroupname="VPN.SSL.Users.elastic" auth_client="IPSec" auth_mechanism="N/A" reason="" src_ip=10.84.234.38 src_mac="" start_time=1591086575 sent_bytes=0 recv_bytes=0 message="User elastic.user@elastic.test.com was logged out of firewall" name="elastic.user@elastic.test.com" timestamp=1591086576 -<30>device="SFW" date=2017-03-16 time=12:56:01 timezone="IST" device_name="XG125w" device_id=S1601E1F9FCB7EE log_id=066811618014 log_type="Event" log_component="RED" log_subtype="System" priority=Information red_id=A350196C47072B0 status="Connected" eventtime="2017-03-16 12:56:01 IST" duration=164000 branch_name=Gaurav Patel recv_bytes=0 sent_bytes=0 message="A350196C47072B0/Gaurav Patel is now re-connected after 164000 ms" -<30>device="SFW" date=2017-03-16 time=12:53:27 timezone="IST" device_name="XG125w" device_id=S1601E1F9FCB7EE log_id=066811618015 log_type="Event" log_component="RED" log_subtype="System" priority=Information red_id=A350196C47072B0 status="Disconnected" eventtime="2017-03-16 12:53:27 IST" duration=0 branch_name=Gaurav Patel recv_bytes=31488 sent_bytes=22368 message="A350196C47072B0/Gaurav Patel is now disconnected" -<30>device="SFW" date=2017-03-16 time=12:46:26 timezone="IST" device_name="XG125w" device_id=S1601E1F9FCB7EE log_id=066811618016 log_type="Event" log_component="RED" log_subtype="System" priority=Information red_id=A350196C47072B0 status="Interim" eventtime="2017-03-16 12:46:26 IST" duration=0 branch_name=NY recv_bytes=0 sent_bytes=0 message="A350196C47072B0/NY transfered bytes TX: 0 RX: 0" -<30>device="SFW" date=2018-06-06 time=11:12:10 timezone="IST" device_name="SG430" device_id=S4000806149EE49 log_id=063711517815 log_type="Event" log_component="DDNS" log_subtype="System" status="Success" priority=Notice host=test1. customtest.dyndns.org updatedip=10.198.232.86 reason="" message="DDNS update for host test1.customtest.dyndns.org was Successful. Updated with IP 10.198.232.86." - +<30>device="SFW" date=2020-05-18 time=14:38:57 timezone="CEST" device_name="XG230" device_id=1234567890123456 log_id=062910617701 log_type="Event" log_component="Firewall Authentication" log_subtype="Authentication" status="Successful" priority=Information user_name="elastic.user@elastic.test.com" usergroupname="Open Group" auth_client="CTA" auth_mechanism="AD" reason="" src_ip=172.17.35.116 message="User elastic.user@elastic.test.com of group Open Group logged in successfully to Firewall through AD authentication mechanism from 172.17.35.116" name="elastic.user@elastic.test.com" src_mac= +<30>device="SFW" date=2020-05-18 time=14:38:58 timezone="CEST" device_name="XG230" device_id=1234567890123456 log_id=062511418055 log_type="Event" log_component="IPSec" log_subtype="System" status="Failed" priority=Warning user_name="elastic.user@elastic.test.com" connectionname="Location-1" connectiontype="0" localinterfaceip=214.167.51.66 localgateway="" localnetwork="172.17.32.0/19" remoteinterfaceip=89.160.20.112 remotenetwork="10.84.234.5/32" message="location-1 - IKE message retransmission timed out (Remote: 89.160.20.112)" +<30>device="SFW" date=2020-05-18 time=14:38:59 timezone="CEST" device_name="XG230" device_id=1234567890123456 log_id=062511318057 log_type="Event" log_component="IPSec" log_subtype="System" status="Expire" priority=Error user_name="" connectionname="" connectiontype="0" localinterfaceip="" localgateway="" localnetwork="" remoteinterfaceip="" remotenetwork="" message="IKE_SA timed out before it could be established" +<30>device="SFW" date=2020-05-18 time=14:39:00 timezone="CEST" device_name="XG230" device_id=1234567890123456 log_id=063210617704 log_type="Event" log_component="My Account Authentication" log_subtype="Authentication" status="Successful" priority=Information user_name="elastic.user@elastic.test.com" usergroupname="" auth_client="N/A" auth_mechanism="Local" reason="" src_ip=67.43.156.13 message="User elastic.user@elastic.test.com logged in successfully to MyAccount through Local authentication mechanism" name="" src_mac= +<30>device="SFW" date=2020-05-18 time=14:39:01 timezone="CEST" device_name="XG230" device_id=1234567890123456 log_id=064011517819 log_type="Event" log_component="Anti-Virus" log_subtype="System" priority=Notice status="Successful" oldversion=1.0.407794 newversion=1.0.407795 message="Avira AV definitions upgraded from 1.0.407794 to 1.0.407795." +<30>device="SFW" date=2020-05-18 time=14:39:02 timezone="CEST" device_name="XG230" device_id=1234567890123457 log_id=063411660022 log_type="Event" log_component="DHCP Server" log_subtype="System" status="Expire" priority=Information ipaddress="192.168.110.10" client_physical_address="-" client_host_name="" message="Lease 192.168.110.10 expired" raw_data="192.168.110.10" +<30>device="SFW" date=2020-05-18 time=14:39:03 timezone="CEST" device_name="XG230" device_id=1234567890123456 log_id=063110617710 log_type="Event" log_component="SSL VPN Authentication" log_subtype="Authentication" status="Successful" priority=Information user_name="elastic.user@elastic.test.com" usergroupname="" auth_client="N/A" auth_mechanism="AD" reason="" src_ip=81.2.69.145 message="User elastic.user@elastic.test.com authenticated successfully to login to SSLVPN through AD authentication mechanism" name="" src_mac= +<30>device="SFW" date=2020-05-18 time=14:39:04 timezone="CEST" device_name="XG230" device_id=1234567890123456 log_id=062811617824 log_type="Event" log_component="SSL VPN" log_subtype="System" priority=Information Mode="Remote Access" sessionid="" starttime=0 user_name="elastic.user@elastic.test.com" ipaddress=10.82.234.5 sent_bytes=0 recv_bytes=0 status="Established" message="SSL VPN User 'elastic.user@elastic.test.com' connected " timestamp=1589960866 connectionname="" remote_ip=10.82.234.12 +<30>device="SFW" date=2020-05-18 time=14:39:05 timezone="CEST" device_name="XG230" device_id=1234567890123456 log_id=063010517708 log_type="Event" log_component="VPN Authentication" log_subtype="Authentication" status="Failed" priority=Notice user_name="hendrikl" usergroupname="" auth_client="N/A" auth_mechanism="AD,AD,Local" reason="wrong credentials" src_ip=1.128.3.4 message="User elastic01 failed to login to VPN through AD,AD,Local authentication mechanism because of wrong credentials" name="" src_mac= +<30>device="SFW" date=2020-05-18 time=14:39:06 timezone="CEST" device_name="XG230" device_id=1234567890123456 log_id=066911518017 log_type="Event" log_component="ATP" log_subtype="System" priority=Notice status="Successful" oldversion=1.0.0297 newversion=1.0.0298 message="ATP definitions upgraded from 1.0.0297 to 1.0.0298." +<30>device="SFW" date=2020-05-18 time=14:39:07 timezone="CEST" device_name="XG230" device_id=1234567890123457 log_id=062009617502 log_type="Event" log_component="GUI" log_subtype="Admin" status="Successful" priority=Information user_name="admin" src_ip=10.83.234.5 SysLog_SERVER_NAME='Logstash' message="SysLog Server 'Logstash' settings were changed by 'admin' from '10.83.234.5' using 'GUI'" +<30>device="SFW" date=2020-05-18 time=14:39:08 timezone="CEST" device_name="XG230" device_id=1234567890123456 log_id=062109517507 log_type="Event" log_component="CLI" log_subtype="Admin" status="Failed" priority=Notice user_name="root" src_ip=175.16.199.1 message="User 'root' failed to login from '175.16.199.1' using ssh because of wrong credentials" +<30>device="SFW" date=2020-05-18 time=14:39:09 timezone="CEST" device_name="XG230" device_id=1234567890123456 log_id=063911517818 log_type="Event" log_component="IPS" log_subtype="System" priority=Notice status="Successful" oldversion=9.17.09 newversion=9.17.10 message="IPS definitions upgraded from 9.17.09 to 9.17.10." +<30>device="SFW" date=2020-05-18 time=14:39:10 timezone="CEST" device_name="XG230" device_id=1234567890123456 log_id=063311617923 log_type="Event" log_component="Appliance" log_subtype="System" priority=Information backup_mode='appliance' message="Scheduled backup to appliance is successful." +<30>device="SFW" date=2020-05-18 time=14:39:20 timezone="CEST" device_name="XG230" device_id=1234567890123457 log_id=062910617703 log_type="Event" log_component="Firewall Authentication" log_subtype="Authentication" status="Successful" priority=Information user_name="elastic.user@elastic.test.com" usergroupname="VPN.SSL.Users.elastic" auth_client="IPSec" auth_mechanism="N/A" reason="" src_ip=10.84.234.38 src_mac="" start_time=1591086575 sent_bytes=0 recv_bytes=0 message="User elastic.user@elastic.test.com was logged out of firewall" name="elastic.user@elastic.test.com" timestamp=1591086576 +<30>device="SFW" date=2017-03-16 time=12:56:01 timezone="IST" device_name="XG125w" device_id=S1601E1F9FCB7EE log_id=066811618014 log_type="Event" log_component="RED" log_subtype="System" priority=Information red_id=A350196C47072B0 status="Connected" eventtime="2017-03-16 12:56:01 IST" duration=164000 branch_name=Gaurav Patel recv_bytes=0 sent_bytes=0 message="A350196C47072B0/Gaurav Patel is now re-connected after 164000 ms" +<30>device="SFW" date=2017-03-16 time=12:53:27 timezone="IST" device_name="XG125w" device_id=S1601E1F9FCB7EE log_id=066811618015 log_type="Event" log_component="RED" log_subtype="System" priority=Information red_id=A350196C47072B0 status="Disconnected" eventtime="2017-03-16 12:53:27 IST" duration=0 branch_name=Gaurav Patel recv_bytes=31488 sent_bytes=22368 message="A350196C47072B0/Gaurav Patel is now disconnected" +<30>device="SFW" date=2017-03-16 time=12:46:26 timezone="IST" device_name="XG125w" device_id=S1601E1F9FCB7EE log_id=066811618016 log_type="Event" log_component="RED" log_subtype="System" priority=Information red_id=A350196C47072B0 status="Interim" eventtime="2017-03-16 12:46:26 IST" duration=0 branch_name=NY recv_bytes=0 sent_bytes=0 message="A350196C47072B0/NY transfered bytes TX: 0 RX: 0" +<30>device="SFW" date=2018-06-06 time=11:12:10 timezone="IST" device_name="SG430" device_id=S4000806149EE49 log_id=063711517815 log_type="Event" log_component="DDNS" log_subtype="System" status="Success" priority=Notice host=test1. customtest.dyndns.org updatedip=10.198.232.86 reason="" message="DDNS update for host test1.customtest.dyndns.org was Successful. Updated with IP 10.198.232.86." + diff --git a/x-pack/filebeat/module/sophos/xg/test/event.log-expected.json b/x-pack/filebeat/module/sophos/xg/test/event.log-expected.json index 55e793967da..26d15e9a785 100644 --- a/x-pack/filebeat/module/sophos/xg/test/event.log-expected.json +++ b/x-pack/filebeat/module/sophos/xg/test/event.log-expected.json @@ -73,7 +73,7 @@ "host.name": "my_fancy_host", "input.type": "log", "log.level": "warning", - "log.offset": 597, + "log.offset": 596, "message": "location-1 - IKE message retransmission timed out (Remote: 89.160.20.112)", "observer.product": "XG", "observer.serial_number": "1234567890123456", @@ -133,7 +133,7 @@ "host.name": "my_fancy_host", "input.type": "log", "log.level": "error", - "log.offset": 1134, + "log.offset": 1132, "message": "IKE_SA timed out before it could be established", "observer.product": "XG", "observer.serial_number": "1234567890123456", @@ -179,7 +179,7 @@ "host.name": "my_fancy_host", "input.type": "log", "log.level": "informational", - "log.offset": 1554, + "log.offset": 1551, "message": "User elastic.user@elastic.test.com logged in successfully to MyAccount through Local authentication mechanism", "observer.product": "XG", "observer.serial_number": "1234567890123456", @@ -238,7 +238,7 @@ "host.name": "my_fancy_host", "input.type": "log", "log.level": "notification", - "log.offset": 2081, + "log.offset": 2077, "message": "Avira AV definitions upgraded from 1.0.407794 to 1.0.407795.", "observer.product": "XG", "observer.serial_number": "1234567890123456", @@ -276,7 +276,7 @@ "host.name": "some_other_host.local", "input.type": "log", "log.level": "informational", - "log.offset": 2429, + "log.offset": 2424, "message": "Lease 192.168.110.10 expired", "observer.product": "XG", "observer.serial_number": "1234567890123457", @@ -323,7 +323,7 @@ "host.name": "my_fancy_host", "input.type": "log", "log.level": "informational", - "log.offset": 2803, + "log.offset": 2797, "message": "User elastic.user@elastic.test.com authenticated successfully to login to SSLVPN through AD authentication mechanism", "observer.product": "XG", "observer.serial_number": "1234567890123456", @@ -379,7 +379,7 @@ "host.name": "my_fancy_host", "input.type": "log", "log.level": "informational", - "log.offset": 3330, + "log.offset": 3323, "message": "SSL VPN User 'elastic.user@elastic.test.com' connected ", "observer.product": "XG", "observer.serial_number": "1234567890123456", @@ -431,7 +431,7 @@ "host.name": "my_fancy_host", "input.type": "log", "log.level": "notification", - "log.offset": 3829, + "log.offset": 3821, "message": "User elastic01 failed to login to VPN through AD,AD,Local authentication mechanism because of wrong credentials", "observer.product": "XG", "observer.serial_number": "1234567890123456", @@ -480,7 +480,7 @@ "host.name": "my_fancy_host", "input.type": "log", "log.level": "notification", - "log.offset": 4341, + "log.offset": 4332, "message": "ATP definitions upgraded from 1.0.0297 to 1.0.0298.", "observer.product": "XG", "observer.serial_number": "1234567890123456", @@ -519,7 +519,7 @@ "host.name": "some_other_host.local", "input.type": "log", "log.level": "informational", - "log.offset": 4669, + "log.offset": 4659, "message": "SysLog Server 'Logstash' settings were changed by 'admin' from '10.83.234.5' using 'GUI'", "observer.product": "XG", "observer.serial_number": "1234567890123457", @@ -566,7 +566,7 @@ "host.name": "my_fancy_host", "input.type": "log", "log.level": "notification", - "log.offset": 5064, + "log.offset": 5053, "message": "User 'root' failed to login from '175.16.199.1' using ssh because of wrong credentials", "observer.product": "XG", "observer.serial_number": "1234567890123456", @@ -618,7 +618,7 @@ "host.name": "my_fancy_host", "input.type": "log", "log.level": "notification", - "log.offset": 5418, + "log.offset": 5406, "message": "IPS definitions upgraded from 9.17.09 to 9.17.10.", "observer.product": "XG", "observer.serial_number": "1234567890123456", @@ -656,7 +656,7 @@ "host.name": "my_fancy_host", "input.type": "log", "log.level": "informational", - "log.offset": 5742, + "log.offset": 5729, "message": "Scheduled backup to appliance is successful.", "observer.product": "XG", "observer.serial_number": "1234567890123456", @@ -705,7 +705,7 @@ "host.name": "some_other_host.local", "input.type": "log", "log.level": "informational", - "log.offset": 6040, + "log.offset": 6026, "message": "User elastic.user@elastic.test.com was logged out of firewall", "observer.product": "XG", "observer.serial_number": "1234567890123457", @@ -761,7 +761,7 @@ "host.name": "firewall.localgroup.local", "input.type": "log", "log.level": "informational", - "log.offset": 6638, + "log.offset": 6623, "message": "A350196C47072B0/Gaurav Patel is now re-connected after 164000 ms", "observer.product": "XG", "observer.serial_number": "S1601E1F9FCB7EE", @@ -775,7 +775,7 @@ "sophos.xg.branch_name": "Gaurav Patel", "sophos.xg.device": "SFW", "sophos.xg.device_name": "XG125w", - "sophos.xg.eventtime": "2017-03-16T12:56:01.000+02:00", + "sophos.xg.eventtime": "2017-03-16T08:56:01.000-02:00", "sophos.xg.log_component": "RED", "sophos.xg.log_subtype": "System", "sophos.xg.log_type": "Event", @@ -807,7 +807,7 @@ "host.name": "firewall.localgroup.local", "input.type": "log", "log.level": "informational", - "log.offset": 7067, + "log.offset": 7051, "message": "A350196C47072B0/Gaurav Patel is now disconnected", "observer.product": "XG", "observer.serial_number": "S1601E1F9FCB7EE", @@ -821,7 +821,7 @@ "sophos.xg.branch_name": "Gaurav Patel", "sophos.xg.device": "SFW", "sophos.xg.device_name": "XG125w", - "sophos.xg.eventtime": "2017-03-16T12:53:27.000+02:00", + "sophos.xg.eventtime": "2017-03-16T08:53:27.000-02:00", "sophos.xg.log_component": "RED", "sophos.xg.log_subtype": "System", "sophos.xg.log_type": "Event", @@ -853,7 +853,7 @@ "host.name": "firewall.localgroup.local", "input.type": "log", "log.level": "informational", - "log.offset": 7486, + "log.offset": 7469, "message": "A350196C47072B0/NY transfered bytes TX: 0 RX: 0", "observer.product": "XG", "observer.serial_number": "S1601E1F9FCB7EE", @@ -867,7 +867,7 @@ "sophos.xg.branch_name": "NY", "sophos.xg.device": "SFW", "sophos.xg.device_name": "XG125w", - "sophos.xg.eventtime": "2017-03-16T12:46:26.000+02:00", + "sophos.xg.eventtime": "2017-03-16T08:46:26.000-02:00", "sophos.xg.log_component": "RED", "sophos.xg.log_subtype": "System", "sophos.xg.log_type": "Event", @@ -894,7 +894,7 @@ "host.name": "firewall.localgroup.local", "input.type": "log", "log.level": "notification", - "log.offset": 7881, + "log.offset": 7863, "message": "DDNS update for host test1.customtest.dyndns.org was Successful. Updated with IP 10.198.232.86.", "observer.product": "XG", "observer.serial_number": "S4000806149EE49", diff --git a/x-pack/filebeat/module/sophos/xg/test/firewall.log b/x-pack/filebeat/module/sophos/xg/test/firewall.log index 920661cc9c2..1abc96cc522 100644 --- a/x-pack/filebeat/module/sophos/xg/test/firewall.log +++ b/x-pack/filebeat/module/sophos/xg/test/firewall.log @@ -1,21 +1,22 @@ -<30>device="SFW" date=2020-05-18 time=14:38:37 timezone="CEST" device_name="XG230" device_id=1234567890123456 log_id=010101600001 log_type="Firewall" log_component="Firewall Rule" log_subtype="Allowed" status="Allow" priority=Information duration=11 fw_rule_id=21 policy_type=1 user_name="" user_gp="" iap=0 ips_policy_id=0 appfilter_policy_id=0 application="HTTP" application_risk=1 application_technology="Browser Based" application_category="General Internet" in_interface="Port1" out_interface="Port2" src_mac=00:00:00:00:00:00 src_ip=1.128.3.4 src_country_code=R1 dst_ip=91.228.167.86 dst_country_code=SVK protocol="TCP" src_port=62841 dst_port=80 sent_pkts=6 recv_pkts=5 sent_bytes=459 recv_bytes=606 tran_src_ip=213.167.51.66 tran_src_port=0 tran_dst_ip="" tran_dst_port=0 srczonetype="LAN" srczone="LAN" dstzonetype="WAN" dstzone="WAN" dir_disp="" connevent="Stop" connid="1617925280" vconnid="" hb_health="No Heartbeat" message="" appresolvedby="Signature" app_is_cloud=0 -<30>device="SFW" date=2020-05-18 time=14:38:38 timezone="CEST" device_name="XG230" device_id=1234567890123457 log_id=010101600001 log_type="Firewall" log_component="Firewall Rule" log_subtype="Allowed" status="Allow" priority=Information duration=0 fw_rule_id=67 policy_type=1 user_name="" user_gp="" iap=0 ips_policy_id=15 appfilter_policy_id=0 application="DNS" application_risk=1 application_technology="Network Protocol" application_category="Infrastructure" in_interface="Port3.400" out_interface="Port2" src_mac=00:00:00:00:00:00 src_ip=67.43.156.12 src_country_code=R1 dst_ip=91.228.165.117 dst_country_code=SVK protocol="UDP" src_port=49144 dst_port=53 sent_pkts=0 recv_pkts=0 sent_bytes=0 recv_bytes=0 tran_src_ip=185.8.209.194 tran_src_port=0 tran_dst_ip="" tran_dst_port=0 srczonetype="DMZ" srczone="DMZ" dstzonetype="WAN" dstzone="WAN" dir_disp="" connevent="Start" connid="3360392048" vconnid="" hb_health="No Heartbeat" message="" appresolvedby="Signature" app_is_cloud=0 -<30>device="SFW" date=2020-05-18 time=14:38:39 timezone="CEST" device_name="XG230" device_id=1234567890123456 log_id=010102600002 log_type="Firewall" log_component="Firewall Rule" log_subtype="Denied" status="Deny" priority=Information duration=0 fw_rule_id=29 policy_type=1 user_name="" user_gp="" iap=2 ips_policy_id=0 appfilter_policy_id=0 application="" application_risk=0 application_technology="" application_category="" in_interface="Port1" out_interface="Port2" src_mac=24:01:c7:07:2b:a2 src_ip=172.17.35.113 src_country_code="" dst_ip=172.20.4.52 dst_country_code="" protocol="TCP" src_port=53287 dst_port=4980 sent_pkts=0 recv_pkts=0 sent_bytes=0 recv_bytes=0 tran_src_ip="" tran_src_port=0 tran_dst_ip="" tran_dst_port=0 srczonetype="" srczone="" dstzonetype="" dstzone="" dir_disp="" connid="" vconnid="" hb_health="No Heartbeat" message="" appresolvedby="Signature" app_is_cloud=0 -<30>device="SFW" date=2020-05-18 time=14:38:40 timezone="CEST" device_name="XG230" device_id=1234567890123456 log_id=010102600002 log_type="Firewall" log_component="Firewall Rule" log_subtype="Denied" status="Deny" priority=Information duration=0 fw_rule_id=29 policy_type=1 user_name="elastic@user.local" user_gp="elastic.group.local" iap=2 ips_policy_id=0 appfilter_policy_id=0 application="" application_risk=0 application_technology="" application_category="" in_interface="tun0" out_interface="Port1" src_mac="" src_ip=10.82.234.6 src_country_code="" dst_ip=192.168.0.1 dst_country_code="" protocol="TCP" src_port=60102 dst_port=53 sent_pkts=0 recv_pkts=0 sent_bytes=0 recv_bytes=0 tran_src_ip="" tran_src_port=0 tran_dst_ip="" tran_dst_port=0 srczonetype="" srczone="" dstzonetype="" dstzone="" dir_disp="" connid="" vconnid="" hb_health="No Heartbeat" message="" appresolvedby="Signature" app_is_cloud=0 -<30>device="SFW" date=2020-05-18 time=14:38:41 timezone="CEST" device_name="XG230" device_id=1234567890123457 log_id=010302602002 log_type="Firewall" log_component="Appliance Access" log_subtype="Denied" status="Deny" priority=Information duration=0 fw_rule_id=0 policy_type=0 user_name="" user_gp="" iap=0 ips_policy_id=0 appfilter_policy_id=0 application="" application_risk=0 application_technology="" application_category="" in_interface="Port2" out_interface="" src_mac=c4:f7:d5:b5:47:f4 src_ip=67.43.156.12 src_country_code="" dst_ip=185.7.209.207 dst_country_code="" protocol="TCP" src_port=55039 dst_port=18 sent_pkts=0 recv_pkts=0 sent_bytes=0 recv_bytes=0 tran_src_ip="" tran_src_port=0 tran_dst_ip="" tran_dst_port=0 srczonetype="" srczone="" dstzonetype="" dstzone="" dir_disp="" connid="" vconnid="" hb_health="No Heartbeat" message="" appresolvedby="Signature" app_is_cloud=0 -<30>device="SFW" date=2020-05-18 time=14:38:42 timezone="CEST" device_name="XG230" device_id=1234567890123456 log_id=010102600002 log_type="Firewall" log_component="Firewall Rule" log_subtype="Denied" status="Deny" priority=Information duration=0 fw_rule_id=29 policy_type=1 user_name="elastic@user.local" user_gp="elastic.group.local" iap=2 ips_policy_id=0 appfilter_policy_id=0 application="" application_risk=0 application_technology="" application_category="" in_interface="Port1" out_interface="Port2" src_mac=24:01:c7:07:2b:a2 src_ip=172.17.35.101 src_country_code="" dst_ip=192.168.5.11 dst_country_code="" protocol="TCP" src_port=51826 dst_port=1109 sent_pkts=0 recv_pkts=0 sent_bytes=0 recv_bytes=0 tran_src_ip="" tran_src_port=0 tran_dst_ip="" tran_dst_port=0 srczonetype="" srczone="" dstzonetype="" dstzone="" dir_disp="" connid="" vconnid="" hb_health="No Heartbeat" message="" appresolvedby="Signature" app_is_cloud=0 -<30>device="SFW" date=2020-05-18 time=14:38:43 timezone="CEST" device_name="XG230" device_id=1234567890123457 log_id=010402403001 log_type="Firewall" log_component="DoS Attack" log_subtype="Denied" status="Deny" priority=Warning duration=0 fw_rule_id=0 policy_type=0 user_name="" user_gp="" iap=0 ips_policy_id=0 appfilter_policy_id=0 application="" application_risk=0 application_technology="" application_category="" in_interface="Port1" out_interface="" src_mac=34:db:fd:83:d8:09 src_ip=172.16.36.105 src_country_code="" dst_ip=10.84.234.14 dst_country_code="" protocol="UDP" src_port=3389 dst_port=64465 sent_pkts=0 recv_pkts=0 sent_bytes=0 recv_bytes=0 tran_src_ip="" tran_src_port=0 tran_dst_ip="" tran_dst_port=0 srczonetype="" srczone="" dstzonetype="" dstzone="" dir_disp="" connid="" vconnid="" hb_health="No Heartbeat" message="" appresolvedby="Signature" app_is_cloud=0 -<30>device="SFW" date=2020-05-18 time=14:38:44 timezone="CEST" device_name="XG230" device_id=1234567890123456 log_id=012802605201 log_type="Firewall" log_component="SSL VPN" log_subtype="Denied" status="Deny" priority=Information duration=0 fw_rule_id=0 policy_type=0 user_name="" user_gp="" iap=0 ips_policy_id=0 appfilter_policy_id=0 application="" application_risk=0 application_technology="" application_category="" in_interface="tun0" out_interface="" src_mac="" src_ip=10.82.234.9 src_country_code="" dst_ip=10.82.234.11 dst_country_code="" protocol="TCP" src_port=58331 dst_port=56267 sent_pkts=0 recv_pkts=0 sent_bytes=0 recv_bytes=0 tran_src_ip="" tran_src_port=0 tran_dst_ip="" tran_dst_port=0 srczonetype="" srczone="" dstzonetype="" dstzone="" dir_disp="" connid="" vconnid="" hb_health="No Heartbeat" message="" appresolvedby="Signature" app_is_cloud=0 -<30>device="SFW" date=2020-05-18 time=14:38:45 timezone="CEST" device_name="XG230" device_id=1234567890123456 log_id=010101600001 log_type="Firewall" log_component="Firewall Rule" log_subtype="Allowed" status="Allow" priority=Information duration=0 fw_rule_id=61 policy_type=2 user_name="elastic@user.local" user_gp="elastic.group.local" iap=0 ips_policy_id=11 appfilter_policy_id=0 application="" application_risk=0 application_technology="" application_category="" in_interface="ipsec0" out_interface="Port2" src_mac=00:00:00:00:00:00 src_ip=10.84.234.7 src_country_code=R1 dst_ip=172.16.34.50 dst_country_code=R1 protocol="TCP" src_port=58543 dst_port=443 sent_pkts=0 recv_pkts=0 sent_bytes=0 recv_bytes=0 tran_src_ip="" tran_src_port=0 tran_dst_ip="" tran_dst_port=0 srczonetype="VPN" srczone="VPN" dstzonetype="VPN" dstzone="VPN" dir_disp="" connevent="Start" connid="1615935064" vconnid="" hb_health="No Heartbeat" message="" appresolvedby="Signature" app_is_cloud=0 -<30>device="SFW" date=2020-05-18 time=14:38:45 timezone="CEST" device_name="XG230" device_id=1234567890123457 log_id=018201500005 log_type="Firewall" log_component="ICMP ERROR MESSAGE" log_subtype="Allowed" status="Allow" priority=Notice duration=0 fw_rule_id=60 policy_type=1 user_name="" user_gp="" iap=0 ips_policy_id=17 appfilter_policy_id=0 application="" application_risk=0 application_technology="" application_category="" in_interface="Port1" out_interface="" src_mac=34:db:fd:83:d8:09 src_ip=192.168.1.254 src_country_code="" dst_ip=172.17.32.19 dst_country_code="" protocol="ICMP" icmp_type=3 icmp_code=1 sent_pkts=0 recv_pkts=0 sent_bytes=0 recv_bytes=0 tran_src_ip="" tran_src_port=0 tran_dst_ip="" tran_dst_port=0 srczonetype="" srczone="" dstzonetype="" dstzone="" dir_disp="" connevent="Interim" connid="2685668438" vconnid="" hb_health="No Heartbeat" message="" appresolvedby="Signature" app_is_cloud=0 -<30>device="SFW" date=2020-06-05 time=12:38:53 timezone="CEST" device_name="XG230" device_id=1234567890123457 log_id=010101600001 log_type="Firewall" log_component="Firewall Rule" log_subtype="Allowed" status="Allow" priority=Information duration=10 fw_rule_id=60 policy_type=1 user_name="" user_gp="" iap=0 ips_policy_id=17 appfilter_policy_id=0 application="" application_risk=0 application_technology="" application_category="" in_interface="ipsec0" out_interface="Port1" src_mac=00:00:00:00:00:00 src_ip=172.17.35.119 src_country_code=R1 dst_ip=172.16.34.10 dst_country_code=R1 protocol="TCP" src_port=61925 dst_port=88 sent_pkts=6 recv_pkts=6 sent_bytes=1802 recv_bytes=1732 tran_src_ip= tran_src_port=0 tran_dst_ip= tran_dst_port=0srczonetype="VPN" srczone="VPN" dstzonetype="LAN" dstzone="LAN" dir_disp="" connevent="Stop" connid="1617126256" vconnid="" hb_health="NoHeartbeat" message="" appresolvedby="Signature" app_is_cloud=0" -<30>device="SFW" date=2018-05-30 time=13:26:37 timezone="IST" device_name="XG125w" device_id=SFDemo-763180a log_id=010202601001 log_type="Firewall" log_component="Invalid Traffic" log_subtype="Denied" status="Deny" priority=Information duration=0 fw_rule_id=0 policy_type=0 user_name="" user_gp="" iap=0 ips_policy_id=0 appfilter_policy_id=0 application="" application_risk=0 application_technology="" application_category="" in_interface="" out_interface="" src_mac= src_ip=10.198.32.19 src_country_code= dst_ip=175.16.199.1 dst_country_code= protocol="UDP" src_port=1353 dst_port=0 sent_pkts=0 recv_pkts=0 sent_bytes=0 recv_bytes=0 tran_src_ip= tran_src_port=0 tran_dst_ip= tran_dst_port=0 srczonetype="" srczone="" dstzonetype="" dstzone="" dir_disp="" connid="" vconnid="" hb_health="No Heartbeat" message="Invalid UDP destination." appresolvedby=" Signature" -<30>device="SFW" date=2018-06-04 time=17:20:24 timezone="IST" device_name="XG125w" device_id=SFDemo-763180a log_id=011402601301 log_type="Firewall" log_component="Fragmented Traffic" log_subtype="Denied" status="Deny" priority=Information duration=0 fw_rule_id=0 policy_type=0 user_name="" user_gp="" iap=0 ips_policy_id=0 appfilter_policy_id=0 application="" application_risk=0 application_technology="" application_category="" in_interface="" out_interface="" src_mac= src_ip=0.0.0.0 src_country_code= dst_ip=0.0.0.0 dst_country_code= protocol="0" src_port=0 dst_port=0 sent_pkts=0 recv_pkts=0 sent_bytes=0 recv_bytes=0 tran_src_ip= tran_src_port=0 tran_dst_ip= tran_dst_port=0 srczonetype="" srczone="" dstzonetype="" dstzone="" dir_disp="" connid="" vconnid="" hb_health="No Heartbeat" message="" appresolvedby="Signature" -<30>device="SFW" date=2018-05-30 time=14:01:32 timezone="IST" device_name="XG125w" device_id=SFDemo-763180a log_id=010302602002 log_type="Firewall" log_component="Appliance Access" log_subtype="Denied" status="Deny" priority=Information duration=0 fw_rule_id=2 policy_type=0 user_name="" user_gp="" iap=0 ips_policy_id=0 appfilter_policy_id=0 application="" application_risk=0 application_technology="" application_category="" in_interface="Port2.611" out_interface="" src_mac=c8:5b:76:ab:72:d3 src_ip=10.198.38.184 src_country_code= dst_ip=10.198.39.255 dst_country_code= protocol="UDP" src_port=137 dst_port=137 sent_pkts=0 recv_pkts=0 sent_bytes=0 recv_bytes=0 tran_src_ip= tran_src_port=0 tran_dst_ip= tran_dst_port=0 srczonetype="" srczone="" dstzonetype="" dstzone="" dir_disp="" connid="" vconnid="" hb_health="No Heartbeat" message="" appresolvedby="Signature" -<30>device="SFW" date=2018-05-30 time=14:17:17 timezone="IST" device_name="XG125w" device_id=SFDemo-763180a log_id=010402403001 log_type="Firewall" log_component="DoS Attack" log_subtype="Denied" status="Deny" priority=Warning duration=0 fw_rule_id=0 policy_type=0 user_name="" user_gp="" iap=0 ips_policy_id=0 appfilter_policy_id=0 application="" application_risk=0 application_technology="" application_category="" in_interface="Port1" out_interface="" src_mac=b8:97:5a:5b:0f:fd src_ip=10.198.32.19 src_country_code= dst_ip=10.198.32.48 dst_country_code= protocol="TCP" src_port=41960 dst_port=22 sent_pkts=0 recv_pkts=0 sent_bytes=0 recv_bytes=0 tran_src_ip= tran_src_port=0 tran_dst_ip= tran_dst_port=0 srczonetype="" srczone="" dstzonetype="" dstzone="" dir_disp="" connid="" vconnid="" hb_health="No Heartbeat" message="" appresolvedby=" Signature" -<30>device="SFW" date=2018-06-05 time=14:30:31 timezone="IST" device_name="XG125w" device_id=SFDemo-763180a log_id=010502604001 log_type="Firewall" log_component="ICMP Redirection" log_subtype="Denied" status="Deny" priority=Information duration=0 fw_rule_id=0 policy_type=0 user_name="" user_gp="" iap=0 ips_policy_id=0 appfilter_policy_id=0 application="" application_risk=0 application_technology="" application_category="" in_interface="" out_interface="" src_mac= src_ip=10.198.37.23 src_country_code= dst_ip=10.198.36.48 dst_country_code= protocol="ICMP" icmp_type=5 icmp_code=1 sent_pkts=0 recv_pkts=0 sent_bytes=0 recv_bytes=0 tran_src_ip= tran_src_port=0 tran_dst_ip= tran_dst_port=0 srczonetype="" srczone="" dstzonetype="" dstzone="" dir_disp="" connid="" vconnid="" hb_health="No Heartbeat" message="" appresolvedby=" Signature" -<30>device="SFW" date=2018-05-31 time=17:05:14 timezone="IST" device_name="XG125w" device_id=SFDemo-763180a log_id=010602605001 log_type="Firewall" log_component="Source Routed" log_subtype="Denied" status="Deny" priority=Information duration=0 fw_rule_id=1 policy_type=1 user_name="" user_gp="" iap=0 ips_policy_id=0 appfilter_policy_id=0 application="" application_risk=0 application_technology="" application_category="" in_interface="" out_interface="" src_mac= src_ip=10.198.12.19 src_country_code= dst_ip=175.16.199.1 dst_country_code= protocol="TCP" src_port=1571 dst_port=80 sent_pkts=0 recv_pkts=0 sent_bytes=0 recv_bytes=0 tran_src_ip= tran_src_port=0 tran_dst_ip= tran_dst_port=0 srczonetype="" srczone="" dstzonetype="" dstzone="" dir_disp="" connid="" vconnid="" hb_health="No Heartbeat" message="" appresolvedby="Signature" -<30>device="SFW" date=2018-05-30 time=15:09:51 timezone="IST" device_name="XG125w" device_id=SFDemo-763180a log_id=011702605051 log_type="Firewall" log_component="MAC Filter" log_subtype="Denied" status="Deny" priority=Information duration=0 fw_rule_id=0 policy_type=0 user_name="" user_gp="" iap=0 ips_policy_id=0 appfilter_policy_id=0 application="" application_risk=0 application_technology="" application_category="" in_interface="Port2.531" out_interface="" src_mac=1e:3a:5a:5b:23:ab src_ip=fe80::59f5:3ce8:c98e:5062 src_country_code= dst_ip=ff02::1:2 dst_country_code= protocol="UDP" src_port=546 dst_port=547 sent_pkts=0 recv_pkts=0 sent_bytes=0 recv_bytes=0 tran_src_ip= tran_src_port=0 tran_dst_ip= tran_dst_port=0 srczonetype="" srczone="" dstzonetype="" dstzone="" dir_disp="" connid="" vconnid="" hb_health="No Heartbeat" message="" appresolvedby="Signature" -<30>device="SFW" date=2018-06-01 time=10:57:55 timezone="BST" device_name="XG310" device_id=SFDemo-9a04c43 log_id=016602600006 log_type="Firewall" log_component="Heartbeat" log_subtype="Denied" status="Deny" priority=Information duration=0 fw_rule_id=16 policy_type=1 user_name="" user_gp="" iap=2 ips_policy_id=0 appfilter_policy_id=0 application="" application_risk=0 application_technology="" application_category="" in_interface="Port3.611" out_interface="" src_mac=08:00:27:4c:49:e3 src_ip=10.198.37.57 src_country_code= dst_ip=10.198.32.19 dst_country_code= protocol="ICMP" icmp_type=8 icmp_code=0 sent_pkts=0 recv_pkts=0 sent_bytes=0 recv_bytes=0 tran_src_ip= tran_src_port=0 tran_dst_ip= tran_dst_port=0 srczonetype="" srczone="" dstzonetype="" dstzone="" dir_disp="" connid="" vconnid="" hb_health="Red" message="" appresolvedby="Signature" app_is_cloud=0 -<30>device="SFW" date=2018-06-01 time=10:55:41 timezone="BST" device_name="XG310" device_id=SFDemo-9a04c43 log_id=016602600003 log_type="Firewall" log_component="Heartbeat" log_subtype="Denied" status="Deny" priority=Information duration=0 fw_rule_id=16 policy_type=1 user_name="" user_gp="" iap=2 ips_policy_id=0 appfilter_policy_id=0 application="" application_risk=0 application_technology="" application_category="" in_interface="Port3.611" out_interface="" src_mac=08:00:27:4c:49:e3 src_ip=10.198.37.57 src_country_code= dst_ip=72.163.4.185 dst_country_code= protocol="ICMP" icmp_type=8 icmp_code=0 sent_pkts=0 recv_pkts=0 sent_bytes=0 recv_bytes=0 tran_src_ip= tran_src_port=0 tran_dst_ip= tran_dst_port=0 srczonetype="" srczone="" dstzonetype="" dstzone="" dir_disp="" connid="" vconnid="" hb_health="Red" message="" appresolvedby="Signature" app_is_cloud=0 - +<30>device="SFW" date=2020-05-18 time=14:38:37 timezone="CEST" device_name="XG230" device_id=1234567890123456 log_id=010101600001 log_type="Firewall" log_component="Firewall Rule" log_subtype="Allowed" status="Allow" priority=Information duration=11 fw_rule_id=21 policy_type=1 user_name="" user_gp="" iap=0 ips_policy_id=0 appfilter_policy_id=0 application="HTTP" application_risk=1 application_technology="Browser Based" application_category="General Internet" in_interface="Port1" out_interface="Port2" src_mac=00:00:00:00:00:00 src_ip=1.128.3.4 src_country_code=R1 dst_ip=91.228.167.86 dst_country_code=SVK protocol="TCP" src_port=62841 dst_port=80 sent_pkts=6 recv_pkts=5 sent_bytes=459 recv_bytes=606 tran_src_ip=213.167.51.66 tran_src_port=0 tran_dst_ip="" tran_dst_port=0 srczonetype="LAN" srczone="LAN" dstzonetype="WAN" dstzone="WAN" dir_disp="" connevent="Stop" connid="1617925280" vconnid="" hb_health="No Heartbeat" message="" appresolvedby="Signature" app_is_cloud=0 +<30>device="SFW" date=2020-05-18 time=14:38:38 timezone="CEST" device_name="XG230" device_id=1234567890123457 log_id=010101600001 log_type="Firewall" log_component="Firewall Rule" log_subtype="Allowed" status="Allow" priority=Information duration=0 fw_rule_id=67 policy_type=1 user_name="" user_gp="" iap=0 ips_policy_id=15 appfilter_policy_id=0 application="DNS" application_risk=1 application_technology="Network Protocol" application_category="Infrastructure" in_interface="Port3.400" out_interface="Port2" src_mac=00:00:00:00:00:00 src_ip=67.43.156.12 src_country_code=R1 dst_ip=91.228.165.117 dst_country_code=SVK protocol="UDP" src_port=49144 dst_port=53 sent_pkts=0 recv_pkts=0 sent_bytes=0 recv_bytes=0 tran_src_ip=185.8.209.194 tran_src_port=0 tran_dst_ip="" tran_dst_port=0 srczonetype="DMZ" srczone="DMZ" dstzonetype="WAN" dstzone="WAN" dir_disp="" connevent="Start" connid="3360392048" vconnid="" hb_health="No Heartbeat" message="" appresolvedby="Signature" app_is_cloud=0 +<30>device="SFW" date=2020-05-18 time=14:38:39 timezone="CEST" device_name="XG230" device_id=1234567890123456 log_id=010102600002 log_type="Firewall" log_component="Firewall Rule" log_subtype="Denied" status="Deny" priority=Information duration=0 fw_rule_id=29 policy_type=1 user_name="" user_gp="" iap=2 ips_policy_id=0 appfilter_policy_id=0 application="" application_risk=0 application_technology="" application_category="" in_interface="Port1" out_interface="Port2" src_mac=24:01:c7:07:2b:a2 src_ip=172.17.35.113 src_country_code="" dst_ip=172.20.4.52 dst_country_code="" protocol="TCP" src_port=53287 dst_port=4980 sent_pkts=0 recv_pkts=0 sent_bytes=0 recv_bytes=0 tran_src_ip="" tran_src_port=0 tran_dst_ip="" tran_dst_port=0 srczonetype="" srczone="" dstzonetype="" dstzone="" dir_disp="" connid="" vconnid="" hb_health="No Heartbeat" message="" appresolvedby="Signature" app_is_cloud=0 +<30>device="SFW" date=2020-05-18 time=14:38:40 timezone="CEST" device_name="XG230" device_id=1234567890123456 log_id=010102600002 log_type="Firewall" log_component="Firewall Rule" log_subtype="Denied" status="Deny" priority=Information duration=0 fw_rule_id=29 policy_type=1 user_name="elastic@user.local" user_gp="elastic.group.local" iap=2 ips_policy_id=0 appfilter_policy_id=0 application="" application_risk=0 application_technology="" application_category="" in_interface="tun0" out_interface="Port1" src_mac="" src_ip=10.82.234.6 src_country_code="" dst_ip=192.168.0.1 dst_country_code="" protocol="TCP" src_port=60102 dst_port=53 sent_pkts=0 recv_pkts=0 sent_bytes=0 recv_bytes=0 tran_src_ip="" tran_src_port=0 tran_dst_ip="" tran_dst_port=0 srczonetype="" srczone="" dstzonetype="" dstzone="" dir_disp="" connid="" vconnid="" hb_health="No Heartbeat" message="" appresolvedby="Signature" app_is_cloud=0 +<30>device="SFW" date=2020-05-18 time=14:38:41 timezone="CEST" device_name="XG230" device_id=1234567890123457 log_id=010302602002 log_type="Firewall" log_component="Appliance Access" log_subtype="Denied" status="Deny" priority=Information duration=0 fw_rule_id=0 policy_type=0 user_name="" user_gp="" iap=0 ips_policy_id=0 appfilter_policy_id=0 application="" application_risk=0 application_technology="" application_category="" in_interface="Port2" out_interface="" src_mac=c4:f7:d5:b5:47:f4 src_ip=67.43.156.12 src_country_code="" dst_ip=185.7.209.207 dst_country_code="" protocol="TCP" src_port=55039 dst_port=18 sent_pkts=0 recv_pkts=0 sent_bytes=0 recv_bytes=0 tran_src_ip="" tran_src_port=0 tran_dst_ip="" tran_dst_port=0 srczonetype="" srczone="" dstzonetype="" dstzone="" dir_disp="" connid="" vconnid="" hb_health="No Heartbeat" message="" appresolvedby="Signature" app_is_cloud=0 +<30>device="SFW" date=2020-05-18 time=14:38:42 timezone="CEST" device_name="XG230" device_id=1234567890123456 log_id=010102600002 log_type="Firewall" log_component="Firewall Rule" log_subtype="Denied" status="Deny" priority=Information duration=0 fw_rule_id=29 policy_type=1 user_name="elastic@user.local" user_gp="elastic.group.local" iap=2 ips_policy_id=0 appfilter_policy_id=0 application="" application_risk=0 application_technology="" application_category="" in_interface="Port1" out_interface="Port2" src_mac=24:01:c7:07:2b:a2 src_ip=172.17.35.101 src_country_code="" dst_ip=192.168.5.11 dst_country_code="" protocol="TCP" src_port=51826 dst_port=1109 sent_pkts=0 recv_pkts=0 sent_bytes=0 recv_bytes=0 tran_src_ip="" tran_src_port=0 tran_dst_ip="" tran_dst_port=0 srczonetype="" srczone="" dstzonetype="" dstzone="" dir_disp="" connid="" vconnid="" hb_health="No Heartbeat" message="" appresolvedby="Signature" app_is_cloud=0 +<30>device="SFW" date=2020-05-18 time=14:38:43 timezone="CEST" device_name="XG230" device_id=1234567890123457 log_id=010402403001 log_type="Firewall" log_component="DoS Attack" log_subtype="Denied" status="Deny" priority=Warning duration=0 fw_rule_id=0 policy_type=0 user_name="" user_gp="" iap=0 ips_policy_id=0 appfilter_policy_id=0 application="" application_risk=0 application_technology="" application_category="" in_interface="Port1" out_interface="" src_mac=34:db:fd:83:d8:09 src_ip=172.16.36.105 src_country_code="" dst_ip=10.84.234.14 dst_country_code="" protocol="UDP" src_port=3389 dst_port=64465 sent_pkts=0 recv_pkts=0 sent_bytes=0 recv_bytes=0 tran_src_ip="" tran_src_port=0 tran_dst_ip="" tran_dst_port=0 srczonetype="" srczone="" dstzonetype="" dstzone="" dir_disp="" connid="" vconnid="" hb_health="No Heartbeat" message="" appresolvedby="Signature" app_is_cloud=0 +<30>device="SFW" date=2020-05-18 time=14:38:44 timezone="CEST" device_name="XG230" device_id=1234567890123456 log_id=012802605201 log_type="Firewall" log_component="SSL VPN" log_subtype="Denied" status="Deny" priority=Information duration=0 fw_rule_id=0 policy_type=0 user_name="" user_gp="" iap=0 ips_policy_id=0 appfilter_policy_id=0 application="" application_risk=0 application_technology="" application_category="" in_interface="tun0" out_interface="" src_mac="" src_ip=10.82.234.9 src_country_code="" dst_ip=10.82.234.11 dst_country_code="" protocol="TCP" src_port=58331 dst_port=56267 sent_pkts=0 recv_pkts=0 sent_bytes=0 recv_bytes=0 tran_src_ip="" tran_src_port=0 tran_dst_ip="" tran_dst_port=0 srczonetype="" srczone="" dstzonetype="" dstzone="" dir_disp="" connid="" vconnid="" hb_health="No Heartbeat" message="" appresolvedby="Signature" app_is_cloud=0 +<30>device="SFW" date=2020-05-18 time=14:38:45 timezone="CEST" device_name="XG230" device_id=1234567890123456 log_id=010101600001 log_type="Firewall" log_component="Firewall Rule" log_subtype="Allowed" status="Allow" priority=Information duration=0 fw_rule_id=61 policy_type=2 user_name="elastic@user.local" user_gp="elastic.group.local" iap=0 ips_policy_id=11 appfilter_policy_id=0 application="" application_risk=0 application_technology="" application_category="" in_interface="ipsec0" out_interface="Port2" src_mac=00:00:00:00:00:00 src_ip=10.84.234.7 src_country_code=R1 dst_ip=172.16.34.50 dst_country_code=R1 protocol="TCP" src_port=58543 dst_port=443 sent_pkts=0 recv_pkts=0 sent_bytes=0 recv_bytes=0 tran_src_ip="" tran_src_port=0 tran_dst_ip="" tran_dst_port=0 srczonetype="VPN" srczone="VPN" dstzonetype="VPN" dstzone="VPN" dir_disp="" connevent="Start" connid="1615935064" vconnid="" hb_health="No Heartbeat" message="" appresolvedby="Signature" app_is_cloud=0 +<30>device="SFW" date=2020-05-18 time=14:38:45 timezone="CEST" device_name="XG230" device_id=1234567890123457 log_id=018201500005 log_type="Firewall" log_component="ICMP ERROR MESSAGE" log_subtype="Allowed" status="Allow" priority=Notice duration=0 fw_rule_id=60 policy_type=1 user_name="" user_gp="" iap=0 ips_policy_id=17 appfilter_policy_id=0 application="" application_risk=0 application_technology="" application_category="" in_interface="Port1" out_interface="" src_mac=34:db:fd:83:d8:09 src_ip=192.168.1.254 src_country_code="" dst_ip=172.17.32.19 dst_country_code="" protocol="ICMP" icmp_type=3 icmp_code=1 sent_pkts=0 recv_pkts=0 sent_bytes=0 recv_bytes=0 tran_src_ip="" tran_src_port=0 tran_dst_ip="" tran_dst_port=0 srczonetype="" srczone="" dstzonetype="" dstzone="" dir_disp="" connevent="Interim" connid="2685668438" vconnid="" hb_health="No Heartbeat" message="" appresolvedby="Signature" app_is_cloud=0 +<30>device="SFW" date=2020-06-05 time=12:38:53 timezone="CEST" device_name="XG230" device_id=1234567890123457 log_id=010101600001 log_type="Firewall" log_component="Firewall Rule" log_subtype="Allowed" status="Allow" priority=Information duration=10 fw_rule_id=60 policy_type=1 user_name="" user_gp="" iap=0 ips_policy_id=17 appfilter_policy_id=0 application="" application_risk=0 application_technology="" application_category="" in_interface="ipsec0" out_interface="Port1" src_mac=00:00:00:00:00:00 src_ip=172.17.35.119 src_country_code=R1 dst_ip=172.16.34.10 dst_country_code=R1 protocol="TCP" src_port=61925 dst_port=88 sent_pkts=6 recv_pkts=6 sent_bytes=1802 recv_bytes=1732 tran_src_ip= tran_src_port=0 tran_dst_ip= tran_dst_port=0srczonetype="VPN" srczone="VPN" dstzonetype="LAN" dstzone="LAN" dir_disp="" connevent="Stop" connid="1617126256" vconnid="" hb_health="NoHeartbeat" message="" appresolvedby="Signature" app_is_cloud=0" +<30>device="SFW" date=2018-05-30 time=13:26:37 timezone="IST" device_name="XG125w" device_id=SFDemo-763180a log_id=010202601001 log_type="Firewall" log_component="Invalid Traffic" log_subtype="Denied" status="Deny" priority=Information duration=0 fw_rule_id=0 policy_type=0 user_name="" user_gp="" iap=0 ips_policy_id=0 appfilter_policy_id=0 application="" application_risk=0 application_technology="" application_category="" in_interface="" out_interface="" src_mac= src_ip=10.198.32.19 src_country_code= dst_ip=175.16.199.1 dst_country_code= protocol="UDP" src_port=1353 dst_port=0 sent_pkts=0 recv_pkts=0 sent_bytes=0 recv_bytes=0 tran_src_ip= tran_src_port=0 tran_dst_ip= tran_dst_port=0 srczonetype="" srczone="" dstzonetype="" dstzone="" dir_disp="" connid="" vconnid="" hb_health="No Heartbeat" message="Invalid UDP destination." appresolvedby=" Signature" +<30>device="SFW" date=2018-06-04 time=17:20:24 timezone="IST" device_name="XG125w" device_id=SFDemo-763180a log_id=011402601301 log_type="Firewall" log_component="Fragmented Traffic" log_subtype="Denied" status="Deny" priority=Information duration=0 fw_rule_id=0 policy_type=0 user_name="" user_gp="" iap=0 ips_policy_id=0 appfilter_policy_id=0 application="" application_risk=0 application_technology="" application_category="" in_interface="" out_interface="" src_mac= src_ip=0.0.0.0 src_country_code= dst_ip=0.0.0.0 dst_country_code= protocol="0" src_port=0 dst_port=0 sent_pkts=0 recv_pkts=0 sent_bytes=0 recv_bytes=0 tran_src_ip= tran_src_port=0 tran_dst_ip= tran_dst_port=0 srczonetype="" srczone="" dstzonetype="" dstzone="" dir_disp="" connid="" vconnid="" hb_health="No Heartbeat" message="" appresolvedby="Signature" +<30>device="SFW" date=2018-05-30 time=14:01:32 timezone="IST" device_name="XG125w" device_id=SFDemo-763180a log_id=010302602002 log_type="Firewall" log_component="Appliance Access" log_subtype="Denied" status="Deny" priority=Information duration=0 fw_rule_id=2 policy_type=0 user_name="" user_gp="" iap=0 ips_policy_id=0 appfilter_policy_id=0 application="" application_risk=0 application_technology="" application_category="" in_interface="Port2.611" out_interface="" src_mac=c8:5b:76:ab:72:d3 src_ip=10.198.38.184 src_country_code= dst_ip=10.198.39.255 dst_country_code= protocol="UDP" src_port=137 dst_port=137 sent_pkts=0 recv_pkts=0 sent_bytes=0 recv_bytes=0 tran_src_ip= tran_src_port=0 tran_dst_ip= tran_dst_port=0 srczonetype="" srczone="" dstzonetype="" dstzone="" dir_disp="" connid="" vconnid="" hb_health="No Heartbeat" message="" appresolvedby="Signature" +<30>device="SFW" date=2018-05-30 time=14:17:17 timezone="IST" device_name="XG125w" device_id=SFDemo-763180a log_id=010402403001 log_type="Firewall" log_component="DoS Attack" log_subtype="Denied" status="Deny" priority=Warning duration=0 fw_rule_id=0 policy_type=0 user_name="" user_gp="" iap=0 ips_policy_id=0 appfilter_policy_id=0 application="" application_risk=0 application_technology="" application_category="" in_interface="Port1" out_interface="" src_mac=b8:97:5a:5b:0f:fd src_ip=10.198.32.19 src_country_code= dst_ip=10.198.32.48 dst_country_code= protocol="TCP" src_port=41960 dst_port=22 sent_pkts=0 recv_pkts=0 sent_bytes=0 recv_bytes=0 tran_src_ip= tran_src_port=0 tran_dst_ip= tran_dst_port=0 srczonetype="" srczone="" dstzonetype="" dstzone="" dir_disp="" connid="" vconnid="" hb_health="No Heartbeat" message="" appresolvedby=" Signature" +<30>device="SFW" date=2018-06-05 time=14:30:31 timezone="IST" device_name="XG125w" device_id=SFDemo-763180a log_id=010502604001 log_type="Firewall" log_component="ICMP Redirection" log_subtype="Denied" status="Deny" priority=Information duration=0 fw_rule_id=0 policy_type=0 user_name="" user_gp="" iap=0 ips_policy_id=0 appfilter_policy_id=0 application="" application_risk=0 application_technology="" application_category="" in_interface="" out_interface="" src_mac= src_ip=10.198.37.23 src_country_code= dst_ip=10.198.36.48 dst_country_code= protocol="ICMP" icmp_type=5 icmp_code=1 sent_pkts=0 recv_pkts=0 sent_bytes=0 recv_bytes=0 tran_src_ip= tran_src_port=0 tran_dst_ip= tran_dst_port=0 srczonetype="" srczone="" dstzonetype="" dstzone="" dir_disp="" connid="" vconnid="" hb_health="No Heartbeat" message="" appresolvedby=" Signature" +<30>device="SFW" date=2018-05-31 time=17:05:14 timezone="IST" device_name="XG125w" device_id=SFDemo-763180a log_id=010602605001 log_type="Firewall" log_component="Source Routed" log_subtype="Denied" status="Deny" priority=Information duration=0 fw_rule_id=1 policy_type=1 user_name="" user_gp="" iap=0 ips_policy_id=0 appfilter_policy_id=0 application="" application_risk=0 application_technology="" application_category="" in_interface="" out_interface="" src_mac= src_ip=10.198.12.19 src_country_code= dst_ip=175.16.199.1 dst_country_code= protocol="TCP" src_port=1571 dst_port=80 sent_pkts=0 recv_pkts=0 sent_bytes=0 recv_bytes=0 tran_src_ip= tran_src_port=0 tran_dst_ip= tran_dst_port=0 srczonetype="" srczone="" dstzonetype="" dstzone="" dir_disp="" connid="" vconnid="" hb_health="No Heartbeat" message="" appresolvedby="Signature" +<30>device="SFW" date=2018-05-30 time=15:09:51 timezone="IST" device_name="XG125w" device_id=SFDemo-763180a log_id=011702605051 log_type="Firewall" log_component="MAC Filter" log_subtype="Denied" status="Deny" priority=Information duration=0 fw_rule_id=0 policy_type=0 user_name="" user_gp="" iap=0 ips_policy_id=0 appfilter_policy_id=0 application="" application_risk=0 application_technology="" application_category="" in_interface="Port2.531" out_interface="" src_mac=1e:3a:5a:5b:23:ab src_ip=fe80::59f5:3ce8:c98e:5062 src_country_code= dst_ip=ff02::1:2 dst_country_code= protocol="UDP" src_port=546 dst_port=547 sent_pkts=0 recv_pkts=0 sent_bytes=0 recv_bytes=0 tran_src_ip= tran_src_port=0 tran_dst_ip= tran_dst_port=0 srczonetype="" srczone="" dstzonetype="" dstzone="" dir_disp="" connid="" vconnid="" hb_health="No Heartbeat" message="" appresolvedby="Signature" +<30>device="SFW" date=2018-06-01 time=10:57:55 timezone="BST" device_name="XG310" device_id=SFDemo-9a04c43 log_id=016602600006 log_type="Firewall" log_component="Heartbeat" log_subtype="Denied" status="Deny" priority=Information duration=0 fw_rule_id=16 policy_type=1 user_name="" user_gp="" iap=2 ips_policy_id=0 appfilter_policy_id=0 application="" application_risk=0 application_technology="" application_category="" in_interface="Port3.611" out_interface="" src_mac=08:00:27:4c:49:e3 src_ip=10.198.37.57 src_country_code= dst_ip=10.198.32.19 dst_country_code= protocol="ICMP" icmp_type=8 icmp_code=0 sent_pkts=0 recv_pkts=0 sent_bytes=0 recv_bytes=0 tran_src_ip= tran_src_port=0 tran_dst_ip= tran_dst_port=0 srczonetype="" srczone="" dstzonetype="" dstzone="" dir_disp="" connid="" vconnid="" hb_health="Red" message="" appresolvedby="Signature" app_is_cloud=0 +<30>device="SFW" date=2018-06-01 time=10:55:41 timezone="BST" device_name="XG310" device_id=SFDemo-9a04c43 log_id=016602600003 log_type="Firewall" log_component="Heartbeat" log_subtype="Denied" status="Deny" priority=Information duration=0 fw_rule_id=16 policy_type=1 user_name="" user_gp="" iap=2 ips_policy_id=0 appfilter_policy_id=0 application="" application_risk=0 application_technology="" application_category="" in_interface="Port3.611" out_interface="" src_mac=08:00:27:4c:49:e3 src_ip=10.198.37.57 src_country_code= dst_ip=72.163.4.185 dst_country_code= protocol="ICMP" icmp_type=8 icmp_code=0 sent_pkts=0 recv_pkts=0 sent_bytes=0 recv_bytes=0 tran_src_ip= tran_src_port=0 tran_dst_ip= tran_dst_port=0 srczonetype="" srczone="" dstzonetype="" dstzone="" dir_disp="" connid="" vconnid="" hb_health="Red" message="" appresolvedby="Signature" app_is_cloud=0 +<01>Feb 11 13:12:45 _gateway device="SFW" date=2021-02-11 time=13:12:45 timezone="CET" device_name="XG210" device_id=dem-dev log_id=010101600001 log_type="Firewall" log_component="Firewall Rule" log_subtype="Allowed" status="Allow" priority=Information duration=0 fw_rule_id=9 nat_rule_id=16 policy_type=1 user_name="" user_gp="" iap=0 ips_policy_id=0 appfilter_policy_id=0 application="" application_risk=0 application_technology="" application_category="" vlan_id="" ether_type=Unknown (0x0000) bridge_name="" bridge_display_name="" in_interface="Port2.109" in_display_interface="CD21-IPs_WAN" out_interface="Port5.200" out_display_interface="Port5" src_mac=11:22:33:44:55:66 dst_mac=66:55:44:33:22:11 src_ip=1.2.3.4 src_country_code=ESP dst_ip=4.3.2.1 dst_country_code=GB protocol="TCP" src_port=33370 dst_port=443 sent_pkts=0 recv_pkts=0 sent_bytes=0 recv_bytes=0 tran_src_ip=2.4.6.8 tran_src_port=0 tran_dst_ip=8.6.4.2 tran_dst_port=0 srczonetype="WAN" srczone="WAN" dstzonetype="DMZ" dstzone="Zone 9" dir_disp="" connevent="Start" connid="3933925696" vconnid="" hb_health="No Heartbeat" message="" appresolvedby="Signature" app_is_cloud=0 +<01>device="SFW" date=2020-06-05 time=03:45:23 timezone="CEST" device_name="SF01V" device_id=SFDemo-ta-vm-55 log_id=010101600001 log_type="Firewall" log_component="Firewall Rule" log_subtype="Allowed" status="Allow" priority=Information duration=0 fw_rule_id=5 nat_rule_id=2 policy_type=1 user_name="" user_gp="" iap=13 ips_policy_id=0 appfilter_policy_id=0 application="" application_risk=0 application_technology="" application_category="" vlan_id="" ether_type=Unknown (0x0000) bridge_name="" bridge_display_name="" in_interface="Port2" in_display_interface="Port2" out_interface="Port1" out_display_interface="Port1" src_mac=00:50:56:99:51:94 dst_mac=00:50:56:99:3D:AC src_ip=10.146.13.30 src_country_code= dst_ip=10.8.142.181 dst_country_code= protocol="TCP" src_port=45294 dst_port=443 sent_pkts=0 recv_pkts=0 sent_bytes=0 recv_bytes=0 tran_src_ip=10.8.13.110 tran_src_port=0 tran_dst_ip= tran_dst_port=0 srczonetype="LAN" srczone="LAN" dstzonetype="WAN" dstzone="WAN" dir_disp="" connevent="Start" connid="2674291981" vconnid="" hb_health="No Heartbeat"message="" appresolvedby="Signature" app_is_cloud=0 log_occurrence=1 diff --git a/x-pack/filebeat/module/sophos/xg/test/firewall.log-expected.json b/x-pack/filebeat/module/sophos/xg/test/firewall.log-expected.json index deb91f6a5a3..d6bb070314e 100644 --- a/x-pack/filebeat/module/sophos/xg/test/firewall.log-expected.json +++ b/x-pack/filebeat/module/sophos/xg/test/firewall.log-expected.json @@ -138,7 +138,7 @@ "host.name": "some_other_host.local", "input.type": "log", "log.level": "informational", - "log.offset": 983, + "log.offset": 982, "network.bytes": 0, "network.direction": "outbound", "network.packets": 0, @@ -243,7 +243,7 @@ "host.name": "my_fancy_host", "input.type": "log", "log.level": "informational", - "log.offset": 1971, + "log.offset": 1969, "network.bytes": 0, "network.packets": 0, "network.transport": "tcp", @@ -329,7 +329,7 @@ "host.name": "my_fancy_host", "input.type": "log", "log.level": "informational", - "log.offset": 2867, + "log.offset": 2864, "network.bytes": 0, "network.packets": 0, "network.transport": "tcp", @@ -420,7 +420,7 @@ "host.name": "some_other_host.local", "input.type": "log", "log.level": "informational", - "log.offset": 3780, + "log.offset": 3776, "network.bytes": 0, "network.packets": 0, "network.transport": "tcp", @@ -512,7 +512,7 @@ "host.name": "my_fancy_host", "input.type": "log", "log.level": "informational", - "log.offset": 4672, + "log.offset": 4667, "network.bytes": 0, "network.packets": 0, "network.transport": "tcp", @@ -605,7 +605,7 @@ "host.name": "some_other_host.local", "input.type": "log", "log.level": "warning", - "log.offset": 5606, + "log.offset": 5600, "network.bytes": 0, "network.packets": 0, "network.transport": "udp", @@ -690,7 +690,7 @@ "host.name": "my_fancy_host", "input.type": "log", "log.level": "informational", - "log.offset": 6490, + "log.offset": 6483, "network.bytes": 0, "network.packets": 0, "network.transport": "tcp", @@ -776,7 +776,7 @@ "host.name": "my_fancy_host", "input.type": "log", "log.level": "informational", - "log.offset": 7358, + "log.offset": 7350, "network.bytes": 0, "network.direction": "internal", "network.packets": 0, @@ -874,7 +874,7 @@ "host.name": "some_other_host.local", "input.type": "log", "log.level": "notification", - "log.offset": 8333, + "log.offset": 8324, "network.bytes": 0, "network.packets": 0, "network.transport": "icmp", @@ -962,7 +962,7 @@ "host.name": "some_other_host.local", "input.type": "log", "log.level": "informational", - "log.offset": 9254, + "log.offset": 9244, "network.bytes": 3534, "network.packets": 12, "network.transport": "tcp", @@ -1060,7 +1060,7 @@ "host.name": "firewall.localgroup.local", "input.type": "log", "log.level": "informational", - "log.offset": 10194, + "log.offset": 10183, "network.bytes": 0, "network.packets": 0, "network.transport": "udp", @@ -1143,7 +1143,7 @@ "host.name": "firewall.localgroup.local", "input.type": "log", "log.level": "informational", - "log.offset": 11059, + "log.offset": 11047, "network.bytes": 0, "network.packets": 0, "network.transport": "0", @@ -1225,7 +1225,7 @@ "host.name": "firewall.localgroup.local", "input.type": "log", "log.level": "informational", - "log.offset": 11887, + "log.offset": 11874, "network.bytes": 0, "network.packets": 0, "network.transport": "udp", @@ -1311,7 +1311,7 @@ "host.name": "firewall.localgroup.local", "input.type": "log", "log.level": "warning", - "log.offset": 12757, + "log.offset": 12743, "network.bytes": 0, "network.packets": 0, "network.transport": "tcp", @@ -1393,7 +1393,7 @@ "host.name": "firewall.localgroup.local", "input.type": "log", "log.level": "informational", - "log.offset": 13613, + "log.offset": 13598, "network.bytes": 0, "network.packets": 0, "network.transport": "icmp", @@ -1484,7 +1484,7 @@ "host.name": "firewall.localgroup.local", "input.type": "log", "log.level": "informational", - "log.offset": 14455, + "log.offset": 14439, "network.bytes": 0, "network.packets": 0, "network.transport": "tcp", @@ -1567,7 +1567,7 @@ "host.name": "firewall.localgroup.local", "input.type": "log", "log.level": "informational", - "log.offset": 15294, + "log.offset": 15277, "network.bytes": 0, "network.packets": 0, "network.transport": "udp", @@ -1650,7 +1650,7 @@ "host.name": "firewall.localgroup.local", "input.type": "log", "log.level": "informational", - "log.offset": 16166, + "log.offset": 16148, "network.bytes": 0, "network.packets": 0, "network.transport": "icmp", @@ -1735,7 +1735,7 @@ "host.name": "firewall.localgroup.local", "input.type": "log", "log.level": "informational", - "log.offset": 17032, + "log.offset": 17013, "network.bytes": 0, "network.packets": 0, "network.transport": "icmp", @@ -1784,5 +1784,205 @@ "forwarded", "sophos-xg" ] + }, + { + "@timestamp": "2021-02-11T13:12:45.000-02:00", + "client.bytes": 0, + "client.ip": "1.2.3.4", + "client.mac": "11:22:33:44:55:66", + "client.nat.port": 0, + "client.packets": 0, + "client.port": 33370, + "destination.bytes": 0, + "destination.ip": "4.3.2.1", + "destination.mac": "66:55:44:33:22:11", + "destination.nat.ip": "8.6.4.2", + "destination.nat.port": 0, + "destination.packets": 0, + "destination.port": 443, + "event.action": "allowed", + "event.category": [ + "network" + ], + "event.code": "010101600001", + "event.dataset": "sophos.xg", + "event.duration": 0, + "event.end": "2021-02-11T13:12:45.000-02:00", + "event.kind": "event", + "event.module": "sophos", + "event.original": "device=\"SFW\" date=2021-02-11 time=13:12:45 timezone=\"CET\" device_name=\"XG210\" device_id=dem-dev log_id=010101600001 log_type=\"Firewall\" log_component=\"Firewall Rule\" log_subtype=\"Allowed\" status=\"Allow\" priority=Information duration=0 fw_rule_id=9 nat_rule_id=16 policy_type=1 user_name=\"\" user_gp=\"\" iap=0 ips_policy_id=0 appfilter_policy_id=0 application=\"\" application_risk=0 application_technology=\"\" application_category=\"\" vlan_id=\"\" ether_type=Unknown (0x0000) bridge_name=\"\" bridge_display_name=\"\" in_interface=\"Port2.109\" in_display_interface=\"CD21-IPs_WAN\" out_interface=\"Port5.200\" out_display_interface=\"Port5\" src_mac=11:22:33:44:55:66 dst_mac=66:55:44:33:22:11 src_ip=1.2.3.4 src_country_code=ESP dst_ip=4.3.2.1 dst_country_code=GB protocol=\"TCP\" src_port=33370 dst_port=443 sent_pkts=0 recv_pkts=0 sent_bytes=0 recv_bytes=0 tran_src_ip=2.4.6.8 tran_src_port=0 tran_dst_ip=8.6.4.2 tran_dst_port=0 srczonetype=\"WAN\" srczone=\"WAN\" dstzonetype=\"DMZ\" dstzone=\"Zone 9\" dir_disp=\"\" connevent=\"Start\" connid=\"3933925696\" vconnid=\"\" hb_health=\"No Heartbeat\" message=\"\" appresolvedby=\"Signature\" app_is_cloud=0", + "event.outcome": "success", + "event.severity": "6", + "event.start": "2021-02-11T13:12:45.000-02:00", + "event.timezone": "-02:00", + "event.type": [ + "allowed", + "connection", + "start" + ], + "fileset.name": "xg", + "host.name": "firewall.localgroup.local", + "input.type": "log", + "log.level": "informational", + "log.offset": 17878, + "network.bytes": 0, + "network.direction": "inbound", + "network.packets": 0, + "network.transport": "tcp", + "observer.egress.interface.name": "Port5.200", + "observer.egress.zone": "DMZ", + "observer.ingress.interface.name": "Port2.109", + "observer.ingress.zone": "WAN", + "observer.product": "XG", + "observer.serial_number": "dem-dev", + "observer.type": "firewall", + "observer.vendor": "Sophos", + "related.hosts": [ + "firewall.localgroup.local" + ], + "related.ip": [ + "1.2.3.4", + "2.4.6.8", + "4.3.2.1", + "8.6.4.2" + ], + "rule.id": "9", + "rule.ruleset": "1", + "server.bytes": 0, + "server.ip": "4.3.2.1", + "server.mac": "66:55:44:33:22:11", + "server.nat.port": 0, + "server.packets": 0, + "server.port": 443, + "service.type": "sophos", + "sophos.xg.app_is_cloud": "0", + "sophos.xg.appfilter_policy_id": "0", + "sophos.xg.application_risk": "0", + "sophos.xg.appresolvedby": "Signature", + "sophos.xg.connevent": "Start", + "sophos.xg.connid": "3933925696", + "sophos.xg.device": "SFW", + "sophos.xg.device_name": "XG210", + "sophos.xg.dst_country_code": "GB", + "sophos.xg.ether_type": "Unknown (0x0000)", + "sophos.xg.hb_health": "No Heartbeat", + "sophos.xg.iap": "0", + "sophos.xg.ips_policy_id": "0", + "sophos.xg.log_component": "Firewall Rule", + "sophos.xg.log_subtype": "Allowed", + "sophos.xg.log_type": "Firewall", + "sophos.xg.message_id": "00001", + "sophos.xg.priority": "Information", + "sophos.xg.src_country_code": "ESP", + "sophos.xg.status": "Allow", + "source.bytes": 0, + "source.ip": "1.2.3.4", + "source.mac": "11:22:33:44:55:66", + "source.nat.ip": "2.4.6.8", + "source.nat.port": 0, + "source.packets": 0, + "source.port": 33370, + "tags": [ + "forwarded", + "sophos-xg" + ] + }, + { + "@timestamp": "2020-06-05T03:45:23.000-02:00", + "client.bytes": 0, + "client.ip": "10.146.13.30", + "client.mac": "00:50:56:99:51:94", + "client.nat.port": 0, + "client.packets": 0, + "client.port": 45294, + "destination.bytes": 0, + "destination.ip": "10.8.142.181", + "destination.mac": "00:50:56:99:3D:AC", + "destination.nat.port": 0, + "destination.packets": 0, + "destination.port": 443, + "event.action": "allowed", + "event.category": [ + "network" + ], + "event.code": "010101600001", + "event.dataset": "sophos.xg", + "event.duration": 0, + "event.end": "2020-06-05T03:45:23.000-02:00", + "event.kind": "event", + "event.module": "sophos", + "event.original": "device=\"SFW\" date=2020-06-05 time=03:45:23 timezone=\"CEST\" device_name=\"SF01V\" device_id=SFDemo-ta-vm-55 log_id=010101600001 log_type=\"Firewall\" log_component=\"Firewall Rule\" log_subtype=\"Allowed\" status=\"Allow\" priority=Information duration=0 fw_rule_id=5 nat_rule_id=2 policy_type=1 user_name=\"\" user_gp=\"\" iap=13 ips_policy_id=0 appfilter_policy_id=0 application=\"\" application_risk=0 application_technology=\"\" application_category=\"\" vlan_id=\"\" ether_type=Unknown (0x0000) bridge_name=\"\" bridge_display_name=\"\" in_interface=\"Port2\" in_display_interface=\"Port2\" out_interface=\"Port1\" out_display_interface=\"Port1\" src_mac=00:50:56:99:51:94 dst_mac=00:50:56:99:3D:AC src_ip=10.146.13.30 src_country_code= dst_ip=10.8.142.181 dst_country_code= protocol=\"TCP\" src_port=45294 dst_port=443 sent_pkts=0 recv_pkts=0 sent_bytes=0 recv_bytes=0 tran_src_ip=10.8.13.110 tran_src_port=0 tran_dst_ip= tran_dst_port=0 srczonetype=\"LAN\" srczone=\"LAN\" dstzonetype=\"WAN\" dstzone=\"WAN\" dir_disp=\"\" connevent=\"Start\" connid=\"2674291981\" vconnid=\"\" hb_health=\"No Heartbeat\"message=\"\" appresolvedby=\"Signature\" app_is_cloud=0 log_occurrence=1", + "event.outcome": "success", + "event.severity": "6", + "event.start": "2020-06-05T03:45:23.000-02:00", + "event.timezone": "-02:00", + "event.type": [ + "allowed", + "connection", + "start" + ], + "fileset.name": "xg", + "host.name": "firewall.localgroup.local", + "input.type": "log", + "log.level": "informational", + "log.offset": 19024, + "network.bytes": 0, + "network.direction": "outbound", + "network.packets": 0, + "network.transport": "tcp", + "observer.egress.interface.name": "Port1", + "observer.egress.zone": "WAN", + "observer.ingress.interface.name": "Port2", + "observer.ingress.zone": "LAN", + "observer.product": "XG", + "observer.serial_number": "SFDemo-ta-vm-55", + "observer.type": "firewall", + "observer.vendor": "Sophos", + "related.hosts": [ + "firewall.localgroup.local" + ], + "related.ip": [ + "10.146.13.30", + "10.8.13.110", + "10.8.142.181" + ], + "rule.id": "5", + "rule.ruleset": "1", + "server.bytes": 0, + "server.ip": "10.8.142.181", + "server.mac": "00:50:56:99:3D:AC", + "server.nat.port": 0, + "server.packets": 0, + "server.port": 443, + "service.type": "sophos", + "sophos.xg.app_is_cloud": "0", + "sophos.xg.appfilter_policy_id": "0", + "sophos.xg.application_risk": "0", + "sophos.xg.appresolvedby": "Signature", + "sophos.xg.connevent": "Start", + "sophos.xg.connid": "2674291981", + "sophos.xg.device": "SFW", + "sophos.xg.device_name": "SF01V", + "sophos.xg.ether_type": "Unknown (0x0000)", + "sophos.xg.hb_health": "No Heartbeat\"message=", + "sophos.xg.iap": "13", + "sophos.xg.ips_policy_id": "0", + "sophos.xg.log_component": "Firewall Rule", + "sophos.xg.log_subtype": "Allowed", + "sophos.xg.log_type": "Firewall", + "sophos.xg.message_id": "00001", + "sophos.xg.priority": "Information", + "sophos.xg.status": "Allow", + "source.bytes": 0, + "source.ip": "10.146.13.30", + "source.mac": "00:50:56:99:51:94", + "source.nat.ip": "10.8.13.110", + "source.nat.port": 0, + "source.packets": 0, + "source.port": 45294, + "tags": [ + "forwarded", + "sophos-xg" + ] } ] \ No newline at end of file diff --git a/x-pack/filebeat/module/sophos/xg/test/idp.log b/x-pack/filebeat/module/sophos/xg/test/idp.log index 818b057ba8f..57d9e84066d 100644 --- a/x-pack/filebeat/module/sophos/xg/test/idp.log +++ b/x-pack/filebeat/module/sophos/xg/test/idp.log @@ -1,6 +1,6 @@ -<30>device="SFW" date=2020-05-18 time=14:38:54 timezone="CEST" device_name="XG230" device_id=1234567890123456 log_id=020804407002 log_type="IDP" log_component="Signatures" log_subtype="Drop" priority=Warning idp_policy_id=7 fw_rule_id=25 user_name="" signature_id=1881 signature_msg="SERVER-WEBAPP bad HTTP 1.1 request - potential worm attack" classification="access to a potentially vulnerable web application" rule_priority=2 src_ip=67.43.156.12 src_country_code=ROU dst_ip=172.16.68.20 dst_country_code=R1 protocol="TCP" src_port=41528 dst_port=80 platform="BSD,Linux,Mac,Other,Solaris,Unix,Windows" category="server-webapp" target="Server" -<30>device="SFW" date=2020-05-18 time=14:38:55 timezone="CEST" device_name="XG230" device_id=1234567890123456 log_id=020804407002 log_type="IDP" log_component="Signatures" log_subtype="Drop" priority=Warning idp_policy_id=7 fw_rule_id=23 user_name="" signature_id=1616 signature_msg="PROTOCOL-DNS named version attempt" classification="Attempted Information Leak" rule_priority=1 src_ip=89.160.20.156 src_country_code=CHN dst_ip=67.43.156.12 dst_country_code=R1 protocol="UDP" src_port=58914 dst_port=53 platform="BSD,Linux,Mac,Other,Solaris,Unix,Windows" category="protocol-dns" target="Server" -<30>device="SFW" date=2020-05-18 time=14:38:56 timezone="CEST" device_name="XG230" device_id=1234567890123457 log_id=020804407002 log_type="IDP" log_component="Signatures" log_subtype="Drop" priority=Warning idp_policy_id=7 fw_rule_id=25 user_name="" signature_id=53589 signature_msg="SERVER-WEBAPP DrayTek multiple products command injection attempt" classification="Web Application Attack" rule_priority=2 src_ip=67.43.156.12 src_country_code=NLD dst_ip=172.16.68.20 dst_country_code=R1 protocol="TCP" src_port=59476 dst_port=80 platform="Linux,Mac,Other,Unix,Windows" category="server-webapp" target="Server" -<30>device="SFW" date=2018-05-23 time=16:20:34 timezone="BST" device_name="XG750" device_id=SFDemo-f64dd6be log_id=020703406001 log_type="IDP" log_component="Anomaly" log_subtype="Detect" priority=Warning idp_policy_id=1 fw_rule_id=2 user_name="" signature_id=26022 signature_msg="FILE-PDF EmbeddedFile contained within a PDF" classification="A Network Trojan was detected" rule_priority=1 src_ip=10.0.0.168 src_country_code=R1 dst_ip=10.1.1.234 dst_country_code=R1 protocol="TCP" src_port=28938 dst_port=25 platform="Windows" category="Malware Communication" target="Server" -<30>device="SFW" date=2018-05-23 time=16:16:43 timezone="BST" device_name="XG750" device_id=SFDemo-f64dd6be log_id=020704406002 log_type="IDP" log_component="Anomaly" log_subtype="Drop" priority=Warning idp_policy_id=1 fw_rule_id=2 user_name="" signature_id=26022 signature_msg="FILE-PDF EmbeddedFile contained within a PDF" classification="A Network Trojan was detected" rule_priority=1 src_ip=10.0.1.31 src_country_code=R1 dst_ip=10.1.0.115 dst_country_code=R1 protocol="TCP" src_port=40140 dst_port=25 platform="Windows" category="Malware Communication" target="Server" - +<30>device="SFW" date=2020-05-18 time=14:38:54 timezone="CEST" device_name="XG230" device_id=1234567890123456 log_id=020804407002 log_type="IDP" log_component="Signatures" log_subtype="Drop" priority=Warning idp_policy_id=7 fw_rule_id=25 user_name="" signature_id=1881 signature_msg="SERVER-WEBAPP bad HTTP 1.1 request - potential worm attack" classification="access to a potentially vulnerable web application" rule_priority=2 src_ip=67.43.156.12 src_country_code=ROU dst_ip=172.16.68.20 dst_country_code=R1 protocol="TCP" src_port=41528 dst_port=80 platform="BSD,Linux,Mac,Other,Solaris,Unix,Windows" category="server-webapp" target="Server" +<30>device="SFW" date=2020-05-18 time=14:38:55 timezone="CEST" device_name="XG230" device_id=1234567890123456 log_id=020804407002 log_type="IDP" log_component="Signatures" log_subtype="Drop" priority=Warning idp_policy_id=7 fw_rule_id=23 user_name="" signature_id=1616 signature_msg="PROTOCOL-DNS named version attempt" classification="Attempted Information Leak" rule_priority=1 src_ip=89.160.20.156 src_country_code=CHN dst_ip=67.43.156.12 dst_country_code=R1 protocol="UDP" src_port=58914 dst_port=53 platform="BSD,Linux,Mac,Other,Solaris,Unix,Windows" category="protocol-dns" target="Server" +<30>device="SFW" date=2020-05-18 time=14:38:56 timezone="CEST" device_name="XG230" device_id=1234567890123457 log_id=020804407002 log_type="IDP" log_component="Signatures" log_subtype="Drop" priority=Warning idp_policy_id=7 fw_rule_id=25 user_name="" signature_id=53589 signature_msg="SERVER-WEBAPP DrayTek multiple products command injection attempt" classification="Web Application Attack" rule_priority=2 src_ip=67.43.156.12 src_country_code=NLD dst_ip=172.16.68.20 dst_country_code=R1 protocol="TCP" src_port=59476 dst_port=80 platform="Linux,Mac,Other,Unix,Windows" category="server-webapp" target="Server" +<30>device="SFW" date=2018-05-23 time=16:20:34 timezone="BST" device_name="XG750" device_id=SFDemo-f64dd6be log_id=020703406001 log_type="IDP" log_component="Anomaly" log_subtype="Detect" priority=Warning idp_policy_id=1 fw_rule_id=2 user_name="" signature_id=26022 signature_msg="FILE-PDF EmbeddedFile contained within a PDF" classification="A Network Trojan was detected" rule_priority=1 src_ip=10.0.0.168 src_country_code=R1 dst_ip=10.1.1.234 dst_country_code=R1 protocol="TCP" src_port=28938 dst_port=25 platform="Windows" category="Malware Communication" target="Server" +<30>device="SFW" date=2018-05-23 time=16:16:43 timezone="BST" device_name="XG750" device_id=SFDemo-f64dd6be log_id=020704406002 log_type="IDP" log_component="Anomaly" log_subtype="Drop" priority=Warning idp_policy_id=1 fw_rule_id=2 user_name="" signature_id=26022 signature_msg="FILE-PDF EmbeddedFile contained within a PDF" classification="A Network Trojan was detected" rule_priority=1 src_ip=10.0.1.31 src_country_code=R1 dst_ip=10.1.0.115 dst_country_code=R1 protocol="TCP" src_port=40140 dst_port=25 platform="Windows" category="Malware Communication" target="Server" + diff --git a/x-pack/filebeat/module/sophos/xg/test/idp.log-expected.json b/x-pack/filebeat/module/sophos/xg/test/idp.log-expected.json index de3cb1b3111..2bfe7cdce63 100644 --- a/x-pack/filebeat/module/sophos/xg/test/idp.log-expected.json +++ b/x-pack/filebeat/module/sophos/xg/test/idp.log-expected.json @@ -106,7 +106,7 @@ "host.name": "my_fancy_host", "input.type": "log", "log.level": "warning", - "log.offset": 645, + "log.offset": 644, "network.transport": "UDP", "observer.product": "XG", "observer.serial_number": "1234567890123456", @@ -184,7 +184,7 @@ "host.name": "some_other_host.local", "input.type": "log", "log.level": "warning", - "log.offset": 1242, + "log.offset": 1240, "network.transport": "TCP", "observer.product": "XG", "observer.serial_number": "1234567890123457", @@ -258,7 +258,7 @@ "host.name": "firewall.localgroup.local", "input.type": "log", "log.level": "warning", - "log.offset": 1855, + "log.offset": 1852, "network.transport": "TCP", "observer.product": "XG", "observer.serial_number": "SFDemo-f64dd6be", @@ -326,7 +326,7 @@ "host.name": "firewall.localgroup.local", "input.type": "log", "log.level": "warning", - "log.offset": 2432, + "log.offset": 2428, "network.transport": "TCP", "observer.product": "XG", "observer.serial_number": "SFDemo-f64dd6be", diff --git a/x-pack/filebeat/module/sophos/xg/test/sandbox.log b/x-pack/filebeat/module/sophos/xg/test/sandbox.log index bd64715de04..097b999d89c 100644 --- a/x-pack/filebeat/module/sophos/xg/test/sandbox.log +++ b/x-pack/filebeat/module/sophos/xg/test/sandbox.log @@ -1,6 +1,6 @@ -<30>device="SFW" date=2017-01-31 time=14:52:11 timezone="IST" device_name="CR750iNG-XP" device_id=C44310050024-P29PUA log_id=138301618041 log_type="Sandbox" log_component="Mail" log_subtype="Allowed" priority=Information user_name="" src_ip= filename="" filetype="" filesize=0 sha1sum="" source="" reason="eligible" destination="" subject="" -<30>device="SFW" date=2017-01-31 time=14:52:11 timezone="IST" device_name="CR750iNG-XP" device_id=C44310050024-P29PUA log_id=138302218042 log_type="Sandbox" log_component="Mail" log_subtype="Denied" priority=Critical user_name="jsmith@iview.com" src_ip=10.198.47.112 filename="1.exe" filetype="application/octet-stream" filesize=153006 sha1sum="83cd339302bf5e8ed5240ca6383418089c337a81" source="jsmith@iview.com" reason="cached malicious" destination="" subject="" -<30>device="SFW" date=2017-01-31 time=15:28:25 timezone="IST" device_name="CR750iNG-XP" device_id=C44313350024-P29PUA log_id=136501618041 log_type="Sandbox" log_component="Web" log_subtype="Allowed" priority=Information user_name="" src_ip= filename="" filetype="" filesize=0 sha1sum="" source="" reason="eligible" destination="" subject="" -<30>device="SFW" date=2017-01-31 time=15:28:25 timezone="IST" device_name="CR750iNG-XP" device_id=C44310050024-P29PUA log_id=136528618043 log_type="Sandbox" log_component="Web" log_subtype="Pending" priority=Information user_name="jsmith" src_ip=10.198.47.112 filename="19.exe" filetype="application/octet-stream" filesize=153010 sha1sum="3ce799580908df9ca0dc649aa8c2d06ab267e8c8" source="10.198.241.50" reason="pending" destination="" subject="" -<30>device="SFW" date=2017-01-31 time=15:28:25 timezone="IST" device_name="CR750iNG-XP" device_id=C44310050024-P29PUA log_id=136502218042 log_type="Sandbox" log_component="Web" log_subtype="Denied" priority=Critical user_name="jsmith" src_ip=10.198.47.112 filename="19.exe" filetype="application/octet-stream" filesize=153010 sha1sum="3ce799580908df9ca0dc649aa8c2d06ab267e8c8" source="10.198.241.50" reason="cloud malicious" destination="" subject=" -<30>device="SFW" date=2020-05-18 time=14:38:36 timezone="IST" device_name="CR750iNG-XP" device_id=C44310050024-P29PUA log_id=136502218042 log_type="Sandbox" log_component="Web" log_subtype="Denied" priority=Critical user_name="" src_ip=172.16.34.24 filename="SBTestFile1.pdf" filetype="application/pdf" filesize=1124 sha1sum="d910c4a81122c360fe57f67a04999425a65249db" source="sophostest.com" reason="cached malicious" destination="" subject="" +<30>device="SFW" date=2017-01-31 time=14:52:11 timezone="IST" device_name="CR750iNG-XP" device_id=C44310050024-P29PUA log_id=138301618041 log_type="Sandbox" log_component="Mail" log_subtype="Allowed" priority=Information user_name="" src_ip= filename="" filetype="" filesize=0 sha1sum="" source="" reason="eligible" destination="" subject="" +<30>device="SFW" date=2017-01-31 time=14:52:11 timezone="IST" device_name="CR750iNG-XP" device_id=C44310050024-P29PUA log_id=138302218042 log_type="Sandbox" log_component="Mail" log_subtype="Denied" priority=Critical user_name="jsmith@iview.com" src_ip=10.198.47.112 filename="1.exe" filetype="application/octet-stream" filesize=153006 sha1sum="83cd339302bf5e8ed5240ca6383418089c337a81" source="jsmith@iview.com" reason="cached malicious" destination="" subject="" +<30>device="SFW" date=2017-01-31 time=15:28:25 timezone="IST" device_name="CR750iNG-XP" device_id=C44313350024-P29PUA log_id=136501618041 log_type="Sandbox" log_component="Web" log_subtype="Allowed" priority=Information user_name="" src_ip= filename="" filetype="" filesize=0 sha1sum="" source="" reason="eligible" destination="" subject="" +<30>device="SFW" date=2017-01-31 time=15:28:25 timezone="IST" device_name="CR750iNG-XP" device_id=C44310050024-P29PUA log_id=136528618043 log_type="Sandbox" log_component="Web" log_subtype="Pending" priority=Information user_name="jsmith" src_ip=10.198.47.112 filename="19.exe" filetype="application/octet-stream" filesize=153010 sha1sum="3ce799580908df9ca0dc649aa8c2d06ab267e8c8" source="10.198.241.50" reason="pending" destination="" subject="" +<30>device="SFW" date=2017-01-31 time=15:28:25 timezone="IST" device_name="CR750iNG-XP" device_id=C44310050024-P29PUA log_id=136502218042 log_type="Sandbox" log_component="Web" log_subtype="Denied" priority=Critical user_name="jsmith" src_ip=10.198.47.112 filename="19.exe" filetype="application/octet-stream" filesize=153010 sha1sum="3ce799580908df9ca0dc649aa8c2d06ab267e8c8" source="10.198.241.50" reason="cloud malicious" destination="" subject=" +<30>device="SFW" date=2020-05-18 time=14:38:36 timezone="IST" device_name="CR750iNG-XP" device_id=C44310050024-P29PUA log_id=136502218042 log_type="Sandbox" log_component="Web" log_subtype="Denied" priority=Critical user_name="" src_ip=172.16.34.24 filename="SBTestFile1.pdf" filetype="application/pdf" filesize=1124 sha1sum="d910c4a81122c360fe57f67a04999425a65249db" source="sophostest.com" reason="cached malicious" destination="" subject="" diff --git a/x-pack/filebeat/module/sophos/xg/test/sandbox.log-expected.json b/x-pack/filebeat/module/sophos/xg/test/sandbox.log-expected.json index a112d1dc23e..21f888b9327 100644 --- a/x-pack/filebeat/module/sophos/xg/test/sandbox.log-expected.json +++ b/x-pack/filebeat/module/sophos/xg/test/sandbox.log-expected.json @@ -72,7 +72,7 @@ "host.name": "firewall.localgroup.local", "input.type": "log", "log.level": "critical", - "log.offset": 343, + "log.offset": 342, "observer.product": "XG", "observer.serial_number": "C44310050024-P29PUA", "observer.type": "firewall", @@ -131,7 +131,7 @@ "host.name": "firewall.localgroup.local", "input.type": "log", "log.level": "informational", - "log.offset": 809, + "log.offset": 807, "observer.product": "XG", "observer.serial_number": "C44313350024-P29PUA", "observer.type": "firewall", @@ -179,7 +179,7 @@ "host.name": "firewall.localgroup.local", "input.type": "log", "log.level": "informational", - "log.offset": 1151, + "log.offset": 1148, "observer.product": "XG", "observer.serial_number": "C44310050024-P29PUA", "observer.type": "firewall", @@ -241,7 +241,7 @@ "host.name": "firewall.localgroup.local", "input.type": "log", "log.level": "critical", - "log.offset": 1599, + "log.offset": 1595, "observer.product": "XG", "observer.serial_number": "C44310050024-P29PUA", "observer.type": "firewall", @@ -303,7 +303,7 @@ "host.name": "firewall.localgroup.local", "input.type": "log", "log.level": "critical", - "log.offset": 2050, + "log.offset": 2045, "observer.product": "XG", "observer.serial_number": "C44310050024-P29PUA", "observer.type": "firewall", diff --git a/x-pack/filebeat/module/sophos/xg/test/waf.log b/x-pack/filebeat/module/sophos/xg/test/waf.log index ed60311864f..2f99b3b9388 100644 --- a/x-pack/filebeat/module/sophos/xg/test/waf.log +++ b/x-pack/filebeat/module/sophos/xg/test/waf.log @@ -1,5 +1,5 @@ -<30>device="SFW" date=2020-05-18 time=14:38:46 timezone="CEST" device_name="XG230" device_id=1234567890123456 log_id=075000617071 log_type="WAF" log_component="Web Application Firewall" priority=Information user_name="-" server=webmail.elasticuser.com sourceip=216.160.83.61 localip=185.8.209.207 ws_protocol="HTTP/1.1" url=/mapi/nspi/ querystring=?MailboxId=642ea57c-90ab-4571-8e05-c6997b2256f8@elastic.user.com cookie="MapiContext=MAPIAAAAAPaw98Xx0uDQ4tL/z/rX59b2x/LI+8z2x/+lhrKGtIO7jbmBsxYNAAAAAAAA;MapiRouting=UlVNOjdmNWY0OGE3LTM5OWItNDc4Yi04ZDgwLWFmZTRmMzAyZTViMDoAitM4bv3XCA==;MapiSequence=10-GtgsIA==;X-BackEndCookie=642ea57c-90ab-4571-8e05-c6997b2256f8=u56Lnp2ejJqByZrHyZ7Mys7Sm8zJnNLLnM3J0sbJxsvSnZzIxs2ans+ezMrLgYHNz83P0s/J0s3Pq87Pxc7PxcrL" referer=- method=POST httpstatus=401 reason="-" extra="-" contenttype="-" useragent="Microsoft Office/16.0 (Windows NT 10.0; Microsoft Outlook 16.0.4954; Pro)" host=216.160.83.61 responsetime=11199 bytessent=5669 bytesrcv=1419 fw_rule_id=79 -<30>device="SFW" date=2020-05-18 time=14:38:47 timezone="CEST" device_name="XG230" device_id=1234567890123457 log_id=075000617071 log_type="WAF" log_component="Web Application Firewall" priority=Information user_name="-" server=webmail.elasticuser.com sourceip=216.160.83.61 localip=185.8.209.207 ws_protocol="HTTP/1.1" url=/mapi/nspi/ querystring=?MailboxId=642ea57c-90ab-4571-8e05-c6997b2256f8@elastic.user.com cookie="MapiContext=MAPIAAAAAPaw98Xx0uDQ4tL/z/rX59b2x/LI+8z2x/+lhrKGtIO7jbmBsw0NAAAAAAAA;MapiRouting=UlVNOjdmNWY0OGE3LTM5OWItNDc4Yi04ZDgwLWFmZTRmMzAyZTViMDpeyft5bv3XCA==;MapiSequence=9-Km2JMg==;X-BackEndCookie=642ea57c-90ab-4571-8e05-c6997b2256f8=u56Lnp2ejJqByZrHyZ7Mys7Sm8zJnNLLnM3J0sbJxsvSnZzIxs2ans+ezMrLgYHNz83P0s/J0s3Pq87Pxc7Oxc3M" referer=- method=POST httpstatus=200 reason="-" extra="-" contenttype="application/mapi-http" useragent="Microsoft Office/16.0 (Windows NT 6.2; Microsoft Outlook 16.0.4954; Pro)" host=216.160.83.61 responsetime=14086 bytessent=1357 bytesrcv=1774 fw_rule_id=79 -<30>device="SFW" date=2020-05-19 time=17:20:29 timezone="IST" device_name="XG230" device_id=1234567890123457 log_id=075000617071 log_type="WAF" log_component="Web Application Firewall" priority=Information user_name="jsmith" server=www.iviewtest.com:8989 sourceip=10.198.235.254 localip=10.198.233.48 ws_protocol="HTTP/1.1" url=/ querystring= cookie="-" referer=- method=GET httpstatus=403 reason="Static URL Hardening" extra="No signature found" contenttype="text/html" useragent="Mozilla/5.0 (Windows NT 6.1; WOW64; rv:50.0) Gecko/20100101 Firefox/50.0" host=10.198.235.254 responsetime=19310 bytessent=726 bytesrcv=510 fw_rule_id=3 -<30>device="SFW" date=2020-05-19 time=18:03:30 timezone="IST" device_name="XG230" device_id=1234567890123456 log_id=075000617071 log_type="WAF" log_component="Web Application Firewall" priority=Information user_name="jsmith" server=www.iviewtest.com:8990 sourceip=10.198.235.254 localip=10.198.233.48 ws_protocol="HTTP/1.1" url=/download/eicarcom2.zip querystring= cookie="; PHPSESSID=jetkd9iadd969hsr77jpj4q974; _pk_id.1.fc3a=3a6250e215194a92.1485866024.1.1485866069.1485866024.; _pk_ses.1.fc3a=*" referer=http://www.iviewtest.com:8990/85-0-Download.html method=GET httpstatus=403 reason="Antivirus" extra="EICAR-AV-Test" contenttype="text/html" useragent="Mozilla/5.0 (Windows NT 6.1; WOW64; rv:50.0) Gecko/20100101 Firefox/50.0" host=10.198.235.254 responsetime=403214 bytessent=739 bytesrcv=715 fw_rule_id=6 -<30>device="SFW" date=2020-05-20 time=18:03:31 timezone="IST" device_name="XG230" device_id=1234567890123457 log_id=075000617071 log_type="WAF" log_component="Web Application Firewall" priority=Information user_name="-" server=- sourceip=89.160.20.112 localip=216.167.51.72 ws_protocol="HTTP/1.0" url=/ querystring="" cookie="-" referer="-" method=GET httpstatus=403 reason="WAF Anomaly" extra="Inbound Anomaly Score Exceeded (Total Score: 7, SQLi=, XSS=): Last Matched Message: Request Missing a User Agent Header" contenttype="text/html" useragent="-" host=89.160.20.112 responsetime=608 bytessent=5353 bytesrcv=295 fw_rule_id=3 +<30>device="SFW" date=2020-05-18 time=14:38:46 timezone="CEST" device_name="XG230" device_id=1234567890123456 log_id=075000617071 log_type="WAF" log_component="Web Application Firewall" priority=Information user_name="-" server=webmail.elasticuser.com sourceip=216.160.83.61 localip=185.8.209.207 ws_protocol="HTTP/1.1" url=/mapi/nspi/ querystring=?MailboxId=642ea57c-90ab-4571-8e05-c6997b2256f8@elastic.user.com cookie="MapiContext=MAPIAAAAAPaw98Xx0uDQ4tL/z/rX59b2x/LI+8z2x/+lhrKGtIO7jbmBsxYNAAAAAAAA;MapiRouting=UlVNOjdmNWY0OGE3LTM5OWItNDc4Yi04ZDgwLWFmZTRmMzAyZTViMDoAitM4bv3XCA==;MapiSequence=10-GtgsIA==;X-BackEndCookie=642ea57c-90ab-4571-8e05-c6997b2256f8=u56Lnp2ejJqByZrHyZ7Mys7Sm8zJnNLLnM3J0sbJxsvSnZzIxs2ans+ezMrLgYHNz83P0s/J0s3Pq87Pxc7PxcrL" referer=- method=POST httpstatus=401 reason="-" extra="-" contenttype="-" useragent="Microsoft Office/16.0 (Windows NT 10.0; Microsoft Outlook 16.0.4954; Pro)" host=216.160.83.61 responsetime=11199 bytessent=5669 bytesrcv=1419 fw_rule_id=79 +<30>device="SFW" date=2020-05-18 time=14:38:47 timezone="CEST" device_name="XG230" device_id=1234567890123457 log_id=075000617071 log_type="WAF" log_component="Web Application Firewall" priority=Information user_name="-" server=webmail.elasticuser.com sourceip=216.160.83.61 localip=185.8.209.207 ws_protocol="HTTP/1.1" url=/mapi/nspi/ querystring=?MailboxId=642ea57c-90ab-4571-8e05-c6997b2256f8@elastic.user.com cookie="MapiContext=MAPIAAAAAPaw98Xx0uDQ4tL/z/rX59b2x/LI+8z2x/+lhrKGtIO7jbmBsw0NAAAAAAAA;MapiRouting=UlVNOjdmNWY0OGE3LTM5OWItNDc4Yi04ZDgwLWFmZTRmMzAyZTViMDpeyft5bv3XCA==;MapiSequence=9-Km2JMg==;X-BackEndCookie=642ea57c-90ab-4571-8e05-c6997b2256f8=u56Lnp2ejJqByZrHyZ7Mys7Sm8zJnNLLnM3J0sbJxsvSnZzIxs2ans+ezMrLgYHNz83P0s/J0s3Pq87Pxc7Oxc3M" referer=- method=POST httpstatus=200 reason="-" extra="-" contenttype="application/mapi-http" useragent="Microsoft Office/16.0 (Windows NT 6.2; Microsoft Outlook 16.0.4954; Pro)" host=216.160.83.61 responsetime=14086 bytessent=1357 bytesrcv=1774 fw_rule_id=79 +<30>device="SFW" date=2020-05-19 time=17:20:29 timezone="IST" device_name="XG230" device_id=1234567890123457 log_id=075000617071 log_type="WAF" log_component="Web Application Firewall" priority=Information user_name="jsmith" server=www.iviewtest.com:8989 sourceip=10.198.235.254 localip=10.198.233.48 ws_protocol="HTTP/1.1" url=/ querystring= cookie="-" referer=- method=GET httpstatus=403 reason="Static URL Hardening" extra="No signature found" contenttype="text/html" useragent="Mozilla/5.0 (Windows NT 6.1; WOW64; rv:50.0) Gecko/20100101 Firefox/50.0" host=10.198.235.254 responsetime=19310 bytessent=726 bytesrcv=510 fw_rule_id=3 +<30>device="SFW" date=2020-05-19 time=18:03:30 timezone="IST" device_name="XG230" device_id=1234567890123456 log_id=075000617071 log_type="WAF" log_component="Web Application Firewall" priority=Information user_name="jsmith" server=www.iviewtest.com:8990 sourceip=10.198.235.254 localip=10.198.233.48 ws_protocol="HTTP/1.1" url=/download/eicarcom2.zip querystring= cookie="; PHPSESSID=jetkd9iadd969hsr77jpj4q974; _pk_id.1.fc3a=3a6250e215194a92.1485866024.1.1485866069.1485866024.; _pk_ses.1.fc3a=*" referer=http://www.iviewtest.com:8990/85-0-Download.html method=GET httpstatus=403 reason="Antivirus" extra="EICAR-AV-Test" contenttype="text/html" useragent="Mozilla/5.0 (Windows NT 6.1; WOW64; rv:50.0) Gecko/20100101 Firefox/50.0" host=10.198.235.254 responsetime=403214 bytessent=739 bytesrcv=715 fw_rule_id=6 +<30>device="SFW" date=2020-05-20 time=18:03:31 timezone="IST" device_name="XG230" device_id=1234567890123457 log_id=075000617071 log_type="WAF" log_component="Web Application Firewall" priority=Information user_name="-" server=- sourceip=89.160.20.112 localip=216.167.51.72 ws_protocol="HTTP/1.0" url=/ querystring="" cookie="-" referer="-" method=GET httpstatus=403 reason="WAF Anomaly" extra="Inbound Anomaly Score Exceeded (Total Score: 7, SQLi=, XSS=): Last Matched Message: Request Missing a User Agent Header" contenttype="text/html" useragent="-" host=89.160.20.112 responsetime=608 bytessent=5353 bytesrcv=295 fw_rule_id=3 diff --git a/x-pack/filebeat/module/sophos/xg/test/waf.log-expected.json b/x-pack/filebeat/module/sophos/xg/test/waf.log-expected.json index 9ed26bd14d0..0408fb4ab4e 100644 --- a/x-pack/filebeat/module/sophos/xg/test/waf.log-expected.json +++ b/x-pack/filebeat/module/sophos/xg/test/waf.log-expected.json @@ -102,7 +102,7 @@ "http.version": "HTTP/1.1", "input.type": "log", "log.level": "informational", - "log.offset": 993, + "log.offset": 992, "observer.product": "XG", "observer.serial_number": "1234567890123457", "observer.type": "firewall", @@ -179,7 +179,7 @@ "http.version": "HTTP/1.1", "input.type": "log", "log.level": "informational", - "log.offset": 2004, + "log.offset": 2002, "observer.product": "XG", "observer.serial_number": "1234567890123457", "observer.type": "firewall", @@ -252,7 +252,7 @@ "http.version": "HTTP/1.1", "input.type": "log", "log.level": "informational", - "log.offset": 2640, + "log.offset": 2637, "observer.product": "XG", "observer.serial_number": "1234567890123456", "observer.type": "firewall", @@ -327,7 +327,7 @@ "http.version": "HTTP/1.0", "input.type": "log", "log.level": "informational", - "log.offset": 3453, + "log.offset": 3449, "observer.product": "XG", "observer.serial_number": "1234567890123457", "observer.type": "firewall", diff --git a/x-pack/filebeat/module/squid/_meta/docs.asciidoc b/x-pack/filebeat/module/squid/_meta/docs.asciidoc index 0708c243f27..10411c4f73d 100644 --- a/x-pack/filebeat/module/squid/_meta/docs.asciidoc +++ b/x-pack/filebeat/module/squid/_meta/docs.asciidoc @@ -28,7 +28,7 @@ NOTE: This was converted from RSA NetWitness log parser XML "squid" device revis *`var.input`*:: -The input from which messages are read. One of `file`, `tcp` or `udp`. +The input from which messages are read. One of `file`, `tcp` or `udp`. Defaults to `udp`. *`var.syslog_host`*:: diff --git a/x-pack/filebeat/module/threatintel/_meta/docs.asciidoc b/x-pack/filebeat/module/threatintel/_meta/docs.asciidoc index a7acdb5f4bd..18c8d57e169 100644 --- a/x-pack/filebeat/module/threatintel/_meta/docs.asciidoc +++ b/x-pack/filebeat/module/threatintel/_meta/docs.asciidoc @@ -12,7 +12,7 @@ https://www.elastic.co/guide/en/security/current/rules-ui-create.html#create-ind Match rules], but is also compatible with other features like https://www.elastic.co/guide/en/elasticsearch/reference/current/enrich-processor.html[Enrich Processors]. The related threat intel attribute that is meant to be used for -matching incoming source data is stored under the `threatintel.indicator.*` +matching incoming source data is stored under the `threat.indicator.*` fields. The available filesets are: @@ -68,9 +68,9 @@ Abuse.ch URL Threat Intel is mapped to the following ECS fields. [options="header"] |============================================================== | URL Threat Intel Fields | ECS Fields -| url | threatintel.indicator.url.full +| url | threat.indicator.url.full | date_added | @timestamp -| host | threatintel.indicator.ip/domain +| host | threat.indicator.ip/domain |============================================================== [[abusemalware]] @@ -112,9 +112,9 @@ Abuse.ch Malware Threat Intel is mapped to the following ECS fields. [options="header"] |================================================================ | Malware Threat IntelFields | ECS Fields -| md5_hash | threatintel.indicator.file.hash.md5 -| sha256_hash | threatintel.indicator.file.hash.sha256 -| file_size | threatintel.indicator.file.size +| md5_hash | threat.indicator.file.hash.md5 +| sha256_hash | threat.indicator.file.hash.sha256 +| file_size | threat.indicator.file.size |================================================================ [[malwarebazaar]] @@ -156,24 +156,25 @@ Malware Bazaar Threat Intel is mapped to the following ECS fields. [options="header"] |================================================================ | Malware Threat IntelFields | ECS Fields -| md5_hash | threatintel.indicator.file.hash.md5 -| sha256_hash | threatintel.indicator.file.hash.sha256 -| tlsh | threatintel.indicator.file.hash.tlsh -| ssdeep | threatintel.indicator.file.hash.ssdeep -| imphash | threatintel.indicator.file.pe.imphash -| file_size | threatintel.indicator.file.size -| file_name | threatintel.indicator.file.name -| file_type_mime | threatintel.indicator.file.mime_type -| file_type | threatintel.indicator.file.type -| reporter | threatintel.indicator.provider -| origin_country | threatintel.indicator.geo.country_iso_code -| signature | threatintel.indicator.signature -| code_sign.subject_cn | threatintel.indicator.file.x509.subject.common_name -| code_sign.issuer_cn | threatintel.indicator.file.x509.issuer.common_name -| code_sign.algorithm | threatintel.indicator.file.x509.public_key_algorithm -| code_sign.valid_from | threatintel.indicator.file.x509.not_before -| code_sign.valid_to | threatintel.indicator.file.x509.not_after -| code_sign.serial_number | threatintel.indicator.file.x509.serial_number +| md5_hash | threat.indicator.file.hash.md5 +| sha256_hash | threat.indicator.file.hash.sha256 +| sha384_hash | threat.indicator.file.hash.sha384 +| tlsh | threat.indicator.file.hash.tlsh +| ssdeep | threat.indicator.file.hash.ssdeep +| imphash | threat.indicator.file.pe.imphash +| file_size | threat.indicator.file.size +| file_name | threat.indicator.file.name +| file_type_mime | threat.indicator.file.mime_type +| file_type | threat.indicator.file.type +| reporter | threat.indicator.provider +| origin_country | threat.indicator.geo.country_iso_code +| signature | threat.indicator.signature +| code_sign.subject_cn | threat.indicator.file.x509.subject.common_name +| code_sign.issuer_cn | threat.indicator.file.x509.issuer.common_name +| code_sign.algorithm | threat.indicator.file.x509.public_key_algorithm +| code_sign.valid_from | threat.indicator.file.x509.not_before +| code_sign.valid_to | threat.indicator.file.x509.not_after +| code_sign.serial_number | threat.indicator.file.x509.serial_number |================================================================ [[misp]] @@ -250,10 +251,10 @@ MISP Threat Intel is mapped to the following ECS fields. [options="header"] |============================================================== | Malware Threat IntelFields | ECS Fields -| misp.first_seen | threatintel.indicator.first_seen -| misp.last_seen | threatintel.indicator.last_seen +| misp.first_seen | threat.indicator.first_seen +| misp.last_seen | threat.indicator.last_seen | misp.tag | tag -| misp.value | threatintel.indicator.* +| misp.value | threat.indicator.* |============================================================== `misp.value` is mapped to the appropriate field dependent on attribute type. @@ -331,9 +332,9 @@ OTX Threat Intel is mapped to the following ECS fields. [options="header"] |============================================================ | Malware Threat Intel Fields | ECS Fields -| otx.type | threatintel.indicator.type -| otx.description | threatintel.indicator.description -| otx.indicator | threatintel.indicator.* +| otx.type | threat.indicator.type +| otx.description | threat.indicator.description +| otx.indicator | threat.indicator.* |============================================================ `otx.indicator` is mapped to the appropriate field dependent on attribute type. @@ -415,10 +416,10 @@ Anomali Threat Intel is mapped to the following ECS fields. [options="header"] |============================================================= | Malware Threat Intel Fields | ECS Fields -| anomali.description | threatintel.indicator.description -| anomali.created | threatintel.indicator.first_seen -| anomali.modified | threatintel.indicator.last_seen -| anomali.pattern | threatintel.indicator.* +| anomali.description | threat.indicator.description +| anomali.created | threat.indicator.first_seen +| anomali.modified | threat.indicator.last_seen +| anomali.pattern | threat.indicator.* | anomali.labels | tags |============================================================= @@ -486,24 +487,24 @@ Anomali ThreatStream fields are mapped to the following ECS fields: [options="header"] |============================================================= | ThreatStream fields | ECS Fields -| asn | threatintel.indicator.as.number -| classification<> | threatintel.indicator.marking.tlp -| confidence<> | threatintel.indicator.confidence -| country | threatintel.indicator.geo.country_iso_code -| date_first | threatintel.indicator.first_seen -| date_last | threatintel.indicator.last_seen +| asn | threat.indicator.as.number +| classification<> | threat.indicator.marking.tlp +| confidence<> | threat.indicator.confidence +| country | threat.indicator.geo.country_iso_code +| date_first | threat.indicator.first_seen +| date_last | threat.indicator.last_seen | detail | tags -| domain | threatintel.indicator.url.domain -| email | threatintel.indicator.email.address -| itype<> | threatintel.indicator.type -| lat | threatintel.indicator.geo.location.lat -| lon | threatintel.indicator.geo.location.lon -| md5 | threatintel.indicator.file.hash -| org | threatintel.indicator.as.organization.name +| domain | threat.indicator.url.domain +| email | threat.indicator.email.address +| itype<> | threat.indicator.type +| lat | threat.indicator.geo.location.lat +| lon | threat.indicator.geo.location.lon +| md5 | threat.indicator.file.hash +| org | threat.indicator.as.organization.name | severity<> | event.severity -| source | threatintel.indicator.provider -| srcip | threatintel.indicator.ip -| url | threatintel.indicator.url.original +| source | threat.indicator.provider +| srcip | threat.indicator.ip +| url | threat.indicator.url.original |============================================================= [[a]] @@ -585,16 +586,16 @@ Recorded Future fields are mapped to the following ECS fields: [options="header"] |============================================================= | Recorded Future fields | ECS Fields -| entity.name | threatintel.indicator.{url,ip,domain,file.hash} -| entity.type | threatintel.indicator.type -| fileHashes | threatintel.indicator.file.hash +| entity.name | threat.indicator.{url,ip,domain,file.hash} +| entity.type | threat.indicator.type +| fileHashes | threat.indicator.file.hash | intelCard | event.reference -| location.asn | threatintel.indicator.as.number -| location.location | threatintel.indicator.geo -| location.organization | threatintel.indicator.as.organization.name +| location.asn | threat.indicator.as.number +| location.location | threat.indicator.geo +| location.organization | threat.indicator.as.organization.name | risk.score | event.risk_score -| timestamps.firstSeen | threatintel.indicator.first_seen -| timestamps.lastSeen | threatintel.indicator.last_seen +| timestamps.firstSeen | threat.indicator.first_seen +| timestamps.lastSeen | threat.indicator.last_seen |============================================================= :has-dashboards!: @@ -702,11 +703,11 @@ Recorded Future fields are mapped to the following ECS fields: [options="header"] |============================================================= | ThreatQ fields | ECS Fields -| type.name | threatintel.indicator.type -| description | threatintel.indicator.description -| score | threatintel.indicator.confidence -| value | threatintel.indicator.{url,ip,domain,file.hash} -| sources | threatintel.indicator.provider +| type.name | threat.indicator.type +| description | threat.indicator.description +| score | threat.indicator.confidence +| value | threat.indicator.{url,ip,domain,file.hash} +| sources | threat.indicator.provider |============================================================= :has-dashboards!: diff --git a/x-pack/filebeat/module/threatintel/_meta/fields.yml b/x-pack/filebeat/module/threatintel/_meta/fields.yml index ee199daa6aa..5fb56abc40a 100644 --- a/x-pack/filebeat/module/threatintel/_meta/fields.yml +++ b/x-pack/filebeat/module/threatintel/_meta/fields.yml @@ -4,388 +4,21 @@ description: > Threat intelligence Filebeat Module. fields: - - name: threatintel + - name: "" type: group - description: > - Fields from the threatintel Filebeat module. fields: - - name: indicator.first_seen - type: date - description: > - The date and time when intelligence source first reported sighting this indicator. - - name: indicator.last_seen - type: date - description: > - The date and time when intelligence source last reported sighting this indicator. - - name: indicator.sightings - type: long - description: > - Number of times this indicator was observed conducting threat activity. - - name: indicator.type + - name: threat.indicator.file.hash.tlsh type: keyword description: > - Type of indicator as represented by Cyber Observable in STIX 2.0. - Expected values - * autonomous-system - * artifact - * directory - * domain-name - * email-addr - * file - * ipv4-addr - * ipv6-addr - * mac-addr - * mutex - * process - * software - * url - * user-account - * windows-registry-key - * x-509-certificate - - name: indicator.description - type: keyword - description: > - Describes the type of action conducted by the threat. - - name: indicator.scanner_stats - type: long - description: > - Count of AV/EDR vendors that successfully detected malicious file or URL. - - name: indicator.provider + The file's import tlsh, if available. + + - name: threat.indicator.file.hash.sha384 type: keyword description: > - Identifies the name of the intelligence provider. - - name: indicator.confidence + The file's sha384 hash, if available. + + - name: threat.feed.name type: keyword - description: > - Identifies the confidence rating assigned by the provider using STIX confidence scales. - Expected values - * Not Specified, None, Low, Medium, High - * 0-10 - * Admirality Scale (1-6) - * DNI Scale (5-95) - * WEP Scale (Impossible - Certain) - - name: indicator.module - type: keyword - description: > - Identifies the name of specific module this data is coming from. - - name: indicator.dataset - type: keyword - description: > - Identifies the name of specific dataset from the intelligence source. - - name: indicator.reference + + - name: threat.feed.dashboard_id type: keyword - description: > - Reference URL linking to additional information about this indicator. - - name: indicator.ip - type: ip - description: > - Identifies a threat indicator as an IP address (irrespective of direction). - - name: indicator.port - type: long - description: > - Identifies a threat indicator as a port number (irrespective of direction). - - name: indicator.email.address - type: keyword - description: > - Identifies a threat indicator as an email address (irrespective of direction). - - name: indicator.marking.tlp - type: keyword - description: > - Traffic Light Protocol sharing markings. - Expected values are: - * White - * Green - * Amber - * Red - - name: indicator.matched - type: group - fields: - - name: atomic - type: keyword - description: > - Identifies the atomic indicator that matched a local environment endpoint or network event. - - name: field - type: keyword - description: > - Identifies the field of the atomic indicator that matched a local environment endpoint or network event. - - name: type - type: keyword - description: > - Identifies the type of the atomic indicator that matched a local environment endpoint or network event. - - name: indicator.as - type: group - fields: - - name: number - type: long - description: - Unique number allocated to the autonomous system. The autonomous system number (ASN) - uniquely identifies each network on the Internet. - example: 15169 - - name: organization.name - type: keyword - ignore_above: 1024 - multi_fields: - - name: text - type: text - norms: false - description: Organization name. - example: Google LLC - - name: indicator.registry - type: group - fields: - - name: data.strings - type: keyword - ignore_above: 1024 - description: > - Content when writing string types. - Populated as an array when writing string data to the registry. For single - string registry types (REG_SZ, REG_EXPAND_SZ), this should be an array with - one string. For sequences of string with REG_MULTI_SZ, this array will be - variable length. For numeric data, such as REG_DWORD and REG_QWORD, this should - be populated with the decimal representation (e.g `"1"`). - example: '["C:\rta\red_ttp\bin\myapp.exe"]' - - name: path - type: keyword - ignore_above: 1024 - description: Full path, including hive, key and value - example: - HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution - Options\winword.exe\Debugger - - name: value - type: keyword - ignore_above: 1024 - description: Name of the value written. - example: Debugger - - name: key - type: keyword - ignore_above: 1024 - description: Registry key value - - name: indicator.geo - type: group - fields: - - name: city_name - type: keyword - ignore_above: 1024 - description: City name. - example: Montreal - - name: continent_name - type: keyword - ignore_above: 1024 - description: Name of the continent. - example: North America - - name: country_iso_code - type: keyword - ignore_above: 1024 - description: Country ISO code. - example: CA - - name: country_name - type: keyword - ignore_above: 1024 - description: Country name. - example: Canada - - name: location - type: geo_point - description: Longitude and latitude. - example: '{ "lon": -73.614830, "lat": 45.505918 }' - - name: region_iso_code - type: keyword - ignore_above: 1024 - description: Region ISO code. - example: CA-QC - - name: region_name - type: keyword - ignore_above: 1024 - description: Region name. - example: Quebec - - name: indicator.file.pe.imphash - type: keyword - ignore_above: 1024 - description: - "A hash of the imports in a PE file. An imphash -- or import hash - -- can be used to fingerprint binaries even after recompilation or other code-level - transformations have occurred, which would change more traditional hash values. - Learn more at https://www.fireeye.com/blog/threat-research/2014/01/tracking-malware-import-hashing.html." - example: 0c6803c4e922103c4dca5963aad36ddf - - name: indicator.file - type: group - fields: - - name: hash - type: group - fields: - - name: tlsh - type: keyword - description: > - The file's import tlsh, if available. - - name: ssdeep - type: keyword - description: > - The file's ssdeep hash, if available. - - name: md5 - type: keyword - description: > - The file's md5 hash, if available. - - name: sha1 - type: keyword - description: > - The file's sha1 hash, if available. - - name: sha256 - type: keyword - description: > - The file's sha256 hash, if available. - - name: sha384 - type: keyword - description: > - The file's sha384 hash, if available. - - name: sha512 - type: keyword - description: > - The file's sha512 hash, if available. - - name: type - type: keyword - ignore_above: 1024 - description: > - The file type. - - name: size - type: long - description: > - The file's total size. - - name: name - type: keyword - description: > - The file's name. - - name: extension - type: keyword - description: > - The file's extension. - - name: mime_type - type: keyword - description: > - The file's MIME type. - - name: indicator.url - type: group - fields: - - name: domain - type: keyword - description: > - Domain of the url, such as "www.elastic.co". - - name: extension - type: keyword - ignore_above: 1024 - description: > - The field contains the file extension from the original request - - name: fragment - type: keyword - ignore_above: 1024 - description: > - Portion of the url after the `#`, such as "top". - - name: full - type: keyword - description: > - If full URLs are important to your use case, they should be stored - in `url.full`, whether this field is reconstructed or present in the event - source. - - name: original - type: keyword - description: > - Unmodified original url as seen in the event source. - Note that in network monitoring, the observed URL may be a full URL, whereas - in access logs, the URL is often just represented as a path. - This field is meant to represent the URL as it was observed, complete or not. - - name: password - type: keyword - ignore_above: 1024 - description: > - Password of the request. - - name: path - type: keyword - description: > - Path of the request, such as "/search". - - name: port - type: long - format: string - description: > - Port of the request, such as 443. - - name: query - type: keyword - ignore_above: 1024 - description: > - The query field describes the query string of the request, such - as "q=elasticsearch". - The `?` is excluded from the query string. If a URL contains no `?`, there - is no query field. If there is a `?` but no query, the query field exists - with an empty string. The `exists` query can be used to differentiate between - the two cases. - - name: registered_domain - type: keyword - description: > - The highest registered url domain, stripped of the subdomain. - For example, the registered domain for "foo.example.com" is "example.com". - This value can be determined precisely with a list like the public suffix - list (http://publicsuffix.org). Trying to approximate this by simply taking - the last two labels will not work well for TLDs such as "co.uk". - - name: scheme - type: keyword - ignore_above: 1024 - description: > - Scheme of the request, such as "https". - - name: subdomain - type: keyword - ignore_above: 1024 - description: > - The subdomain portion of a fully qualified domain name includes - all of the names except the host name under the registered_domain. In a partially - qualified domain, or if the the qualification level of the full name cannot - be determined, subdomain contains all of the names below the registered domain. - For example the subdomain portion of "www.east.mydomain.co.uk" is "east". - If the domain has multiple levels of subdomain, such as "sub2.sub1.example.com", - the subdomain field should contain "sub2.sub1", with no trailing period. - - name: top_level_domain - type: keyword - ignore_above: 1024 - description: > - The effective top level domain (eTLD), also known as the domain - suffix, is the last part of the domain name. For example, the top level domain - for example.com is "com". - This value can be determined precisely with a list like the public suffix - list (http://publicsuffix.org). Trying to approximate this by simply taking - the last label will not work well for effective TLDs such as "co.uk". - - name: username - type: keyword - ignore_above: 1024 - description: > - Username of the request. - - name: indicator.x509 - type: group - fields: - - name: serial_number - type: keyword - ignore_above: 1024 - description: - Unique serial number issued by the certificate authority. For consistency, - if this value is alphanumeric, it should be formatted without colons and uppercase - characters. - example: 55FBB9C7DEBF09809D12CCAA - - name: issuer - type: keyword - ignore_above: 1024 - description: Name of issuing certificate authority. Could be either Distinguished Name (DN) or Common Name (CN), depending on source. - example: - C=US, O=Example Inc, OU=www.example.com, CN=Example SHA2 High Assurance - Server CA - - name: subject - type: keyword - ignore_above: 1024 - description: Name of the certificate subject entity. Could be either Distinguished Name (DN) or Common Name (CN), depending on source. - example: C=US, ST=California, L=San Francisco, O=Example, Inc., CN=shared.global.example.net - - name: alternative_names - type: keyword - ignore_above: 1024 - description: - List of subject alternative names (SAN). Name types vary by certificate - authority and certificate type but commonly contain IP addresses, DNS names - (and wildcards), and email addresses. - example: "*.elastic.co" - - name: indicator.signature - type: keyword - description: > - Malware family of sample (if available). diff --git a/x-pack/filebeat/module/threatintel/_meta/kibana/7/lens/021ba940-de96-11eb-8f2b-753caedf727d.json b/x-pack/filebeat/module/threatintel/_meta/kibana/7/lens/021ba940-de96-11eb-8f2b-753caedf727d.json index 993d2edccce..91a5cc79018 100644 --- a/x-pack/filebeat/module/threatintel/_meta/kibana/7/lens/021ba940-de96-11eb-8f2b-753caedf727d.json +++ b/x-pack/filebeat/module/threatintel/_meta/kibana/7/lens/021ba940-de96-11eb-8f2b-753caedf727d.json @@ -28,7 +28,7 @@ "size": 5 }, "scale": "ordinal", - "sourceField": "threatintel.indicator.type" + "sourceField": "threat.indicator.type" }, "9afb1b09-0f20-488c-9242-a94f7d11800b": { "dataType": "number", @@ -96,4 +96,4 @@ "type": "lens", "updated_at": "2021-08-04T16:34:28.102Z", "version": "WzQ1ODAsMV0=" -} \ No newline at end of file +} diff --git a/x-pack/filebeat/module/threatintel/_meta/kibana/7/lens/028175a0-ff74-11eb-acb2-2960a7069ed1.json b/x-pack/filebeat/module/threatintel/_meta/kibana/7/lens/028175a0-ff74-11eb-acb2-2960a7069ed1.json index 14722019106..c6ef974933e 100644 --- a/x-pack/filebeat/module/threatintel/_meta/kibana/7/lens/028175a0-ff74-11eb-acb2-2960a7069ed1.json +++ b/x-pack/filebeat/module/threatintel/_meta/kibana/7/lens/028175a0-ff74-11eb-acb2-2960a7069ed1.json @@ -28,7 +28,7 @@ "size": 5 }, "scale": "ordinal", - "sourceField": "threatintel.indicator.provider" + "sourceField": "threat.indicator.provider" }, "11576d1f-5400-4a71-bf04-681099e755d5": { "dataType": "number", @@ -95,4 +95,4 @@ "type": "lens", "updated_at": "2021-10-11T08:02:55.512Z", "version": "WzUyOSwxXQ==" -} \ No newline at end of file +} diff --git a/x-pack/filebeat/module/threatintel/_meta/kibana/7/lens/037e2af0-df50-11eb-8f2b-753caedf727d.json b/x-pack/filebeat/module/threatintel/_meta/kibana/7/lens/037e2af0-df50-11eb-8f2b-753caedf727d.json index 5be6f447603..0c677668719 100644 --- a/x-pack/filebeat/module/threatintel/_meta/kibana/7/lens/037e2af0-df50-11eb-8f2b-753caedf727d.json +++ b/x-pack/filebeat/module/threatintel/_meta/kibana/7/lens/037e2af0-df50-11eb-8f2b-753caedf727d.json @@ -28,7 +28,7 @@ "size": 5 }, "scale": "ordinal", - "sourceField": "threatintel.indicator.type" + "sourceField": "threat.indicator.type" }, "9afb1b09-0f20-488c-9242-a94f7d11800b": { "dataType": "number", @@ -96,4 +96,4 @@ "type": "lens", "updated_at": "2021-08-04T16:34:33.127Z", "version": "WzQ2NjIsMV0=" -} \ No newline at end of file +} diff --git a/x-pack/filebeat/module/threatintel/_meta/kibana/7/lens/06744e90-df52-11eb-8f2b-753caedf727d.json b/x-pack/filebeat/module/threatintel/_meta/kibana/7/lens/06744e90-df52-11eb-8f2b-753caedf727d.json index b427db18d51..38b8c85420e 100644 --- a/x-pack/filebeat/module/threatintel/_meta/kibana/7/lens/06744e90-df52-11eb-8f2b-753caedf727d.json +++ b/x-pack/filebeat/module/threatintel/_meta/kibana/7/lens/06744e90-df52-11eb-8f2b-753caedf727d.json @@ -28,7 +28,7 @@ "size": 10 }, "scale": "ordinal", - "sourceField": "threatintel.indicator.ip" + "sourceField": "threat.indicator.ip" }, "9afb1b09-0f20-488c-9242-a94f7d11800b": { "dataType": "number", @@ -47,7 +47,7 @@ "filters": [], "query": { "language": "kuery", - "query": "event.dataset:\"threatintel.recordedfuture\" and threatintel.indicator.type:ipv6-addr" + "query": "event.dataset:\"threatintel.recordedfuture\" and threat.indicator.type:ipv6-addr" }, "visualization": { "columns": [ @@ -91,4 +91,4 @@ "type": "lens", "updated_at": "2021-08-04T16:34:33.127Z", "version": "WzQ2NzAsMV0=" -} \ No newline at end of file +} diff --git a/x-pack/filebeat/module/threatintel/_meta/kibana/7/lens/0db62ee0-72e6-11eb-a3e3-b3cc7c78a70f.json b/x-pack/filebeat/module/threatintel/_meta/kibana/7/lens/0db62ee0-72e6-11eb-a3e3-b3cc7c78a70f.json index a053c190ada..b4182474c23 100644 --- a/x-pack/filebeat/module/threatintel/_meta/kibana/7/lens/0db62ee0-72e6-11eb-a3e3-b3cc7c78a70f.json +++ b/x-pack/filebeat/module/threatintel/_meta/kibana/7/lens/0db62ee0-72e6-11eb-a3e3-b3cc7c78a70f.json @@ -14,7 +14,7 @@ "959db113-1ce6-46fc-97c3-dbf5fd5abb9a": { "dataType": "string", "isBucketed": true, - "label": "Top values of threatintel.abusemalware.signature", + "label": "Top values of abusech.malware.signature", "operationType": "terms", "params": { "missingBucket": false, @@ -27,7 +27,7 @@ "size": 10 }, "scale": "ordinal", - "sourceField": "threatintel.abusemalware.signature" + "sourceField": "abusech.malware.signature" }, "de396547-655b-4db2-8a21-e9850acff0b0": { "dataType": "number", @@ -91,13 +91,13 @@ "store": "appState" }, "exists": { - "field": "threatintel.abusemalware.signature" + "field": "abusech.malware.signature" }, "meta": { "alias": null, "disabled": false, "indexRefName": "filter-index-pattern-2", - "key": "threatintel.abusemalware.signature", + "key": "abusech.malware.signature", "negate": false, "type": "exists", "value": "exists" @@ -168,4 +168,4 @@ "type": "lens", "updated_at": "2021-08-04T16:34:29.041Z", "version": "WzQ2MDMsMV0=" -} \ No newline at end of file +} diff --git a/x-pack/filebeat/module/threatintel/_meta/kibana/7/lens/1136ceb0-de95-11eb-8f2b-753caedf727d.json b/x-pack/filebeat/module/threatintel/_meta/kibana/7/lens/1136ceb0-de95-11eb-8f2b-753caedf727d.json index 05d17760abc..c771588f924 100644 --- a/x-pack/filebeat/module/threatintel/_meta/kibana/7/lens/1136ceb0-de95-11eb-8f2b-753caedf727d.json +++ b/x-pack/filebeat/module/threatintel/_meta/kibana/7/lens/1136ceb0-de95-11eb-8f2b-753caedf727d.json @@ -28,7 +28,7 @@ "size": 10 }, "scale": "ordinal", - "sourceField": "threatintel.anomalithreatstream.resource_uri" + "sourceField": "anomali.threatstream.resource_uri" }, "9afb1b09-0f20-488c-9242-a94f7d11800b": { "dataType": "number", @@ -91,4 +91,4 @@ "type": "lens", "updated_at": "2021-08-04T16:34:28.102Z", "version": "WzQ1OTksMV0=" -} \ No newline at end of file +} diff --git a/x-pack/filebeat/module/threatintel/_meta/kibana/7/lens/139c7da0-df51-11eb-8f2b-753caedf727d.json b/x-pack/filebeat/module/threatintel/_meta/kibana/7/lens/139c7da0-df51-11eb-8f2b-753caedf727d.json index d8abec34b65..e2269eea6d9 100644 --- a/x-pack/filebeat/module/threatintel/_meta/kibana/7/lens/139c7da0-df51-11eb-8f2b-753caedf727d.json +++ b/x-pack/filebeat/module/threatintel/_meta/kibana/7/lens/139c7da0-df51-11eb-8f2b-753caedf727d.json @@ -36,7 +36,7 @@ "size": 10 }, "scale": "ordinal", - "sourceField": "threatintel.indicator.file.hash.sha256" + "sourceField": "threat.indicator.file.hash.sha256" } }, "incompleteColumns": {} @@ -90,4 +90,4 @@ "type": "lens", "updated_at": "2021-08-04T16:34:33.127Z", "version": "WzQ2NzMsMV0=" -} \ No newline at end of file +} diff --git a/x-pack/filebeat/module/threatintel/_meta/kibana/7/lens/36f61650-de96-11eb-8f2b-753caedf727d.json b/x-pack/filebeat/module/threatintel/_meta/kibana/7/lens/36f61650-de96-11eb-8f2b-753caedf727d.json index e48267b1fd8..86507728c60 100644 --- a/x-pack/filebeat/module/threatintel/_meta/kibana/7/lens/36f61650-de96-11eb-8f2b-753caedf727d.json +++ b/x-pack/filebeat/module/threatintel/_meta/kibana/7/lens/36f61650-de96-11eb-8f2b-753caedf727d.json @@ -28,7 +28,7 @@ "size": 5 }, "scale": "ordinal", - "sourceField": "threatintel.anomalithreatstream.classification" + "sourceField": "anomali.threatstream.classification" }, "9afb1b09-0f20-488c-9242-a94f7d11800b": { "dataType": "number", @@ -94,4 +94,4 @@ "type": "lens", "updated_at": "2021-08-04T16:34:28.102Z", "version": "WzQ1ODUsMV0=" -} \ No newline at end of file +} diff --git a/x-pack/filebeat/module/threatintel/_meta/kibana/7/lens/3c40f4d0-de97-11eb-8f2b-753caedf727d.json b/x-pack/filebeat/module/threatintel/_meta/kibana/7/lens/3c40f4d0-de97-11eb-8f2b-753caedf727d.json index 4f33f959e3a..bdfbd6b5096 100644 --- a/x-pack/filebeat/module/threatintel/_meta/kibana/7/lens/3c40f4d0-de97-11eb-8f2b-753caedf727d.json +++ b/x-pack/filebeat/module/threatintel/_meta/kibana/7/lens/3c40f4d0-de97-11eb-8f2b-753caedf727d.json @@ -28,7 +28,7 @@ "size": 5 }, "scale": "ordinal", - "sourceField": "threatintel.anomalithreatstream.itype" + "sourceField": "anomali.threatstream.itype" }, "9afb1b09-0f20-488c-9242-a94f7d11800b": { "dataType": "number", @@ -94,4 +94,4 @@ "type": "lens", "updated_at": "2021-08-04T16:34:28.102Z", "version": "WzQ1ODEsMV0=" -} \ No newline at end of file +} diff --git a/x-pack/filebeat/module/threatintel/_meta/kibana/7/lens/3c996410-df52-11eb-8f2b-753caedf727d.json b/x-pack/filebeat/module/threatintel/_meta/kibana/7/lens/3c996410-df52-11eb-8f2b-753caedf727d.json index 88c19ed280d..da5e6785b5a 100644 --- a/x-pack/filebeat/module/threatintel/_meta/kibana/7/lens/3c996410-df52-11eb-8f2b-753caedf727d.json +++ b/x-pack/filebeat/module/threatintel/_meta/kibana/7/lens/3c996410-df52-11eb-8f2b-753caedf727d.json @@ -28,7 +28,7 @@ "size": 10 }, "scale": "ordinal", - "sourceField": "threatintel.indicator.domain" + "sourceField": "threat.indicator.url.domain" }, "9afb1b09-0f20-488c-9242-a94f7d11800b": { "dataType": "number", @@ -91,4 +91,4 @@ "type": "lens", "updated_at": "2021-08-04T16:34:33.127Z", "version": "WzQ2NzcsMV0=" -} \ No newline at end of file +} diff --git a/x-pack/filebeat/module/threatintel/_meta/kibana/7/lens/5e76ef90-df51-11eb-8f2b-753caedf727d.json b/x-pack/filebeat/module/threatintel/_meta/kibana/7/lens/5e76ef90-df51-11eb-8f2b-753caedf727d.json index 03bafd193b3..a6fde56bd64 100644 --- a/x-pack/filebeat/module/threatintel/_meta/kibana/7/lens/5e76ef90-df51-11eb-8f2b-753caedf727d.json +++ b/x-pack/filebeat/module/threatintel/_meta/kibana/7/lens/5e76ef90-df51-11eb-8f2b-753caedf727d.json @@ -36,7 +36,7 @@ "size": 10 }, "scale": "ordinal", - "sourceField": "threatintel.indicator.url.domain" + "sourceField": "threat.indicator.url.domain" } }, "incompleteColumns": {} @@ -90,4 +90,4 @@ "type": "lens", "updated_at": "2021-08-04T16:34:33.127Z", "version": "WzQ2NzUsMV0=" -} \ No newline at end of file +} diff --git a/x-pack/filebeat/module/threatintel/_meta/kibana/7/lens/5ef7b430-de94-11eb-8f2b-753caedf727d.json b/x-pack/filebeat/module/threatintel/_meta/kibana/7/lens/5ef7b430-de94-11eb-8f2b-753caedf727d.json index 88642bb872e..27fee210ffd 100644 --- a/x-pack/filebeat/module/threatintel/_meta/kibana/7/lens/5ef7b430-de94-11eb-8f2b-753caedf727d.json +++ b/x-pack/filebeat/module/threatintel/_meta/kibana/7/lens/5ef7b430-de94-11eb-8f2b-753caedf727d.json @@ -36,7 +36,7 @@ "size": 10 }, "scale": "ordinal", - "sourceField": "threatintel.indicator.ip" + "sourceField": "threat.indicator.ip" } }, "incompleteColumns": {} @@ -91,4 +91,4 @@ "type": "lens", "updated_at": "2021-08-04T16:34:28.102Z", "version": "WzQ1OTIsMV0=" -} \ No newline at end of file +} diff --git a/x-pack/filebeat/module/threatintel/_meta/kibana/7/lens/790cd040-df51-11eb-8f2b-753caedf727d.json b/x-pack/filebeat/module/threatintel/_meta/kibana/7/lens/790cd040-df51-11eb-8f2b-753caedf727d.json index 2abc0bb7316..781a6a42a39 100644 --- a/x-pack/filebeat/module/threatintel/_meta/kibana/7/lens/790cd040-df51-11eb-8f2b-753caedf727d.json +++ b/x-pack/filebeat/module/threatintel/_meta/kibana/7/lens/790cd040-df51-11eb-8f2b-753caedf727d.json @@ -28,7 +28,7 @@ "size": 10 }, "scale": "ordinal", - "sourceField": "threatintel.indicator.url.original" + "sourceField": "threat.indicator.url.original" }, "9afb1b09-0f20-488c-9242-a94f7d11800b": { "dataType": "number", @@ -91,4 +91,4 @@ "type": "lens", "updated_at": "2021-08-04T16:34:33.127Z", "version": "WzQ2NzgsMV0=" -} \ No newline at end of file +} diff --git a/x-pack/filebeat/module/threatintel/_meta/kibana/7/lens/7d9c70f0-de95-11eb-8f2b-753caedf727d.json b/x-pack/filebeat/module/threatintel/_meta/kibana/7/lens/7d9c70f0-de95-11eb-8f2b-753caedf727d.json index dbdc1f05605..741a17e6b10 100644 --- a/x-pack/filebeat/module/threatintel/_meta/kibana/7/lens/7d9c70f0-de95-11eb-8f2b-753caedf727d.json +++ b/x-pack/filebeat/module/threatintel/_meta/kibana/7/lens/7d9c70f0-de95-11eb-8f2b-753caedf727d.json @@ -28,7 +28,7 @@ "size": 10 }, "scale": "ordinal", - "sourceField": "threatintel.anomali.name" + "sourceField": "anomali.limo.name" }, "9afb1b09-0f20-488c-9242-a94f7d11800b": { "dataType": "number", @@ -91,4 +91,4 @@ "type": "lens", "updated_at": "2021-08-04T16:34:28.102Z", "version": "WzQ1OTYsMV0=" -} \ No newline at end of file +} diff --git a/x-pack/filebeat/module/threatintel/_meta/kibana/7/lens/7ec83f60-de98-11eb-8f2b-753caedf727d.json b/x-pack/filebeat/module/threatintel/_meta/kibana/7/lens/7ec83f60-de98-11eb-8f2b-753caedf727d.json index b321f95bae8..e1b1dfc2fc8 100644 --- a/x-pack/filebeat/module/threatintel/_meta/kibana/7/lens/7ec83f60-de98-11eb-8f2b-753caedf727d.json +++ b/x-pack/filebeat/module/threatintel/_meta/kibana/7/lens/7ec83f60-de98-11eb-8f2b-753caedf727d.json @@ -28,7 +28,7 @@ "size": 10 }, "scale": "ordinal", - "sourceField": "threatintel.indicator.file.hash.sha256" + "sourceField": "threat.indicator.file.hash.sha256" }, "9afb1b09-0f20-488c-9242-a94f7d11800b": { "dataType": "number", @@ -91,4 +91,4 @@ "type": "lens", "updated_at": "2021-08-04T16:34:28.102Z", "version": "WzQ1OTUsMV0=" -} \ No newline at end of file +} diff --git a/x-pack/filebeat/module/threatintel/_meta/kibana/7/lens/8a6f7b20-de94-11eb-8f2b-753caedf727d.json b/x-pack/filebeat/module/threatintel/_meta/kibana/7/lens/8a6f7b20-de94-11eb-8f2b-753caedf727d.json index 86e2c969773..16f93c3473b 100644 --- a/x-pack/filebeat/module/threatintel/_meta/kibana/7/lens/8a6f7b20-de94-11eb-8f2b-753caedf727d.json +++ b/x-pack/filebeat/module/threatintel/_meta/kibana/7/lens/8a6f7b20-de94-11eb-8f2b-753caedf727d.json @@ -36,7 +36,7 @@ "size": 10 }, "scale": "ordinal", - "sourceField": "threatintel.indicator.url.original" + "sourceField": "threat.indicator.url.original" } }, "incompleteColumns": {} @@ -91,4 +91,4 @@ "type": "lens", "updated_at": "2021-08-04T16:34:28.102Z", "version": "WzQ1OTAsMV0=" -} \ No newline at end of file +} diff --git a/x-pack/filebeat/module/threatintel/_meta/kibana/7/lens/8fb01a00-df51-11eb-8f2b-753caedf727d.json b/x-pack/filebeat/module/threatintel/_meta/kibana/7/lens/8fb01a00-df51-11eb-8f2b-753caedf727d.json index be51533efa4..b8cc9578146 100644 --- a/x-pack/filebeat/module/threatintel/_meta/kibana/7/lens/8fb01a00-df51-11eb-8f2b-753caedf727d.json +++ b/x-pack/filebeat/module/threatintel/_meta/kibana/7/lens/8fb01a00-df51-11eb-8f2b-753caedf727d.json @@ -28,7 +28,7 @@ "size": 10 }, "scale": "ordinal", - "sourceField": "threatintel.indicator.url.path" + "sourceField": "threat.indicator.url.path" }, "9afb1b09-0f20-488c-9242-a94f7d11800b": { "dataType": "number", @@ -91,4 +91,4 @@ "type": "lens", "updated_at": "2021-08-04T16:34:33.127Z", "version": "WzQ2NzYsMV0=" -} \ No newline at end of file +} diff --git a/x-pack/filebeat/module/threatintel/_meta/kibana/7/lens/9282afc0-72d9-11eb-a3e3-b3cc7c78a70f.json b/x-pack/filebeat/module/threatintel/_meta/kibana/7/lens/9282afc0-72d9-11eb-a3e3-b3cc7c78a70f.json index 42d14abd0ec..09935680d66 100644 --- a/x-pack/filebeat/module/threatintel/_meta/kibana/7/lens/9282afc0-72d9-11eb-a3e3-b3cc7c78a70f.json +++ b/x-pack/filebeat/module/threatintel/_meta/kibana/7/lens/9282afc0-72d9-11eb-a3e3-b3cc7c78a70f.json @@ -22,7 +22,7 @@ "a6319ec8-2ec8-4d3a-bc54-efe0a306786f": { "dataType": "string", "isBucketed": true, - "label": "Top values of threatintel.indicator.type", + "label": "Top values of threat.indicator.type", "operationType": "terms", "params": { "missingBucket": false, @@ -35,7 +35,7 @@ "size": 10 }, "scale": "ordinal", - "sourceField": "threatintel.indicator.type" + "sourceField": "threat.indicator.type" } }, "incompleteColumns": {} @@ -70,13 +70,13 @@ "store": "appState" }, "exists": { - "field": "threatintel.indicator.type" + "field": "threat.indicator.type" }, "meta": { "alias": null, "disabled": false, "indexRefName": "filter-index-pattern-1", - "key": "threatintel.indicator.type", + "key": "threat.indicator.type", "negate": false, "type": "exists", "value": "exists" @@ -147,4 +147,4 @@ "type": "lens", "updated_at": "2021-08-04T16:34:32.145Z", "version": "WzQ2NTMsMV0=" -} \ No newline at end of file +} diff --git a/x-pack/filebeat/module/threatintel/_meta/kibana/7/lens/949bc180-df52-11eb-8f2b-753caedf727d.json b/x-pack/filebeat/module/threatintel/_meta/kibana/7/lens/949bc180-df52-11eb-8f2b-753caedf727d.json index b4784339ef2..ec09008e580 100644 --- a/x-pack/filebeat/module/threatintel/_meta/kibana/7/lens/949bc180-df52-11eb-8f2b-753caedf727d.json +++ b/x-pack/filebeat/module/threatintel/_meta/kibana/7/lens/949bc180-df52-11eb-8f2b-753caedf727d.json @@ -28,7 +28,7 @@ "size": 10 }, "scale": "ordinal", - "sourceField": "threatintel.recordedfuture.risk.riskSummary" + "sourceField": "recordedfuture.risk.riskSummary" }, "9afb1b09-0f20-488c-9242-a94f7d11800b": { "dataType": "number", @@ -91,4 +91,4 @@ "type": "lens", "updated_at": "2021-08-04T16:34:33.127Z", "version": "WzQ2NjYsMV0=" -} \ No newline at end of file +} diff --git a/x-pack/filebeat/module/threatintel/_meta/kibana/7/lens/976620a0-de98-11eb-8f2b-753caedf727d.json b/x-pack/filebeat/module/threatintel/_meta/kibana/7/lens/976620a0-de98-11eb-8f2b-753caedf727d.json index b9d9b336d1e..7bfea0d313e 100644 --- a/x-pack/filebeat/module/threatintel/_meta/kibana/7/lens/976620a0-de98-11eb-8f2b-753caedf727d.json +++ b/x-pack/filebeat/module/threatintel/_meta/kibana/7/lens/976620a0-de98-11eb-8f2b-753caedf727d.json @@ -28,7 +28,7 @@ "size": 10 }, "scale": "ordinal", - "sourceField": "threatintel.indicator.file.hash.md5" + "sourceField": "threat.indicator.file.hash.md5" }, "9afb1b09-0f20-488c-9242-a94f7d11800b": { "dataType": "number", @@ -91,4 +91,4 @@ "type": "lens", "updated_at": "2021-08-04T16:34:28.102Z", "version": "WzQ1OTMsMV0=" -} \ No newline at end of file +} diff --git a/x-pack/filebeat/module/threatintel/_meta/kibana/7/lens/9c78ade0-de95-11eb-8f2b-753caedf727d.json b/x-pack/filebeat/module/threatintel/_meta/kibana/7/lens/9c78ade0-de95-11eb-8f2b-753caedf727d.json index cb82ae74ba5..b6a60ae06c2 100644 --- a/x-pack/filebeat/module/threatintel/_meta/kibana/7/lens/9c78ade0-de95-11eb-8f2b-753caedf727d.json +++ b/x-pack/filebeat/module/threatintel/_meta/kibana/7/lens/9c78ade0-de95-11eb-8f2b-753caedf727d.json @@ -28,7 +28,7 @@ "size": 10 }, "scale": "ordinal", - "sourceField": "threatintel.anomali.description" + "sourceField": "anomali.limo.description" }, "9afb1b09-0f20-488c-9242-a94f7d11800b": { "dataType": "number", @@ -91,4 +91,4 @@ "type": "lens", "updated_at": "2021-08-04T16:34:28.102Z", "version": "WzQ1OTcsMV0=" -} \ No newline at end of file +} diff --git a/x-pack/filebeat/module/threatintel/_meta/kibana/7/lens/a0a31740-df51-11eb-8f2b-753caedf727d.json b/x-pack/filebeat/module/threatintel/_meta/kibana/7/lens/a0a31740-df51-11eb-8f2b-753caedf727d.json index ce6d74b3763..7a4ccbec7ff 100644 --- a/x-pack/filebeat/module/threatintel/_meta/kibana/7/lens/a0a31740-df51-11eb-8f2b-753caedf727d.json +++ b/x-pack/filebeat/module/threatintel/_meta/kibana/7/lens/a0a31740-df51-11eb-8f2b-753caedf727d.json @@ -28,7 +28,7 @@ "size": 10 }, "scale": "ordinal", - "sourceField": "threatintel.indicator.url.scheme" + "sourceField": "threat.indicator.url.scheme" }, "9afb1b09-0f20-488c-9242-a94f7d11800b": { "dataType": "number", @@ -91,4 +91,4 @@ "type": "lens", "updated_at": "2021-08-04T16:34:33.127Z", "version": "WzQ2NzQsMV0=" -} \ No newline at end of file +} diff --git a/x-pack/filebeat/module/threatintel/_meta/kibana/7/lens/aac00bc0-de98-11eb-8f2b-753caedf727d.json b/x-pack/filebeat/module/threatintel/_meta/kibana/7/lens/aac00bc0-de98-11eb-8f2b-753caedf727d.json index 2e80121c2e4..062ccc359f7 100644 --- a/x-pack/filebeat/module/threatintel/_meta/kibana/7/lens/aac00bc0-de98-11eb-8f2b-753caedf727d.json +++ b/x-pack/filebeat/module/threatintel/_meta/kibana/7/lens/aac00bc0-de98-11eb-8f2b-753caedf727d.json @@ -28,7 +28,7 @@ "size": 10 }, "scale": "ordinal", - "sourceField": "threatintel.indicator.file.hash.sha1" + "sourceField": "threat.indicator.file.hash.sha1" }, "9afb1b09-0f20-488c-9242-a94f7d11800b": { "dataType": "number", @@ -91,4 +91,4 @@ "type": "lens", "updated_at": "2021-08-04T16:34:28.102Z", "version": "WzQ1OTQsMV0=" -} \ No newline at end of file +} diff --git a/x-pack/filebeat/module/threatintel/_meta/kibana/7/lens/ae5934e0-de94-11eb-8f2b-753caedf727d.json b/x-pack/filebeat/module/threatintel/_meta/kibana/7/lens/ae5934e0-de94-11eb-8f2b-753caedf727d.json index 02719d9dcb0..17f6d2ccc21 100644 --- a/x-pack/filebeat/module/threatintel/_meta/kibana/7/lens/ae5934e0-de94-11eb-8f2b-753caedf727d.json +++ b/x-pack/filebeat/module/threatintel/_meta/kibana/7/lens/ae5934e0-de94-11eb-8f2b-753caedf727d.json @@ -36,7 +36,7 @@ "size": 10 }, "scale": "ordinal", - "sourceField": "threatintel.indicator.url.domain" + "sourceField": "threat.indicator.url.domain" } }, "incompleteColumns": {} @@ -91,4 +91,4 @@ "type": "lens", "updated_at": "2021-08-04T16:34:28.102Z", "version": "WzQ1OTEsMV0=" -} \ No newline at end of file +} diff --git a/x-pack/filebeat/module/threatintel/_meta/kibana/7/lens/b0837690-df52-11eb-8f2b-753caedf727d.json b/x-pack/filebeat/module/threatintel/_meta/kibana/7/lens/b0837690-df52-11eb-8f2b-753caedf727d.json index c7587803107..2ee5c4b1a2a 100644 --- a/x-pack/filebeat/module/threatintel/_meta/kibana/7/lens/b0837690-df52-11eb-8f2b-753caedf727d.json +++ b/x-pack/filebeat/module/threatintel/_meta/kibana/7/lens/b0837690-df52-11eb-8f2b-753caedf727d.json @@ -28,7 +28,7 @@ "size": 10 }, "scale": "ordinal", - "sourceField": "threatintel.recordedfuture.risk.criticalityLabel" + "sourceField": "recordedfuture.risk.criticalityLabel" }, "9afb1b09-0f20-488c-9242-a94f7d11800b": { "dataType": "number", @@ -94,4 +94,4 @@ "type": "lens", "updated_at": "2021-08-04T16:34:33.127Z", "version": "WzQ2NjMsMV0=" -} \ No newline at end of file +} diff --git a/x-pack/filebeat/module/threatintel/_meta/kibana/7/lens/bd28cb00-de96-11eb-8f2b-753caedf727d.json b/x-pack/filebeat/module/threatintel/_meta/kibana/7/lens/bd28cb00-de96-11eb-8f2b-753caedf727d.json index ed51bcc85fb..5f95d44b92d 100644 --- a/x-pack/filebeat/module/threatintel/_meta/kibana/7/lens/bd28cb00-de96-11eb-8f2b-753caedf727d.json +++ b/x-pack/filebeat/module/threatintel/_meta/kibana/7/lens/bd28cb00-de96-11eb-8f2b-753caedf727d.json @@ -36,7 +36,7 @@ "size": 3 }, "scale": "ordinal", - "sourceField": "threatintel.anomalithreatstream.severity" + "sourceField": "anomali.threatstream.severity" } }, "incompleteColumns": {} @@ -98,4 +98,4 @@ "type": "lens", "updated_at": "2021-08-04T16:34:28.102Z", "version": "WzQ1ODIsMV0=" -} \ No newline at end of file +} diff --git a/x-pack/filebeat/module/threatintel/_meta/kibana/7/lens/bfd2bfe0-de97-11eb-8f2b-753caedf727d.json b/x-pack/filebeat/module/threatintel/_meta/kibana/7/lens/bfd2bfe0-de97-11eb-8f2b-753caedf727d.json index 0850075db5b..c1110d8d611 100644 --- a/x-pack/filebeat/module/threatintel/_meta/kibana/7/lens/bfd2bfe0-de97-11eb-8f2b-753caedf727d.json +++ b/x-pack/filebeat/module/threatintel/_meta/kibana/7/lens/bfd2bfe0-de97-11eb-8f2b-753caedf727d.json @@ -28,7 +28,7 @@ "size": 5 }, "scale": "ordinal", - "sourceField": "threatintel.indicator.confidence" + "sourceField": "threat.indicator.confidence" }, "9afb1b09-0f20-488c-9242-a94f7d11800b": { "dataType": "number", @@ -94,4 +94,4 @@ "type": "lens", "updated_at": "2021-08-04T16:34:28.102Z", "version": "WzQ1NzgsMV0=" -} \ No newline at end of file +} diff --git a/x-pack/filebeat/module/threatintel/_meta/kibana/7/lens/c2a5c180-df51-11eb-8f2b-753caedf727d.json b/x-pack/filebeat/module/threatintel/_meta/kibana/7/lens/c2a5c180-df51-11eb-8f2b-753caedf727d.json index 5915a46aca5..6163c46e0b0 100644 --- a/x-pack/filebeat/module/threatintel/_meta/kibana/7/lens/c2a5c180-df51-11eb-8f2b-753caedf727d.json +++ b/x-pack/filebeat/module/threatintel/_meta/kibana/7/lens/c2a5c180-df51-11eb-8f2b-753caedf727d.json @@ -28,7 +28,7 @@ "size": 10 }, "scale": "ordinal", - "sourceField": "threatintel.indicator.ip" + "sourceField": "threat.indicator.ip" }, "9afb1b09-0f20-488c-9242-a94f7d11800b": { "dataType": "number", @@ -47,7 +47,7 @@ "filters": [], "query": { "language": "kuery", - "query": "event.dataset:\"threatintel.recordedfuture\" and threatintel.indicator.type:ipv4-addr" + "query": "event.dataset:\"threatintel.recordedfuture\" and threat.indicator.type:ipv4-addr" }, "visualization": { "columns": [ @@ -91,4 +91,4 @@ "type": "lens", "updated_at": "2021-08-04T16:34:33.127Z", "version": "WzQ2NjksMV0=" -} \ No newline at end of file +} diff --git a/x-pack/filebeat/module/threatintel/_meta/kibana/7/lens/c91fcd10-de95-11eb-8f2b-753caedf727d.json b/x-pack/filebeat/module/threatintel/_meta/kibana/7/lens/c91fcd10-de95-11eb-8f2b-753caedf727d.json index 63c9a1eebde..9eecce1a1c3 100644 --- a/x-pack/filebeat/module/threatintel/_meta/kibana/7/lens/c91fcd10-de95-11eb-8f2b-753caedf727d.json +++ b/x-pack/filebeat/module/threatintel/_meta/kibana/7/lens/c91fcd10-de95-11eb-8f2b-753caedf727d.json @@ -36,7 +36,7 @@ "size": 10 }, "scale": "ordinal", - "sourceField": "threatintel.indicator.provider" + "sourceField": "threat.indicator.provider" } }, "incompleteColumns": {} @@ -91,4 +91,4 @@ "type": "lens", "updated_at": "2021-08-04T16:34:28.102Z", "version": "WzQ1ODQsMV0=" -} \ No newline at end of file +} diff --git a/x-pack/filebeat/module/threatintel/_meta/kibana/7/lens/cf4b4e40-ff69-11eb-acb2-2960a7069ed1.json b/x-pack/filebeat/module/threatintel/_meta/kibana/7/lens/cf4b4e40-ff69-11eb-acb2-2960a7069ed1.json index 0d2bc89d441..ddb2717dd0e 100644 --- a/x-pack/filebeat/module/threatintel/_meta/kibana/7/lens/cf4b4e40-ff69-11eb-acb2-2960a7069ed1.json +++ b/x-pack/filebeat/module/threatintel/_meta/kibana/7/lens/cf4b4e40-ff69-11eb-acb2-2960a7069ed1.json @@ -15,7 +15,7 @@ "73cdbb81-57ca-4474-a86c-bca60a527d29": { "dataType": "string", "isBucketed": true, - "label": "Top values of threatintel.indicator.type", + "label": "Top values of threat.indicator.type", "operationType": "terms", "params": { "missingBucket": false, @@ -28,7 +28,7 @@ "size": 15 }, "scale": "ordinal", - "sourceField": "threatintel.indicator.type" + "sourceField": "threat.indicator.type" }, "89f18519-9360-4d37-ae52-134604ac6cfc": { "customLabel": true, @@ -118,4 +118,4 @@ "type": "lens", "updated_at": "2021-10-11T08:02:55.512Z", "version": "WzUyOCwxXQ==" -} \ No newline at end of file +} diff --git a/x-pack/filebeat/module/threatintel/_meta/kibana/7/lens/d991e510-de96-11eb-8f2b-753caedf727d.json b/x-pack/filebeat/module/threatintel/_meta/kibana/7/lens/d991e510-de96-11eb-8f2b-753caedf727d.json index f630743094f..e718c098360 100644 --- a/x-pack/filebeat/module/threatintel/_meta/kibana/7/lens/d991e510-de96-11eb-8f2b-753caedf727d.json +++ b/x-pack/filebeat/module/threatintel/_meta/kibana/7/lens/d991e510-de96-11eb-8f2b-753caedf727d.json @@ -36,7 +36,7 @@ "size": 5 }, "scale": "ordinal", - "sourceField": "threatintel.anomalithreatstream.state" + "sourceField": "anomali.threatstream.state" } }, "incompleteColumns": {} @@ -112,4 +112,4 @@ "type": "lens", "updated_at": "2021-08-04T16:34:28.102Z", "version": "WzQ1ODcsMV0=" -} \ No newline at end of file +} diff --git a/x-pack/filebeat/module/threatintel/_meta/kibana/7/lens/dd4a3da0-df50-11eb-8f2b-753caedf727d.json b/x-pack/filebeat/module/threatintel/_meta/kibana/7/lens/dd4a3da0-df50-11eb-8f2b-753caedf727d.json index b9b2341c0b1..4a25b4df0ef 100644 --- a/x-pack/filebeat/module/threatintel/_meta/kibana/7/lens/dd4a3da0-df50-11eb-8f2b-753caedf727d.json +++ b/x-pack/filebeat/module/threatintel/_meta/kibana/7/lens/dd4a3da0-df50-11eb-8f2b-753caedf727d.json @@ -36,7 +36,7 @@ "size": 10 }, "scale": "ordinal", - "sourceField": "threatintel.indicator.file.hash.md5" + "sourceField": "threat.indicator.file.hash.md5" } }, "incompleteColumns": {} @@ -90,4 +90,4 @@ "type": "lens", "updated_at": "2021-08-04T16:34:33.127Z", "version": "WzQ2NzEsMV0=" -} \ No newline at end of file +} diff --git a/x-pack/filebeat/module/threatintel/_meta/kibana/7/lens/e5f07800-de94-11eb-8f2b-753caedf727d.json b/x-pack/filebeat/module/threatintel/_meta/kibana/7/lens/e5f07800-de94-11eb-8f2b-753caedf727d.json index 1985a727380..03d75c58b2f 100644 --- a/x-pack/filebeat/module/threatintel/_meta/kibana/7/lens/e5f07800-de94-11eb-8f2b-753caedf727d.json +++ b/x-pack/filebeat/module/threatintel/_meta/kibana/7/lens/e5f07800-de94-11eb-8f2b-753caedf727d.json @@ -36,7 +36,7 @@ "size": 10 }, "scale": "ordinal", - "sourceField": "threatintel.anomalithreatstream.id" + "sourceField": "anomali.threatstream.id" } }, "incompleteColumns": {} @@ -91,4 +91,4 @@ "type": "lens", "updated_at": "2021-08-04T16:34:28.102Z", "version": "WzQ1OTgsMV0=" -} \ No newline at end of file +} diff --git a/x-pack/filebeat/module/threatintel/_meta/kibana/7/lens/f37f8350-df50-11eb-8f2b-753caedf727d.json b/x-pack/filebeat/module/threatintel/_meta/kibana/7/lens/f37f8350-df50-11eb-8f2b-753caedf727d.json index 45745f96eb0..f4c84cc7426 100644 --- a/x-pack/filebeat/module/threatintel/_meta/kibana/7/lens/f37f8350-df50-11eb-8f2b-753caedf727d.json +++ b/x-pack/filebeat/module/threatintel/_meta/kibana/7/lens/f37f8350-df50-11eb-8f2b-753caedf727d.json @@ -36,7 +36,7 @@ "size": 10 }, "scale": "ordinal", - "sourceField": "threatintel.indicator.file.hash.sha1" + "sourceField": "threat.indicator.file.hash.sha1" } }, "incompleteColumns": {} @@ -90,4 +90,4 @@ "type": "lens", "updated_at": "2021-08-04T16:34:33.127Z", "version": "WzQ2NzIsMV0=" -} \ No newline at end of file +} diff --git a/x-pack/filebeat/module/threatintel/_meta/kibana/7/lens/f52a9720-de93-11eb-8f2b-753caedf727d.json b/x-pack/filebeat/module/threatintel/_meta/kibana/7/lens/f52a9720-de93-11eb-8f2b-753caedf727d.json index a3740f838db..7e2446f1e8d 100644 --- a/x-pack/filebeat/module/threatintel/_meta/kibana/7/lens/f52a9720-de93-11eb-8f2b-753caedf727d.json +++ b/x-pack/filebeat/module/threatintel/_meta/kibana/7/lens/f52a9720-de93-11eb-8f2b-753caedf727d.json @@ -28,7 +28,7 @@ "size": 10 }, "scale": "ordinal", - "sourceField": "threatintel.indicator.email.address" + "sourceField": "threat.indicator.email.address" }, "9afb1b09-0f20-488c-9242-a94f7d11800b": { "dataType": "number", @@ -91,4 +91,4 @@ "type": "lens", "updated_at": "2021-08-04T16:34:28.102Z", "version": "WzQ1ODksMV0=" -} \ No newline at end of file +} diff --git a/x-pack/filebeat/module/threatintel/_meta/kibana/7/lens/f5f18940-de96-11eb-8f2b-753caedf727d.json b/x-pack/filebeat/module/threatintel/_meta/kibana/7/lens/f5f18940-de96-11eb-8f2b-753caedf727d.json index c5c7c021b28..9b281bf4769 100644 --- a/x-pack/filebeat/module/threatintel/_meta/kibana/7/lens/f5f18940-de96-11eb-8f2b-753caedf727d.json +++ b/x-pack/filebeat/module/threatintel/_meta/kibana/7/lens/f5f18940-de96-11eb-8f2b-753caedf727d.json @@ -28,7 +28,7 @@ "size": 5 }, "scale": "ordinal", - "sourceField": "threatintel.indicator.marking.tlp" + "sourceField": "threat.indicator.marking.tlp" }, "9afb1b09-0f20-488c-9242-a94f7d11800b": { "dataType": "number", @@ -112,4 +112,4 @@ "type": "lens", "updated_at": "2021-08-04T16:34:28.102Z", "version": "WzQ1ODMsMV0=" -} \ No newline at end of file +} diff --git a/x-pack/filebeat/module/threatintel/_meta/kibana/7/map/63365b50-82aa-11eb-ac13-d5ca87cb8fa2.json b/x-pack/filebeat/module/threatintel/_meta/kibana/7/map/63365b50-82aa-11eb-ac13-d5ca87cb8fa2.json index 63e7825a56b..b37986b02eb 100644 --- a/x-pack/filebeat/module/threatintel/_meta/kibana/7/map/63365b50-82aa-11eb-ac13-d5ca87cb8fa2.json +++ b/x-pack/filebeat/module/threatintel/_meta/kibana/7/map/63365b50-82aa-11eb-ac13-d5ca87cb8fa2.json @@ -35,7 +35,7 @@ "type": "count" } ], - "term": "threatintel.indicator.geo.country_iso_code", + "term": "threat.indicator.geo.country_iso_code", "type": "ES_TERM_SOURCE" } } @@ -205,4 +205,4 @@ "type": "map", "updated_at": "2021-08-04T16:34:30.070Z", "version": "WzQ2MTksMV0=" -} \ No newline at end of file +} diff --git a/x-pack/filebeat/module/threatintel/_meta/kibana/7/map/ec5aa090-df42-11eb-8f2b-753caedf727d.json b/x-pack/filebeat/module/threatintel/_meta/kibana/7/map/ec5aa090-df42-11eb-8f2b-753caedf727d.json index 8100b60e6b3..e5e94752566 100644 --- a/x-pack/filebeat/module/threatintel/_meta/kibana/7/map/ec5aa090-df42-11eb-8f2b-753caedf727d.json +++ b/x-pack/filebeat/module/threatintel/_meta/kibana/7/map/ec5aa090-df42-11eb-8f2b-753caedf727d.json @@ -29,16 +29,16 @@ "applyGlobalQuery": true, "applyGlobalTime": true, "filterByMapBounds": true, - "geoField": "threatintel.indicator.geo.location", + "geoField": "threat.indicator.geo.location", "id": "a3ecc6af-0299-4cb9-a29c-0b70f666b011", "indexPatternRefName": "layer_1_source_index_pattern", "scalingType": "LIMIT", "sortField": "", "sortOrder": "desc", "tooltipProperties": [ - "threatintel.indicator.as.number", - "threatintel.indicator.as.organization.name", - "threatintel.indicator.geo.country_iso_code" + "threat.indicator.as.number", + "threat.indicator.as.organization.name", + "threat.indicator.geo.country_iso_code" ], "topHitsSize": 1, "topHitsSplitField": "", @@ -195,4 +195,4 @@ "type": "map", "updated_at": "2021-08-04T16:34:28.102Z", "version": "WzQ1ODgsMV0=" -} \ No newline at end of file +} diff --git a/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/01c261b0-7aa9-11eb-ac13-d5ca87cb8fa2.json b/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/01c261b0-7aa9-11eb-ac13-d5ca87cb8fa2.json index 93d283d07e0..3bc7559fbf6 100644 --- a/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/01c261b0-7aa9-11eb-ac13-d5ca87cb8fa2.json +++ b/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/01c261b0-7aa9-11eb-ac13-d5ca87cb8fa2.json @@ -30,13 +30,13 @@ "store": "appState" }, "exists": { - "field": "threatintel.otx.title" + "field": "otx.title" }, "meta": { "alias": null, "disabled": false, "indexRefName": "kibanaSavedObjectMeta.searchSourceJSON.filter[1].meta.index", - "key": "threatintel.otx.title", + "key": "otx.title", "negate": false, "type": "exists", "value": "exists" @@ -67,7 +67,7 @@ "id": "2", "params": { "customLabel": "AlienVault OTX Indicator Title", - "field": "threatintel.otx.title", + "field": "otx.title", "missingBucket": false, "missingBucketLabel": "Missing", "order": "desc", @@ -123,4 +123,4 @@ "type": "visualization", "updated_at": "2021-08-04T16:34:27.014Z", "version": "WzQ1NzQsMV0=" -} \ No newline at end of file +} diff --git a/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/02294f80-73c7-11eb-a3e3-b3cc7c78a70f.json b/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/02294f80-73c7-11eb-a3e3-b3cc7c78a70f.json index 822c006ccc2..ff5c6b0b875 100644 --- a/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/02294f80-73c7-11eb-a3e3-b3cc7c78a70f.json +++ b/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/02294f80-73c7-11eb-a3e3-b3cc7c78a70f.json @@ -30,13 +30,13 @@ "store": "appState" }, "exists": { - "field": "threatintel.indicator.file.hash.sha1" + "field": "threat.indicator.file.hash.sha1" }, "meta": { "alias": null, "disabled": false, "indexRefName": "kibanaSavedObjectMeta.searchSourceJSON.filter[1].meta.index", - "key": "threatintel.indicator.file.hash.sha1", + "key": "threat.indicator.file.hash.sha1", "negate": false, "type": "exists", "value": "exists" @@ -67,7 +67,7 @@ "id": "2", "params": { "customLabel": "MISP SHA1 Hash Indicator", - "field": "threatintel.indicator.file.hash.sha1", + "field": "threat.indicator.file.hash.sha1", "missingBucket": false, "missingBucketLabel": "Missing", "order": "desc", @@ -123,4 +123,4 @@ "type": "visualization", "updated_at": "2021-08-04T16:34:31.083Z", "version": "WzQ2NDEsMV0=" -} \ No newline at end of file +} diff --git a/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/0ccdda50-76ce-11eb-a3e3-b3cc7c78a70f.json b/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/0ccdda50-76ce-11eb-a3e3-b3cc7c78a70f.json index 1197b8b4a7e..44b6e23d553 100644 --- a/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/0ccdda50-76ce-11eb-a3e3-b3cc7c78a70f.json +++ b/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/0ccdda50-76ce-11eb-a3e3-b3cc7c78a70f.json @@ -30,13 +30,13 @@ "store": "appState" }, "exists": { - "field": "threatintel.indicator.file.hash.md5" + "field": "threat.indicator.file.hash.md5" }, "meta": { "alias": null, "disabled": false, "indexRefName": "kibanaSavedObjectMeta.searchSourceJSON.filter[1].meta.index", - "key": "threatintel.indicator.file.hash.md5", + "key": "threat.indicator.file.hash.md5", "negate": false, "type": "exists", "value": "exists" @@ -67,7 +67,7 @@ "id": "2", "params": { "customLabel": "AlienVault OTX MD5 Hash Indicator", - "field": "threatintel.indicator.file.hash.md5", + "field": "threat.indicator.file.hash.md5", "missingBucket": false, "missingBucketLabel": "Missing", "order": "desc", @@ -123,4 +123,4 @@ "type": "visualization", "updated_at": "2021-08-04T16:34:27.014Z", "version": "WzQ1NzMsMV0=" -} \ No newline at end of file +} diff --git a/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/142fb6c0-82a8-11eb-ac13-d5ca87cb8fa2.json b/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/142fb6c0-82a8-11eb-ac13-d5ca87cb8fa2.json index bf55ff3b237..624dde62b61 100644 --- a/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/142fb6c0-82a8-11eb-ac13-d5ca87cb8fa2.json +++ b/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/142fb6c0-82a8-11eb-ac13-d5ca87cb8fa2.json @@ -30,13 +30,13 @@ "store": "appState" }, "exists": { - "field": "threatintel.indicator.file.hash.sha1" + "field": "threat.indicator.file.hash.sha1" }, "meta": { "alias": null, "disabled": false, "indexRefName": "kibanaSavedObjectMeta.searchSourceJSON.filter[1].meta.index", - "key": "threatintel.indicator.file.hash.sha1", + "key": "threat.indicator.file.hash.sha1", "negate": false, "type": "exists", "value": "exists" @@ -78,7 +78,7 @@ "id": "2", "params": { "customLabel": "SHA1 Hash", - "field": "threatintel.indicator.file.hash.sha1", + "field": "threat.indicator.file.hash.sha1", "missingBucket": false, "missingBucketLabel": "Missing", "order": "desc", @@ -134,4 +134,4 @@ "type": "visualization", "updated_at": "2021-08-04T16:34:30.070Z", "version": "WzQ2MjYsMV0=" -} \ No newline at end of file +} diff --git a/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/1a0d5250-72e5-11eb-a3e3-b3cc7c78a70f.json b/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/1a0d5250-72e5-11eb-a3e3-b3cc7c78a70f.json index f9fc2390a2b..f43232fe645 100644 --- a/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/1a0d5250-72e5-11eb-a3e3-b3cc7c78a70f.json +++ b/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/1a0d5250-72e5-11eb-a3e3-b3cc7c78a70f.json @@ -30,13 +30,13 @@ "store": "appState" }, "exists": { - "field": "threatintel.indicator.file.hash.sha256" + "field": "threat.indicator.file.hash.sha256" }, "meta": { "alias": null, "disabled": false, "indexRefName": "kibanaSavedObjectMeta.searchSourceJSON.filter[1].meta.index", - "key": "threatintel.indicator.file.hash.sha256", + "key": "threat.indicator.file.hash.sha256", "negate": false, "type": "exists", "value": "exists" @@ -47,13 +47,13 @@ "store": "appState" }, "exists": { - "field": "threatintel.indicator.type" + "field": "threat.indicator.type" }, "meta": { "alias": null, "disabled": false, "indexRefName": "kibanaSavedObjectMeta.searchSourceJSON.filter[2].meta.index", - "key": "threatintel.indicator.type", + "key": "threat.indicator.type", "negate": false, "type": "exists", "value": "exists" @@ -84,7 +84,7 @@ "id": "2", "params": { "customLabel": "SHA256 Hash", - "field": "threatintel.indicator.file.hash.sha256", + "field": "threat.indicator.file.hash.sha256", "missingBucket": false, "missingBucketLabel": "Missing", "order": "desc", @@ -101,7 +101,7 @@ "id": "3", "params": { "customLabel": "File Type", - "field": "threatintel.indicator.file.type", + "field": "threat.indicator.file.type", "missingBucket": false, "missingBucketLabel": "Missing", "order": "desc", @@ -162,4 +162,4 @@ "type": "visualization", "updated_at": "2021-08-04T16:34:29.041Z", "version": "WzQ2MDYsMV0=" -} \ No newline at end of file +} diff --git a/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/1a1c60c0-72d5-11eb-a3e3-b3cc7c78a70f.json b/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/1a1c60c0-72d5-11eb-a3e3-b3cc7c78a70f.json index b2e430cff4c..e972911d995 100644 --- a/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/1a1c60c0-72d5-11eb-a3e3-b3cc7c78a70f.json +++ b/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/1a1c60c0-72d5-11eb-a3e3-b3cc7c78a70f.json @@ -26,13 +26,13 @@ "store": "appState" }, "exists": { - "field": "threatintel.indicator.type" + "field": "threat.indicator.type" }, "meta": { "alias": null, "disabled": false, "indexRefName": "kibanaSavedObjectMeta.searchSourceJSON.filter[1].meta.index", - "key": "threatintel.indicator.type", + "key": "threat.indicator.type", "negate": false, "type": "exists", "value": "exists" @@ -78,7 +78,7 @@ "enabled": true, "id": "3", "params": { - "field": "threatintel.indicator.type", + "field": "threat.indicator.type", "missingBucket": false, "missingBucketLabel": "Missing", "order": "desc", @@ -143,4 +143,4 @@ "type": "visualization", "updated_at": "2021-08-04T16:34:32.145Z", "version": "WzQ2NDksMV0=" -} \ No newline at end of file +} diff --git a/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/1adff580-72ee-11eb-a3e3-b3cc7c78a70f.json b/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/1adff580-72ee-11eb-a3e3-b3cc7c78a70f.json index 71144247760..550140b912f 100644 --- a/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/1adff580-72ee-11eb-a3e3-b3cc7c78a70f.json +++ b/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/1adff580-72ee-11eb-a3e3-b3cc7c78a70f.json @@ -30,13 +30,13 @@ "store": "appState" }, "exists": { - "field": "threatintel.indicator.domain" + "field": "threat.indicator.url.domain" }, "meta": { "alias": null, "disabled": false, "indexRefName": "kibanaSavedObjectMeta.searchSourceJSON.filter[1].meta.index", - "key": "threatintel.indicator.domain", + "key": "threat.indicator.url.domain", "negate": false, "type": "exists", "value": "exists" @@ -67,7 +67,7 @@ "id": "2", "params": { "customLabel": "Threat Indicator Domain", - "field": "threatintel.indicator.domain", + "field": "threat.indicator.url.domain", "missingBucket": false, "missingBucketLabel": "Missing", "order": "desc", @@ -123,4 +123,4 @@ "type": "visualization", "updated_at": "2021-08-04T16:34:25.974Z", "version": "WzQ1NTQsMV0=" -} \ No newline at end of file +} diff --git a/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/1c969990-73c7-11eb-a3e3-b3cc7c78a70f.json b/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/1c969990-73c7-11eb-a3e3-b3cc7c78a70f.json index e2f3d6fda09..e77a6cee76b 100644 --- a/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/1c969990-73c7-11eb-a3e3-b3cc7c78a70f.json +++ b/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/1c969990-73c7-11eb-a3e3-b3cc7c78a70f.json @@ -30,13 +30,13 @@ "store": "appState" }, "exists": { - "field": "threatintel.indicator.file.hash.sha256" + "field": "threat.indicator.file.hash.sha256" }, "meta": { "alias": null, "disabled": false, "indexRefName": "kibanaSavedObjectMeta.searchSourceJSON.filter[1].meta.index", - "key": "threatintel.indicator.file.hash.sha256", + "key": "threat.indicator.file.hash.sha256", "negate": false, "type": "exists", "value": "exists" @@ -67,7 +67,7 @@ "id": "2", "params": { "customLabel": "MISP SHA256 Hash Indicator", - "field": "threatintel.indicator.file.hash.sha256", + "field": "threat.indicator.file.hash.sha256", "missingBucket": false, "missingBucketLabel": "Missing", "order": "desc", @@ -123,4 +123,4 @@ "type": "visualization", "updated_at": "2021-08-04T16:34:31.083Z", "version": "WzQ2NDIsMV0=" -} \ No newline at end of file +} diff --git a/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/1d8002d0-82a7-11eb-ac13-d5ca87cb8fa2.json b/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/1d8002d0-82a7-11eb-ac13-d5ca87cb8fa2.json index 328a64f0785..57ca90543d3 100644 --- a/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/1d8002d0-82a7-11eb-ac13-d5ca87cb8fa2.json +++ b/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/1d8002d0-82a7-11eb-ac13-d5ca87cb8fa2.json @@ -30,13 +30,13 @@ "store": "appState" }, "exists": { - "field": "threatintel.indicator.file.pe.imphash" + "field": "threat.indicator.file.pe.imphash" }, "meta": { "alias": null, "disabled": false, "indexRefName": "kibanaSavedObjectMeta.searchSourceJSON.filter[1].meta.index", - "key": "threatintel.indicator.file.pe.imphash", + "key": "threat.indicator.file.pe.imphash", "negate": false, "type": "exists", "value": "exists" @@ -78,7 +78,7 @@ "id": "2", "params": { "customLabel": "Imphash Hash", - "field": "threatintel.indicator.file.pe.imphash", + "field": "threat.indicator.file.pe.imphash", "missingBucket": false, "missingBucketLabel": "Missing", "order": "desc", @@ -134,4 +134,4 @@ "type": "visualization", "updated_at": "2021-08-04T16:34:30.070Z", "version": "WzQ2MjgsMV0=" -} \ No newline at end of file +} diff --git a/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/21ff17c0-82a6-11eb-ac13-d5ca87cb8fa2.json b/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/21ff17c0-82a6-11eb-ac13-d5ca87cb8fa2.json index b3e12fb4193..4bec354e536 100644 --- a/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/21ff17c0-82a6-11eb-ac13-d5ca87cb8fa2.json +++ b/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/21ff17c0-82a6-11eb-ac13-d5ca87cb8fa2.json @@ -30,13 +30,13 @@ "store": "appState" }, "exists": { - "field": "threatintel.indicator.file.hash.md5" + "field": "threat.indicator.file.hash.md5" }, "meta": { "alias": null, "disabled": false, "indexRefName": "kibanaSavedObjectMeta.searchSourceJSON.filter[1].meta.index", - "key": "threatintel.indicator.file.hash.md5", + "key": "threat.indicator.file.hash.md5", "negate": false, "type": "exists", "value": "exists" @@ -78,7 +78,7 @@ "id": "2", "params": { "customLabel": "MD5 Hash", - "field": "threatintel.indicator.file.hash.md5", + "field": "threat.indicator.file.hash.md5", "missingBucket": false, "missingBucketLabel": "Missing", "order": "desc", @@ -134,4 +134,4 @@ "type": "visualization", "updated_at": "2021-08-04T16:34:30.070Z", "version": "WzQ2MjUsMV0=" -} \ No newline at end of file +} diff --git a/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/302cd5b0-76cd-11eb-a3e3-b3cc7c78a70f.json b/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/302cd5b0-76cd-11eb-a3e3-b3cc7c78a70f.json index 0e395ef2431..9bb6455feea 100644 --- a/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/302cd5b0-76cd-11eb-a3e3-b3cc7c78a70f.json +++ b/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/302cd5b0-76cd-11eb-a3e3-b3cc7c78a70f.json @@ -30,13 +30,13 @@ "store": "appState" }, "exists": { - "field": "threatintel.indicator.ip" + "field": "threat.indicator.ip" }, "meta": { "alias": null, "disabled": false, "indexRefName": "kibanaSavedObjectMeta.searchSourceJSON.filter[1].meta.index", - "key": "threatintel.indicator.ip", + "key": "threat.indicator.ip", "negate": false, "type": "exists", "value": "exists" @@ -67,7 +67,7 @@ "id": "2", "params": { "customLabel": "AlienVault OTX IP Indicator", - "field": "threatintel.indicator.ip", + "field": "threat.indicator.ip", "missingBucket": false, "missingBucketLabel": "Missing", "order": "desc", @@ -123,4 +123,4 @@ "type": "visualization", "updated_at": "2021-08-04T16:34:27.014Z", "version": "WzQ1NjcsMV0=" -} \ No newline at end of file +} diff --git a/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/302d0850-ff7b-11eb-acb2-2960a7069ed1.json b/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/302d0850-ff7b-11eb-acb2-2960a7069ed1.json index f931164c888..50f2a9cebc5 100644 --- a/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/302d0850-ff7b-11eb-acb2-2960a7069ed1.json +++ b/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/302d0850-ff7b-11eb-acb2-2960a7069ed1.json @@ -28,7 +28,7 @@ "id": "2", "params": { "customLabel": "Confidence", - "field": "threatintel.indicator.confidence", + "field": "threat.indicator.confidence", "missingBucket": false, "missingBucketLabel": "Missing", "order": "desc", @@ -148,4 +148,4 @@ "type": "visualization", "updated_at": "2021-10-11T08:02:55.512Z", "version": "WzUzMCwxXQ==" -} \ No newline at end of file +} diff --git a/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/346136f0-76d5-11eb-a3e3-b3cc7c78a70f.json b/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/346136f0-76d5-11eb-a3e3-b3cc7c78a70f.json index 3edcd79c797..bc86816afc3 100644 --- a/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/346136f0-76d5-11eb-a3e3-b3cc7c78a70f.json +++ b/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/346136f0-76d5-11eb-a3e3-b3cc7c78a70f.json @@ -30,13 +30,13 @@ "store": "appState" }, "exists": { - "field": "threatintel.indicator.url.original" + "field": "threat.indicator.url.original" }, "meta": { "alias": null, "disabled": false, "indexRefName": "kibanaSavedObjectMeta.searchSourceJSON.filter[1].meta.index", - "key": "threatintel.indicator.url.original", + "key": "threat.indicator.url.original", "negate": false, "type": "exists", "value": "exists" @@ -67,7 +67,7 @@ "id": "2", "params": { "customLabel": "AlienVault OTX URL Indicator", - "field": "threatintel.indicator.url.original", + "field": "threat.indicator.url.original", "missingBucket": false, "missingBucketLabel": "Missing", "order": "desc", @@ -123,4 +123,4 @@ "type": "visualization", "updated_at": "2021-08-04T16:34:27.014Z", "version": "WzQ1NjksMV0=" -} \ No newline at end of file +} diff --git a/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/40d61ab0-72e6-11eb-a3e3-b3cc7c78a70f.json b/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/40d61ab0-72e6-11eb-a3e3-b3cc7c78a70f.json index f8d2e419a2b..a3e2646eea2 100644 --- a/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/40d61ab0-72e6-11eb-a3e3-b3cc7c78a70f.json +++ b/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/40d61ab0-72e6-11eb-a3e3-b3cc7c78a70f.json @@ -27,7 +27,7 @@ "enabled": true, "id": "2", "params": { - "field": "threatintel.indicator.file.type", + "field": "threat.indicator.file.type", "missingBucket": false, "missingBucketLabel": "Missing", "order": "desc", @@ -82,4 +82,4 @@ "type": "visualization", "updated_at": "2021-08-04T16:34:29.041Z", "version": "WzQ2MDcsMV0=" -} \ No newline at end of file +} diff --git a/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/41100be0-72e5-11eb-a3e3-b3cc7c78a70f.json b/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/41100be0-72e5-11eb-a3e3-b3cc7c78a70f.json index d1e07d3fbbb..37aa10e1c04 100644 --- a/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/41100be0-72e5-11eb-a3e3-b3cc7c78a70f.json +++ b/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/41100be0-72e5-11eb-a3e3-b3cc7c78a70f.json @@ -30,13 +30,13 @@ "store": "appState" }, "exists": { - "field": "threatintel.indicator.file.hash.ssdeep" + "field": "threat.indicator.file.hash.ssdeep" }, "meta": { "alias": null, "disabled": false, "indexRefName": "kibanaSavedObjectMeta.searchSourceJSON.filter[1].meta.index", - "key": "threatintel.indicator.file.hash.ssdeep", + "key": "threat.indicator.file.hash.ssdeep", "negate": false, "type": "exists", "value": "exists" @@ -47,13 +47,13 @@ "store": "appState" }, "exists": { - "field": "threatintel.indicator.type" + "field": "threat.indicator.type" }, "meta": { "alias": null, "disabled": false, "indexRefName": "kibanaSavedObjectMeta.searchSourceJSON.filter[2].meta.index", - "key": "threatintel.indicator.type", + "key": "threat.indicator.type", "negate": false, "type": "exists", "value": "exists" @@ -84,7 +84,7 @@ "id": "2", "params": { "customLabel": "ssdeep Hash", - "field": "threatintel.indicator.file.hash.ssdeep", + "field": "threat.indicator.file.hash.ssdeep", "missingBucket": false, "missingBucketLabel": "Missing", "order": "desc", @@ -101,7 +101,7 @@ "id": "3", "params": { "customLabel": "File Type", - "field": "threatintel.indicator.file.type", + "field": "threat.indicator.file.type", "missingBucket": false, "missingBucketLabel": "Missing", "order": "desc", @@ -162,4 +162,4 @@ "type": "visualization", "updated_at": "2021-08-04T16:34:29.041Z", "version": "WzQ2MDgsMV0=" -} \ No newline at end of file +} diff --git a/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/49f0c060-76cd-11eb-a3e3-b3cc7c78a70f.json b/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/49f0c060-76cd-11eb-a3e3-b3cc7c78a70f.json index 79f94d2a046..65880a6f4bb 100644 --- a/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/49f0c060-76cd-11eb-a3e3-b3cc7c78a70f.json +++ b/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/49f0c060-76cd-11eb-a3e3-b3cc7c78a70f.json @@ -30,13 +30,13 @@ "store": "appState" }, "exists": { - "field": "threatintel.indicator.domain" + "field": "threat.indicator.url.domain" }, "meta": { "alias": null, "disabled": false, "indexRefName": "kibanaSavedObjectMeta.searchSourceJSON.filter[1].meta.index", - "key": "threatintel.indicator.domain", + "key": "threat.indicator.url.domain", "negate": false, "type": "exists", "value": "exists" @@ -67,7 +67,7 @@ "id": "2", "params": { "customLabel": "AlienVault OTX IP Indicator", - "field": "threatintel.indicator.domain", + "field": "threat.indicator.url.domain", "missingBucket": false, "missingBucketLabel": "Missing", "order": "desc", @@ -123,4 +123,4 @@ "type": "visualization", "updated_at": "2021-08-04T16:34:27.014Z", "version": "WzQ1NjgsMV0=" -} \ No newline at end of file +} diff --git a/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/4e5d25c0-76ce-11eb-a3e3-b3cc7c78a70f.json b/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/4e5d25c0-76ce-11eb-a3e3-b3cc7c78a70f.json index f44f7a32fa3..324c632ab27 100644 --- a/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/4e5d25c0-76ce-11eb-a3e3-b3cc7c78a70f.json +++ b/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/4e5d25c0-76ce-11eb-a3e3-b3cc7c78a70f.json @@ -30,13 +30,13 @@ "store": "appState" }, "exists": { - "field": "threatintel.indicator.file.hash.sha256" + "field": "threat.indicator.file.hash.sha256" }, "meta": { "alias": null, "disabled": false, "indexRefName": "kibanaSavedObjectMeta.searchSourceJSON.filter[1].meta.index", - "key": "threatintel.indicator.file.hash.sha256", + "key": "threat.indicator.file.hash.sha256", "negate": false, "type": "exists", "value": "exists" @@ -67,7 +67,7 @@ "id": "2", "params": { "customLabel": "AlienVault OTX SHA256 Hash Indicator", - "field": "threatintel.indicator.file.hash.sha256", + "field": "threat.indicator.file.hash.sha256", "missingBucket": false, "missingBucketLabel": "Missing", "order": "desc", @@ -123,4 +123,4 @@ "type": "visualization", "updated_at": "2021-08-04T16:34:27.014Z", "version": "WzQ1NzIsMV0=" -} \ No newline at end of file +} diff --git a/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/57faae10-73c5-11eb-a3e3-b3cc7c78a70f.json b/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/57faae10-73c5-11eb-a3e3-b3cc7c78a70f.json index 927f457e351..014612f2d3c 100644 --- a/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/57faae10-73c5-11eb-a3e3-b3cc7c78a70f.json +++ b/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/57faae10-73c5-11eb-a3e3-b3cc7c78a70f.json @@ -30,13 +30,13 @@ "store": "appState" }, "exists": { - "field": "threatintel.indicator.provider" + "field": "threat.indicator.provider" }, "meta": { "alias": null, "disabled": false, "indexRefName": "kibanaSavedObjectMeta.searchSourceJSON.filter[1].meta.index", - "key": "threatintel.indicator.provider", + "key": "threat.indicator.provider", "negate": false, "type": "exists", "value": "exists" @@ -72,7 +72,7 @@ "enabled": true, "id": "2", "params": { - "field": "threatintel.indicator.provider", + "field": "threat.indicator.provider", "missingBucket": false, "missingBucketLabel": "Missing", "order": "desc", @@ -137,4 +137,4 @@ "type": "visualization", "updated_at": "2021-08-04T16:34:31.083Z", "version": "WzQ2NDMsMV0=" -} \ No newline at end of file +} diff --git a/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/5b4877b0-82a6-11eb-ac13-d5ca87cb8fa2.json b/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/5b4877b0-82a6-11eb-ac13-d5ca87cb8fa2.json index db8a7fcef7e..ad4c74b0110 100644 --- a/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/5b4877b0-82a6-11eb-ac13-d5ca87cb8fa2.json +++ b/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/5b4877b0-82a6-11eb-ac13-d5ca87cb8fa2.json @@ -30,13 +30,13 @@ "store": "appState" }, "exists": { - "field": "threatintel.indicator.file.hash.sha256" + "field": "threat.indicator.file.hash.sha256" }, "meta": { "alias": null, "disabled": false, "indexRefName": "kibanaSavedObjectMeta.searchSourceJSON.filter[1].meta.index", - "key": "threatintel.indicator.file.hash.sha256", + "key": "threat.indicator.file.hash.sha256", "negate": false, "type": "exists", "value": "exists" @@ -78,7 +78,7 @@ "id": "2", "params": { "customLabel": "SHA256 Hash", - "field": "threatintel.indicator.file.hash.sha256", + "field": "threat.indicator.file.hash.sha256", "missingBucket": false, "missingBucketLabel": "Missing", "order": "desc", @@ -134,4 +134,4 @@ "type": "visualization", "updated_at": "2021-08-04T16:34:30.070Z", "version": "WzQ2MjcsMV0=" -} \ No newline at end of file +} diff --git a/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/5d395d80-ff71-11eb-acb2-2960a7069ed1.json b/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/5d395d80-ff71-11eb-acb2-2960a7069ed1.json index f559210728b..b5fe450d273 100644 --- a/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/5d395d80-ff71-11eb-acb2-2960a7069ed1.json +++ b/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/5d395d80-ff71-11eb-acb2-2960a7069ed1.json @@ -28,7 +28,7 @@ "id": "2", "params": { "customLabel": "Most Linked Adversaries", - "field": "threatintel.threatq.adversaries", + "field": "threatq.adversaries", "missingBucket": false, "missingBucketLabel": "Missing", "order": "desc", @@ -74,4 +74,4 @@ "type": "visualization", "updated_at": "2021-10-11T08:02:55.512Z", "version": "WzUyNiwxXQ==" -} \ No newline at end of file +} diff --git a/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/5eb61d00-ff72-11eb-acb2-2960a7069ed1.json b/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/5eb61d00-ff72-11eb-acb2-2960a7069ed1.json index fde00ab644d..3626ee406b7 100644 --- a/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/5eb61d00-ff72-11eb-acb2-2960a7069ed1.json +++ b/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/5eb61d00-ff72-11eb-acb2-2960a7069ed1.json @@ -31,7 +31,7 @@ "id": "2", "params": { "customLabel": "Indicator Type", - "field": "threatintel.indicator.type", + "field": "threat.indicator.type", "missingBucket": false, "missingBucketLabel": "Missing", "order": "desc", @@ -48,7 +48,7 @@ "id": "3", "params": { "customLabel": "Indicator Value", - "field": "threatintel.threatq.indicator_value", + "field": "threatq.indicator_value", "missingBucket": false, "missingBucketLabel": "Missing", "order": "desc", @@ -94,4 +94,4 @@ "type": "visualization", "updated_at": "2021-10-11T08:07:14.354Z", "version": "WzYxNCwxXQ==" -} \ No newline at end of file +} diff --git a/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/6077fd00-76d5-11eb-a3e3-b3cc7c78a70f.json b/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/6077fd00-76d5-11eb-a3e3-b3cc7c78a70f.json index 4e9740c9a10..75b7601754b 100644 --- a/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/6077fd00-76d5-11eb-a3e3-b3cc7c78a70f.json +++ b/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/6077fd00-76d5-11eb-a3e3-b3cc7c78a70f.json @@ -30,13 +30,13 @@ "store": "appState" }, "exists": { - "field": "threatintel.indicator.url.path" + "field": "threat.indicator.url.path" }, "meta": { "alias": null, "disabled": false, "indexRefName": "kibanaSavedObjectMeta.searchSourceJSON.filter[1].meta.index", - "key": "threatintel.indicator.url.path", + "key": "threat.indicator.url.path", "negate": false, "type": "exists", "value": "exists" @@ -67,7 +67,7 @@ "id": "2", "params": { "customLabel": "AlienVault OTX URI Indicator", - "field": "threatintel.indicator.url.path", + "field": "threat.indicator.url.path", "missingBucket": false, "missingBucketLabel": "Missing", "order": "desc", @@ -123,4 +123,4 @@ "type": "visualization", "updated_at": "2021-08-04T16:34:27.014Z", "version": "WzQ1NzEsMV0=" -} \ No newline at end of file +} diff --git a/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/62f6daa0-72ee-11eb-a3e3-b3cc7c78a70f.json b/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/62f6daa0-72ee-11eb-a3e3-b3cc7c78a70f.json index c0879c8aff7..039e88b7677 100644 --- a/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/62f6daa0-72ee-11eb-a3e3-b3cc7c78a70f.json +++ b/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/62f6daa0-72ee-11eb-a3e3-b3cc7c78a70f.json @@ -30,13 +30,13 @@ "store": "appState" }, "exists": { - "field": "threatintel.indicator.url.full" + "field": "threat.indicator.url.full" }, "meta": { "alias": null, "disabled": false, "indexRefName": "kibanaSavedObjectMeta.searchSourceJSON.filter[1].meta.index", - "key": "threatintel.indicator.url.full", + "key": "threat.indicator.url.full", "negate": false, "type": "exists", "value": "exists" @@ -67,7 +67,7 @@ "id": "2", "params": { "customLabel": "Threat Indicator URL", - "field": "threatintel.indicator.url.full", + "field": "threat.indicator.url.full", "missingBucket": false, "missingBucketLabel": "Missing", "order": "desc", @@ -123,4 +123,4 @@ "type": "visualization", "updated_at": "2021-08-04T16:34:25.974Z", "version": "WzQ1NTUsMV0=" -} \ No newline at end of file +} diff --git a/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/7546ac40-82a6-11eb-ac13-d5ca87cb8fa2.json b/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/7546ac40-82a6-11eb-ac13-d5ca87cb8fa2.json index 479d7e408e3..4de8710a0e2 100644 --- a/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/7546ac40-82a6-11eb-ac13-d5ca87cb8fa2.json +++ b/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/7546ac40-82a6-11eb-ac13-d5ca87cb8fa2.json @@ -30,13 +30,13 @@ "store": "appState" }, "exists": { - "field": "threatintel.indicator.file.hash.ssdeep" + "field": "threat.indicator.file.hash.ssdeep" }, "meta": { "alias": null, "disabled": false, "indexRefName": "kibanaSavedObjectMeta.searchSourceJSON.filter[1].meta.index", - "key": "threatintel.indicator.file.hash.ssdeep", + "key": "threat.indicator.file.hash.ssdeep", "negate": false, "type": "exists", "value": "exists" @@ -78,7 +78,7 @@ "id": "2", "params": { "customLabel": "ssdeep Hash", - "field": "threatintel.indicator.file.hash.ssdeep", + "field": "threat.indicator.file.hash.ssdeep", "missingBucket": false, "missingBucketLabel": "Missing", "order": "desc", @@ -134,4 +134,4 @@ "type": "visualization", "updated_at": "2021-08-04T16:34:30.070Z", "version": "WzQ2MjQsMV0=" -} \ No newline at end of file +} diff --git a/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/7582b030-73c6-11eb-a3e3-b3cc7c78a70f.json b/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/7582b030-73c6-11eb-a3e3-b3cc7c78a70f.json index 6767b7e0d19..e2833363e12 100644 --- a/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/7582b030-73c6-11eb-a3e3-b3cc7c78a70f.json +++ b/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/7582b030-73c6-11eb-a3e3-b3cc7c78a70f.json @@ -30,13 +30,13 @@ "store": "appState" }, "exists": { - "field": "threatintel.indicator.domain" + "field": "threat.indicator.url.domain" }, "meta": { "alias": null, "disabled": false, "indexRefName": "kibanaSavedObjectMeta.searchSourceJSON.filter[1].meta.index", - "key": "threatintel.indicator.domain", + "key": "threat.indicator.url.domain", "negate": false, "type": "exists", "value": "exists" @@ -67,7 +67,7 @@ "id": "2", "params": { "customLabel": "MISP Domain Indicator", - "field": "threatintel.indicator.domain", + "field": "threat.indicator.url.domain", "missingBucket": false, "missingBucketLabel": "Missing", "order": "desc", @@ -123,4 +123,4 @@ "type": "visualization", "updated_at": "2021-08-04T16:34:31.083Z", "version": "WzQ2MzIsMV0=" -} \ No newline at end of file +} diff --git a/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/786546d0-82a5-11eb-ac13-d5ca87cb8fa2.json b/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/786546d0-82a5-11eb-ac13-d5ca87cb8fa2.json index bc70c5824da..773a823e514 100644 --- a/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/786546d0-82a5-11eb-ac13-d5ca87cb8fa2.json +++ b/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/786546d0-82a5-11eb-ac13-d5ca87cb8fa2.json @@ -30,13 +30,13 @@ "store": "appState" }, "exists": { - "field": "threatintel.indicator.file.hash.tlsh" + "field": "threat.indicator.file.hash.tlsh" }, "meta": { "alias": null, "disabled": false, "indexRefName": "kibanaSavedObjectMeta.searchSourceJSON.filter[1].meta.index", - "key": "threatintel.indicator.file.hash.tlsh", + "key": "threat.indicator.file.hash.tlsh", "negate": false, "type": "exists", "value": "exists" @@ -78,7 +78,7 @@ "id": "2", "params": { "customLabel": "TLSH Hash", - "field": "threatintel.indicator.file.hash.tlsh", + "field": "threat.indicator.file.hash.tlsh", "missingBucket": false, "missingBucketLabel": "Missing", "order": "desc", @@ -134,4 +134,4 @@ "type": "visualization", "updated_at": "2021-08-04T16:34:30.070Z", "version": "WzQ2MjMsMV0=" -} \ No newline at end of file +} diff --git a/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/79da77d0-72e5-11eb-a3e3-b3cc7c78a70f.json b/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/79da77d0-72e5-11eb-a3e3-b3cc7c78a70f.json index 50bed6e06e4..0551a2e4428 100644 --- a/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/79da77d0-72e5-11eb-a3e3-b3cc7c78a70f.json +++ b/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/79da77d0-72e5-11eb-a3e3-b3cc7c78a70f.json @@ -30,13 +30,13 @@ "store": "appState" }, "exists": { - "field": "threatintel.indicator.file.hash.tlsh" + "field": "threat.indicator.file.hash.tlsh" }, "meta": { "alias": null, "disabled": false, "indexRefName": "kibanaSavedObjectMeta.searchSourceJSON.filter[1].meta.index", - "key": "threatintel.indicator.file.hash.tlsh", + "key": "threat.indicator.file.hash.tlsh", "negate": false, "type": "exists", "value": "exists" @@ -47,13 +47,13 @@ "store": "appState" }, "exists": { - "field": "threatintel.indicator.type" + "field": "threat.indicator.type" }, "meta": { "alias": null, "disabled": false, "indexRefName": "kibanaSavedObjectMeta.searchSourceJSON.filter[2].meta.index", - "key": "threatintel.indicator.type", + "key": "threat.indicator.type", "negate": false, "type": "exists", "value": "exists" @@ -84,7 +84,7 @@ "id": "2", "params": { "customLabel": "TLSH Hash", - "field": "threatintel.indicator.file.hash.tlsh", + "field": "threat.indicator.file.hash.tlsh", "missingBucket": false, "missingBucketLabel": "Missing", "order": "desc", @@ -101,7 +101,7 @@ "id": "3", "params": { "customLabel": "File Type", - "field": "threatintel.indicator.file.type", + "field": "threat.indicator.file.type", "missingBucket": false, "missingBucketLabel": "Missing", "order": "desc", @@ -162,4 +162,4 @@ "type": "visualization", "updated_at": "2021-08-04T16:34:29.041Z", "version": "WzQ2MDIsMV0=" -} \ No newline at end of file +} diff --git a/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/7c7d3750-73c3-11eb-a3e3-b3cc7c78a70f.json b/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/7c7d3750-73c3-11eb-a3e3-b3cc7c78a70f.json index 6ca2835a167..ffb99fa0838 100644 --- a/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/7c7d3750-73c3-11eb-a3e3-b3cc7c78a70f.json +++ b/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/7c7d3750-73c3-11eb-a3e3-b3cc7c78a70f.json @@ -30,13 +30,13 @@ "store": "appState" }, "exists": { - "field": "threatintel.indicator.type" + "field": "threat.indicator.type" }, "meta": { "alias": null, "disabled": false, "indexRefName": "kibanaSavedObjectMeta.searchSourceJSON.filter[1].meta.index", - "key": "threatintel.indicator.type", + "key": "threat.indicator.type", "negate": false, "type": "exists", "value": "exists" @@ -66,7 +66,7 @@ "enabled": true, "id": "2", "params": { - "field": "threatintel.indicator.type", + "field": "threat.indicator.type", "missingBucket": false, "missingBucketLabel": "Missing", "order": "desc", @@ -131,4 +131,4 @@ "type": "visualization", "updated_at": "2021-08-04T16:34:31.083Z", "version": "WzQ2MzQsMV0=" -} \ No newline at end of file +} diff --git a/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/7cbe5900-82ab-11eb-ac13-d5ca87cb8fa2.json b/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/7cbe5900-82ab-11eb-ac13-d5ca87cb8fa2.json index 08ea90539c1..75f21ca1a42 100644 --- a/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/7cbe5900-82ab-11eb-ac13-d5ca87cb8fa2.json +++ b/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/7cbe5900-82ab-11eb-ac13-d5ca87cb8fa2.json @@ -30,13 +30,13 @@ "store": "appState" }, "exists": { - "field": "threatintel.indicator.first_seen" + "field": "threat.indicator.first_seen" }, "meta": { "alias": null, "disabled": false, "indexRefName": "kibanaSavedObjectMeta.searchSourceJSON.filter[1].meta.index", - "key": "threatintel.indicator.first_seen", + "key": "threat.indicator.first_seen", "negate": false, "type": "exists", "value": "exists" @@ -76,7 +76,7 @@ "id": "2", "params": { "customLabel": "Indicator First Seen", - "field": "threatintel.indicator.first_seen", + "field": "threat.indicator.first_seen", "missingBucket": false, "missingBucketLabel": "Missing", "order": "desc", @@ -132,4 +132,4 @@ "type": "visualization", "updated_at": "2021-08-04T16:34:30.070Z", "version": "WzQ2MjIsMV0=" -} \ No newline at end of file +} diff --git a/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/87980f70-72ec-11eb-a3e3-b3cc7c78a70f.json b/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/87980f70-72ec-11eb-a3e3-b3cc7c78a70f.json index 3001eca6082..0b947ec09cd 100644 --- a/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/87980f70-72ec-11eb-a3e3-b3cc7c78a70f.json +++ b/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/87980f70-72ec-11eb-a3e3-b3cc7c78a70f.json @@ -30,13 +30,13 @@ "store": "appState" }, "exists": { - "field": "threatintel.abuseurl.threat" + "field": "abusech.url.threat" }, "meta": { "alias": null, "disabled": false, "indexRefName": "kibanaSavedObjectMeta.searchSourceJSON.filter[1].meta.index", - "key": "threatintel.abuseurl.threat", + "key": "abusech.url.threat", "negate": false, "type": "exists", "value": "exists" @@ -73,7 +73,7 @@ "id": "2", "params": { "customLabel": "Abuse URL Threat", - "field": "threatintel.abuseurl.threat", + "field": "abusech.url.threat", "missingBucket": false, "missingBucketLabel": "Missing", "order": "desc", @@ -204,4 +204,4 @@ "type": "visualization", "updated_at": "2021-08-04T16:34:25.974Z", "version": "WzQ1NTAsMV0=" -} \ No newline at end of file +} diff --git a/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/8b2a64a0-82a8-11eb-ac13-d5ca87cb8fa2.json b/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/8b2a64a0-82a8-11eb-ac13-d5ca87cb8fa2.json index 8fd2ef65b07..13aee45f317 100644 --- a/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/8b2a64a0-82a8-11eb-ac13-d5ca87cb8fa2.json +++ b/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/8b2a64a0-82a8-11eb-ac13-d5ca87cb8fa2.json @@ -30,13 +30,13 @@ "store": "appState" }, "exists": { - "field": "threatintel.indicator.file.extension" + "field": "threat.indicator.file.extension" }, "meta": { "alias": null, "disabled": false, "indexRefName": "kibanaSavedObjectMeta.searchSourceJSON.filter[1].meta.index", - "key": "threatintel.indicator.file.extension", + "key": "threat.indicator.file.extension", "negate": false, "type": "exists", "value": "exists" @@ -66,7 +66,7 @@ "enabled": true, "id": "2", "params": { - "field": "threatintel.indicator.file.extension", + "field": "threat.indicator.file.extension", "missingBucket": false, "missingBucketLabel": "Missing", "order": "desc", @@ -131,4 +131,4 @@ "type": "visualization", "updated_at": "2021-08-04T16:34:30.070Z", "version": "WzQ2MTcsMV0=" -} \ No newline at end of file +} diff --git a/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/9047e8b0-72de-11eb-a3e3-b3cc7c78a70f.json b/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/9047e8b0-72de-11eb-a3e3-b3cc7c78a70f.json index cfa8fad3789..652e363bbf0 100644 --- a/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/9047e8b0-72de-11eb-a3e3-b3cc7c78a70f.json +++ b/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/9047e8b0-72de-11eb-a3e3-b3cc7c78a70f.json @@ -34,7 +34,7 @@ "id": "2", "params": { "customLabel": "Threat Indicator Provider", - "field": "threatintel.indicator.provider", + "field": "threat.indicator.provider", "missingBucket": false, "missingBucketLabel": "Missing", "order": "desc", @@ -156,4 +156,4 @@ "type": "visualization", "updated_at": "2021-08-04T16:34:32.145Z", "version": "WzQ2NTUsMV0=" -} \ No newline at end of file +} diff --git a/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/9109e490-76cd-11eb-a3e3-b3cc7c78a70f.json b/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/9109e490-76cd-11eb-a3e3-b3cc7c78a70f.json index 3e1c8861ced..9146d87144a 100644 --- a/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/9109e490-76cd-11eb-a3e3-b3cc7c78a70f.json +++ b/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/9109e490-76cd-11eb-a3e3-b3cc7c78a70f.json @@ -30,13 +30,13 @@ "store": "appState" }, "exists": { - "field": "threatintel.indicator.url.domain" + "field": "threat.indicator.url.domain" }, "meta": { "alias": null, "disabled": false, "indexRefName": "kibanaSavedObjectMeta.searchSourceJSON.filter[1].meta.index", - "key": "threatintel.indicator.url.domain", + "key": "threat.indicator.url.domain", "negate": false, "type": "exists", "value": "exists" @@ -67,7 +67,7 @@ "id": "2", "params": { "customLabel": "AlienVault OTX URL Domain Indicator", - "field": "threatintel.indicator.url.domain", + "field": "threat.indicator.url.domain", "missingBucket": false, "missingBucketLabel": "Missing", "order": "desc", @@ -123,4 +123,4 @@ "type": "visualization", "updated_at": "2021-08-04T16:34:27.014Z", "version": "WzQ1NzAsMV0=" -} \ No newline at end of file +} diff --git a/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/92961600-7621-11eb-a3e3-b3cc7c78a70f.json b/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/92961600-7621-11eb-a3e3-b3cc7c78a70f.json index f9a63566f09..c6ec332aa22 100644 --- a/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/92961600-7621-11eb-a3e3-b3cc7c78a70f.json +++ b/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/92961600-7621-11eb-a3e3-b3cc7c78a70f.json @@ -33,7 +33,7 @@ "type": "list" }, { - "fieldName": "threatintel.indicator.provider", + "fieldName": "threat.indicator.provider", "id": "1614117093181", "indexPatternRefName": "control_1_index_pattern", "label": "Indicator Provider", @@ -48,7 +48,7 @@ "type": "list" }, { - "fieldName": "threatintel.indicator.type", + "fieldName": "threat.indicator.type", "id": "1614117117360", "indexPatternRefName": "control_2_index_pattern", "label": "Indicator Type", @@ -101,4 +101,4 @@ "type": "visualization", "updated_at": "2021-08-04T16:34:32.145Z", "version": "WzQ2NDcsMV0=" -} \ No newline at end of file +} diff --git a/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/95f384b0-76d8-11eb-a3e3-b3cc7c78a70f.json b/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/95f384b0-76d8-11eb-a3e3-b3cc7c78a70f.json index a9c17ee0611..b2f747547b3 100644 --- a/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/95f384b0-76d8-11eb-a3e3-b3cc7c78a70f.json +++ b/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/95f384b0-76d8-11eb-a3e3-b3cc7c78a70f.json @@ -35,7 +35,7 @@ "id": "2", "params": { "customLabel": "", - "field": "threatintel.indicator.url.scheme", + "field": "threat.indicator.url.scheme", "missingBucket": false, "missingBucketLabel": "Missing", "order": "desc", @@ -156,4 +156,4 @@ "type": "visualization", "updated_at": "2021-08-04T16:34:27.014Z", "version": "WzQ1NjQsMV0=" -} \ No newline at end of file +} diff --git a/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/98d42ee0-76b6-11eb-a3e3-b3cc7c78a70f.json b/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/98d42ee0-76b6-11eb-a3e3-b3cc7c78a70f.json index 0c5102dfd14..03edc5edc0b 100644 --- a/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/98d42ee0-76b6-11eb-a3e3-b3cc7c78a70f.json +++ b/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/98d42ee0-76b6-11eb-a3e3-b3cc7c78a70f.json @@ -30,13 +30,13 @@ "store": "appState" }, "exists": { - "field": "threatintel.abuseurl.tags" + "field": "abusech.url.tags" }, "meta": { "alias": null, "disabled": false, "indexRefName": "kibanaSavedObjectMeta.searchSourceJSON.filter[1].meta.index", - "key": "threatintel.abuseurl.tags", + "key": "abusech.url.tags", "negate": false, "type": "exists", "value": "exists" @@ -67,7 +67,7 @@ "id": "2", "params": { "customLabel": "Abuse URL Tags", - "field": "threatintel.abuseurl.tags", + "field": "abusech.url.tags", "missingBucket": false, "missingBucketLabel": "Missing", "order": "desc", @@ -123,4 +123,4 @@ "type": "visualization", "updated_at": "2021-08-04T16:34:25.974Z", "version": "WzQ1NTEsMV0=" -} \ No newline at end of file +} diff --git a/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/a09329d0-73c6-11eb-a3e3-b3cc7c78a70f.json b/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/a09329d0-73c6-11eb-a3e3-b3cc7c78a70f.json index d81abd72e48..d34f5079186 100644 --- a/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/a09329d0-73c6-11eb-a3e3-b3cc7c78a70f.json +++ b/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/a09329d0-73c6-11eb-a3e3-b3cc7c78a70f.json @@ -30,13 +30,13 @@ "store": "appState" }, "exists": { - "field": "threatintel.indicator.ip" + "field": "threat.indicator.ip" }, "meta": { "alias": null, "disabled": false, "indexRefName": "kibanaSavedObjectMeta.searchSourceJSON.filter[1].meta.index", - "key": "threatintel.indicator.ip", + "key": "threat.indicator.ip", "negate": false, "type": "exists", "value": "exists" @@ -67,7 +67,7 @@ "id": "2", "params": { "customLabel": "MISP IP Indicator", - "field": "threatintel.indicator.ip", + "field": "threat.indicator.ip", "missingBucket": false, "missingBucketLabel": "Missing", "order": "desc", @@ -123,4 +123,4 @@ "type": "visualization", "updated_at": "2021-08-04T16:34:31.083Z", "version": "WzQ2MzMsMV0=" -} \ No newline at end of file +} diff --git a/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/a1616dd0-72eb-11eb-a3e3-b3cc7c78a70f.json b/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/a1616dd0-72eb-11eb-a3e3-b3cc7c78a70f.json index 419dcc323d1..ba4ce6e4ea7 100644 --- a/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/a1616dd0-72eb-11eb-a3e3-b3cc7c78a70f.json +++ b/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/a1616dd0-72eb-11eb-a3e3-b3cc7c78a70f.json @@ -30,13 +30,13 @@ "store": "appState" }, "exists": { - "field": "threatintel.abuseurl.blacklists.spamhaus_dbl" + "field": "abusech.url.blacklists.spamhaus_dbl" }, "meta": { "alias": null, "disabled": false, "indexRefName": "kibanaSavedObjectMeta.searchSourceJSON.filter[1].meta.index", - "key": "threatintel.abuseurl.blacklists.spamhaus_dbl", + "key": "abusech.url.blacklists.spamhaus_dbl", "negate": false, "type": "exists", "value": "exists" @@ -47,13 +47,13 @@ "store": "appState" }, "exists": { - "field": "threatintel.abuseurl.blacklists.surbl" + "field": "abusech.url.blacklists.surbl" }, "meta": { "alias": null, "disabled": false, "indexRefName": "kibanaSavedObjectMeta.searchSourceJSON.filter[2].meta.index", - "key": "threatintel.abuseurl.blacklists.surbl", + "key": "abusech.url.blacklists.surbl", "negate": false, "type": "exists", "value": "exists" @@ -84,7 +84,7 @@ "id": "2", "params": { "customLabel": "Spamhaus DBL Blacklist Status", - "field": "threatintel.abuseurl.blacklists.spamhaus_dbl", + "field": "abusech.url.blacklists.spamhaus_dbl", "missingBucket": false, "missingBucketLabel": "Missing", "order": "desc", @@ -101,7 +101,7 @@ "id": "3", "params": { "customLabel": "SURBL Blacklist Status", - "field": "threatintel.abuseurl.blacklists.surbl", + "field": "abusech.url.blacklists.surbl", "missingBucket": false, "missingBucketLabel": "Missing", "order": "desc", @@ -162,4 +162,4 @@ "type": "visualization", "updated_at": "2021-08-04T16:34:25.974Z", "version": "WzQ1NjAsMV0=" -} \ No newline at end of file +} diff --git a/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/a7b6e910-72ed-11eb-a3e3-b3cc7c78a70f.json b/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/a7b6e910-72ed-11eb-a3e3-b3cc7c78a70f.json index 007929c6d0a..81340059012 100644 --- a/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/a7b6e910-72ed-11eb-a3e3-b3cc7c78a70f.json +++ b/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/a7b6e910-72ed-11eb-a3e3-b3cc7c78a70f.json @@ -30,13 +30,13 @@ "store": "appState" }, "exists": { - "field": "threatintel.indicator.url.scheme" + "field": "threat.indicator.url.scheme" }, "meta": { "alias": null, "disabled": false, "indexRefName": "kibanaSavedObjectMeta.searchSourceJSON.filter[1].meta.index", - "key": "threatintel.indicator.url.scheme", + "key": "threat.indicator.url.scheme", "negate": false, "type": "exists", "value": "exists" @@ -74,7 +74,7 @@ "id": "2", "params": { "customLabel": "URL Scheme", - "field": "threatintel.indicator.url.scheme", + "field": "threat.indicator.url.scheme", "missingBucket": false, "missingBucketLabel": "Missing", "order": "desc", @@ -90,7 +90,7 @@ "enabled": true, "id": "3", "params": { - "field": "threatintel.indicator.url.scheme", + "field": "threat.indicator.url.scheme", "missingBucket": false, "missingBucketLabel": "Missing", "order": "desc", @@ -220,4 +220,4 @@ "type": "visualization", "updated_at": "2021-08-04T16:34:25.974Z", "version": "WzQ1NTIsMV0=" -} \ No newline at end of file +} diff --git a/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/a911a8b0-ff77-11eb-acb2-2960a7069ed1.json b/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/a911a8b0-ff77-11eb-acb2-2960a7069ed1.json index 59f66be7644..25929d8fef8 100644 --- a/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/a911a8b0-ff77-11eb-acb2-2960a7069ed1.json +++ b/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/a911a8b0-ff77-11eb-acb2-2960a7069ed1.json @@ -27,7 +27,7 @@ "enabled": true, "id": "2", "params": { - "field": "threatintel.indicator.marking.tlp", + "field": "threat.indicator.marking.tlp", "missingBucket": false, "missingBucketLabel": "Missing", "order": "desc", @@ -82,4 +82,4 @@ "type": "visualization", "updated_at": "2021-10-11T08:02:55.512Z", "version": "WzUyNSwxXQ==" -} \ No newline at end of file +} diff --git a/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/ad55b1e0-73c8-11eb-a3e3-b3cc7c78a70f.json b/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/ad55b1e0-73c8-11eb-a3e3-b3cc7c78a70f.json index a0719389fc8..0b6cc17dce5 100644 --- a/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/ad55b1e0-73c8-11eb-a3e3-b3cc7c78a70f.json +++ b/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/ad55b1e0-73c8-11eb-a3e3-b3cc7c78a70f.json @@ -35,7 +35,7 @@ "id": "2", "params": { "customLabel": "Indicator Marking TLP", - "field": "threatintel.indicator.marking.tlp", + "field": "threat.indicator.marking.tlp", "missingBucket": false, "missingBucketLabel": "Missing", "order": "desc", @@ -51,7 +51,7 @@ "enabled": true, "id": "3", "params": { - "field": "threatintel.indicator.marking.tlp", + "field": "threat.indicator.marking.tlp", "missingBucket": false, "missingBucketLabel": "Missing", "order": "desc", @@ -171,4 +171,4 @@ "type": "visualization", "updated_at": "2021-08-04T16:34:31.083Z", "version": "WzQ2MzgsMV0=" -} \ No newline at end of file +} diff --git a/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/aebde030-72d2-11eb-a3e3-b3cc7c78a70f.json b/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/aebde030-72d2-11eb-a3e3-b3cc7c78a70f.json index 0d3c70a156f..09bbd1da8a4 100644 --- a/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/aebde030-72d2-11eb-a3e3-b3cc7c78a70f.json +++ b/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/aebde030-72d2-11eb-a3e3-b3cc7c78a70f.json @@ -9,13 +9,13 @@ "store": "appState" }, "exists": { - "field": "threatintel.indicator.marking.tlp" + "field": "threat.indicator.marking.tlp" }, "meta": { "alias": null, "disabled": false, "indexRefName": "kibanaSavedObjectMeta.searchSourceJSON.filter[0].meta.index", - "key": "threatintel.indicator.marking.tlp", + "key": "threat.indicator.marking.tlp", "negate": false, "type": "exists", "value": "exists" @@ -55,7 +55,7 @@ "id": "2", "params": { "customLabel": "Indicator Marking TLP", - "field": "threatintel.indicator.marking.tlp", + "field": "threat.indicator.marking.tlp", "missingBucket": false, "missingBucketLabel": "Missing", "order": "desc", @@ -71,7 +71,7 @@ "enabled": true, "id": "3", "params": { - "field": "threatintel.indicator.marking.tlp", + "field": "threat.indicator.marking.tlp", "missingBucket": false, "missingBucketLabel": "Missing", "order": "desc", @@ -196,4 +196,4 @@ "type": "visualization", "updated_at": "2021-08-04T16:34:32.145Z", "version": "WzQ2NTcsMV0=" -} \ No newline at end of file +} diff --git a/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/b9533f50-72e5-11eb-a3e3-b3cc7c78a70f.json b/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/b9533f50-72e5-11eb-a3e3-b3cc7c78a70f.json index dd4771dced6..6b53ad4b086 100644 --- a/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/b9533f50-72e5-11eb-a3e3-b3cc7c78a70f.json +++ b/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/b9533f50-72e5-11eb-a3e3-b3cc7c78a70f.json @@ -30,13 +30,13 @@ "store": "appState" }, "exists": { - "field": "threatintel.indicator.file.pe.imphash" + "field": "threat.indicator.file.pe.imphash" }, "meta": { "alias": null, "disabled": false, "indexRefName": "kibanaSavedObjectMeta.searchSourceJSON.filter[1].meta.index", - "key": "threatintel.indicator.file.pe.imphash", + "key": "threat.indicator.file.pe.imphash", "negate": false, "type": "exists", "value": "exists" @@ -47,13 +47,13 @@ "store": "appState" }, "exists": { - "field": "threatintel.indicator.type" + "field": "threat.indicator.type" }, "meta": { "alias": null, "disabled": false, "indexRefName": "kibanaSavedObjectMeta.searchSourceJSON.filter[2].meta.index", - "key": "threatintel.indicator.type", + "key": "threat.indicator.type", "negate": false, "type": "exists", "value": "exists" @@ -84,7 +84,7 @@ "id": "2", "params": { "customLabel": "Imphash Hash", - "field": "threatintel.indicator.file.pe.imphash", + "field": "threat.indicator.file.pe.imphash", "missingBucket": false, "missingBucketLabel": "Missing", "order": "desc", @@ -101,7 +101,7 @@ "id": "3", "params": { "customLabel": "File Type", - "field": "threatintel.indicator.file.type", + "field": "threat.indicator.file.type", "missingBucket": false, "missingBucketLabel": "Missing", "order": "desc", @@ -162,4 +162,4 @@ "type": "visualization", "updated_at": "2021-08-04T16:34:29.041Z", "version": "WzQ2MDUsMV0=" -} \ No newline at end of file +} diff --git a/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/bc4790b0-82aa-11eb-ac13-d5ca87cb8fa2.json b/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/bc4790b0-82aa-11eb-ac13-d5ca87cb8fa2.json index f1fc5472b6b..395627036b1 100644 --- a/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/bc4790b0-82aa-11eb-ac13-d5ca87cb8fa2.json +++ b/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/bc4790b0-82aa-11eb-ac13-d5ca87cb8fa2.json @@ -30,13 +30,13 @@ "store": "appState" }, "exists": { - "field": "threatintel.malwarebazaar.intelligence.downloads" + "field": "abusech.malwarebazaar.intelligence.downloads" }, "meta": { "alias": null, "disabled": false, "indexRefName": "kibanaSavedObjectMeta.searchSourceJSON.filter[1].meta.index", - "key": "threatintel.malwarebazaar.intelligence.downloads", + "key": "abusech.malwarebazaar.intelligence.downloads", "negate": false, "type": "exists", "value": "exists" @@ -76,7 +76,7 @@ "id": "2", "params": { "customLabel": "Malware Bazaar Downloads", - "field": "threatintel.malwarebazaar.intelligence.downloads", + "field": "abusech.malwarebazaar.intelligence.downloads", "missingBucket": false, "missingBucketLabel": "Missing", "order": "desc", @@ -132,4 +132,4 @@ "type": "visualization", "updated_at": "2021-08-04T16:34:30.070Z", "version": "WzQ2MjAsMV0=" -} \ No newline at end of file +} diff --git a/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/bf3dfde0-73c3-11eb-a3e3-b3cc7c78a70f.json b/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/bf3dfde0-73c3-11eb-a3e3-b3cc7c78a70f.json index f65bf82d5b3..f71bb235922 100644 --- a/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/bf3dfde0-73c3-11eb-a3e3-b3cc7c78a70f.json +++ b/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/bf3dfde0-73c3-11eb-a3e3-b3cc7c78a70f.json @@ -30,13 +30,13 @@ "store": "appState" }, "exists": { - "field": "threatintel.misp.published" + "field": "misp.published" }, "meta": { "alias": null, "disabled": false, "indexRefName": "kibanaSavedObjectMeta.searchSourceJSON.filter[1].meta.index", - "key": "threatintel.misp.published", + "key": "misp.published", "negate": false, "type": "exists", "value": "exists" @@ -72,7 +72,7 @@ "enabled": true, "id": "2", "params": { - "field": "threatintel.misp.published", + "field": "misp.published", "missingBucket": false, "missingBucketLabel": "Missing", "order": "desc", @@ -137,4 +137,4 @@ "type": "visualization", "updated_at": "2021-08-04T16:34:31.083Z", "version": "WzQ2MzksMV0=" -} \ No newline at end of file +} diff --git a/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/c102b0f0-73c6-11eb-a3e3-b3cc7c78a70f.json b/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/c102b0f0-73c6-11eb-a3e3-b3cc7c78a70f.json index 4ee6602cf67..e992bfb8585 100644 --- a/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/c102b0f0-73c6-11eb-a3e3-b3cc7c78a70f.json +++ b/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/c102b0f0-73c6-11eb-a3e3-b3cc7c78a70f.json @@ -30,13 +30,13 @@ "store": "appState" }, "exists": { - "field": "threatintel.indicator.url.full" + "field": "threat.indicator.url.full" }, "meta": { "alias": null, "disabled": false, "indexRefName": "kibanaSavedObjectMeta.searchSourceJSON.filter[1].meta.index", - "key": "threatintel.indicator.url.full", + "key": "threat.indicator.url.full", "negate": false, "type": "exists", "value": "exists" @@ -67,7 +67,7 @@ "id": "2", "params": { "customLabel": "MISP URL Indicator", - "field": "threatintel.indicator.url.full", + "field": "threat.indicator.url.full", "missingBucket": false, "missingBucketLabel": "Missing", "order": "desc", @@ -123,4 +123,4 @@ "type": "visualization", "updated_at": "2021-08-04T16:34:31.083Z", "version": "WzQ2MzYsMV0=" -} \ No newline at end of file +} diff --git a/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/c7d5db50-82a8-11eb-ac13-d5ca87cb8fa2.json b/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/c7d5db50-82a8-11eb-ac13-d5ca87cb8fa2.json index 225ca993710..ad6317b4101 100644 --- a/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/c7d5db50-82a8-11eb-ac13-d5ca87cb8fa2.json +++ b/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/c7d5db50-82a8-11eb-ac13-d5ca87cb8fa2.json @@ -30,13 +30,13 @@ "store": "appState" }, "exists": { - "field": "threatintel.indicator.provider" + "field": "threat.indicator.provider" }, "meta": { "alias": null, "disabled": false, "indexRefName": "kibanaSavedObjectMeta.searchSourceJSON.filter[1].meta.index", - "key": "threatintel.indicator.provider", + "key": "threat.indicator.provider", "negate": false, "type": "exists", "value": "exists" @@ -73,7 +73,7 @@ "id": "2", "params": { "customLabel": "Indicator Provider", - "field": "threatintel.indicator.provider", + "field": "threat.indicator.provider", "missingBucket": false, "missingBucketLabel": "Missing", "order": "desc", @@ -204,4 +204,4 @@ "type": "visualization", "updated_at": "2021-08-04T16:34:30.070Z", "version": "WzQ2MTgsMV0=" -} \ No newline at end of file +} diff --git a/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/c813c5d0-72dd-11eb-a3e3-b3cc7c78a70f.json b/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/c813c5d0-72dd-11eb-a3e3-b3cc7c78a70f.json index 18539863d1a..6619c3564fe 100644 --- a/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/c813c5d0-72dd-11eb-a3e3-b3cc7c78a70f.json +++ b/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/c813c5d0-72dd-11eb-a3e3-b3cc7c78a70f.json @@ -9,13 +9,13 @@ "store": "appState" }, "exists": { - "field": "threatintel.indicator.type" + "field": "threat.indicator.type" }, "meta": { "alias": null, "disabled": false, "indexRefName": "kibanaSavedObjectMeta.searchSourceJSON.filter[0].meta.index", - "key": "threatintel.indicator.type", + "key": "threat.indicator.type", "negate": false, "type": "exists", "value": "exists" @@ -67,7 +67,7 @@ "enabled": true, "id": "3", "params": { - "field": "threatintel.indicator.type", + "field": "threat.indicator.type", "missingBucket": false, "missingBucketLabel": "Missing", "order": "desc", @@ -192,4 +192,4 @@ "type": "visualization", "updated_at": "2021-08-04T16:34:32.145Z", "version": "WzQ2NTgsMV0=" -} \ No newline at end of file +} diff --git a/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/d22c1090-82a5-11eb-ac13-d5ca87cb8fa2.json b/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/d22c1090-82a5-11eb-ac13-d5ca87cb8fa2.json index 107bf321eac..340bcc359c8 100644 --- a/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/d22c1090-82a5-11eb-ac13-d5ca87cb8fa2.json +++ b/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/d22c1090-82a5-11eb-ac13-d5ca87cb8fa2.json @@ -30,13 +30,13 @@ "store": "appState" }, "exists": { - "field": "threatintel.indicator.file.mime_type" + "field": "threat.indicator.file.mime_type" }, "meta": { "alias": null, "disabled": false, "indexRefName": "kibanaSavedObjectMeta.searchSourceJSON.filter[1].meta.index", - "key": "threatintel.indicator.file.mime_type", + "key": "threat.indicator.file.mime_type", "negate": false, "type": "exists", "value": "exists" @@ -78,7 +78,7 @@ "id": "3", "params": { "customLabel": "File MIME Type", - "field": "threatintel.indicator.file.mime_type", + "field": "threat.indicator.file.mime_type", "missingBucket": false, "missingBucketLabel": "Missing", "order": "desc", @@ -134,4 +134,4 @@ "type": "visualization", "updated_at": "2021-08-04T16:34:30.070Z", "version": "WzQ2MTUsMV0=" -} \ No newline at end of file +} diff --git a/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/d5d76c60-72ee-11eb-a3e3-b3cc7c78a70f.json b/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/d5d76c60-72ee-11eb-a3e3-b3cc7c78a70f.json index 26f577c2864..7450b383291 100644 --- a/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/d5d76c60-72ee-11eb-a3e3-b3cc7c78a70f.json +++ b/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/d5d76c60-72ee-11eb-a3e3-b3cc7c78a70f.json @@ -30,13 +30,13 @@ "store": "appState" }, "exists": { - "field": "threatintel.indicator.url.full" + "field": "threat.indicator.url.full" }, "meta": { "alias": null, "disabled": false, "indexRefName": "kibanaSavedObjectMeta.searchSourceJSON.filter[1].meta.index", - "key": "threatintel.indicator.url.full", + "key": "threat.indicator.url.full", "negate": false, "type": "exists", "value": "exists" @@ -123,4 +123,4 @@ "type": "visualization", "updated_at": "2021-08-04T16:34:25.974Z", "version": "WzQ1NTgsMV0=" -} \ No newline at end of file +} diff --git a/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/dbd199d0-82aa-11eb-ac13-d5ca87cb8fa2.json b/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/dbd199d0-82aa-11eb-ac13-d5ca87cb8fa2.json index bd6250bdc9b..a3f14f00b0e 100644 --- a/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/dbd199d0-82aa-11eb-ac13-d5ca87cb8fa2.json +++ b/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/dbd199d0-82aa-11eb-ac13-d5ca87cb8fa2.json @@ -30,13 +30,13 @@ "store": "appState" }, "exists": { - "field": "threatintel.malwarebazaar.intelligence.uploads" + "field": "abusech.malwarebazaar.intelligence.uploads" }, "meta": { "alias": null, "disabled": false, "indexRefName": "kibanaSavedObjectMeta.searchSourceJSON.filter[1].meta.index", - "key": "threatintel.malwarebazaar.intelligence.uploads", + "key": "abusech.malwarebazaar.intelligence.uploads", "negate": false, "type": "exists", "value": "exists" @@ -76,7 +76,7 @@ "id": "2", "params": { "customLabel": "Malware Bazaar Uploads", - "field": "threatintel.malwarebazaar.intelligence.uploads", + "field": "abusech.malwarebazaar.intelligence.uploads", "missingBucket": false, "missingBucketLabel": "Missing", "order": "desc", @@ -132,4 +132,4 @@ "type": "visualization", "updated_at": "2021-08-04T16:34:30.070Z", "version": "WzQ2MjEsMV0=" -} \ No newline at end of file +} diff --git a/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/ea5879c0-72eb-11eb-a3e3-b3cc7c78a70f.json b/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/ea5879c0-72eb-11eb-a3e3-b3cc7c78a70f.json index 3674297d158..fa58d2934c7 100644 --- a/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/ea5879c0-72eb-11eb-a3e3-b3cc7c78a70f.json +++ b/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/ea5879c0-72eb-11eb-a3e3-b3cc7c78a70f.json @@ -30,13 +30,13 @@ "store": "appState" }, "exists": { - "field": "threatintel.abuseurl.url_status" + "field": "abusech.url.url_status" }, "meta": { "alias": null, "disabled": false, "indexRefName": "kibanaSavedObjectMeta.searchSourceJSON.filter[1].meta.index", - "key": "threatintel.abuseurl.url_status", + "key": "abusech.url.url_status", "negate": false, "type": "exists", "value": "exists" @@ -67,7 +67,7 @@ "id": "2", "params": { "customLabel": "URL Status", - "field": "threatintel.abuseurl.url_status", + "field": "abusech.url.url_status", "missingBucket": false, "missingBucketLabel": "Missing", "order": "desc", @@ -123,4 +123,4 @@ "type": "visualization", "updated_at": "2021-08-04T16:34:25.974Z", "version": "WzQ1NTksMV0=" -} \ No newline at end of file +} diff --git a/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/eba4ec60-72ea-11eb-a3e3-b3cc7c78a70f.json b/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/eba4ec60-72ea-11eb-a3e3-b3cc7c78a70f.json index e05220ceeab..8745f6c3ca3 100644 --- a/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/eba4ec60-72ea-11eb-a3e3-b3cc7c78a70f.json +++ b/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/eba4ec60-72ea-11eb-a3e3-b3cc7c78a70f.json @@ -30,13 +30,13 @@ "store": "appState" }, "exists": { - "field": "threatintel.abuseurl.larted" + "field": "abusech.url.larted" }, "meta": { "alias": null, "disabled": false, "indexRefName": "kibanaSavedObjectMeta.searchSourceJSON.filter[1].meta.index", - "key": "threatintel.abuseurl.larted", + "key": "abusech.url.larted", "negate": false, "type": "exists", "value": "exists" @@ -73,7 +73,7 @@ "id": "2", "params": { "customLabel": "Hosting Provider Notified", - "field": "threatintel.abuseurl.larted", + "field": "abusech.url.larted", "missingBucket": false, "missingBucketLabel": "Missing", "order": "desc", @@ -138,4 +138,4 @@ "type": "visualization", "updated_at": "2021-08-04T16:34:25.974Z", "version": "WzQ1NTMsMV0=" -} \ No newline at end of file +} diff --git a/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/ec68c4a0-73c6-11eb-a3e3-b3cc7c78a70f.json b/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/ec68c4a0-73c6-11eb-a3e3-b3cc7c78a70f.json index 4a7c4dfa740..517fa9c84ce 100644 --- a/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/ec68c4a0-73c6-11eb-a3e3-b3cc7c78a70f.json +++ b/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/ec68c4a0-73c6-11eb-a3e3-b3cc7c78a70f.json @@ -30,13 +30,13 @@ "store": "appState" }, "exists": { - "field": "threatintel.indicator.file.hash.md5" + "field": "threat.indicator.file.hash.md5" }, "meta": { "alias": null, "disabled": false, "indexRefName": "kibanaSavedObjectMeta.searchSourceJSON.filter[1].meta.index", - "key": "threatintel.indicator.file.hash.md5", + "key": "threat.indicator.file.hash.md5", "negate": false, "type": "exists", "value": "exists" @@ -67,7 +67,7 @@ "id": "2", "params": { "customLabel": "MISP MD5 Hash Indicator", - "field": "threatintel.indicator.file.hash.md5", + "field": "threat.indicator.file.hash.md5", "missingBucket": false, "missingBucketLabel": "Missing", "order": "desc", @@ -123,4 +123,4 @@ "type": "visualization", "updated_at": "2021-08-04T16:34:31.083Z", "version": "WzQ2NDAsMV0=" -} \ No newline at end of file +} diff --git a/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/ecf74b10-72ec-11eb-a3e3-b3cc7c78a70f.json b/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/ecf74b10-72ec-11eb-a3e3-b3cc7c78a70f.json index ea0aef5cb86..16d083d8762 100644 --- a/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/ecf74b10-72ec-11eb-a3e3-b3cc7c78a70f.json +++ b/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/ecf74b10-72ec-11eb-a3e3-b3cc7c78a70f.json @@ -30,13 +30,13 @@ "store": "appState" }, "exists": { - "field": "threatintel.abuseurl.threat" + "field": "abusech.url.threat" }, "meta": { "alias": null, "disabled": false, "indexRefName": "kibanaSavedObjectMeta.searchSourceJSON.filter[1].meta.index", - "key": "threatintel.abuseurl.threat", + "key": "abusech.url.threat", "negate": false, "type": "exists", "value": "exists" @@ -72,7 +72,7 @@ "enabled": true, "id": "2", "params": { - "field": "threatintel.indicator.provider", + "field": "threat.indicator.provider", "missingBucket": false, "missingBucketLabel": "Missing", "order": "desc", @@ -203,4 +203,4 @@ "type": "visualization", "updated_at": "2021-08-04T16:34:25.974Z", "version": "WzQ1NTYsMV0=" -} \ No newline at end of file +} diff --git a/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/f33125b0-76d8-11eb-a3e3-b3cc7c78a70f.json b/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/f33125b0-76d8-11eb-a3e3-b3cc7c78a70f.json index 3d473b4e17d..41b0ecfa65b 100644 --- a/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/f33125b0-76d8-11eb-a3e3-b3cc7c78a70f.json +++ b/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/f33125b0-76d8-11eb-a3e3-b3cc7c78a70f.json @@ -30,13 +30,13 @@ "store": "appState" }, "exists": { - "field": "threatintel.indicator.type" + "field": "threat.indicator.type" }, "meta": { "alias": null, "disabled": false, "indexRefName": "kibanaSavedObjectMeta.searchSourceJSON.filter[1].meta.index", - "key": "threatintel.indicator.type", + "key": "threat.indicator.type", "negate": false, "type": "exists", "value": "exists" @@ -66,7 +66,7 @@ "enabled": true, "id": "2", "params": { - "field": "threatintel.indicator.type", + "field": "threat.indicator.type", "missingBucket": false, "missingBucketLabel": "Missing", "order": "desc", @@ -131,4 +131,4 @@ "type": "visualization", "updated_at": "2021-08-04T16:34:27.014Z", "version": "WzQ1NjYsMV0=" -} \ No newline at end of file +} diff --git a/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/f91e9620-82a8-11eb-ac13-d5ca87cb8fa2.json b/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/f91e9620-82a8-11eb-ac13-d5ca87cb8fa2.json index 958c15dba69..664816cccba 100644 --- a/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/f91e9620-82a8-11eb-ac13-d5ca87cb8fa2.json +++ b/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/f91e9620-82a8-11eb-ac13-d5ca87cb8fa2.json @@ -30,13 +30,13 @@ "store": "appState" }, "exists": { - "field": "threatintel.malwarebazaar.tags" + "field": "abusech.malwarebazaar.tags" }, "meta": { "alias": null, "disabled": false, "indexRefName": "kibanaSavedObjectMeta.searchSourceJSON.filter[1].meta.index", - "key": "threatintel.malwarebazaar.tags", + "key": "abusech.malwarebazaar.tags", "negate": false, "type": "exists", "value": "exists" @@ -67,7 +67,7 @@ "id": "2", "params": { "customLabel": "Malware Bazaar Tags", - "field": "threatintel.malwarebazaar.tags", + "field": "abusech.malwarebazaar.tags", "missingBucket": false, "missingBucketLabel": "Missing", "order": "desc", @@ -123,4 +123,4 @@ "type": "visualization", "updated_at": "2021-08-04T16:34:30.070Z", "version": "WzQ2MTQsMV0=" -} \ No newline at end of file +} diff --git a/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/f9c6ba80-72e5-11eb-a3e3-b3cc7c78a70f.json b/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/f9c6ba80-72e5-11eb-a3e3-b3cc7c78a70f.json index 21660b248e4..516a572fb88 100644 --- a/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/f9c6ba80-72e5-11eb-a3e3-b3cc7c78a70f.json +++ b/x-pack/filebeat/module/threatintel/_meta/kibana/7/visualization/f9c6ba80-72e5-11eb-a3e3-b3cc7c78a70f.json @@ -30,13 +30,13 @@ "store": "appState" }, "exists": { - "field": "threatintel.abusemalware.virustotal.link" + "field": "abusech.malware.virustotal.link" }, "meta": { "alias": null, "disabled": false, "indexRefName": "kibanaSavedObjectMeta.searchSourceJSON.filter[1].meta.index", - "key": "threatintel.abusemalware.virustotal.link", + "key": "abusech.malware.virustotal.link", "negate": false, "type": "exists", "value": "exists" @@ -47,13 +47,13 @@ "store": "appState" }, "exists": { - "field": "threatintel.abusemalware.virustotal.result" + "field": "abusech.malware.virustotal.result" }, "meta": { "alias": null, "disabled": false, "indexRefName": "kibanaSavedObjectMeta.searchSourceJSON.filter[2].meta.index", - "key": "threatintel.abusemalware.virustotal.result", + "key": "abusech.malware.virustotal.result", "negate": false, "type": "exists", "value": "exists" @@ -95,7 +95,7 @@ "id": "2", "params": { "customLabel": "VirusTotal URL", - "field": "threatintel.abusemalware.virustotal.link", + "field": "abusech.malware.virustotal.link", "missingBucket": false, "missingBucketLabel": "Missing", "order": "desc", @@ -112,7 +112,7 @@ "id": "3", "params": { "customLabel": "VirusTotal Result", - "field": "threatintel.abusemalware.virustotal.result", + "field": "abusech.malware.virustotal.result", "missingBucket": false, "missingBucketLabel": "Missing", "order": "desc", @@ -173,4 +173,4 @@ "type": "visualization", "updated_at": "2021-08-04T16:34:29.041Z", "version": "WzQ2MTAsMV0=" -} \ No newline at end of file +} diff --git a/x-pack/filebeat/module/threatintel/abusemalware/_meta/fields.yml b/x-pack/filebeat/module/threatintel/abusemalware/_meta/fields.yml index 55f8657bc6e..73aae20e07f 100644 --- a/x-pack/filebeat/module/threatintel/abusemalware/_meta/fields.yml +++ b/x-pack/filebeat/module/threatintel/abusemalware/_meta/fields.yml @@ -1,4 +1,4 @@ -- name: abusemalware +- name: abusech.malware type: group description: > Fields for AbuseCH Malware Threat Intel @@ -31,4 +31,4 @@ - name: virustotal.link type: keyword description: > - Link to the Virustotal report. \ No newline at end of file + Link to the Virustotal report. diff --git a/x-pack/filebeat/module/threatintel/abusemalware/config/config.yml b/x-pack/filebeat/module/threatintel/abusemalware/config/config.yml index e7f4f8cc264..b4365bd3e5b 100644 --- a/x-pack/filebeat/module/threatintel/abusemalware/config/config.yml +++ b/x-pack/filebeat/module/threatintel/abusemalware/config/config.yml @@ -11,10 +11,9 @@ request.ssl: {{ .ssl | tojson }} request.proxy_url: {{ .proxy_url }} {{ end }} request.url: {{ .url }} -request.transforms: -- set: - target: header.Content-Type - value: application/json +{{ if .http_client_timeout }} +request.timeout: {{ .http_client_timeout }} +{{ end }} response.split: target: body.payloads @@ -30,17 +29,12 @@ exclude_files: [".gz$"] {{ end }} -tags: {{.tags | tojson}} -publisher_pipeline.disable_host: {{ inList .tags "forwarded" }} +tags: +{{if .preserve_original_event}} + - preserve_original_event +{{end}} +{{range $val := .tags}} + - {{$val}} +{{end}} -processors: - - decode_json_fields: - fields: [message] - target: json - - fingerprint: - fields: ["json.md5_hash"] - target_field: "@metadata._id" - - add_fields: - target: '' - fields: - ecs.version: 1.12.0 +publisher_pipeline.disable_host: {{ inList .tags "forwarded" }} diff --git a/x-pack/filebeat/module/threatintel/abusemalware/ingest/pipeline.yml b/x-pack/filebeat/module/threatintel/abusemalware/ingest/pipeline.yml index 5e24b68c52e..da0b365724f 100644 --- a/x-pack/filebeat/module/threatintel/abusemalware/ingest/pipeline.yml +++ b/x-pack/filebeat/module/threatintel/abusemalware/ingest/pipeline.yml @@ -1,4 +1,5 @@ -description: Pipeline for parsing Abuse.ch Malware Threat Intel +--- +description: Pipeline for parsing Abuse.ch URL Threat Intel processors: #################### # Event ECS fields # @@ -6,6 +7,9 @@ processors: - set: field: event.ingested value: "{{_ingest.timestamp}}" + - set: + field: ecs.version + value: "1.12" - set: field: event.kind value: enrichment @@ -20,92 +24,110 @@ processors: # General ECS fields # ###################### - rename: - field: json - target_field: threatintel.abusemalware + field: message + target_field: event.original ignore_missing: true + - json: + field: event.original + target_field: abusech.malware + - fingerprint: + fields: + - abusech.malware.md5_hash + - abusech.malware.sha256_hash + target_field: "_id" ##################### # Threat ECS Fields # ##################### + - set: + field: threat.feed.name + value: "[Filebeat] AbuseCH Malware" + - set: + field: threat.feed.dashboard_id + value: "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f" - date: - field: threatintel.abusemalware.firstseen - target_field: threatintel.indicator.first_seen + field: abusech.malware.firstseen + target_field: threat.indicator.first_seen formats: - "yyyy-MM-dd HH:mm:ss z" - "yyyy-MM-dd HH:mm:ss Z" - "yyyy-MM-dd HH:mm:ss" - if: "ctx?.threatintel?.abusemalware.firstseen != null" + if: "ctx.abusech?.malware?.firstseen != null" - set: - field: threatintel.indicator.type + field: threat.indicator.type value: file - rename: - field: threatintel.abusemalware.file_size - target_field: threatintel.indicator.file.size + field: abusech.malware.file_size + target_field: threat.indicator.file.size ignore_missing: true - rename: - field: threatintel.abusemalware.file_type - target_field: threatintel.indicator.file.type + field: abusech.malware.file_type + target_field: threat.indicator.file.type ignore_missing: true # This includes a direct link to malicious files, we do not want them to appear in Kibana # in case they are accidently clicked. - remove: - field: threatintel.abusemalware.urlhaus_download + field: abusech.malware.urlhaus_download ignore_missing: true - convert: - field: threatintel.indicator.file.size + field: threat.indicator.file.size type: long ignore_missing: true + - convert: + field: abusech.malware.virustotal.percent + type: float + ignore_missing: true - rename: - field: threatintel.abusemalware.md5_hash - target_field: threatintel.indicator.file.hash.md5 + field: abusech.malware.md5_hash + target_field: threat.indicator.file.hash.md5 ignore_missing: true - rename: - field: threatintel.abusemalware.sha256_hash - target_field: threatintel.indicator.file.hash.sha256 + field: abusech.malware.sha256_hash + target_field: threat.indicator.file.hash.sha256 ignore_missing: true - rename: - field: threatintel.abusemalware.imphash - target_field: threatintel.indicator.file.pe.imphash + field: abusech.malware.imphash + target_field: threat.indicator.file.pe.imphash ignore_missing: true - rename: - field: threatintel.abusemalware.ssdeep - target_field: threatintel.indicator.file.hash.ssdeep + field: abusech.malware.ssdeep + target_field: threat.indicator.file.hash.ssdeep ignore_missing: true - rename: - field: threatintel.abusemalware.tlsh - target_field: threatintel.indicator.file.hash.tlsh + field: abusech.malware.tlsh + target_field: threat.indicator.file.hash.tlsh ignore_missing: true - append: field: related.hash - value: "{{ threatintel.indicator.file.hash.md5 }}" - if: ctx?.threatintel?.indicator?.file?.hash?.md5 != null + value: "{{{threat.indicator.file.hash.md5}}}" + if: ctx?.threat?.indicator?.file?.hash?.md5 != null - append: field: related.hash - value: "{{ threatintel.indicator.file.hash.sha256 }}" - if: ctx?.threatintel?.indicator?.file?.hash?.sha256 != null + value: "{{{threat.indicator.file.hash.sha256}}}" + if: ctx?.threat?.indicator?.file?.hash?.sha256 != null - append: field: related.hash - value: "{{ threatintel.indicator.file.hash.ssdeep }}" - if: ctx?.threatintel?.indicator?.file?.hash?.ssdeep != null + value: "{{{threat.indicator.file.hash.ssdeep}}}" + if: ctx?.threat?.indicator?.file?.hash?.ssdeep != null - append: field: related.hash - value: "{{ threatintel.indicator.file.pe.imphash }}" - if: ctx?.threatintel?.indicator?.file?.pe?.imphash != null + value: "{{{threat.indicator.file.pe.imphash}}}" + if: ctx?.threat?.indicator?.file?.pe?.imphash != null - append: field: related.hash - value: "{{ threatintel.indicator.file.hash.tlsh }}" - if: ctx?.threatintel?.indicator?.file?.hash?.tlsh != null + value: "{{{threat.indicator.file.hash.tlsh}}}" + if: ctx?.threat?.indicator?.file?.hash?.tlsh != null ###################### # Cleanup processors # ###################### - set: - field: threatintel.indicator.type + field: threat.indicator.type value: unknown - if: ctx?.threatintel?.indicator?.type == null + if: ctx?.threat?.indicator?.type == null - script: lang: painless - if: ctx?.threatintel != null + if: ctx?.abusech != null source: | void handleMap(Map map) { for (def x : map.values()) { @@ -127,9 +149,14 @@ processors: } } handleMap(ctx); + - remove: + field: event.original + if: "ctx?.tags == null || !(ctx.tags.contains('preserve_original_event'))" + ignore_failure: true + ignore_missing: true - remove: field: - - threatintel.abusemalware.firstseen + - abusech.malware.firstseen - message ignore_missing: true on_failure: diff --git a/x-pack/filebeat/module/threatintel/abusemalware/manifest.yml b/x-pack/filebeat/module/threatintel/abusemalware/manifest.yml index 5fe3a155180..0d755b7b38d 100644 --- a/x-pack/filebeat/module/threatintel/abusemalware/manifest.yml +++ b/x-pack/filebeat/module/threatintel/abusemalware/manifest.yml @@ -11,6 +11,9 @@ var: - name: tags default: [threatintel-abusemalware, forwarded] - name: proxy_url + - name: preserve_original_event + default: false + - name: http_client_timeout ingest_pipeline: - ingest/pipeline.yml diff --git a/x-pack/filebeat/module/threatintel/abusemalware/test/abusechmalware.ndjson.log-expected.json b/x-pack/filebeat/module/threatintel/abusemalware/test/abusechmalware.ndjson.log-expected.json index 6c31b6f779c..75a4d118ba3 100644 --- a/x-pack/filebeat/module/threatintel/abusemalware/test/abusechmalware.ndjson.log-expected.json +++ b/x-pack/filebeat/module/threatintel/abusemalware/test/abusechmalware.ndjson.log-expected.json @@ -20,15 +20,17 @@ "forwarded", "threatintel-abusemalware" ], - "threatintel.indicator.file.hash.md5": "7871286a8f1f68a14b18ae475683f724", - "threatintel.indicator.file.hash.sha256": "48a6aee18bcfe9058b35b1018832aef1c9efd8f50ac822f49abb484a5e2a4b1f", - "threatintel.indicator.file.hash.ssdeep": "6144:+60EDP6uCLfGw/GpxXinM1BCo1PlumGx2mx2tXd0t115JG5:X5DpBw/KViMTB1MnEWk0115JW", - "threatintel.indicator.file.hash.tlsh": "1344D022AD13DD37E1F400FCA6A58F8561626E381F00A89777D41F8A98356F1BB2B717", - "threatintel.indicator.file.pe.imphash": "68aea345b134d576ccdef7f06db86088", - "threatintel.indicator.file.size": 277504, - "threatintel.indicator.file.type": "dll", - "threatintel.indicator.first_seen": "2021-01-14T06:14:05.000Z", - "threatintel.indicator.type": "file" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] AbuseCH Malware", + "threat.indicator.file.hash.md5": "7871286a8f1f68a14b18ae475683f724", + "threat.indicator.file.hash.sha256": "48a6aee18bcfe9058b35b1018832aef1c9efd8f50ac822f49abb484a5e2a4b1f", + "threat.indicator.file.hash.ssdeep": "6144:+60EDP6uCLfGw/GpxXinM1BCo1PlumGx2mx2tXd0t115JG5:X5DpBw/KViMTB1MnEWk0115JW", + "threat.indicator.file.hash.tlsh": "1344D022AD13DD37E1F400FCA6A58F8561626E381F00A89777D41F8A98356F1BB2B717", + "threat.indicator.file.pe.imphash": "68aea345b134d576ccdef7f06db86088", + "threat.indicator.file.size": 277504, + "threat.indicator.file.type": "dll", + "threat.indicator.first_seen": "2021-01-14T06:14:05.000Z", + "threat.indicator.type": "file" }, { "event.category": "threat", @@ -51,17 +53,22 @@ "forwarded", "threatintel-abusemalware" ], - "threatintel.indicator.file.hash.md5": "7b4c77dc293347b467fb860e34515163", - "threatintel.indicator.file.hash.sha256": "ec59538e8de8525b1674b3b8fe0c180ac822145350bcce054ad3fc6b95b1b5a4", - "threatintel.indicator.file.hash.ssdeep": "6144:+60EDP6uCLfGw/GpxXinM1BCo1PlumGx2mx2tXd0t115JGY:X5DpBw/KViMTB1MnEWk0115Jr", - "threatintel.indicator.file.hash.tlsh": "4E44D022AD13DD37E1F400FCA6A58F8561626E381F00A89777D41F8A98356F1BB2B717", - "threatintel.indicator.file.pe.imphash": "68aea345b134d576ccdef7f06db86088", - "threatintel.indicator.file.size": 277504, - "threatintel.indicator.file.type": "dll", - "threatintel.indicator.first_seen": "2021-01-14T06:11:41.000Z", - "threatintel.indicator.type": "file" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] AbuseCH Malware", + "threat.indicator.file.hash.md5": "7b4c77dc293347b467fb860e34515163", + "threat.indicator.file.hash.sha256": "ec59538e8de8525b1674b3b8fe0c180ac822145350bcce054ad3fc6b95b1b5a4", + "threat.indicator.file.hash.ssdeep": "6144:+60EDP6uCLfGw/GpxXinM1BCo1PlumGx2mx2tXd0t115JGY:X5DpBw/KViMTB1MnEWk0115Jr", + "threat.indicator.file.hash.tlsh": "4E44D022AD13DD37E1F400FCA6A58F8561626E381F00A89777D41F8A98356F1BB2B717", + "threat.indicator.file.pe.imphash": "68aea345b134d576ccdef7f06db86088", + "threat.indicator.file.size": 277504, + "threat.indicator.file.type": "dll", + "threat.indicator.first_seen": "2021-01-14T06:11:41.000Z", + "threat.indicator.type": "file" }, { + "abusech.malware.virustotal.link": "https://www.virustotal.com/gui/file/b0e914d1bbe19433cc9df64ea1ca07fe77f7b150b511b786e46e007941a62bd7/detection/f-b0e914d", + "abusech.malware.virustotal.percent": 37.88, + "abusech.malware.virustotal.result": "25 / 66", "event.category": "threat", "event.dataset": "threatintel.abusemalware", "event.kind": "enrichment", @@ -82,18 +89,17 @@ "forwarded", "threatintel-abusemalware" ], - "threatintel.abusemalware.virustotal.link": "https://www.virustotal.com/gui/file/b0e914d1bbe19433cc9df64ea1ca07fe77f7b150b511b786e46e007941a62bd7/detection/f-b0e914d", - "threatintel.abusemalware.virustotal.percent": "37.88", - "threatintel.abusemalware.virustotal.result": "25 / 66", - "threatintel.indicator.file.hash.md5": "373d34874d7bc89fd4cefa6272ee80bf", - "threatintel.indicator.file.hash.sha256": "b0e914d1bbe19433cc9df64ea1ca07fe77f7b150b511b786e46e007941a62bd7", - "threatintel.indicator.file.hash.ssdeep": "6144:+60EDP6uCLfGw/GpxXinM1BCo1PlumGx2mx2tXd0t115JGG:X5DpBw/KViMTB1MnEWk0115Jd", - "threatintel.indicator.file.hash.tlsh": "7544D022AD13DD37E1F400FCA6A58F8561626E381F00A89777D41F8A98356F1BB2B717", - "threatintel.indicator.file.pe.imphash": "68aea345b134d576ccdef7f06db86088", - "threatintel.indicator.file.size": 277504, - "threatintel.indicator.file.type": "dll", - "threatintel.indicator.first_seen": "2021-01-14T06:11:22.000Z", - "threatintel.indicator.type": "file" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] AbuseCH Malware", + "threat.indicator.file.hash.md5": "373d34874d7bc89fd4cefa6272ee80bf", + "threat.indicator.file.hash.sha256": "b0e914d1bbe19433cc9df64ea1ca07fe77f7b150b511b786e46e007941a62bd7", + "threat.indicator.file.hash.ssdeep": "6144:+60EDP6uCLfGw/GpxXinM1BCo1PlumGx2mx2tXd0t115JGG:X5DpBw/KViMTB1MnEWk0115Jd", + "threat.indicator.file.hash.tlsh": "7544D022AD13DD37E1F400FCA6A58F8561626E381F00A89777D41F8A98356F1BB2B717", + "threat.indicator.file.pe.imphash": "68aea345b134d576ccdef7f06db86088", + "threat.indicator.file.size": 277504, + "threat.indicator.file.type": "dll", + "threat.indicator.first_seen": "2021-01-14T06:11:22.000Z", + "threat.indicator.type": "file" }, { "event.category": "threat", @@ -116,15 +122,17 @@ "forwarded", "threatintel-abusemalware" ], - "threatintel.indicator.file.hash.md5": "e2e02aae857488dbdbe6631c29abf3f8", - "threatintel.indicator.file.hash.sha256": "7483e834a73fb6817769596fe4c0fa01d28639f52bbbdc2b8a56c36d466dd7f8", - "threatintel.indicator.file.hash.ssdeep": "6144:0hlBeZgR9LqvgFcwNAwhGV52n5Dv4JdEqvQykqRqYdBx8pRA7OZJ9:0h3eZgRQCcw+MN54dEq7kqRtoLZH", - "threatintel.indicator.file.hash.tlsh": "5554CF22E642C926F1E900FCB2A98B4451257E355F40F4D777C40FABA835AE2AF27717", - "threatintel.indicator.file.pe.imphash": "68aea345b134d576ccdef7f06db86088", - "threatintel.indicator.file.size": 284672, - "threatintel.indicator.file.type": "dll", - "threatintel.indicator.first_seen": "2021-01-14T06:11:21.000Z", - "threatintel.indicator.type": "file" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] AbuseCH Malware", + "threat.indicator.file.hash.md5": "e2e02aae857488dbdbe6631c29abf3f8", + "threat.indicator.file.hash.sha256": "7483e834a73fb6817769596fe4c0fa01d28639f52bbbdc2b8a56c36d466dd7f8", + "threat.indicator.file.hash.ssdeep": "6144:0hlBeZgR9LqvgFcwNAwhGV52n5Dv4JdEqvQykqRqYdBx8pRA7OZJ9:0h3eZgRQCcw+MN54dEq7kqRtoLZH", + "threat.indicator.file.hash.tlsh": "5554CF22E642C926F1E900FCB2A98B4451257E355F40F4D777C40FABA835AE2AF27717", + "threat.indicator.file.pe.imphash": "68aea345b134d576ccdef7f06db86088", + "threat.indicator.file.size": 284672, + "threat.indicator.file.type": "dll", + "threat.indicator.first_seen": "2021-01-14T06:11:21.000Z", + "threat.indicator.type": "file" }, { "event.category": "threat", @@ -146,16 +154,21 @@ "forwarded", "threatintel-abusemalware" ], - "threatintel.indicator.file.hash.md5": "3e988e32b0c3c230d534e286665b89a5", - "threatintel.indicator.file.hash.sha256": "760e729426fb115b967a41e5a6f2f42d7a52a5cee74ed99065a6dc39bf89f59b", - "threatintel.indicator.file.hash.ssdeep": "6:TE6ll8uXi0jIAv6BHvPuA7RKTmOQamsQMGvMQgTYbtsWsQ72hCqPZG/:TTll8uTo5uA7RKtQamsS0QJfsQ7mCR", - "threatintel.indicator.file.hash.tlsh": "3CE0C002AB26C036500D154C221655B3B871911503CA14E6A6824BEA765D4A3290D190", - "threatintel.indicator.file.size": 352, - "threatintel.indicator.file.type": "unknown", - "threatintel.indicator.first_seen": "2021-01-14T06:08:02.000Z", - "threatintel.indicator.type": "file" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] AbuseCH Malware", + "threat.indicator.file.hash.md5": "3e988e32b0c3c230d534e286665b89a5", + "threat.indicator.file.hash.sha256": "760e729426fb115b967a41e5a6f2f42d7a52a5cee74ed99065a6dc39bf89f59b", + "threat.indicator.file.hash.ssdeep": "6:TE6ll8uXi0jIAv6BHvPuA7RKTmOQamsQMGvMQgTYbtsWsQ72hCqPZG/:TTll8uTo5uA7RKtQamsS0QJfsQ7mCR", + "threat.indicator.file.hash.tlsh": "3CE0C002AB26C036500D154C221655B3B871911503CA14E6A6824BEA765D4A3290D190", + "threat.indicator.file.size": 352, + "threat.indicator.file.type": "unknown", + "threat.indicator.first_seen": "2021-01-14T06:08:02.000Z", + "threat.indicator.type": "file" }, { + "abusech.malware.virustotal.link": "https://www.virustotal.com/gui/file/86655c0bcf9b21b5efc682f58eb80f42811042ba152358e1bfbbb867315a60ac/detection/f-86655c0", + "abusech.malware.virustotal.percent": 39.13, + "abusech.malware.virustotal.result": "27 / 69", "event.category": "threat", "event.dataset": "threatintel.abusemalware", "event.kind": "enrichment", @@ -176,18 +189,17 @@ "forwarded", "threatintel-abusemalware" ], - "threatintel.abusemalware.virustotal.link": "https://www.virustotal.com/gui/file/86655c0bcf9b21b5efc682f58eb80f42811042ba152358e1bfbbb867315a60ac/detection/f-86655c0", - "threatintel.abusemalware.virustotal.percent": "39.13", - "threatintel.abusemalware.virustotal.result": "27 / 69", - "threatintel.indicator.file.hash.md5": "dcc20d534cdf29eab03d8148bf728857", - "threatintel.indicator.file.hash.sha256": "86655c0bcf9b21b5efc682f58eb80f42811042ba152358e1bfbbb867315a60ac", - "threatintel.indicator.file.hash.ssdeep": "6144:+60EDP6uCLfGw/GpxXinM1BCo1PlumGx2mx2tXd0t115JGI:X5DpBw/KViMTB1MnEWk0115JH", - "threatintel.indicator.file.hash.tlsh": "0D44D022AD13DD37E1F400FCA6A58F8561626E381F00A89777D41F8A98356F1BB2B717", - "threatintel.indicator.file.pe.imphash": "68aea345b134d576ccdef7f06db86088", - "threatintel.indicator.file.size": 277504, - "threatintel.indicator.file.type": "dll", - "threatintel.indicator.first_seen": "2021-01-14T06:08:02.000Z", - "threatintel.indicator.type": "file" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] AbuseCH Malware", + "threat.indicator.file.hash.md5": "dcc20d534cdf29eab03d8148bf728857", + "threat.indicator.file.hash.sha256": "86655c0bcf9b21b5efc682f58eb80f42811042ba152358e1bfbbb867315a60ac", + "threat.indicator.file.hash.ssdeep": "6144:+60EDP6uCLfGw/GpxXinM1BCo1PlumGx2mx2tXd0t115JGI:X5DpBw/KViMTB1MnEWk0115JH", + "threat.indicator.file.hash.tlsh": "0D44D022AD13DD37E1F400FCA6A58F8561626E381F00A89777D41F8A98356F1BB2B717", + "threat.indicator.file.pe.imphash": "68aea345b134d576ccdef7f06db86088", + "threat.indicator.file.size": 277504, + "threat.indicator.file.type": "dll", + "threat.indicator.first_seen": "2021-01-14T06:08:02.000Z", + "threat.indicator.type": "file" }, { "event.category": "threat", @@ -210,15 +222,17 @@ "forwarded", "threatintel-abusemalware" ], - "threatintel.indicator.file.hash.md5": "f6facbf7a90b9e67a6de9f6634eb40ba", - "threatintel.indicator.file.hash.sha256": "e91c9e11d3ce4f55fabd7196279367482d2fabfa32df81e614b15fc53b4e26be", - "threatintel.indicator.file.hash.ssdeep": "6144:0hlBeZgR9LqvgFcwNAwhGV52n5Dv4JdEqvQykqRqYdBx8pRA7OZJ1:0h3eZgRQCcw+MN54dEq7kqRtoLZL", - "threatintel.indicator.file.hash.tlsh": "2554CF22E642C926F1E900FCB2A98B4451257E355F40F4D777C40FABA835AE2AF27717", - "threatintel.indicator.file.pe.imphash": "68aea345b134d576ccdef7f06db86088", - "threatintel.indicator.file.size": 284672, - "threatintel.indicator.file.type": "dll", - "threatintel.indicator.first_seen": "2021-01-14T06:07:53.000Z", - "threatintel.indicator.type": "file" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] AbuseCH Malware", + "threat.indicator.file.hash.md5": "f6facbf7a90b9e67a6de9f6634eb40ba", + "threat.indicator.file.hash.sha256": "e91c9e11d3ce4f55fabd7196279367482d2fabfa32df81e614b15fc53b4e26be", + "threat.indicator.file.hash.ssdeep": "6144:0hlBeZgR9LqvgFcwNAwhGV52n5Dv4JdEqvQykqRqYdBx8pRA7OZJ1:0h3eZgRQCcw+MN54dEq7kqRtoLZL", + "threat.indicator.file.hash.tlsh": "2554CF22E642C926F1E900FCB2A98B4451257E355F40F4D777C40FABA835AE2AF27717", + "threat.indicator.file.pe.imphash": "68aea345b134d576ccdef7f06db86088", + "threat.indicator.file.size": 284672, + "threat.indicator.file.type": "dll", + "threat.indicator.first_seen": "2021-01-14T06:07:53.000Z", + "threat.indicator.type": "file" }, { "event.category": "threat", @@ -241,17 +255,20 @@ "forwarded", "threatintel-abusemalware" ], - "threatintel.indicator.file.hash.md5": "44325fd5bdda2e2cdea07c3a39953bb1", - "threatintel.indicator.file.hash.sha256": "beedbbcacfc34b5edd8c68e3e4acf364992ebbcd989548e09e38fa03c5659bac", - "threatintel.indicator.file.hash.ssdeep": "6144:+60EDP6uCLfGw/GpxXinM1BCo1PlumGx2mx2tXd0t115JG/:X5DpBw/KViMTB1MnEWk0115Jg", - "threatintel.indicator.file.hash.tlsh": "A044D022AD13DD37E1F400FCA6A58F8561626E381F00A89777D41F8A98356F1BB2B717", - "threatintel.indicator.file.pe.imphash": "68aea345b134d576ccdef7f06db86088", - "threatintel.indicator.file.size": 277504, - "threatintel.indicator.file.type": "dll", - "threatintel.indicator.first_seen": "2021-01-14T06:07:41.000Z", - "threatintel.indicator.type": "file" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] AbuseCH Malware", + "threat.indicator.file.hash.md5": "44325fd5bdda2e2cdea07c3a39953bb1", + "threat.indicator.file.hash.sha256": "beedbbcacfc34b5edd8c68e3e4acf364992ebbcd989548e09e38fa03c5659bac", + "threat.indicator.file.hash.ssdeep": "6144:+60EDP6uCLfGw/GpxXinM1BCo1PlumGx2mx2tXd0t115JG/:X5DpBw/KViMTB1MnEWk0115Jg", + "threat.indicator.file.hash.tlsh": "A044D022AD13DD37E1F400FCA6A58F8561626E381F00A89777D41F8A98356F1BB2B717", + "threat.indicator.file.pe.imphash": "68aea345b134d576ccdef7f06db86088", + "threat.indicator.file.size": 277504, + "threat.indicator.file.type": "dll", + "threat.indicator.first_seen": "2021-01-14T06:07:41.000Z", + "threat.indicator.type": "file" }, { + "abusech.malware.signature": "Heodo", "event.category": "threat", "event.dataset": "threatintel.abusemalware", "event.kind": "enrichment", @@ -272,16 +289,17 @@ "forwarded", "threatintel-abusemalware" ], - "threatintel.abusemalware.signature": "Heodo", - "threatintel.indicator.file.hash.md5": "4c549051950522a3f1b0814aa9b1f6d1", - "threatintel.indicator.file.hash.sha256": "7cba55da723c0e020267a02e6ffc83e03a83701757fc4ec65ea398618ad881cf", - "threatintel.indicator.file.hash.ssdeep": "6144:+60EDP6uCLfGw/GpxXinM1BCo1PlumGx2mx2tXd0t115JG4:X5DpBw/KViMTB1MnEWk0115Jv", - "threatintel.indicator.file.hash.tlsh": "4544D022AD13DD37E1F400FCA6A58F8561626E381F00A89777D41F8A98356F1BB2B717", - "threatintel.indicator.file.pe.imphash": "68aea345b134d576ccdef7f06db86088", - "threatintel.indicator.file.size": 277504, - "threatintel.indicator.file.type": "dll", - "threatintel.indicator.first_seen": "2021-01-14T06:07:31.000Z", - "threatintel.indicator.type": "file" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] AbuseCH Malware", + "threat.indicator.file.hash.md5": "4c549051950522a3f1b0814aa9b1f6d1", + "threat.indicator.file.hash.sha256": "7cba55da723c0e020267a02e6ffc83e03a83701757fc4ec65ea398618ad881cf", + "threat.indicator.file.hash.ssdeep": "6144:+60EDP6uCLfGw/GpxXinM1BCo1PlumGx2mx2tXd0t115JG4:X5DpBw/KViMTB1MnEWk0115Jv", + "threat.indicator.file.hash.tlsh": "4544D022AD13DD37E1F400FCA6A58F8561626E381F00A89777D41F8A98356F1BB2B717", + "threat.indicator.file.pe.imphash": "68aea345b134d576ccdef7f06db86088", + "threat.indicator.file.size": 277504, + "threat.indicator.file.type": "dll", + "threat.indicator.first_seen": "2021-01-14T06:07:31.000Z", + "threat.indicator.type": "file" }, { "event.category": "threat", @@ -304,15 +322,17 @@ "forwarded", "threatintel-abusemalware" ], - "threatintel.indicator.file.hash.md5": "d7333113098d88b6a5dd5b8eb24f9b87", - "threatintel.indicator.file.hash.sha256": "426be5e085e6bbad8430223dc89d8d3ced497133f8d478fd00005bcbb73399d4", - "threatintel.indicator.file.hash.ssdeep": "6144:0hlBeZgR9LqvgFcwNAwhGV52n5Dv4JdEqvQykqRqYdBx8pRA7OZJw:0h3eZgRQCcw+MN54dEq7kqRtoLZW", - "threatintel.indicator.file.hash.tlsh": "9454CF22E642C926F1E900FCB2A98B4451257E355F40F4D777C40FABA835AE2AF27717", - "threatintel.indicator.file.pe.imphash": "68aea345b134d576ccdef7f06db86088", - "threatintel.indicator.file.size": 284672, - "threatintel.indicator.file.type": "dll", - "threatintel.indicator.first_seen": "2021-01-14T06:07:07.000Z", - "threatintel.indicator.type": "file" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] AbuseCH Malware", + "threat.indicator.file.hash.md5": "d7333113098d88b6a5dd5b8eb24f9b87", + "threat.indicator.file.hash.sha256": "426be5e085e6bbad8430223dc89d8d3ced497133f8d478fd00005bcbb73399d4", + "threat.indicator.file.hash.ssdeep": "6144:0hlBeZgR9LqvgFcwNAwhGV52n5Dv4JdEqvQykqRqYdBx8pRA7OZJw:0h3eZgRQCcw+MN54dEq7kqRtoLZW", + "threat.indicator.file.hash.tlsh": "9454CF22E642C926F1E900FCB2A98B4451257E355F40F4D777C40FABA835AE2AF27717", + "threat.indicator.file.pe.imphash": "68aea345b134d576ccdef7f06db86088", + "threat.indicator.file.size": 284672, + "threat.indicator.file.type": "dll", + "threat.indicator.first_seen": "2021-01-14T06:07:07.000Z", + "threat.indicator.type": "file" }, { "event.category": "threat", @@ -335,15 +355,17 @@ "forwarded", "threatintel-abusemalware" ], - "threatintel.indicator.file.hash.md5": "c8dbb261c1f450534c3693da2f4b479f", - "threatintel.indicator.file.hash.sha256": "25093afdaeb3ea000743ab843360a6b64f58c0a1ab950072ba6528056735deb9", - "threatintel.indicator.file.hash.ssdeep": "6144:+60EDP6uCLfGw/GpxXinM1BCo1PlumGx2mx2tXd0t115JGe:X5DpBw/KViMTB1MnEWk0115JR", - "threatintel.indicator.file.hash.tlsh": "F344D022AD13DD37E1F400FCA6A58F8561626E381F00A89777D41F8A98356F1BB2B717", - "threatintel.indicator.file.pe.imphash": "68aea345b134d576ccdef7f06db86088", - "threatintel.indicator.file.size": 277504, - "threatintel.indicator.file.type": "dll", - "threatintel.indicator.first_seen": "2021-01-14T06:07:07.000Z", - "threatintel.indicator.type": "file" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] AbuseCH Malware", + "threat.indicator.file.hash.md5": "c8dbb261c1f450534c3693da2f4b479f", + "threat.indicator.file.hash.sha256": "25093afdaeb3ea000743ab843360a6b64f58c0a1ab950072ba6528056735deb9", + "threat.indicator.file.hash.ssdeep": "6144:+60EDP6uCLfGw/GpxXinM1BCo1PlumGx2mx2tXd0t115JGe:X5DpBw/KViMTB1MnEWk0115JR", + "threat.indicator.file.hash.tlsh": "F344D022AD13DD37E1F400FCA6A58F8561626E381F00A89777D41F8A98356F1BB2B717", + "threat.indicator.file.pe.imphash": "68aea345b134d576ccdef7f06db86088", + "threat.indicator.file.size": 277504, + "threat.indicator.file.type": "dll", + "threat.indicator.first_seen": "2021-01-14T06:07:07.000Z", + "threat.indicator.type": "file" }, { "event.category": "threat", @@ -366,15 +388,17 @@ "forwarded", "threatintel-abusemalware" ], - "threatintel.indicator.file.hash.md5": "714953f1d0031a4bb2f0c44afd015931", - "threatintel.indicator.file.hash.sha256": "b3327a96280365e441057f490df6261c9a2400fd63719eb9a7a0c9db95beecc5", - "threatintel.indicator.file.hash.ssdeep": "6144:+60EDP6uCLfGw/GpxXinM1BCo1PlumGx2mx2tXd0t115JGc:X5DpBw/KViMTB1MnEWk0115J7", - "threatintel.indicator.file.hash.tlsh": "F644D022AD13DD37E1F400FCA6A58F8561626E381F00A89777D41F8A98356F1BB2B717", - "threatintel.indicator.file.pe.imphash": "68aea345b134d576ccdef7f06db86088", - "threatintel.indicator.file.size": 277504, - "threatintel.indicator.file.type": "dll", - "threatintel.indicator.first_seen": "2021-01-14T06:07:06.000Z", - "threatintel.indicator.type": "file" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] AbuseCH Malware", + "threat.indicator.file.hash.md5": "714953f1d0031a4bb2f0c44afd015931", + "threat.indicator.file.hash.sha256": "b3327a96280365e441057f490df6261c9a2400fd63719eb9a7a0c9db95beecc5", + "threat.indicator.file.hash.ssdeep": "6144:+60EDP6uCLfGw/GpxXinM1BCo1PlumGx2mx2tXd0t115JGc:X5DpBw/KViMTB1MnEWk0115J7", + "threat.indicator.file.hash.tlsh": "F644D022AD13DD37E1F400FCA6A58F8561626E381F00A89777D41F8A98356F1BB2B717", + "threat.indicator.file.pe.imphash": "68aea345b134d576ccdef7f06db86088", + "threat.indicator.file.size": 277504, + "threat.indicator.file.type": "dll", + "threat.indicator.first_seen": "2021-01-14T06:07:06.000Z", + "threat.indicator.type": "file" }, { "event.category": "threat", @@ -397,15 +421,17 @@ "forwarded", "threatintel-abusemalware" ], - "threatintel.indicator.file.hash.md5": "20fd22742500d4cec123398afc3d3672", - "threatintel.indicator.file.hash.sha256": "e92b54904391c171238863b584355197ba4508f73320a8e89afbb5425fc2dc4b", - "threatintel.indicator.file.hash.ssdeep": "6144:+60EDP6uCLfGw/GpxXinM1BCo1PlumGx2mx2tXd0t115JGc:X5DpBw/KViMTB1MnEWk0115JP", - "threatintel.indicator.file.hash.tlsh": "BE44D022AD13DD37E1F400FCA6A58F8561626E381F00A89777D41F8A98356F1BB2B717", - "threatintel.indicator.file.pe.imphash": "68aea345b134d576ccdef7f06db86088", - "threatintel.indicator.file.size": 277504, - "threatintel.indicator.file.type": "dll", - "threatintel.indicator.first_seen": "2021-01-14T06:07:00.000Z", - "threatintel.indicator.type": "file" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] AbuseCH Malware", + "threat.indicator.file.hash.md5": "20fd22742500d4cec123398afc3d3672", + "threat.indicator.file.hash.sha256": "e92b54904391c171238863b584355197ba4508f73320a8e89afbb5425fc2dc4b", + "threat.indicator.file.hash.ssdeep": "6144:+60EDP6uCLfGw/GpxXinM1BCo1PlumGx2mx2tXd0t115JGc:X5DpBw/KViMTB1MnEWk0115JP", + "threat.indicator.file.hash.tlsh": "BE44D022AD13DD37E1F400FCA6A58F8561626E381F00A89777D41F8A98356F1BB2B717", + "threat.indicator.file.pe.imphash": "68aea345b134d576ccdef7f06db86088", + "threat.indicator.file.size": 277504, + "threat.indicator.file.type": "dll", + "threat.indicator.first_seen": "2021-01-14T06:07:00.000Z", + "threat.indicator.type": "file" }, { "event.category": "threat", @@ -428,17 +454,20 @@ "forwarded", "threatintel-abusemalware" ], - "threatintel.indicator.file.hash.md5": "aa81ceea053797a6f8c38a0f2f9b80b0", - "threatintel.indicator.file.hash.sha256": "dd15e74b3cd3a4fdb5f47adefd6f90e27d5a20e01316cc791711f6dce7c0f52e", - "threatintel.indicator.file.hash.ssdeep": "6144:+60EDP6uCLfGw/GpxXinM1BCo1PlumGx2mx2tXd0t115JGf:X5DpBw/KViMTB1MnEWk0115Jo", - "threatintel.indicator.file.hash.tlsh": "CC44D022AD13DD37E1F400FCA6A58F8561626E381F00A89777D41F8A98356F1BB2B717", - "threatintel.indicator.file.pe.imphash": "68aea345b134d576ccdef7f06db86088", - "threatintel.indicator.file.size": 277504, - "threatintel.indicator.file.type": "dll", - "threatintel.indicator.first_seen": "2021-01-14T06:06:36.000Z", - "threatintel.indicator.type": "file" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] AbuseCH Malware", + "threat.indicator.file.hash.md5": "aa81ceea053797a6f8c38a0f2f9b80b0", + "threat.indicator.file.hash.sha256": "dd15e74b3cd3a4fdb5f47adefd6f90e27d5a20e01316cc791711f6dce7c0f52e", + "threat.indicator.file.hash.ssdeep": "6144:+60EDP6uCLfGw/GpxXinM1BCo1PlumGx2mx2tXd0t115JGf:X5DpBw/KViMTB1MnEWk0115Jo", + "threat.indicator.file.hash.tlsh": "CC44D022AD13DD37E1F400FCA6A58F8561626E381F00A89777D41F8A98356F1BB2B717", + "threat.indicator.file.pe.imphash": "68aea345b134d576ccdef7f06db86088", + "threat.indicator.file.size": 277504, + "threat.indicator.file.type": "dll", + "threat.indicator.first_seen": "2021-01-14T06:06:36.000Z", + "threat.indicator.type": "file" }, { + "abusech.malware.signature": "Heodo", "event.category": "threat", "event.dataset": "threatintel.abusemalware", "event.kind": "enrichment", @@ -459,16 +488,17 @@ "forwarded", "threatintel-abusemalware" ], - "threatintel.abusemalware.signature": "Heodo", - "threatintel.indicator.file.hash.md5": "a2ce6795664c0fa93b07fa54ba868991", - "threatintel.indicator.file.hash.sha256": "0fae1eeabc4f5e07bd16f7851aec5ab6032d407c7ff0270f2b6e85c2a3efebd1", - "threatintel.indicator.file.hash.ssdeep": "6144:+60EDP6uCLfGw/GpxXinM1BCo1PlumGx2mx2tXd0t115JGD:X5DpBw/KViMTB1MnEWk0115JY", - "threatintel.indicator.file.hash.tlsh": "8C44D022AD13DD37E1F400FCA6A58F8561626E381F00A89777D41F8A98356F1BB2B717", - "threatintel.indicator.file.pe.imphash": "68aea345b134d576ccdef7f06db86088", - "threatintel.indicator.file.size": 277504, - "threatintel.indicator.file.type": "dll", - "threatintel.indicator.first_seen": "2021-01-14T06:06:13.000Z", - "threatintel.indicator.type": "file" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] AbuseCH Malware", + "threat.indicator.file.hash.md5": "a2ce6795664c0fa93b07fa54ba868991", + "threat.indicator.file.hash.sha256": "0fae1eeabc4f5e07bd16f7851aec5ab6032d407c7ff0270f2b6e85c2a3efebd1", + "threat.indicator.file.hash.ssdeep": "6144:+60EDP6uCLfGw/GpxXinM1BCo1PlumGx2mx2tXd0t115JGD:X5DpBw/KViMTB1MnEWk0115JY", + "threat.indicator.file.hash.tlsh": "8C44D022AD13DD37E1F400FCA6A58F8561626E381F00A89777D41F8A98356F1BB2B717", + "threat.indicator.file.pe.imphash": "68aea345b134d576ccdef7f06db86088", + "threat.indicator.file.size": 277504, + "threat.indicator.file.type": "dll", + "threat.indicator.first_seen": "2021-01-14T06:06:13.000Z", + "threat.indicator.type": "file" }, { "event.category": "threat", @@ -491,15 +521,17 @@ "forwarded", "threatintel-abusemalware" ], - "threatintel.indicator.file.hash.md5": "9b9bac158dacb9c2f5511e9c464a7de4", - "threatintel.indicator.file.hash.sha256": "07a9d84c0b2c8cf1fd90ab409b9399d06920ab4b6efb647b5a3b9bef1045ee7e", - "threatintel.indicator.file.hash.ssdeep": "6144:WlLMUG2gFWLDFO9vNa11y3NPcJufFFTXNZrjJTKk:W5MT4WNaHy9P1FjbrjlKk", - "threatintel.indicator.file.hash.tlsh": "6B54CF217A53C826F5E800FCA6E9878914167F346F44A4C773D40F6AA8759E2EF2B317", - "threatintel.indicator.file.pe.imphash": "68aea345b134d576ccdef7f06db86088", - "threatintel.indicator.file.size": 280064, - "threatintel.indicator.file.type": "dll", - "threatintel.indicator.first_seen": "2021-01-14T06:05:52.000Z", - "threatintel.indicator.type": "file" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] AbuseCH Malware", + "threat.indicator.file.hash.md5": "9b9bac158dacb9c2f5511e9c464a7de4", + "threat.indicator.file.hash.sha256": "07a9d84c0b2c8cf1fd90ab409b9399d06920ab4b6efb647b5a3b9bef1045ee7e", + "threat.indicator.file.hash.ssdeep": "6144:WlLMUG2gFWLDFO9vNa11y3NPcJufFFTXNZrjJTKk:W5MT4WNaHy9P1FjbrjlKk", + "threat.indicator.file.hash.tlsh": "6B54CF217A53C826F5E800FCA6E9878914167F346F44A4C773D40F6AA8759E2EF2B317", + "threat.indicator.file.pe.imphash": "68aea345b134d576ccdef7f06db86088", + "threat.indicator.file.size": 280064, + "threat.indicator.file.type": "dll", + "threat.indicator.first_seen": "2021-01-14T06:05:52.000Z", + "threat.indicator.type": "file" }, { "event.category": "threat", @@ -522,17 +554,20 @@ "forwarded", "threatintel-abusemalware" ], - "threatintel.indicator.file.hash.md5": "e48e3fa5e0f7b21c1ecf1efc81ff91e8", - "threatintel.indicator.file.hash.sha256": "708c0193aec6354af6877f314d4b0e3864552bac77258bee9ee5bf886a116df5", - "threatintel.indicator.file.hash.ssdeep": "6144:+60EDP6uCLfGw/GpxXinM1BCo1PlumGx2mx2tXd0t115JGo:X5DpBw/KViMTB1MnEWk0115Jj", - "threatintel.indicator.file.hash.tlsh": "6644D022AD13DD37E1F400FCA6A58F8561626E381F00A89777D41F8A98356F1BB2B717", - "threatintel.indicator.file.pe.imphash": "68aea345b134d576ccdef7f06db86088", - "threatintel.indicator.file.size": 277504, - "threatintel.indicator.file.type": "dll", - "threatintel.indicator.first_seen": "2021-01-14T06:05:51.000Z", - "threatintel.indicator.type": "file" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] AbuseCH Malware", + "threat.indicator.file.hash.md5": "e48e3fa5e0f7b21c1ecf1efc81ff91e8", + "threat.indicator.file.hash.sha256": "708c0193aec6354af6877f314d4b0e3864552bac77258bee9ee5bf886a116df5", + "threat.indicator.file.hash.ssdeep": "6144:+60EDP6uCLfGw/GpxXinM1BCo1PlumGx2mx2tXd0t115JGo:X5DpBw/KViMTB1MnEWk0115Jj", + "threat.indicator.file.hash.tlsh": "6644D022AD13DD37E1F400FCA6A58F8561626E381F00A89777D41F8A98356F1BB2B717", + "threat.indicator.file.pe.imphash": "68aea345b134d576ccdef7f06db86088", + "threat.indicator.file.size": 277504, + "threat.indicator.file.type": "dll", + "threat.indicator.first_seen": "2021-01-14T06:05:51.000Z", + "threat.indicator.type": "file" }, { + "abusech.malware.signature": "Heodo", "event.category": "threat", "event.dataset": "threatintel.abusemalware", "event.kind": "enrichment", @@ -553,16 +588,17 @@ "forwarded", "threatintel-abusemalware" ], - "threatintel.abusemalware.signature": "Heodo", - "threatintel.indicator.file.hash.md5": "8957f5347633ab4b10c2ae4fb92c8572", - "threatintel.indicator.file.hash.sha256": "f70a3c016fe791eb30959961f0bcaa08ba7b738491b9ae61cb4a667cd1de8b37", - "threatintel.indicator.file.hash.ssdeep": "6144:0hlBeZgR9LqvgFcwNAwhGV52n5Dv4JdEqvQykqRqYdBx8pRA7OZJy:0h3eZgRQCcw+MN54dEq7kqRtoLZM", - "threatintel.indicator.file.hash.tlsh": "0754CF22E642C926F1E900FCB2A98B4451257E355F40F4D777C40FABA835AE2AF27717", - "threatintel.indicator.file.pe.imphash": "68aea345b134d576ccdef7f06db86088", - "threatintel.indicator.file.size": 284672, - "threatintel.indicator.file.type": "dll", - "threatintel.indicator.first_seen": "2021-01-14T06:05:50.000Z", - "threatintel.indicator.type": "file" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] AbuseCH Malware", + "threat.indicator.file.hash.md5": "8957f5347633ab4b10c2ae4fb92c8572", + "threat.indicator.file.hash.sha256": "f70a3c016fe791eb30959961f0bcaa08ba7b738491b9ae61cb4a667cd1de8b37", + "threat.indicator.file.hash.ssdeep": "6144:0hlBeZgR9LqvgFcwNAwhGV52n5Dv4JdEqvQykqRqYdBx8pRA7OZJy:0h3eZgRQCcw+MN54dEq7kqRtoLZM", + "threat.indicator.file.hash.tlsh": "0754CF22E642C926F1E900FCB2A98B4451257E355F40F4D777C40FABA835AE2AF27717", + "threat.indicator.file.pe.imphash": "68aea345b134d576ccdef7f06db86088", + "threat.indicator.file.size": 284672, + "threat.indicator.file.type": "dll", + "threat.indicator.first_seen": "2021-01-14T06:05:50.000Z", + "threat.indicator.type": "file" }, { "event.category": "threat", @@ -585,15 +621,17 @@ "forwarded", "threatintel-abusemalware" ], - "threatintel.indicator.file.hash.md5": "09cc76b7077b4d5704e46e864575ff03", - "threatintel.indicator.file.hash.sha256": "94ca186561b13fa9b1bf15f7e66118debc686b40d2a62a5cf4b3c6ca6ee1c7a1", - "threatintel.indicator.file.hash.ssdeep": "6144:+60EDP6uCLfGw/GpxXinM1BCo1PlumGx2mx2tXd0t115JG/:X5DpBw/KViMTB1MnEWk0115Js", - "threatintel.indicator.file.hash.tlsh": "BB44D022AD13DD37E1F400FCA6A58F8561626E381F00A89777D41F8A98356F1BB2B717", - "threatintel.indicator.file.pe.imphash": "68aea345b134d576ccdef7f06db86088", - "threatintel.indicator.file.size": 277504, - "threatintel.indicator.file.type": "dll", - "threatintel.indicator.first_seen": "2021-01-14T06:05:36.000Z", - "threatintel.indicator.type": "file" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] AbuseCH Malware", + "threat.indicator.file.hash.md5": "09cc76b7077b4d5704e46e864575ff03", + "threat.indicator.file.hash.sha256": "94ca186561b13fa9b1bf15f7e66118debc686b40d2a62a5cf4b3c6ca6ee1c7a1", + "threat.indicator.file.hash.ssdeep": "6144:+60EDP6uCLfGw/GpxXinM1BCo1PlumGx2mx2tXd0t115JG/:X5DpBw/KViMTB1MnEWk0115Js", + "threat.indicator.file.hash.tlsh": "BB44D022AD13DD37E1F400FCA6A58F8561626E381F00A89777D41F8A98356F1BB2B717", + "threat.indicator.file.pe.imphash": "68aea345b134d576ccdef7f06db86088", + "threat.indicator.file.size": 277504, + "threat.indicator.file.type": "dll", + "threat.indicator.first_seen": "2021-01-14T06:05:36.000Z", + "threat.indicator.type": "file" }, { "event.category": "threat", @@ -616,17 +654,20 @@ "forwarded", "threatintel-abusemalware" ], - "threatintel.indicator.file.hash.md5": "98a1cdf7de4232363f1d1e0f33dbfd99", - "threatintel.indicator.file.hash.sha256": "909f890dbc5748845cf06d0fb0b73a5c0cb17761f37e9cd4810eea0d0eb8627f", - "threatintel.indicator.file.hash.ssdeep": "6144:0hlBeZgR9LqvgFcwNAwhGV52n5Dv4JdEqvQykqRqYdBx8pRA7OZJQ:0h3eZgRQCcw+MN54dEq7kqRtoLZ+", - "threatintel.indicator.file.hash.tlsh": "C554CF22E642C926F1E900FCB2A98B4451257E355F40F4D777C40FABA835AE2AF27717", - "threatintel.indicator.file.pe.imphash": "68aea345b134d576ccdef7f06db86088", - "threatintel.indicator.file.size": 284672, - "threatintel.indicator.file.type": "dll", - "threatintel.indicator.first_seen": "2021-01-14T06:05:16.000Z", - "threatintel.indicator.type": "file" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] AbuseCH Malware", + "threat.indicator.file.hash.md5": "98a1cdf7de4232363f1d1e0f33dbfd99", + "threat.indicator.file.hash.sha256": "909f890dbc5748845cf06d0fb0b73a5c0cb17761f37e9cd4810eea0d0eb8627f", + "threat.indicator.file.hash.ssdeep": "6144:0hlBeZgR9LqvgFcwNAwhGV52n5Dv4JdEqvQykqRqYdBx8pRA7OZJQ:0h3eZgRQCcw+MN54dEq7kqRtoLZ+", + "threat.indicator.file.hash.tlsh": "C554CF22E642C926F1E900FCB2A98B4451257E355F40F4D777C40FABA835AE2AF27717", + "threat.indicator.file.pe.imphash": "68aea345b134d576ccdef7f06db86088", + "threat.indicator.file.size": 284672, + "threat.indicator.file.type": "dll", + "threat.indicator.first_seen": "2021-01-14T06:05:16.000Z", + "threat.indicator.type": "file" }, { + "abusech.malware.signature": "Heodo", "event.category": "threat", "event.dataset": "threatintel.abusemalware", "event.kind": "enrichment", @@ -647,16 +688,17 @@ "forwarded", "threatintel-abusemalware" ], - "threatintel.abusemalware.signature": "Heodo", - "threatintel.indicator.file.hash.md5": "8a51830c1662513ba6bd44e2f7849547", - "threatintel.indicator.file.hash.sha256": "d1fa76346bef5bc8adaa615e109894a7c30f0bef07ab6272409c4056ea8d52aa", - "threatintel.indicator.file.hash.ssdeep": "6144:0hlBeZgR9LqvgFcwNAwhGV52n5Dv4JdEqvQykqRqYdBx8pRA7OZJh:0h3eZgRQCcw+MN54dEq7kqRtoLZ/", - "threatintel.indicator.file.hash.tlsh": "1654CF22E642C926F1E900FCB2A98B4451257E355F40F4D777C40FABA835AE2AF27717", - "threatintel.indicator.file.pe.imphash": "68aea345b134d576ccdef7f06db86088", - "threatintel.indicator.file.size": 284672, - "threatintel.indicator.file.type": "dll", - "threatintel.indicator.first_seen": "2021-01-14T06:05:15.000Z", - "threatintel.indicator.type": "file" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] AbuseCH Malware", + "threat.indicator.file.hash.md5": "8a51830c1662513ba6bd44e2f7849547", + "threat.indicator.file.hash.sha256": "d1fa76346bef5bc8adaa615e109894a7c30f0bef07ab6272409c4056ea8d52aa", + "threat.indicator.file.hash.ssdeep": "6144:0hlBeZgR9LqvgFcwNAwhGV52n5Dv4JdEqvQykqRqYdBx8pRA7OZJh:0h3eZgRQCcw+MN54dEq7kqRtoLZ/", + "threat.indicator.file.hash.tlsh": "1654CF22E642C926F1E900FCB2A98B4451257E355F40F4D777C40FABA835AE2AF27717", + "threat.indicator.file.pe.imphash": "68aea345b134d576ccdef7f06db86088", + "threat.indicator.file.size": 284672, + "threat.indicator.file.type": "dll", + "threat.indicator.first_seen": "2021-01-14T06:05:15.000Z", + "threat.indicator.type": "file" }, { "event.category": "threat", @@ -679,15 +721,17 @@ "forwarded", "threatintel-abusemalware" ], - "threatintel.indicator.file.hash.md5": "ae21d742a8118d6b86674aa5370bd6a7", - "threatintel.indicator.file.hash.sha256": "3b9698b6c18bcba15ee33378440dd3f42509730e6b1d2d5832c71a74b1920e51", - "threatintel.indicator.file.hash.ssdeep": "6144:WlLMUG2gFWLDFO9vNa11y3NPcJufFFTXNZrjJTKS:W5MT4WNaHy9P1FjbrjlKS", - "threatintel.indicator.file.hash.tlsh": "5454CF217A53C826F5E800FCA6E9878925167F346F44A4C373D40F6AA8759E2DF2B317", - "threatintel.indicator.file.pe.imphash": "68aea345b134d576ccdef7f06db86088", - "threatintel.indicator.file.size": 280064, - "threatintel.indicator.file.type": "dll", - "threatintel.indicator.first_seen": "2021-01-14T06:05:12.000Z", - "threatintel.indicator.type": "file" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] AbuseCH Malware", + "threat.indicator.file.hash.md5": "ae21d742a8118d6b86674aa5370bd6a7", + "threat.indicator.file.hash.sha256": "3b9698b6c18bcba15ee33378440dd3f42509730e6b1d2d5832c71a74b1920e51", + "threat.indicator.file.hash.ssdeep": "6144:WlLMUG2gFWLDFO9vNa11y3NPcJufFFTXNZrjJTKS:W5MT4WNaHy9P1FjbrjlKS", + "threat.indicator.file.hash.tlsh": "5454CF217A53C826F5E800FCA6E9878925167F346F44A4C373D40F6AA8759E2DF2B317", + "threat.indicator.file.pe.imphash": "68aea345b134d576ccdef7f06db86088", + "threat.indicator.file.size": 280064, + "threat.indicator.file.type": "dll", + "threat.indicator.first_seen": "2021-01-14T06:05:12.000Z", + "threat.indicator.type": "file" }, { "event.category": "threat", @@ -710,15 +754,17 @@ "forwarded", "threatintel-abusemalware" ], - "threatintel.indicator.file.hash.md5": "78c9d88d24ed1d982a83216eed1590f6", - "threatintel.indicator.file.hash.sha256": "d11edc90f0e879a175abc6e2ce5c94a263aa2a01cd3b6e8b9fdf93a51235ae99", - "threatintel.indicator.file.hash.ssdeep": "6144:+60EDP6uCLfGw/GpxXinM1BCo1PlumGx2mx2tXd0t115JG8:X5DpBw/KViMTB1MnEWk0115Jr", - "threatintel.indicator.file.hash.tlsh": "6044D022AD13DD37E1F400FCA6A58F8561626E381F00A89777D41F8A98356F1BB2B717", - "threatintel.indicator.file.pe.imphash": "68aea345b134d576ccdef7f06db86088", - "threatintel.indicator.file.size": 277504, - "threatintel.indicator.file.type": "dll", - "threatintel.indicator.first_seen": "2021-01-14T06:04:38.000Z", - "threatintel.indicator.type": "file" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] AbuseCH Malware", + "threat.indicator.file.hash.md5": "78c9d88d24ed1d982a83216eed1590f6", + "threat.indicator.file.hash.sha256": "d11edc90f0e879a175abc6e2ce5c94a263aa2a01cd3b6e8b9fdf93a51235ae99", + "threat.indicator.file.hash.ssdeep": "6144:+60EDP6uCLfGw/GpxXinM1BCo1PlumGx2mx2tXd0t115JG8:X5DpBw/KViMTB1MnEWk0115Jr", + "threat.indicator.file.hash.tlsh": "6044D022AD13DD37E1F400FCA6A58F8561626E381F00A89777D41F8A98356F1BB2B717", + "threat.indicator.file.pe.imphash": "68aea345b134d576ccdef7f06db86088", + "threat.indicator.file.size": 277504, + "threat.indicator.file.type": "dll", + "threat.indicator.first_seen": "2021-01-14T06:04:38.000Z", + "threat.indicator.type": "file" }, { "event.category": "threat", @@ -741,15 +787,17 @@ "forwarded", "threatintel-abusemalware" ], - "threatintel.indicator.file.hash.md5": "236577d5d83e2a8d08623a7a7f724188", - "threatintel.indicator.file.hash.sha256": "8cd28fed7ebdcd79ea2509dca84f0a727ca28d4eaaed5a92cd10b1279ff16afa", - "threatintel.indicator.file.hash.ssdeep": "6144:X1G3WVIOY6Bdjehj+qudd96ou/6mv5wdC:X1GmSafShjYdd96z/6cwdC", - "threatintel.indicator.file.hash.tlsh": "8D34BE41B28B8B4BD163163C2976D1F8953CFC909761CE693B64B22F0F739D0892E7A5", - "threatintel.indicator.file.pe.imphash": "ed2860c18f5483e3b5388bad75169dc1", - "threatintel.indicator.file.size": 241664, - "threatintel.indicator.file.type": "dll", - "threatintel.indicator.first_seen": "2021-01-14T06:04:26.000Z", - "threatintel.indicator.type": "file" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] AbuseCH Malware", + "threat.indicator.file.hash.md5": "236577d5d83e2a8d08623a7a7f724188", + "threat.indicator.file.hash.sha256": "8cd28fed7ebdcd79ea2509dca84f0a727ca28d4eaaed5a92cd10b1279ff16afa", + "threat.indicator.file.hash.ssdeep": "6144:X1G3WVIOY6Bdjehj+qudd96ou/6mv5wdC:X1GmSafShjYdd96z/6cwdC", + "threat.indicator.file.hash.tlsh": "8D34BE41B28B8B4BD163163C2976D1F8953CFC909761CE693B64B22F0F739D0892E7A5", + "threat.indicator.file.pe.imphash": "ed2860c18f5483e3b5388bad75169dc1", + "threat.indicator.file.size": 241664, + "threat.indicator.file.type": "dll", + "threat.indicator.first_seen": "2021-01-14T06:04:26.000Z", + "threat.indicator.type": "file" }, { "event.category": "threat", @@ -772,14 +820,16 @@ "forwarded", "threatintel-abusemalware" ], - "threatintel.indicator.file.hash.md5": "ff60107d82dcda7e6726d214528758e7", - "threatintel.indicator.file.hash.sha256": "fb25d13188a5d0913bbcf5aeff6c7e3208ad92a7d10ab6bed2735f4d43310a27", - "threatintel.indicator.file.hash.ssdeep": "6144:+60EDP6uCLfGw/GpxXinM1BCo1PlumGx2mx2tXd0t115JGz:X5DpBw/KViMTB1MnEWk0115JU", - "threatintel.indicator.file.hash.tlsh": "9244D022AD13DD37E1F400FCA6A58F8561626E381F00A89777D41F8A98356F1BB2B717", - "threatintel.indicator.file.pe.imphash": "68aea345b134d576ccdef7f06db86088", - "threatintel.indicator.file.size": 277504, - "threatintel.indicator.file.type": "dll", - "threatintel.indicator.first_seen": "2021-01-14T06:04:20.000Z", - "threatintel.indicator.type": "file" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] AbuseCH Malware", + "threat.indicator.file.hash.md5": "ff60107d82dcda7e6726d214528758e7", + "threat.indicator.file.hash.sha256": "fb25d13188a5d0913bbcf5aeff6c7e3208ad92a7d10ab6bed2735f4d43310a27", + "threat.indicator.file.hash.ssdeep": "6144:+60EDP6uCLfGw/GpxXinM1BCo1PlumGx2mx2tXd0t115JGz:X5DpBw/KViMTB1MnEWk0115JU", + "threat.indicator.file.hash.tlsh": "9244D022AD13DD37E1F400FCA6A58F8561626E381F00A89777D41F8A98356F1BB2B717", + "threat.indicator.file.pe.imphash": "68aea345b134d576ccdef7f06db86088", + "threat.indicator.file.size": 277504, + "threat.indicator.file.type": "dll", + "threat.indicator.first_seen": "2021-01-14T06:04:20.000Z", + "threat.indicator.type": "file" } ] \ No newline at end of file diff --git a/x-pack/filebeat/module/threatintel/abuseurl/_meta/fields.yml b/x-pack/filebeat/module/threatintel/abuseurl/_meta/fields.yml index a93f91d339c..f407bb8d615 100644 --- a/x-pack/filebeat/module/threatintel/abuseurl/_meta/fields.yml +++ b/x-pack/filebeat/module/threatintel/abuseurl/_meta/fields.yml @@ -1,4 +1,4 @@ -- name: abuseurl +- name: abusech.url type: group description: > Fields for AbuseCH Malware Threat Intel diff --git a/x-pack/filebeat/module/threatintel/abuseurl/config/config.yml b/x-pack/filebeat/module/threatintel/abuseurl/config/config.yml index da01bc61c40..f577594ec06 100644 --- a/x-pack/filebeat/module/threatintel/abuseurl/config/config.yml +++ b/x-pack/filebeat/module/threatintel/abuseurl/config/config.yml @@ -11,10 +11,6 @@ request.ssl: {{ .ssl | tojson }} request.proxy_url: {{ .proxy_url }} {{ end }} request.url: {{ .url }} -request.transforms: -- set: - target: header.Content-Type - value: application/json response.split: target: body.urls @@ -30,17 +26,12 @@ exclude_files: [".gz$"] {{ end }} -tags: {{.tags | tojson}} -publisher_pipeline.disable_host: {{ inList .tags "forwarded" }} +tags: +{{if .preserve_original_event}} + - preserve_original_event +{{end}} +{{range $val := .tags}} + - {{$val}} +{{end}} -processors: - - decode_json_fields: - fields: [message] - target: json - - fingerprint: - fields: ["json.id"] - target_field: "@metadata._id" - - add_fields: - target: '' - fields: - ecs.version: 1.12.0 +publisher_pipeline.disable_host: {{ inList .tags "forwarded" }} diff --git a/x-pack/filebeat/module/threatintel/abuseurl/ingest/pipeline.yml b/x-pack/filebeat/module/threatintel/abuseurl/ingest/pipeline.yml index bf674ba2c88..f762db7351e 100644 --- a/x-pack/filebeat/module/threatintel/abuseurl/ingest/pipeline.yml +++ b/x-pack/filebeat/module/threatintel/abuseurl/ingest/pipeline.yml @@ -1,3 +1,4 @@ +--- description: Pipeline for parsing Abuse.ch URL Threat Intel processors: #################### @@ -6,6 +7,9 @@ processors: - set: field: event.ingested value: "{{_ingest.timestamp}}" + - set: + field: ecs.version + value: "1.12" - set: field: event.kind value: enrichment @@ -20,62 +24,75 @@ processors: # General ECS fields # ###################### - rename: - field: json - target_field: threatintel.abuseurl + field: message + target_field: event.original ignore_missing: true + - json: + field: event.original + target_field: abusech.url + - fingerprint: + fields: + - abusech.url.id + target_field: "_id" ##################### # Threat ECS Fields # ##################### - set: - field: threatintel.indicator.type + field: threat.feed.name + value: "[Filebeat] AbuseCH URL" + - set: + field: threat.feed.dashboard_id + value: "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f" + - set: + field: threat.indicator.type value: url - date: - field: threatintel.abuseurl.date_added - target_field: threatintel.indicator.first_seen + field: abusech.url.date_added + target_field: threat.indicator.first_seen formats: - "yyyy-MM-dd HH:mm:ss z" - "yyyy-MM-dd HH:mm:ss Z" - if: "ctx?.threatintel?.abuseurl?.date_added != null" + if: "ctx.abusech?.url?.date_added != null" - uri_parts: - field: threatintel.abuseurl.url - target_field: threatintel.indicator.url + field: abusech.url.url + target_field: threat.indicator.url keep_original: true remove_if_successful: true - set: - field: threatintel.indicator.url.full - value: "{{{threatintel.indicator.url.original}}}" + field: threat.indicator.url.full + value: "{{{threat.indicator.url.original}}}" ignore_empty_value: true - rename: - field: threatintel.abuseurl.urlhaus_reference - target_field: threatintel.indicator.reference + field: abusech.url.urlhaus_reference + target_field: threat.indicator.reference ignore_missing: true # Host can be both IP addresses and domain names - grok: - field: threatintel.abuseurl.host + field: abusech.url.host patterns: - - "(?:%{IP:threatintel.indicator.ip}|%{GREEDYDATA:threatintel.indicator.url.domain})" + - "(?:%{IP:threat.indicator.ip}|%{GREEDYDATA:threat.indicator.url.domain})" ignore_failure: true - rename: - field: threatintel.abuseurl.reporter - target_field: threatintel.indicator.provider + field: abusech.url.reporter + target_field: threat.indicator.provider ignore_missing: true ###################### # Cleanup processors # ###################### - set: - field: threatintel.indicator.type + field: threat.indicator.type value: unknown - if: ctx?.threatintel?.indicator?.type == null + if: ctx?.threat?.indicator?.type == null - convert: - field: threatintel.abuseurl.larted + field: abusech.url.larted type: boolean ignore_missing: true - script: lang: painless - if: ctx?.threatintel != null + if: ctx?.abusech != null source: | void handleMap(Map map) { for (def x : map.values()) { @@ -97,11 +114,16 @@ processors: } } handleMap(ctx); + - remove: + field: event.original + if: "ctx?.tags == null || !(ctx.tags.contains('preserve_original_event'))" + ignore_failure: true + ignore_missing: true - remove: field: - - threatintel.abuseurl.date_added - - threatintel.abuseurl.url - - threatintel.abuseurl.host + - abusech.url.date_added + - abusech.url.url + - abusech.url.host - message ignore_missing: true on_failure: diff --git a/x-pack/filebeat/module/threatintel/abuseurl/manifest.yml b/x-pack/filebeat/module/threatintel/abuseurl/manifest.yml index 13b5e663c4a..2f71ad88253 100644 --- a/x-pack/filebeat/module/threatintel/abuseurl/manifest.yml +++ b/x-pack/filebeat/module/threatintel/abuseurl/manifest.yml @@ -11,6 +11,8 @@ var: - name: tags default: [threatintel-abuseurls, forwarded] - name: proxy_url + - name: preserve_original_event + default: false ingest_pipeline: - ingest/pipeline.yml diff --git a/x-pack/filebeat/module/threatintel/abuseurl/test/abusechurl.ndjson.log-expected.json b/x-pack/filebeat/module/threatintel/abuseurl/test/abusechurl.ndjson.log-expected.json index 3b312440b34..c76728b3c16 100644 --- a/x-pack/filebeat/module/threatintel/abuseurl/test/abusechurl.ndjson.log-expected.json +++ b/x-pack/filebeat/module/threatintel/abuseurl/test/abusechurl.ndjson.log-expected.json @@ -1,5 +1,15 @@ [ { + "abusech.url.blacklists.spamhaus_dbl": "not listed", + "abusech.url.blacklists.surbl": "not listed", + "abusech.url.id": "961548", + "abusech.url.larted": false, + "abusech.url.tags": [ + "Mozi", + "elf" + ], + "abusech.url.threat": "malware_download", + "abusech.url.url_status": "online", "event.category": "threat", "event.dataset": "threatintel.abuseurl", "event.kind": "enrichment", @@ -13,30 +23,32 @@ "forwarded", "threatintel-abuseurls" ], - "threatintel.abuseurl.blacklists.spamhaus_dbl": "not listed", - "threatintel.abuseurl.blacklists.surbl": "not listed", - "threatintel.abuseurl.id": "961548", - "threatintel.abuseurl.larted": false, - "threatintel.abuseurl.tags": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] AbuseCH URL", + "threat.indicator.first_seen": "2021-01-14T21:19:13.000Z", + "threat.indicator.ip": "103.72.223.103", + "threat.indicator.provider": "lrz_urlhaus", + "threat.indicator.reference": "https://urlhaus.abuse.ch/url/961548/", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "103.72.223.103", + "threat.indicator.url.extension": "m", + "threat.indicator.url.full": "http://103.72.223.103:34613/Mozi.m", + "threat.indicator.url.original": "http://103.72.223.103:34613/Mozi.m", + "threat.indicator.url.path": "/Mozi.m", + "threat.indicator.url.port": 34613, + "threat.indicator.url.scheme": "http" + }, + { + "abusech.url.blacklists.spamhaus_dbl": "not listed", + "abusech.url.blacklists.surbl": "not listed", + "abusech.url.id": "961546", + "abusech.url.larted": false, + "abusech.url.tags": [ "Mozi", "elf" ], - "threatintel.abuseurl.threat": "malware_download", - "threatintel.abuseurl.url_status": "online", - "threatintel.indicator.first_seen": "2021-01-14T21:19:13.000Z", - "threatintel.indicator.ip": "103.72.223.103", - "threatintel.indicator.provider": "lrz_urlhaus", - "threatintel.indicator.reference": "https://urlhaus.abuse.ch/url/961548/", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "103.72.223.103", - "threatintel.indicator.url.extension": "m", - "threatintel.indicator.url.full": "http://103.72.223.103:34613/Mozi.m", - "threatintel.indicator.url.original": "http://103.72.223.103:34613/Mozi.m", - "threatintel.indicator.url.path": "/Mozi.m", - "threatintel.indicator.url.port": 34613, - "threatintel.indicator.url.scheme": "http" - }, - { + "abusech.url.threat": "malware_download", + "abusech.url.url_status": "online", "event.category": "threat", "event.dataset": "threatintel.abuseurl", "event.kind": "enrichment", @@ -50,30 +62,32 @@ "forwarded", "threatintel-abuseurls" ], - "threatintel.abuseurl.blacklists.spamhaus_dbl": "not listed", - "threatintel.abuseurl.blacklists.surbl": "not listed", - "threatintel.abuseurl.id": "961546", - "threatintel.abuseurl.larted": false, - "threatintel.abuseurl.tags": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] AbuseCH URL", + "threat.indicator.first_seen": "2021-01-14T21:19:05.000Z", + "threat.indicator.ip": "112.30.97.184", + "threat.indicator.provider": "lrz_urlhaus", + "threat.indicator.reference": "https://urlhaus.abuse.ch/url/961546/", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "112.30.97.184", + "threat.indicator.url.extension": "m", + "threat.indicator.url.full": "http://112.30.97.184:44941/Mozi.m", + "threat.indicator.url.original": "http://112.30.97.184:44941/Mozi.m", + "threat.indicator.url.path": "/Mozi.m", + "threat.indicator.url.port": 44941, + "threat.indicator.url.scheme": "http" + }, + { + "abusech.url.blacklists.spamhaus_dbl": "not listed", + "abusech.url.blacklists.surbl": "not listed", + "abusech.url.id": "961547", + "abusech.url.larted": false, + "abusech.url.tags": [ "Mozi", "elf" ], - "threatintel.abuseurl.threat": "malware_download", - "threatintel.abuseurl.url_status": "online", - "threatintel.indicator.first_seen": "2021-01-14T21:19:05.000Z", - "threatintel.indicator.ip": "112.30.97.184", - "threatintel.indicator.provider": "lrz_urlhaus", - "threatintel.indicator.reference": "https://urlhaus.abuse.ch/url/961546/", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "112.30.97.184", - "threatintel.indicator.url.extension": "m", - "threatintel.indicator.url.full": "http://112.30.97.184:44941/Mozi.m", - "threatintel.indicator.url.original": "http://112.30.97.184:44941/Mozi.m", - "threatintel.indicator.url.path": "/Mozi.m", - "threatintel.indicator.url.port": 44941, - "threatintel.indicator.url.scheme": "http" - }, - { + "abusech.url.threat": "malware_download", + "abusech.url.url_status": "online", "event.category": "threat", "event.dataset": "threatintel.abuseurl", "event.kind": "enrichment", @@ -87,30 +101,32 @@ "forwarded", "threatintel-abuseurls" ], - "threatintel.abuseurl.blacklists.spamhaus_dbl": "not listed", - "threatintel.abuseurl.blacklists.surbl": "not listed", - "threatintel.abuseurl.id": "961547", - "threatintel.abuseurl.larted": false, - "threatintel.abuseurl.tags": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] AbuseCH URL", + "threat.indicator.first_seen": "2021-01-14T21:19:05.000Z", + "threat.indicator.ip": "113.110.198.53", + "threat.indicator.provider": "lrz_urlhaus", + "threat.indicator.reference": "https://urlhaus.abuse.ch/url/961547/", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "113.110.198.53", + "threat.indicator.url.extension": "m", + "threat.indicator.url.full": "http://113.110.198.53:37173/Mozi.m", + "threat.indicator.url.original": "http://113.110.198.53:37173/Mozi.m", + "threat.indicator.url.path": "/Mozi.m", + "threat.indicator.url.port": 37173, + "threat.indicator.url.scheme": "http" + }, + { + "abusech.url.blacklists.spamhaus_dbl": "not listed", + "abusech.url.blacklists.surbl": "not listed", + "abusech.url.id": "961545", + "abusech.url.larted": false, + "abusech.url.tags": [ "Mozi", "elf" ], - "threatintel.abuseurl.threat": "malware_download", - "threatintel.abuseurl.url_status": "online", - "threatintel.indicator.first_seen": "2021-01-14T21:19:05.000Z", - "threatintel.indicator.ip": "113.110.198.53", - "threatintel.indicator.provider": "lrz_urlhaus", - "threatintel.indicator.reference": "https://urlhaus.abuse.ch/url/961547/", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "113.110.198.53", - "threatintel.indicator.url.extension": "m", - "threatintel.indicator.url.full": "http://113.110.198.53:37173/Mozi.m", - "threatintel.indicator.url.original": "http://113.110.198.53:37173/Mozi.m", - "threatintel.indicator.url.path": "/Mozi.m", - "threatintel.indicator.url.port": 37173, - "threatintel.indicator.url.scheme": "http" - }, - { + "abusech.url.threat": "malware_download", + "abusech.url.url_status": "online", "event.category": "threat", "event.dataset": "threatintel.abuseurl", "event.kind": "enrichment", @@ -124,30 +140,32 @@ "forwarded", "threatintel-abuseurls" ], - "threatintel.abuseurl.blacklists.spamhaus_dbl": "not listed", - "threatintel.abuseurl.blacklists.surbl": "not listed", - "threatintel.abuseurl.id": "961545", - "threatintel.abuseurl.larted": false, - "threatintel.abuseurl.tags": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] AbuseCH URL", + "threat.indicator.first_seen": "2021-01-14T21:19:04.000Z", + "threat.indicator.ip": "101.20.183.170", + "threat.indicator.provider": "lrz_urlhaus", + "threat.indicator.reference": "https://urlhaus.abuse.ch/url/961545/", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "101.20.183.170", + "threat.indicator.url.extension": "m", + "threat.indicator.url.full": "http://101.20.183.170:47545/Mozi.m", + "threat.indicator.url.original": "http://101.20.183.170:47545/Mozi.m", + "threat.indicator.url.path": "/Mozi.m", + "threat.indicator.url.port": 47545, + "threat.indicator.url.scheme": "http" + }, + { + "abusech.url.blacklists.spamhaus_dbl": "not listed", + "abusech.url.blacklists.surbl": "not listed", + "abusech.url.id": "961544", + "abusech.url.larted": true, + "abusech.url.tags": [ "Mozi", "elf" ], - "threatintel.abuseurl.threat": "malware_download", - "threatintel.abuseurl.url_status": "online", - "threatintel.indicator.first_seen": "2021-01-14T21:19:04.000Z", - "threatintel.indicator.ip": "101.20.183.170", - "threatintel.indicator.provider": "lrz_urlhaus", - "threatintel.indicator.reference": "https://urlhaus.abuse.ch/url/961545/", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "101.20.183.170", - "threatintel.indicator.url.extension": "m", - "threatintel.indicator.url.full": "http://101.20.183.170:47545/Mozi.m", - "threatintel.indicator.url.original": "http://101.20.183.170:47545/Mozi.m", - "threatintel.indicator.url.path": "/Mozi.m", - "threatintel.indicator.url.port": 47545, - "threatintel.indicator.url.scheme": "http" - }, - { + "abusech.url.threat": "malware_download", + "abusech.url.url_status": "online", "event.category": "threat", "event.dataset": "threatintel.abuseurl", "event.kind": "enrichment", @@ -161,30 +179,32 @@ "forwarded", "threatintel-abuseurls" ], - "threatintel.abuseurl.blacklists.spamhaus_dbl": "not listed", - "threatintel.abuseurl.blacklists.surbl": "not listed", - "threatintel.abuseurl.id": "961544", - "threatintel.abuseurl.larted": true, - "threatintel.abuseurl.tags": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] AbuseCH URL", + "threat.indicator.first_seen": "2021-01-14T21:07:07.000Z", + "threat.indicator.ip": "59.8.35.22", + "threat.indicator.provider": "lrz_urlhaus", + "threat.indicator.reference": "https://urlhaus.abuse.ch/url/961544/", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "59.8.35.22", + "threat.indicator.url.extension": "a", + "threat.indicator.url.full": "http://59.8.35.22:44782/Mozi.a", + "threat.indicator.url.original": "http://59.8.35.22:44782/Mozi.a", + "threat.indicator.url.path": "/Mozi.a", + "threat.indicator.url.port": 44782, + "threat.indicator.url.scheme": "http" + }, + { + "abusech.url.blacklists.spamhaus_dbl": "not listed", + "abusech.url.blacklists.surbl": "not listed", + "abusech.url.id": "961543", + "abusech.url.larted": true, + "abusech.url.tags": [ "Mozi", "elf" ], - "threatintel.abuseurl.threat": "malware_download", - "threatintel.abuseurl.url_status": "online", - "threatintel.indicator.first_seen": "2021-01-14T21:07:07.000Z", - "threatintel.indicator.ip": "59.8.35.22", - "threatintel.indicator.provider": "lrz_urlhaus", - "threatintel.indicator.reference": "https://urlhaus.abuse.ch/url/961544/", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "59.8.35.22", - "threatintel.indicator.url.extension": "a", - "threatintel.indicator.url.full": "http://59.8.35.22:44782/Mozi.a", - "threatintel.indicator.url.original": "http://59.8.35.22:44782/Mozi.a", - "threatintel.indicator.url.path": "/Mozi.a", - "threatintel.indicator.url.port": 44782, - "threatintel.indicator.url.scheme": "http" - }, - { + "abusech.url.threat": "malware_download", + "abusech.url.url_status": "online", "event.category": "threat", "event.dataset": "threatintel.abuseurl", "event.kind": "enrichment", @@ -198,30 +218,32 @@ "forwarded", "threatintel-abuseurls" ], - "threatintel.abuseurl.blacklists.spamhaus_dbl": "not listed", - "threatintel.abuseurl.blacklists.surbl": "not listed", - "threatintel.abuseurl.id": "961543", - "threatintel.abuseurl.larted": true, - "threatintel.abuseurl.tags": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] AbuseCH URL", + "threat.indicator.first_seen": "2021-01-14T21:07:06.000Z", + "threat.indicator.ip": "59.96.37.35", + "threat.indicator.provider": "lrz_urlhaus", + "threat.indicator.reference": "https://urlhaus.abuse.ch/url/961543/", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "59.96.37.35", + "threat.indicator.url.extension": "a", + "threat.indicator.url.full": "http://59.96.37.35:44359/Mozi.a", + "threat.indicator.url.original": "http://59.96.37.35:44359/Mozi.a", + "threat.indicator.url.path": "/Mozi.a", + "threat.indicator.url.port": 44359, + "threat.indicator.url.scheme": "http" + }, + { + "abusech.url.blacklists.spamhaus_dbl": "not listed", + "abusech.url.blacklists.surbl": "not listed", + "abusech.url.id": "961540", + "abusech.url.larted": true, + "abusech.url.tags": [ "Mozi", "elf" ], - "threatintel.abuseurl.threat": "malware_download", - "threatintel.abuseurl.url_status": "online", - "threatintel.indicator.first_seen": "2021-01-14T21:07:06.000Z", - "threatintel.indicator.ip": "59.96.37.35", - "threatintel.indicator.provider": "lrz_urlhaus", - "threatintel.indicator.reference": "https://urlhaus.abuse.ch/url/961543/", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "59.96.37.35", - "threatintel.indicator.url.extension": "a", - "threatintel.indicator.url.full": "http://59.96.37.35:44359/Mozi.a", - "threatintel.indicator.url.original": "http://59.96.37.35:44359/Mozi.a", - "threatintel.indicator.url.path": "/Mozi.a", - "threatintel.indicator.url.port": 44359, - "threatintel.indicator.url.scheme": "http" - }, - { + "abusech.url.threat": "malware_download", + "abusech.url.url_status": "online", "event.category": "threat", "event.dataset": "threatintel.abuseurl", "event.kind": "enrichment", @@ -235,30 +257,32 @@ "forwarded", "threatintel-abuseurls" ], - "threatintel.abuseurl.blacklists.spamhaus_dbl": "not listed", - "threatintel.abuseurl.blacklists.surbl": "not listed", - "threatintel.abuseurl.id": "961540", - "threatintel.abuseurl.larted": true, - "threatintel.abuseurl.tags": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] AbuseCH URL", + "threat.indicator.first_seen": "2021-01-14T21:07:05.000Z", + "threat.indicator.ip": "42.239.233.17", + "threat.indicator.provider": "lrz_urlhaus", + "threat.indicator.reference": "https://urlhaus.abuse.ch/url/961540/", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "42.239.233.17", + "threat.indicator.url.extension": "m", + "threat.indicator.url.full": "http://42.239.233.17:56507/Mozi.m", + "threat.indicator.url.original": "http://42.239.233.17:56507/Mozi.m", + "threat.indicator.url.path": "/Mozi.m", + "threat.indicator.url.port": 56507, + "threat.indicator.url.scheme": "http" + }, + { + "abusech.url.blacklists.spamhaus_dbl": "not listed", + "abusech.url.blacklists.surbl": "not listed", + "abusech.url.id": "961541", + "abusech.url.larted": true, + "abusech.url.tags": [ "Mozi", "elf" ], - "threatintel.abuseurl.threat": "malware_download", - "threatintel.abuseurl.url_status": "online", - "threatintel.indicator.first_seen": "2021-01-14T21:07:05.000Z", - "threatintel.indicator.ip": "42.239.233.17", - "threatintel.indicator.provider": "lrz_urlhaus", - "threatintel.indicator.reference": "https://urlhaus.abuse.ch/url/961540/", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "42.239.233.17", - "threatintel.indicator.url.extension": "m", - "threatintel.indicator.url.full": "http://42.239.233.17:56507/Mozi.m", - "threatintel.indicator.url.original": "http://42.239.233.17:56507/Mozi.m", - "threatintel.indicator.url.path": "/Mozi.m", - "threatintel.indicator.url.port": 56507, - "threatintel.indicator.url.scheme": "http" - }, - { + "abusech.url.threat": "malware_download", + "abusech.url.url_status": "online", "event.category": "threat", "event.dataset": "threatintel.abuseurl", "event.kind": "enrichment", @@ -272,30 +296,32 @@ "forwarded", "threatintel-abuseurls" ], - "threatintel.abuseurl.blacklists.spamhaus_dbl": "not listed", - "threatintel.abuseurl.blacklists.surbl": "not listed", - "threatintel.abuseurl.id": "961541", - "threatintel.abuseurl.larted": true, - "threatintel.abuseurl.tags": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] AbuseCH URL", + "threat.indicator.first_seen": "2021-01-14T21:07:05.000Z", + "threat.indicator.ip": "58.252.178.20", + "threat.indicator.provider": "lrz_urlhaus", + "threat.indicator.reference": "https://urlhaus.abuse.ch/url/961541/", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "58.252.178.20", + "threat.indicator.url.extension": "m", + "threat.indicator.url.full": "http://58.252.178.20:57562/Mozi.m", + "threat.indicator.url.original": "http://58.252.178.20:57562/Mozi.m", + "threat.indicator.url.path": "/Mozi.m", + "threat.indicator.url.port": 57562, + "threat.indicator.url.scheme": "http" + }, + { + "abusech.url.blacklists.spamhaus_dbl": "not listed", + "abusech.url.blacklists.surbl": "not listed", + "abusech.url.id": "961542", + "abusech.url.larted": true, + "abusech.url.tags": [ "Mozi", "elf" ], - "threatintel.abuseurl.threat": "malware_download", - "threatintel.abuseurl.url_status": "online", - "threatintel.indicator.first_seen": "2021-01-14T21:07:05.000Z", - "threatintel.indicator.ip": "58.252.178.20", - "threatintel.indicator.provider": "lrz_urlhaus", - "threatintel.indicator.reference": "https://urlhaus.abuse.ch/url/961541/", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "58.252.178.20", - "threatintel.indicator.url.extension": "m", - "threatintel.indicator.url.full": "http://58.252.178.20:57562/Mozi.m", - "threatintel.indicator.url.original": "http://58.252.178.20:57562/Mozi.m", - "threatintel.indicator.url.path": "/Mozi.m", - "threatintel.indicator.url.port": 57562, - "threatintel.indicator.url.scheme": "http" - }, - { + "abusech.url.threat": "malware_download", + "abusech.url.url_status": "online", "event.category": "threat", "event.dataset": "threatintel.abuseurl", "event.kind": "enrichment", @@ -309,30 +335,32 @@ "forwarded", "threatintel-abuseurls" ], - "threatintel.abuseurl.blacklists.spamhaus_dbl": "not listed", - "threatintel.abuseurl.blacklists.surbl": "not listed", - "threatintel.abuseurl.id": "961542", - "threatintel.abuseurl.larted": true, - "threatintel.abuseurl.tags": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] AbuseCH URL", + "threat.indicator.first_seen": "2021-01-14T21:07:05.000Z", + "threat.indicator.ip": "45.176.111.95", + "threat.indicator.provider": "lrz_urlhaus", + "threat.indicator.reference": "https://urlhaus.abuse.ch/url/961542/", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "45.176.111.95", + "threat.indicator.url.extension": "m", + "threat.indicator.url.full": "http://45.176.111.95:48845/Mozi.m", + "threat.indicator.url.original": "http://45.176.111.95:48845/Mozi.m", + "threat.indicator.url.path": "/Mozi.m", + "threat.indicator.url.port": 48845, + "threat.indicator.url.scheme": "http" + }, + { + "abusech.url.blacklists.spamhaus_dbl": "not listed", + "abusech.url.blacklists.surbl": "not listed", + "abusech.url.id": "961539", + "abusech.url.larted": true, + "abusech.url.tags": [ "Mozi", "elf" ], - "threatintel.abuseurl.threat": "malware_download", - "threatintel.abuseurl.url_status": "online", - "threatintel.indicator.first_seen": "2021-01-14T21:07:05.000Z", - "threatintel.indicator.ip": "45.176.111.95", - "threatintel.indicator.provider": "lrz_urlhaus", - "threatintel.indicator.reference": "https://urlhaus.abuse.ch/url/961542/", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "45.176.111.95", - "threatintel.indicator.url.extension": "m", - "threatintel.indicator.url.full": "http://45.176.111.95:48845/Mozi.m", - "threatintel.indicator.url.original": "http://45.176.111.95:48845/Mozi.m", - "threatintel.indicator.url.path": "/Mozi.m", - "threatintel.indicator.url.port": 48845, - "threatintel.indicator.url.scheme": "http" - }, - { + "abusech.url.threat": "malware_download", + "abusech.url.url_status": "online", "event.category": "threat", "event.dataset": "threatintel.abuseurl", "event.kind": "enrichment", @@ -346,30 +374,32 @@ "forwarded", "threatintel-abuseurls" ], - "threatintel.abuseurl.blacklists.spamhaus_dbl": "not listed", - "threatintel.abuseurl.blacklists.surbl": "not listed", - "threatintel.abuseurl.id": "961539", - "threatintel.abuseurl.larted": true, - "threatintel.abuseurl.tags": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] AbuseCH URL", + "threat.indicator.first_seen": "2021-01-14T21:07:04.000Z", + "threat.indicator.ip": "42.224.68.97", + "threat.indicator.provider": "lrz_urlhaus", + "threat.indicator.reference": "https://urlhaus.abuse.ch/url/961539/", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "42.224.68.97", + "threat.indicator.url.extension": "m", + "threat.indicator.url.full": "http://42.224.68.97:58245/Mozi.m", + "threat.indicator.url.original": "http://42.224.68.97:58245/Mozi.m", + "threat.indicator.url.path": "/Mozi.m", + "threat.indicator.url.port": 58245, + "threat.indicator.url.scheme": "http" + }, + { + "abusech.url.blacklists.spamhaus_dbl": "not listed", + "abusech.url.blacklists.surbl": "not listed", + "abusech.url.id": "961538", + "abusech.url.larted": true, + "abusech.url.tags": [ "Mozi", "elf" ], - "threatintel.abuseurl.threat": "malware_download", - "threatintel.abuseurl.url_status": "online", - "threatintel.indicator.first_seen": "2021-01-14T21:07:04.000Z", - "threatintel.indicator.ip": "42.224.68.97", - "threatintel.indicator.provider": "lrz_urlhaus", - "threatintel.indicator.reference": "https://urlhaus.abuse.ch/url/961539/", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "42.224.68.97", - "threatintel.indicator.url.extension": "m", - "threatintel.indicator.url.full": "http://42.224.68.97:58245/Mozi.m", - "threatintel.indicator.url.original": "http://42.224.68.97:58245/Mozi.m", - "threatintel.indicator.url.path": "/Mozi.m", - "threatintel.indicator.url.port": 58245, - "threatintel.indicator.url.scheme": "http" - }, - { + "abusech.url.threat": "malware_download", + "abusech.url.url_status": "online", "event.category": "threat", "event.dataset": "threatintel.abuseurl", "event.kind": "enrichment", @@ -383,30 +413,32 @@ "forwarded", "threatintel-abuseurls" ], - "threatintel.abuseurl.blacklists.spamhaus_dbl": "not listed", - "threatintel.abuseurl.blacklists.surbl": "not listed", - "threatintel.abuseurl.id": "961538", - "threatintel.abuseurl.larted": true, - "threatintel.abuseurl.tags": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] AbuseCH URL", + "threat.indicator.first_seen": "2021-01-14T21:06:08.000Z", + "threat.indicator.ip": "222.81.144.207", + "threat.indicator.provider": "lrz_urlhaus", + "threat.indicator.reference": "https://urlhaus.abuse.ch/url/961538/", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "222.81.144.207", + "threat.indicator.url.extension": "m", + "threat.indicator.url.full": "http://222.81.144.207:37198/Mozi.m", + "threat.indicator.url.original": "http://222.81.144.207:37198/Mozi.m", + "threat.indicator.url.path": "/Mozi.m", + "threat.indicator.url.port": 37198, + "threat.indicator.url.scheme": "http" + }, + { + "abusech.url.blacklists.spamhaus_dbl": "not listed", + "abusech.url.blacklists.surbl": "not listed", + "abusech.url.id": "961537", + "abusech.url.larted": true, + "abusech.url.tags": [ "Mozi", "elf" ], - "threatintel.abuseurl.threat": "malware_download", - "threatintel.abuseurl.url_status": "online", - "threatintel.indicator.first_seen": "2021-01-14T21:06:08.000Z", - "threatintel.indicator.ip": "222.81.144.207", - "threatintel.indicator.provider": "lrz_urlhaus", - "threatintel.indicator.reference": "https://urlhaus.abuse.ch/url/961538/", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "222.81.144.207", - "threatintel.indicator.url.extension": "m", - "threatintel.indicator.url.full": "http://222.81.144.207:37198/Mozi.m", - "threatintel.indicator.url.original": "http://222.81.144.207:37198/Mozi.m", - "threatintel.indicator.url.path": "/Mozi.m", - "threatintel.indicator.url.port": 37198, - "threatintel.indicator.url.scheme": "http" - }, - { + "abusech.url.threat": "malware_download", + "abusech.url.url_status": "online", "event.category": "threat", "event.dataset": "threatintel.abuseurl", "event.kind": "enrichment", @@ -420,30 +452,32 @@ "forwarded", "threatintel-abuseurls" ], - "threatintel.abuseurl.blacklists.spamhaus_dbl": "not listed", - "threatintel.abuseurl.blacklists.surbl": "not listed", - "threatintel.abuseurl.id": "961537", - "threatintel.abuseurl.larted": true, - "threatintel.abuseurl.tags": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] AbuseCH URL", + "threat.indicator.first_seen": "2021-01-14T21:06:06.000Z", + "threat.indicator.ip": "182.127.185.137", + "threat.indicator.provider": "lrz_urlhaus", + "threat.indicator.reference": "https://urlhaus.abuse.ch/url/961537/", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "182.127.185.137", + "threat.indicator.url.extension": "m", + "threat.indicator.url.full": "http://182.127.185.137:33524/Mozi.m", + "threat.indicator.url.original": "http://182.127.185.137:33524/Mozi.m", + "threat.indicator.url.path": "/Mozi.m", + "threat.indicator.url.port": 33524, + "threat.indicator.url.scheme": "http" + }, + { + "abusech.url.blacklists.spamhaus_dbl": "not listed", + "abusech.url.blacklists.surbl": "not listed", + "abusech.url.id": "961531", + "abusech.url.larted": true, + "abusech.url.tags": [ "Mozi", "elf" ], - "threatintel.abuseurl.threat": "malware_download", - "threatintel.abuseurl.url_status": "online", - "threatintel.indicator.first_seen": "2021-01-14T21:06:06.000Z", - "threatintel.indicator.ip": "182.127.185.137", - "threatintel.indicator.provider": "lrz_urlhaus", - "threatintel.indicator.reference": "https://urlhaus.abuse.ch/url/961537/", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "182.127.185.137", - "threatintel.indicator.url.extension": "m", - "threatintel.indicator.url.full": "http://182.127.185.137:33524/Mozi.m", - "threatintel.indicator.url.original": "http://182.127.185.137:33524/Mozi.m", - "threatintel.indicator.url.path": "/Mozi.m", - "threatintel.indicator.url.port": 33524, - "threatintel.indicator.url.scheme": "http" - }, - { + "abusech.url.threat": "malware_download", + "abusech.url.url_status": "online", "event.category": "threat", "event.dataset": "threatintel.abuseurl", "event.kind": "enrichment", @@ -457,30 +491,32 @@ "forwarded", "threatintel-abuseurls" ], - "threatintel.abuseurl.blacklists.spamhaus_dbl": "not listed", - "threatintel.abuseurl.blacklists.surbl": "not listed", - "threatintel.abuseurl.id": "961531", - "threatintel.abuseurl.larted": true, - "threatintel.abuseurl.tags": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] AbuseCH URL", + "threat.indicator.first_seen": "2021-01-14T21:06:05.000Z", + "threat.indicator.ip": "39.84.175.185", + "threat.indicator.provider": "lrz_urlhaus", + "threat.indicator.reference": "https://urlhaus.abuse.ch/url/961531/", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "39.84.175.185", + "threat.indicator.url.extension": "a", + "threat.indicator.url.full": "http://39.84.175.185:48261/Mozi.a", + "threat.indicator.url.original": "http://39.84.175.185:48261/Mozi.a", + "threat.indicator.url.path": "/Mozi.a", + "threat.indicator.url.port": 48261, + "threat.indicator.url.scheme": "http" + }, + { + "abusech.url.blacklists.spamhaus_dbl": "not listed", + "abusech.url.blacklists.surbl": "not listed", + "abusech.url.id": "961532", + "abusech.url.larted": true, + "abusech.url.tags": [ "Mozi", "elf" ], - "threatintel.abuseurl.threat": "malware_download", - "threatintel.abuseurl.url_status": "online", - "threatintel.indicator.first_seen": "2021-01-14T21:06:05.000Z", - "threatintel.indicator.ip": "39.84.175.185", - "threatintel.indicator.provider": "lrz_urlhaus", - "threatintel.indicator.reference": "https://urlhaus.abuse.ch/url/961531/", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "39.84.175.185", - "threatintel.indicator.url.extension": "a", - "threatintel.indicator.url.full": "http://39.84.175.185:48261/Mozi.a", - "threatintel.indicator.url.original": "http://39.84.175.185:48261/Mozi.a", - "threatintel.indicator.url.path": "/Mozi.a", - "threatintel.indicator.url.port": 48261, - "threatintel.indicator.url.scheme": "http" - }, - { + "abusech.url.threat": "malware_download", + "abusech.url.url_status": "online", "event.category": "threat", "event.dataset": "threatintel.abuseurl", "event.kind": "enrichment", @@ -494,30 +530,32 @@ "forwarded", "threatintel-abuseurls" ], - "threatintel.abuseurl.blacklists.spamhaus_dbl": "not listed", - "threatintel.abuseurl.blacklists.surbl": "not listed", - "threatintel.abuseurl.id": "961532", - "threatintel.abuseurl.larted": true, - "threatintel.abuseurl.tags": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] AbuseCH URL", + "threat.indicator.first_seen": "2021-01-14T21:06:05.000Z", + "threat.indicator.ip": "27.41.11.238", + "threat.indicator.provider": "lrz_urlhaus", + "threat.indicator.reference": "https://urlhaus.abuse.ch/url/961532/", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "27.41.11.238", + "threat.indicator.url.extension": "m", + "threat.indicator.url.full": "http://27.41.11.238:34478/Mozi.m", + "threat.indicator.url.original": "http://27.41.11.238:34478/Mozi.m", + "threat.indicator.url.path": "/Mozi.m", + "threat.indicator.url.port": 34478, + "threat.indicator.url.scheme": "http" + }, + { + "abusech.url.blacklists.spamhaus_dbl": "not listed", + "abusech.url.blacklists.surbl": "not listed", + "abusech.url.id": "961533", + "abusech.url.larted": true, + "abusech.url.tags": [ "Mozi", "elf" ], - "threatintel.abuseurl.threat": "malware_download", - "threatintel.abuseurl.url_status": "online", - "threatintel.indicator.first_seen": "2021-01-14T21:06:05.000Z", - "threatintel.indicator.ip": "27.41.11.238", - "threatintel.indicator.provider": "lrz_urlhaus", - "threatintel.indicator.reference": "https://urlhaus.abuse.ch/url/961532/", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "27.41.11.238", - "threatintel.indicator.url.extension": "m", - "threatintel.indicator.url.full": "http://27.41.11.238:34478/Mozi.m", - "threatintel.indicator.url.original": "http://27.41.11.238:34478/Mozi.m", - "threatintel.indicator.url.path": "/Mozi.m", - "threatintel.indicator.url.port": 34478, - "threatintel.indicator.url.scheme": "http" - }, - { + "abusech.url.threat": "malware_download", + "abusech.url.url_status": "online", "event.category": "threat", "event.dataset": "threatintel.abuseurl", "event.kind": "enrichment", @@ -531,30 +569,32 @@ "forwarded", "threatintel-abuseurls" ], - "threatintel.abuseurl.blacklists.spamhaus_dbl": "not listed", - "threatintel.abuseurl.blacklists.surbl": "not listed", - "threatintel.abuseurl.id": "961533", - "threatintel.abuseurl.larted": true, - "threatintel.abuseurl.tags": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] AbuseCH URL", + "threat.indicator.first_seen": "2021-01-14T21:06:05.000Z", + "threat.indicator.ip": "182.127.133.68", + "threat.indicator.provider": "lrz_urlhaus", + "threat.indicator.reference": "https://urlhaus.abuse.ch/url/961533/", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "182.127.133.68", + "threat.indicator.url.extension": "a", + "threat.indicator.url.full": "http://182.127.133.68:35703/Mozi.a", + "threat.indicator.url.original": "http://182.127.133.68:35703/Mozi.a", + "threat.indicator.url.path": "/Mozi.a", + "threat.indicator.url.port": 35703, + "threat.indicator.url.scheme": "http" + }, + { + "abusech.url.blacklists.spamhaus_dbl": "not listed", + "abusech.url.blacklists.surbl": "not listed", + "abusech.url.id": "961534", + "abusech.url.larted": true, + "abusech.url.tags": [ "Mozi", "elf" ], - "threatintel.abuseurl.threat": "malware_download", - "threatintel.abuseurl.url_status": "online", - "threatintel.indicator.first_seen": "2021-01-14T21:06:05.000Z", - "threatintel.indicator.ip": "182.127.133.68", - "threatintel.indicator.provider": "lrz_urlhaus", - "threatintel.indicator.reference": "https://urlhaus.abuse.ch/url/961533/", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "182.127.133.68", - "threatintel.indicator.url.extension": "a", - "threatintel.indicator.url.full": "http://182.127.133.68:35703/Mozi.a", - "threatintel.indicator.url.original": "http://182.127.133.68:35703/Mozi.a", - "threatintel.indicator.url.path": "/Mozi.a", - "threatintel.indicator.url.port": 35703, - "threatintel.indicator.url.scheme": "http" - }, - { + "abusech.url.threat": "malware_download", + "abusech.url.url_status": "online", "event.category": "threat", "event.dataset": "threatintel.abuseurl", "event.kind": "enrichment", @@ -568,30 +608,32 @@ "forwarded", "threatintel-abuseurls" ], - "threatintel.abuseurl.blacklists.spamhaus_dbl": "not listed", - "threatintel.abuseurl.blacklists.surbl": "not listed", - "threatintel.abuseurl.id": "961534", - "threatintel.abuseurl.larted": true, - "threatintel.abuseurl.tags": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] AbuseCH URL", + "threat.indicator.first_seen": "2021-01-14T21:06:05.000Z", + "threat.indicator.ip": "27.46.44.102", + "threat.indicator.provider": "lrz_urlhaus", + "threat.indicator.reference": "https://urlhaus.abuse.ch/url/961534/", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "27.46.44.102", + "threat.indicator.url.extension": "m", + "threat.indicator.url.full": "http://27.46.44.102:48666/Mozi.m", + "threat.indicator.url.original": "http://27.46.44.102:48666/Mozi.m", + "threat.indicator.url.path": "/Mozi.m", + "threat.indicator.url.port": 48666, + "threat.indicator.url.scheme": "http" + }, + { + "abusech.url.blacklists.spamhaus_dbl": "not listed", + "abusech.url.blacklists.surbl": "not listed", + "abusech.url.id": "961535", + "abusech.url.larted": true, + "abusech.url.tags": [ "Mozi", "elf" ], - "threatintel.abuseurl.threat": "malware_download", - "threatintel.abuseurl.url_status": "online", - "threatintel.indicator.first_seen": "2021-01-14T21:06:05.000Z", - "threatintel.indicator.ip": "27.46.44.102", - "threatintel.indicator.provider": "lrz_urlhaus", - "threatintel.indicator.reference": "https://urlhaus.abuse.ch/url/961534/", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "27.46.44.102", - "threatintel.indicator.url.extension": "m", - "threatintel.indicator.url.full": "http://27.46.44.102:48666/Mozi.m", - "threatintel.indicator.url.original": "http://27.46.44.102:48666/Mozi.m", - "threatintel.indicator.url.path": "/Mozi.m", - "threatintel.indicator.url.port": 48666, - "threatintel.indicator.url.scheme": "http" - }, - { + "abusech.url.threat": "malware_download", + "abusech.url.url_status": "online", "event.category": "threat", "event.dataset": "threatintel.abuseurl", "event.kind": "enrichment", @@ -605,30 +647,32 @@ "forwarded", "threatintel-abuseurls" ], - "threatintel.abuseurl.blacklists.spamhaus_dbl": "not listed", - "threatintel.abuseurl.blacklists.surbl": "not listed", - "threatintel.abuseurl.id": "961535", - "threatintel.abuseurl.larted": true, - "threatintel.abuseurl.tags": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] AbuseCH URL", + "threat.indicator.first_seen": "2021-01-14T21:06:05.000Z", + "threat.indicator.ip": "39.70.88.65", + "threat.indicator.provider": "lrz_urlhaus", + "threat.indicator.reference": "https://urlhaus.abuse.ch/url/961535/", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "39.70.88.65", + "threat.indicator.url.extension": "m", + "threat.indicator.url.full": "http://39.70.88.65:53923/Mozi.m", + "threat.indicator.url.original": "http://39.70.88.65:53923/Mozi.m", + "threat.indicator.url.path": "/Mozi.m", + "threat.indicator.url.port": 53923, + "threat.indicator.url.scheme": "http" + }, + { + "abusech.url.blacklists.spamhaus_dbl": "not listed", + "abusech.url.blacklists.surbl": "not listed", + "abusech.url.id": "961536", + "abusech.url.larted": true, + "abusech.url.tags": [ "Mozi", "elf" ], - "threatintel.abuseurl.threat": "malware_download", - "threatintel.abuseurl.url_status": "online", - "threatintel.indicator.first_seen": "2021-01-14T21:06:05.000Z", - "threatintel.indicator.ip": "39.70.88.65", - "threatintel.indicator.provider": "lrz_urlhaus", - "threatintel.indicator.reference": "https://urlhaus.abuse.ch/url/961535/", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "39.70.88.65", - "threatintel.indicator.url.extension": "m", - "threatintel.indicator.url.full": "http://39.70.88.65:53923/Mozi.m", - "threatintel.indicator.url.original": "http://39.70.88.65:53923/Mozi.m", - "threatintel.indicator.url.path": "/Mozi.m", - "threatintel.indicator.url.port": 53923, - "threatintel.indicator.url.scheme": "http" - }, - { + "abusech.url.threat": "malware_download", + "abusech.url.url_status": "online", "event.category": "threat", "event.dataset": "threatintel.abuseurl", "event.kind": "enrichment", @@ -642,30 +686,32 @@ "forwarded", "threatintel-abuseurls" ], - "threatintel.abuseurl.blacklists.spamhaus_dbl": "not listed", - "threatintel.abuseurl.blacklists.surbl": "not listed", - "threatintel.abuseurl.id": "961536", - "threatintel.abuseurl.larted": true, - "threatintel.abuseurl.tags": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] AbuseCH URL", + "threat.indicator.first_seen": "2021-01-14T21:06:05.000Z", + "threat.indicator.ip": "42.224.136.237", + "threat.indicator.provider": "lrz_urlhaus", + "threat.indicator.reference": "https://urlhaus.abuse.ch/url/961536/", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "42.224.136.237", + "threat.indicator.url.extension": "m", + "threat.indicator.url.full": "http://42.224.136.237:52794/Mozi.m", + "threat.indicator.url.original": "http://42.224.136.237:52794/Mozi.m", + "threat.indicator.url.path": "/Mozi.m", + "threat.indicator.url.port": 52794, + "threat.indicator.url.scheme": "http" + }, + { + "abusech.url.blacklists.spamhaus_dbl": "not listed", + "abusech.url.blacklists.surbl": "not listed", + "abusech.url.id": "961530", + "abusech.url.larted": false, + "abusech.url.tags": [ "Mozi", "elf" ], - "threatintel.abuseurl.threat": "malware_download", - "threatintel.abuseurl.url_status": "online", - "threatintel.indicator.first_seen": "2021-01-14T21:06:05.000Z", - "threatintel.indicator.ip": "42.224.136.237", - "threatintel.indicator.provider": "lrz_urlhaus", - "threatintel.indicator.reference": "https://urlhaus.abuse.ch/url/961536/", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "42.224.136.237", - "threatintel.indicator.url.extension": "m", - "threatintel.indicator.url.full": "http://42.224.136.237:52794/Mozi.m", - "threatintel.indicator.url.original": "http://42.224.136.237:52794/Mozi.m", - "threatintel.indicator.url.path": "/Mozi.m", - "threatintel.indicator.url.port": 52794, - "threatintel.indicator.url.scheme": "http" - }, - { + "abusech.url.threat": "malware_download", + "abusech.url.url_status": "offline", "event.category": "threat", "event.dataset": "threatintel.abuseurl", "event.kind": "enrichment", @@ -679,30 +725,32 @@ "forwarded", "threatintel-abuseurls" ], - "threatintel.abuseurl.blacklists.spamhaus_dbl": "not listed", - "threatintel.abuseurl.blacklists.surbl": "not listed", - "threatintel.abuseurl.id": "961530", - "threatintel.abuseurl.larted": false, - "threatintel.abuseurl.tags": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] AbuseCH URL", + "threat.indicator.first_seen": "2021-01-14T21:05:34.000Z", + "threat.indicator.ip": "117.208.135.63", + "threat.indicator.provider": "lrz_urlhaus", + "threat.indicator.reference": "https://urlhaus.abuse.ch/url/961530/", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "117.208.135.63", + "threat.indicator.url.extension": "a", + "threat.indicator.url.full": "http://117.208.135.63:49312/Mozi.a", + "threat.indicator.url.original": "http://117.208.135.63:49312/Mozi.a", + "threat.indicator.url.path": "/Mozi.a", + "threat.indicator.url.port": 49312, + "threat.indicator.url.scheme": "http" + }, + { + "abusech.url.blacklists.spamhaus_dbl": "not listed", + "abusech.url.blacklists.surbl": "not listed", + "abusech.url.id": "961525", + "abusech.url.larted": true, + "abusech.url.tags": [ "Mozi", "elf" ], - "threatintel.abuseurl.threat": "malware_download", - "threatintel.abuseurl.url_status": "offline", - "threatintel.indicator.first_seen": "2021-01-14T21:05:34.000Z", - "threatintel.indicator.ip": "117.208.135.63", - "threatintel.indicator.provider": "lrz_urlhaus", - "threatintel.indicator.reference": "https://urlhaus.abuse.ch/url/961530/", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "117.208.135.63", - "threatintel.indicator.url.extension": "a", - "threatintel.indicator.url.full": "http://117.208.135.63:49312/Mozi.a", - "threatintel.indicator.url.original": "http://117.208.135.63:49312/Mozi.a", - "threatintel.indicator.url.path": "/Mozi.a", - "threatintel.indicator.url.port": 49312, - "threatintel.indicator.url.scheme": "http" - }, - { + "abusech.url.threat": "malware_download", + "abusech.url.url_status": "online", "event.category": "threat", "event.dataset": "threatintel.abuseurl", "event.kind": "enrichment", @@ -716,30 +764,32 @@ "forwarded", "threatintel-abuseurls" ], - "threatintel.abuseurl.blacklists.spamhaus_dbl": "not listed", - "threatintel.abuseurl.blacklists.surbl": "not listed", - "threatintel.abuseurl.id": "961525", - "threatintel.abuseurl.larted": true, - "threatintel.abuseurl.tags": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] AbuseCH URL", + "threat.indicator.first_seen": "2021-01-14T21:05:06.000Z", + "threat.indicator.ip": "125.47.66.60", + "threat.indicator.provider": "lrz_urlhaus", + "threat.indicator.reference": "https://urlhaus.abuse.ch/url/961525/", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "125.47.66.60", + "threat.indicator.url.extension": "m", + "threat.indicator.url.full": "http://125.47.66.60:38961/Mozi.m", + "threat.indicator.url.original": "http://125.47.66.60:38961/Mozi.m", + "threat.indicator.url.path": "/Mozi.m", + "threat.indicator.url.port": 38961, + "threat.indicator.url.scheme": "http" + }, + { + "abusech.url.blacklists.spamhaus_dbl": "not listed", + "abusech.url.blacklists.surbl": "not listed", + "abusech.url.id": "961526", + "abusech.url.larted": true, + "abusech.url.tags": [ "Mozi", "elf" ], - "threatintel.abuseurl.threat": "malware_download", - "threatintel.abuseurl.url_status": "online", - "threatintel.indicator.first_seen": "2021-01-14T21:05:06.000Z", - "threatintel.indicator.ip": "125.47.66.60", - "threatintel.indicator.provider": "lrz_urlhaus", - "threatintel.indicator.reference": "https://urlhaus.abuse.ch/url/961525/", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "125.47.66.60", - "threatintel.indicator.url.extension": "m", - "threatintel.indicator.url.full": "http://125.47.66.60:38961/Mozi.m", - "threatintel.indicator.url.original": "http://125.47.66.60:38961/Mozi.m", - "threatintel.indicator.url.path": "/Mozi.m", - "threatintel.indicator.url.port": 38961, - "threatintel.indicator.url.scheme": "http" - }, - { + "abusech.url.threat": "malware_download", + "abusech.url.url_status": "online", "event.category": "threat", "event.dataset": "threatintel.abuseurl", "event.kind": "enrichment", @@ -753,30 +803,32 @@ "forwarded", "threatintel-abuseurls" ], - "threatintel.abuseurl.blacklists.spamhaus_dbl": "not listed", - "threatintel.abuseurl.blacklists.surbl": "not listed", - "threatintel.abuseurl.id": "961526", - "threatintel.abuseurl.larted": true, - "threatintel.abuseurl.tags": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] AbuseCH URL", + "threat.indicator.first_seen": "2021-01-14T21:05:06.000Z", + "threat.indicator.ip": "182.117.95.148", + "threat.indicator.provider": "lrz_urlhaus", + "threat.indicator.reference": "https://urlhaus.abuse.ch/url/961526/", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "182.117.95.148", + "threat.indicator.url.extension": "a", + "threat.indicator.url.full": "http://182.117.95.148:50420/Mozi.a", + "threat.indicator.url.original": "http://182.117.95.148:50420/Mozi.a", + "threat.indicator.url.path": "/Mozi.a", + "threat.indicator.url.port": 50420, + "threat.indicator.url.scheme": "http" + }, + { + "abusech.url.blacklists.spamhaus_dbl": "not listed", + "abusech.url.blacklists.surbl": "not listed", + "abusech.url.id": "961527", + "abusech.url.larted": true, + "abusech.url.tags": [ "Mozi", "elf" ], - "threatintel.abuseurl.threat": "malware_download", - "threatintel.abuseurl.url_status": "online", - "threatintel.indicator.first_seen": "2021-01-14T21:05:06.000Z", - "threatintel.indicator.ip": "182.117.95.148", - "threatintel.indicator.provider": "lrz_urlhaus", - "threatintel.indicator.reference": "https://urlhaus.abuse.ch/url/961526/", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "182.117.95.148", - "threatintel.indicator.url.extension": "a", - "threatintel.indicator.url.full": "http://182.117.95.148:50420/Mozi.a", - "threatintel.indicator.url.original": "http://182.117.95.148:50420/Mozi.a", - "threatintel.indicator.url.path": "/Mozi.a", - "threatintel.indicator.url.port": 50420, - "threatintel.indicator.url.scheme": "http" - }, - { + "abusech.url.threat": "malware_download", + "abusech.url.url_status": "online", "event.category": "threat", "event.dataset": "threatintel.abuseurl", "event.kind": "enrichment", @@ -790,30 +842,32 @@ "forwarded", "threatintel-abuseurls" ], - "threatintel.abuseurl.blacklists.spamhaus_dbl": "not listed", - "threatintel.abuseurl.blacklists.surbl": "not listed", - "threatintel.abuseurl.id": "961527", - "threatintel.abuseurl.larted": true, - "threatintel.abuseurl.tags": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] AbuseCH URL", + "threat.indicator.first_seen": "2021-01-14T21:05:06.000Z", + "threat.indicator.ip": "117.202.71.48", + "threat.indicator.provider": "lrz_urlhaus", + "threat.indicator.reference": "https://urlhaus.abuse.ch/url/961527/", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "117.202.71.48", + "threat.indicator.url.extension": "m", + "threat.indicator.url.full": "http://117.202.71.48:55007/Mozi.m", + "threat.indicator.url.original": "http://117.202.71.48:55007/Mozi.m", + "threat.indicator.url.path": "/Mozi.m", + "threat.indicator.url.port": 55007, + "threat.indicator.url.scheme": "http" + }, + { + "abusech.url.blacklists.spamhaus_dbl": "not listed", + "abusech.url.blacklists.surbl": "not listed", + "abusech.url.id": "961528", + "abusech.url.larted": true, + "abusech.url.tags": [ "Mozi", "elf" ], - "threatintel.abuseurl.threat": "malware_download", - "threatintel.abuseurl.url_status": "online", - "threatintel.indicator.first_seen": "2021-01-14T21:05:06.000Z", - "threatintel.indicator.ip": "117.202.71.48", - "threatintel.indicator.provider": "lrz_urlhaus", - "threatintel.indicator.reference": "https://urlhaus.abuse.ch/url/961527/", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "117.202.71.48", - "threatintel.indicator.url.extension": "m", - "threatintel.indicator.url.full": "http://117.202.71.48:55007/Mozi.m", - "threatintel.indicator.url.original": "http://117.202.71.48:55007/Mozi.m", - "threatintel.indicator.url.path": "/Mozi.m", - "threatintel.indicator.url.port": 55007, - "threatintel.indicator.url.scheme": "http" - }, - { + "abusech.url.threat": "malware_download", + "abusech.url.url_status": "online", "event.category": "threat", "event.dataset": "threatintel.abuseurl", "event.kind": "enrichment", @@ -827,30 +881,32 @@ "forwarded", "threatintel-abuseurls" ], - "threatintel.abuseurl.blacklists.spamhaus_dbl": "not listed", - "threatintel.abuseurl.blacklists.surbl": "not listed", - "threatintel.abuseurl.id": "961528", - "threatintel.abuseurl.larted": true, - "threatintel.abuseurl.tags": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] AbuseCH URL", + "threat.indicator.first_seen": "2021-01-14T21:05:06.000Z", + "threat.indicator.ip": "125.99.132.118", + "threat.indicator.provider": "lrz_urlhaus", + "threat.indicator.reference": "https://urlhaus.abuse.ch/url/961528/", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "125.99.132.118", + "threat.indicator.url.extension": "m", + "threat.indicator.url.full": "http://125.99.132.118:51143/Mozi.m", + "threat.indicator.url.original": "http://125.99.132.118:51143/Mozi.m", + "threat.indicator.url.path": "/Mozi.m", + "threat.indicator.url.port": 51143, + "threat.indicator.url.scheme": "http" + }, + { + "abusech.url.blacklists.spamhaus_dbl": "not listed", + "abusech.url.blacklists.surbl": "not listed", + "abusech.url.id": "961529", + "abusech.url.larted": true, + "abusech.url.tags": [ "Mozi", "elf" ], - "threatintel.abuseurl.threat": "malware_download", - "threatintel.abuseurl.url_status": "online", - "threatintel.indicator.first_seen": "2021-01-14T21:05:06.000Z", - "threatintel.indicator.ip": "125.99.132.118", - "threatintel.indicator.provider": "lrz_urlhaus", - "threatintel.indicator.reference": "https://urlhaus.abuse.ch/url/961528/", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "125.99.132.118", - "threatintel.indicator.url.extension": "m", - "threatintel.indicator.url.full": "http://125.99.132.118:51143/Mozi.m", - "threatintel.indicator.url.original": "http://125.99.132.118:51143/Mozi.m", - "threatintel.indicator.url.path": "/Mozi.m", - "threatintel.indicator.url.port": 51143, - "threatintel.indicator.url.scheme": "http" - }, - { + "abusech.url.threat": "malware_download", + "abusech.url.url_status": "online", "event.category": "threat", "event.dataset": "threatintel.abuseurl", "event.kind": "enrichment", @@ -864,30 +920,31 @@ "forwarded", "threatintel-abuseurls" ], - "threatintel.abuseurl.blacklists.spamhaus_dbl": "not listed", - "threatintel.abuseurl.blacklists.surbl": "not listed", - "threatintel.abuseurl.id": "961529", - "threatintel.abuseurl.larted": true, - "threatintel.abuseurl.tags": [ - "Mozi", - "elf" - ], - "threatintel.abuseurl.threat": "malware_download", - "threatintel.abuseurl.url_status": "online", - "threatintel.indicator.first_seen": "2021-01-14T21:05:06.000Z", - "threatintel.indicator.ip": "182.114.123.69", - "threatintel.indicator.provider": "lrz_urlhaus", - "threatintel.indicator.reference": "https://urlhaus.abuse.ch/url/961529/", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "182.114.123.69", - "threatintel.indicator.url.extension": "m", - "threatintel.indicator.url.full": "http://182.114.123.69:41003/Mozi.m", - "threatintel.indicator.url.original": "http://182.114.123.69:41003/Mozi.m", - "threatintel.indicator.url.path": "/Mozi.m", - "threatintel.indicator.url.port": 41003, - "threatintel.indicator.url.scheme": "http" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] AbuseCH URL", + "threat.indicator.first_seen": "2021-01-14T21:05:06.000Z", + "threat.indicator.ip": "182.114.123.69", + "threat.indicator.provider": "lrz_urlhaus", + "threat.indicator.reference": "https://urlhaus.abuse.ch/url/961529/", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "182.114.123.69", + "threat.indicator.url.extension": "m", + "threat.indicator.url.full": "http://182.114.123.69:41003/Mozi.m", + "threat.indicator.url.original": "http://182.114.123.69:41003/Mozi.m", + "threat.indicator.url.path": "/Mozi.m", + "threat.indicator.url.port": 41003, + "threat.indicator.url.scheme": "http" }, { + "abusech.url.blacklists.spamhaus_dbl": "not listed", + "abusech.url.blacklists.surbl": "not listed", + "abusech.url.id": "961524", + "abusech.url.larted": false, + "abusech.url.tags": [ + "Mozi" + ], + "abusech.url.threat": "malware_download", + "abusech.url.url_status": "offline", "event.category": "threat", "event.dataset": "threatintel.abuseurl", "event.kind": "enrichment", @@ -901,29 +958,31 @@ "forwarded", "threatintel-abuseurls" ], - "threatintel.abuseurl.blacklists.spamhaus_dbl": "not listed", - "threatintel.abuseurl.blacklists.surbl": "not listed", - "threatintel.abuseurl.id": "961524", - "threatintel.abuseurl.larted": false, - "threatintel.abuseurl.tags": [ - "Mozi" - ], - "threatintel.abuseurl.threat": "malware_download", - "threatintel.abuseurl.url_status": "offline", - "threatintel.indicator.first_seen": "2021-01-14T21:04:38.000Z", - "threatintel.indicator.ip": "116.19.127.37", - "threatintel.indicator.provider": "Gandylyan1", - "threatintel.indicator.reference": "https://urlhaus.abuse.ch/url/961524/", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "116.19.127.37", - "threatintel.indicator.url.extension": "m", - "threatintel.indicator.url.full": "http://116.19.127.37:35739/Mozi.m", - "threatintel.indicator.url.original": "http://116.19.127.37:35739/Mozi.m", - "threatintel.indicator.url.path": "/Mozi.m", - "threatintel.indicator.url.port": 35739, - "threatintel.indicator.url.scheme": "http" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] AbuseCH URL", + "threat.indicator.first_seen": "2021-01-14T21:04:38.000Z", + "threat.indicator.ip": "116.19.127.37", + "threat.indicator.provider": "Gandylyan1", + "threat.indicator.reference": "https://urlhaus.abuse.ch/url/961524/", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "116.19.127.37", + "threat.indicator.url.extension": "m", + "threat.indicator.url.full": "http://116.19.127.37:35739/Mozi.m", + "threat.indicator.url.original": "http://116.19.127.37:35739/Mozi.m", + "threat.indicator.url.path": "/Mozi.m", + "threat.indicator.url.port": 35739, + "threat.indicator.url.scheme": "http" }, { + "abusech.url.blacklists.spamhaus_dbl": "not listed", + "abusech.url.blacklists.surbl": "not listed", + "abusech.url.id": "961523", + "abusech.url.larted": false, + "abusech.url.tags": [ + "Mozi" + ], + "abusech.url.threat": "malware_download", + "abusech.url.url_status": "offline", "event.category": "threat", "event.dataset": "threatintel.abuseurl", "event.kind": "enrichment", @@ -937,29 +996,31 @@ "forwarded", "threatintel-abuseurls" ], - "threatintel.abuseurl.blacklists.spamhaus_dbl": "not listed", - "threatintel.abuseurl.blacklists.surbl": "not listed", - "threatintel.abuseurl.id": "961523", - "threatintel.abuseurl.larted": false, - "threatintel.abuseurl.tags": [ - "Mozi" - ], - "threatintel.abuseurl.threat": "malware_download", - "threatintel.abuseurl.url_status": "offline", - "threatintel.indicator.first_seen": "2021-01-14T21:04:36.000Z", - "threatintel.indicator.ip": "42.239.253.55", - "threatintel.indicator.provider": "Gandylyan1", - "threatintel.indicator.reference": "https://urlhaus.abuse.ch/url/961523/", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "42.239.253.55", - "threatintel.indicator.url.extension": "m", - "threatintel.indicator.url.full": "http://42.239.253.55:45653/Mozi.m", - "threatintel.indicator.url.original": "http://42.239.253.55:45653/Mozi.m", - "threatintel.indicator.url.path": "/Mozi.m", - "threatintel.indicator.url.port": 45653, - "threatintel.indicator.url.scheme": "http" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] AbuseCH URL", + "threat.indicator.first_seen": "2021-01-14T21:04:36.000Z", + "threat.indicator.ip": "42.239.253.55", + "threat.indicator.provider": "Gandylyan1", + "threat.indicator.reference": "https://urlhaus.abuse.ch/url/961523/", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "42.239.253.55", + "threat.indicator.url.extension": "m", + "threat.indicator.url.full": "http://42.239.253.55:45653/Mozi.m", + "threat.indicator.url.original": "http://42.239.253.55:45653/Mozi.m", + "threat.indicator.url.path": "/Mozi.m", + "threat.indicator.url.port": 45653, + "threat.indicator.url.scheme": "http" }, { + "abusech.url.blacklists.spamhaus_dbl": "not listed", + "abusech.url.blacklists.surbl": "not listed", + "abusech.url.id": "961520", + "abusech.url.larted": false, + "abusech.url.tags": [ + "Mozi" + ], + "abusech.url.threat": "malware_download", + "abusech.url.url_status": "offline", "event.category": "threat", "event.dataset": "threatintel.abuseurl", "event.kind": "enrichment", @@ -973,29 +1034,31 @@ "forwarded", "threatintel-abuseurls" ], - "threatintel.abuseurl.blacklists.spamhaus_dbl": "not listed", - "threatintel.abuseurl.blacklists.surbl": "not listed", - "threatintel.abuseurl.id": "961520", - "threatintel.abuseurl.larted": false, - "threatintel.abuseurl.tags": [ - "Mozi" - ], - "threatintel.abuseurl.threat": "malware_download", - "threatintel.abuseurl.url_status": "offline", - "threatintel.indicator.first_seen": "2021-01-14T21:04:33.000Z", - "threatintel.indicator.ip": "103.217.121.228", - "threatintel.indicator.provider": "Gandylyan1", - "threatintel.indicator.reference": "https://urlhaus.abuse.ch/url/961520/", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "103.217.121.228", - "threatintel.indicator.url.extension": "m", - "threatintel.indicator.url.full": "http://103.217.121.228:41349/Mozi.m", - "threatintel.indicator.url.original": "http://103.217.121.228:41349/Mozi.m", - "threatintel.indicator.url.path": "/Mozi.m", - "threatintel.indicator.url.port": 41349, - "threatintel.indicator.url.scheme": "http" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] AbuseCH URL", + "threat.indicator.first_seen": "2021-01-14T21:04:33.000Z", + "threat.indicator.ip": "103.217.121.228", + "threat.indicator.provider": "Gandylyan1", + "threat.indicator.reference": "https://urlhaus.abuse.ch/url/961520/", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "103.217.121.228", + "threat.indicator.url.extension": "m", + "threat.indicator.url.full": "http://103.217.121.228:41349/Mozi.m", + "threat.indicator.url.original": "http://103.217.121.228:41349/Mozi.m", + "threat.indicator.url.path": "/Mozi.m", + "threat.indicator.url.port": 41349, + "threat.indicator.url.scheme": "http" }, { + "abusech.url.blacklists.spamhaus_dbl": "not listed", + "abusech.url.blacklists.surbl": "not listed", + "abusech.url.id": "961521", + "abusech.url.larted": false, + "abusech.url.tags": [ + "Mozi" + ], + "abusech.url.threat": "malware_download", + "abusech.url.url_status": "offline", "event.category": "threat", "event.dataset": "threatintel.abuseurl", "event.kind": "enrichment", @@ -1009,29 +1072,31 @@ "forwarded", "threatintel-abuseurls" ], - "threatintel.abuseurl.blacklists.spamhaus_dbl": "not listed", - "threatintel.abuseurl.blacklists.surbl": "not listed", - "threatintel.abuseurl.id": "961521", - "threatintel.abuseurl.larted": false, - "threatintel.abuseurl.tags": [ - "Mozi" - ], - "threatintel.abuseurl.threat": "malware_download", - "threatintel.abuseurl.url_status": "offline", - "threatintel.indicator.first_seen": "2021-01-14T21:04:33.000Z", - "threatintel.indicator.ip": "111.92.81.255", - "threatintel.indicator.provider": "Gandylyan1", - "threatintel.indicator.reference": "https://urlhaus.abuse.ch/url/961521/", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "111.92.81.255", - "threatintel.indicator.url.extension": "m", - "threatintel.indicator.url.full": "http://111.92.81.255:48586/Mozi.m", - "threatintel.indicator.url.original": "http://111.92.81.255:48586/Mozi.m", - "threatintel.indicator.url.path": "/Mozi.m", - "threatintel.indicator.url.port": 48586, - "threatintel.indicator.url.scheme": "http" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] AbuseCH URL", + "threat.indicator.first_seen": "2021-01-14T21:04:33.000Z", + "threat.indicator.ip": "111.92.81.255", + "threat.indicator.provider": "Gandylyan1", + "threat.indicator.reference": "https://urlhaus.abuse.ch/url/961521/", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "111.92.81.255", + "threat.indicator.url.extension": "m", + "threat.indicator.url.full": "http://111.92.81.255:48586/Mozi.m", + "threat.indicator.url.original": "http://111.92.81.255:48586/Mozi.m", + "threat.indicator.url.path": "/Mozi.m", + "threat.indicator.url.port": 48586, + "threat.indicator.url.scheme": "http" }, { + "abusech.url.blacklists.spamhaus_dbl": "not listed", + "abusech.url.blacklists.surbl": "not listed", + "abusech.url.id": "961522", + "abusech.url.larted": false, + "abusech.url.tags": [ + "Mozi" + ], + "abusech.url.threat": "malware_download", + "abusech.url.url_status": "offline", "event.category": "threat", "event.dataset": "threatintel.abuseurl", "event.kind": "enrichment", @@ -1045,29 +1110,31 @@ "forwarded", "threatintel-abuseurls" ], - "threatintel.abuseurl.blacklists.spamhaus_dbl": "not listed", - "threatintel.abuseurl.blacklists.surbl": "not listed", - "threatintel.abuseurl.id": "961522", - "threatintel.abuseurl.larted": false, - "threatintel.abuseurl.tags": [ - "Mozi" - ], - "threatintel.abuseurl.threat": "malware_download", - "threatintel.abuseurl.url_status": "offline", - "threatintel.indicator.first_seen": "2021-01-14T21:04:33.000Z", - "threatintel.indicator.ip": "45.229.55.75", - "threatintel.indicator.provider": "Gandylyan1", - "threatintel.indicator.reference": "https://urlhaus.abuse.ch/url/961522/", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "45.229.55.75", - "threatintel.indicator.url.extension": "m", - "threatintel.indicator.url.full": "http://45.229.55.75:38111/Mozi.m", - "threatintel.indicator.url.original": "http://45.229.55.75:38111/Mozi.m", - "threatintel.indicator.url.path": "/Mozi.m", - "threatintel.indicator.url.port": 38111, - "threatintel.indicator.url.scheme": "http" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] AbuseCH URL", + "threat.indicator.first_seen": "2021-01-14T21:04:33.000Z", + "threat.indicator.ip": "45.229.55.75", + "threat.indicator.provider": "Gandylyan1", + "threat.indicator.reference": "https://urlhaus.abuse.ch/url/961522/", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "45.229.55.75", + "threat.indicator.url.extension": "m", + "threat.indicator.url.full": "http://45.229.55.75:38111/Mozi.m", + "threat.indicator.url.original": "http://45.229.55.75:38111/Mozi.m", + "threat.indicator.url.path": "/Mozi.m", + "threat.indicator.url.port": 38111, + "threat.indicator.url.scheme": "http" }, { + "abusech.url.blacklists.spamhaus_dbl": "not listed", + "abusech.url.blacklists.surbl": "not listed", + "abusech.url.id": "961518", + "abusech.url.larted": true, + "abusech.url.tags": [ + "Mozi" + ], + "abusech.url.threat": "malware_download", + "abusech.url.url_status": "online", "event.category": "threat", "event.dataset": "threatintel.abuseurl", "event.kind": "enrichment", @@ -1081,29 +1148,32 @@ "forwarded", "threatintel-abuseurls" ], - "threatintel.abuseurl.blacklists.spamhaus_dbl": "not listed", - "threatintel.abuseurl.blacklists.surbl": "not listed", - "threatintel.abuseurl.id": "961518", - "threatintel.abuseurl.larted": true, - "threatintel.abuseurl.tags": [ - "Mozi" - ], - "threatintel.abuseurl.threat": "malware_download", - "threatintel.abuseurl.url_status": "online", - "threatintel.indicator.first_seen": "2021-01-14T21:04:10.000Z", - "threatintel.indicator.ip": "182.121.242.148", - "threatintel.indicator.provider": "Gandylyan1", - "threatintel.indicator.reference": "https://urlhaus.abuse.ch/url/961518/", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "182.121.242.148", - "threatintel.indicator.url.extension": "m", - "threatintel.indicator.url.full": "http://182.121.242.148:34556/Mozi.m", - "threatintel.indicator.url.original": "http://182.121.242.148:34556/Mozi.m", - "threatintel.indicator.url.path": "/Mozi.m", - "threatintel.indicator.url.port": 34556, - "threatintel.indicator.url.scheme": "http" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] AbuseCH URL", + "threat.indicator.first_seen": "2021-01-14T21:04:10.000Z", + "threat.indicator.ip": "182.121.242.148", + "threat.indicator.provider": "Gandylyan1", + "threat.indicator.reference": "https://urlhaus.abuse.ch/url/961518/", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "182.121.242.148", + "threat.indicator.url.extension": "m", + "threat.indicator.url.full": "http://182.121.242.148:34556/Mozi.m", + "threat.indicator.url.original": "http://182.121.242.148:34556/Mozi.m", + "threat.indicator.url.path": "/Mozi.m", + "threat.indicator.url.port": 34556, + "threat.indicator.url.scheme": "http" }, { + "abusech.url.blacklists.spamhaus_dbl": "not listed", + "abusech.url.blacklists.surbl": "not listed", + "abusech.url.id": "961519", + "abusech.url.larted": true, + "abusech.url.tags": [ + "Mozi", + "elf" + ], + "abusech.url.threat": "malware_download", + "abusech.url.url_status": "online", "event.category": "threat", "event.dataset": "threatintel.abuseurl", "event.kind": "enrichment", @@ -1117,30 +1187,33 @@ "forwarded", "threatintel-abuseurls" ], - "threatintel.abuseurl.blacklists.spamhaus_dbl": "not listed", - "threatintel.abuseurl.blacklists.surbl": "not listed", - "threatintel.abuseurl.id": "961519", - "threatintel.abuseurl.larted": true, - "threatintel.abuseurl.tags": [ - "Mozi", - "elf" - ], - "threatintel.abuseurl.threat": "malware_download", - "threatintel.abuseurl.url_status": "online", - "threatintel.indicator.first_seen": "2021-01-14T21:04:10.000Z", - "threatintel.indicator.ip": "106.115.189.249", - "threatintel.indicator.provider": "lrz_urlhaus", - "threatintel.indicator.reference": "https://urlhaus.abuse.ch/url/961519/", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "106.115.189.249", - "threatintel.indicator.url.extension": "m", - "threatintel.indicator.url.full": "http://106.115.189.249:59815/Mozi.m", - "threatintel.indicator.url.original": "http://106.115.189.249:59815/Mozi.m", - "threatintel.indicator.url.path": "/Mozi.m", - "threatintel.indicator.url.port": 59815, - "threatintel.indicator.url.scheme": "http" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] AbuseCH URL", + "threat.indicator.first_seen": "2021-01-14T21:04:10.000Z", + "threat.indicator.ip": "106.115.189.249", + "threat.indicator.provider": "lrz_urlhaus", + "threat.indicator.reference": "https://urlhaus.abuse.ch/url/961519/", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "106.115.189.249", + "threat.indicator.url.extension": "m", + "threat.indicator.url.full": "http://106.115.189.249:59815/Mozi.m", + "threat.indicator.url.original": "http://106.115.189.249:59815/Mozi.m", + "threat.indicator.url.path": "/Mozi.m", + "threat.indicator.url.port": 59815, + "threat.indicator.url.scheme": "http" }, { + "abusech.url.blacklists.spamhaus_dbl": "not listed", + "abusech.url.blacklists.surbl": "not listed", + "abusech.url.id": "961516", + "abusech.url.larted": true, + "abusech.url.tags": [ + "32-bit", + "elf", + "mips" + ], + "abusech.url.threat": "malware_download", + "abusech.url.url_status": "online", "event.category": "threat", "event.dataset": "threatintel.abuseurl", "event.kind": "enrichment", @@ -1154,31 +1227,32 @@ "forwarded", "threatintel-abuseurls" ], - "threatintel.abuseurl.blacklists.spamhaus_dbl": "not listed", - "threatintel.abuseurl.blacklists.surbl": "not listed", - "threatintel.abuseurl.id": "961516", - "threatintel.abuseurl.larted": true, - "threatintel.abuseurl.tags": [ - "32-bit", - "elf", - "mips" - ], - "threatintel.abuseurl.threat": "malware_download", - "threatintel.abuseurl.url_status": "online", - "threatintel.indicator.first_seen": "2021-01-14T21:04:08.000Z", - "threatintel.indicator.ip": "182.117.93.110", - "threatintel.indicator.provider": "geenensp", - "threatintel.indicator.reference": "https://urlhaus.abuse.ch/url/961516/", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "182.117.93.110", - "threatintel.indicator.url.extension": "sh", - "threatintel.indicator.url.full": "http://182.117.93.110:50587/bin.sh", - "threatintel.indicator.url.original": "http://182.117.93.110:50587/bin.sh", - "threatintel.indicator.url.path": "/bin.sh", - "threatintel.indicator.url.port": 50587, - "threatintel.indicator.url.scheme": "http" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] AbuseCH URL", + "threat.indicator.first_seen": "2021-01-14T21:04:08.000Z", + "threat.indicator.ip": "182.117.93.110", + "threat.indicator.provider": "geenensp", + "threat.indicator.reference": "https://urlhaus.abuse.ch/url/961516/", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "182.117.93.110", + "threat.indicator.url.extension": "sh", + "threat.indicator.url.full": "http://182.117.93.110:50587/bin.sh", + "threat.indicator.url.original": "http://182.117.93.110:50587/bin.sh", + "threat.indicator.url.path": "/bin.sh", + "threat.indicator.url.port": 50587, + "threat.indicator.url.scheme": "http" }, { + "abusech.url.blacklists.spamhaus_dbl": "not listed", + "abusech.url.blacklists.surbl": "not listed", + "abusech.url.id": "961517", + "abusech.url.larted": true, + "abusech.url.tags": [ + "Mozi", + "elf" + ], + "abusech.url.threat": "malware_download", + "abusech.url.url_status": "online", "event.category": "threat", "event.dataset": "threatintel.abuseurl", "event.kind": "enrichment", @@ -1192,30 +1266,31 @@ "forwarded", "threatintel-abuseurls" ], - "threatintel.abuseurl.blacklists.spamhaus_dbl": "not listed", - "threatintel.abuseurl.blacklists.surbl": "not listed", - "threatintel.abuseurl.id": "961517", - "threatintel.abuseurl.larted": true, - "threatintel.abuseurl.tags": [ - "Mozi", - "elf" - ], - "threatintel.abuseurl.threat": "malware_download", - "threatintel.abuseurl.url_status": "online", - "threatintel.indicator.first_seen": "2021-01-14T21:04:08.000Z", - "threatintel.indicator.ip": "110.251.5.169", - "threatintel.indicator.provider": "lrz_urlhaus", - "threatintel.indicator.reference": "https://urlhaus.abuse.ch/url/961517/", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "110.251.5.169", - "threatintel.indicator.url.extension": "m", - "threatintel.indicator.url.full": "http://110.251.5.169:48322/Mozi.m", - "threatintel.indicator.url.original": "http://110.251.5.169:48322/Mozi.m", - "threatintel.indicator.url.path": "/Mozi.m", - "threatintel.indicator.url.port": 48322, - "threatintel.indicator.url.scheme": "http" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] AbuseCH URL", + "threat.indicator.first_seen": "2021-01-14T21:04:08.000Z", + "threat.indicator.ip": "110.251.5.169", + "threat.indicator.provider": "lrz_urlhaus", + "threat.indicator.reference": "https://urlhaus.abuse.ch/url/961517/", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "110.251.5.169", + "threat.indicator.url.extension": "m", + "threat.indicator.url.full": "http://110.251.5.169:48322/Mozi.m", + "threat.indicator.url.original": "http://110.251.5.169:48322/Mozi.m", + "threat.indicator.url.path": "/Mozi.m", + "threat.indicator.url.port": 48322, + "threat.indicator.url.scheme": "http" }, { + "abusech.url.blacklists.spamhaus_dbl": "not listed", + "abusech.url.blacklists.surbl": "not listed", + "abusech.url.id": "961515", + "abusech.url.larted": true, + "abusech.url.tags": [ + "Mozi" + ], + "abusech.url.threat": "malware_download", + "abusech.url.url_status": "online", "event.category": "threat", "event.dataset": "threatintel.abuseurl", "event.kind": "enrichment", @@ -1229,29 +1304,31 @@ "forwarded", "threatintel-abuseurls" ], - "threatintel.abuseurl.blacklists.spamhaus_dbl": "not listed", - "threatintel.abuseurl.blacklists.surbl": "not listed", - "threatintel.abuseurl.id": "961515", - "threatintel.abuseurl.larted": true, - "threatintel.abuseurl.tags": [ - "Mozi" - ], - "threatintel.abuseurl.threat": "malware_download", - "threatintel.abuseurl.url_status": "online", - "threatintel.indicator.first_seen": "2021-01-14T21:04:06.000Z", - "threatintel.indicator.ip": "101.51.117.186", - "threatintel.indicator.provider": "Gandylyan1", - "threatintel.indicator.reference": "https://urlhaus.abuse.ch/url/961515/", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "101.51.117.186", - "threatintel.indicator.url.extension": "m", - "threatintel.indicator.url.full": "http://101.51.117.186:33317/Mozi.m", - "threatintel.indicator.url.original": "http://101.51.117.186:33317/Mozi.m", - "threatintel.indicator.url.path": "/Mozi.m", - "threatintel.indicator.url.port": 33317, - "threatintel.indicator.url.scheme": "http" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] AbuseCH URL", + "threat.indicator.first_seen": "2021-01-14T21:04:06.000Z", + "threat.indicator.ip": "101.51.117.186", + "threat.indicator.provider": "Gandylyan1", + "threat.indicator.reference": "https://urlhaus.abuse.ch/url/961515/", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "101.51.117.186", + "threat.indicator.url.extension": "m", + "threat.indicator.url.full": "http://101.51.117.186:33317/Mozi.m", + "threat.indicator.url.original": "http://101.51.117.186:33317/Mozi.m", + "threat.indicator.url.path": "/Mozi.m", + "threat.indicator.url.port": 33317, + "threat.indicator.url.scheme": "http" }, { + "abusech.url.blacklists.spamhaus_dbl": "not listed", + "abusech.url.blacklists.surbl": "not listed", + "abusech.url.id": "961513", + "abusech.url.larted": true, + "abusech.url.tags": [ + "Mozi" + ], + "abusech.url.threat": "malware_download", + "abusech.url.url_status": "online", "event.category": "threat", "event.dataset": "threatintel.abuseurl", "event.kind": "enrichment", @@ -1265,29 +1342,31 @@ "forwarded", "threatintel-abuseurls" ], - "threatintel.abuseurl.blacklists.spamhaus_dbl": "not listed", - "threatintel.abuseurl.blacklists.surbl": "not listed", - "threatintel.abuseurl.id": "961513", - "threatintel.abuseurl.larted": true, - "threatintel.abuseurl.tags": [ - "Mozi" - ], - "threatintel.abuseurl.threat": "malware_download", - "threatintel.abuseurl.url_status": "online", - "threatintel.indicator.first_seen": "2021-01-14T21:04:05.000Z", - "threatintel.indicator.ip": "121.151.78.166", - "threatintel.indicator.provider": "Gandylyan1", - "threatintel.indicator.reference": "https://urlhaus.abuse.ch/url/961513/", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "121.151.78.166", - "threatintel.indicator.url.extension": "m", - "threatintel.indicator.url.full": "http://121.151.78.166:41516/Mozi.m", - "threatintel.indicator.url.original": "http://121.151.78.166:41516/Mozi.m", - "threatintel.indicator.url.path": "/Mozi.m", - "threatintel.indicator.url.port": 41516, - "threatintel.indicator.url.scheme": "http" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] AbuseCH URL", + "threat.indicator.first_seen": "2021-01-14T21:04:05.000Z", + "threat.indicator.ip": "121.151.78.166", + "threat.indicator.provider": "Gandylyan1", + "threat.indicator.reference": "https://urlhaus.abuse.ch/url/961513/", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "121.151.78.166", + "threat.indicator.url.extension": "m", + "threat.indicator.url.full": "http://121.151.78.166:41516/Mozi.m", + "threat.indicator.url.original": "http://121.151.78.166:41516/Mozi.m", + "threat.indicator.url.path": "/Mozi.m", + "threat.indicator.url.port": 41516, + "threat.indicator.url.scheme": "http" }, { + "abusech.url.blacklists.spamhaus_dbl": "not listed", + "abusech.url.blacklists.surbl": "not listed", + "abusech.url.id": "961514", + "abusech.url.larted": true, + "abusech.url.tags": [ + "Mozi" + ], + "abusech.url.threat": "malware_download", + "abusech.url.url_status": "online", "event.category": "threat", "event.dataset": "threatintel.abuseurl", "event.kind": "enrichment", @@ -1301,29 +1380,31 @@ "forwarded", "threatintel-abuseurls" ], - "threatintel.abuseurl.blacklists.spamhaus_dbl": "not listed", - "threatintel.abuseurl.blacklists.surbl": "not listed", - "threatintel.abuseurl.id": "961514", - "threatintel.abuseurl.larted": true, - "threatintel.abuseurl.tags": [ - "Mozi" - ], - "threatintel.abuseurl.threat": "malware_download", - "threatintel.abuseurl.url_status": "online", - "threatintel.indicator.first_seen": "2021-01-14T21:04:05.000Z", - "threatintel.indicator.ip": "116.72.92.97", - "threatintel.indicator.provider": "Gandylyan1", - "threatintel.indicator.reference": "https://urlhaus.abuse.ch/url/961514/", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "116.72.92.97", - "threatintel.indicator.url.extension": "m", - "threatintel.indicator.url.full": "http://116.72.92.97:57798/Mozi.m", - "threatintel.indicator.url.original": "http://116.72.92.97:57798/Mozi.m", - "threatintel.indicator.url.path": "/Mozi.m", - "threatintel.indicator.url.port": 57798, - "threatintel.indicator.url.scheme": "http" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] AbuseCH URL", + "threat.indicator.first_seen": "2021-01-14T21:04:05.000Z", + "threat.indicator.ip": "116.72.92.97", + "threat.indicator.provider": "Gandylyan1", + "threat.indicator.reference": "https://urlhaus.abuse.ch/url/961514/", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "116.72.92.97", + "threat.indicator.url.extension": "m", + "threat.indicator.url.full": "http://116.72.92.97:57798/Mozi.m", + "threat.indicator.url.original": "http://116.72.92.97:57798/Mozi.m", + "threat.indicator.url.path": "/Mozi.m", + "threat.indicator.url.port": 57798, + "threat.indicator.url.scheme": "http" }, { + "abusech.url.blacklists.spamhaus_dbl": "not listed", + "abusech.url.blacklists.surbl": "not listed", + "abusech.url.id": "961509", + "abusech.url.larted": true, + "abusech.url.tags": [ + "Mozi" + ], + "abusech.url.threat": "malware_download", + "abusech.url.url_status": "online", "event.category": "threat", "event.dataset": "threatintel.abuseurl", "event.kind": "enrichment", @@ -1337,29 +1418,31 @@ "forwarded", "threatintel-abuseurls" ], - "threatintel.abuseurl.blacklists.spamhaus_dbl": "not listed", - "threatintel.abuseurl.blacklists.surbl": "not listed", - "threatintel.abuseurl.id": "961509", - "threatintel.abuseurl.larted": true, - "threatintel.abuseurl.tags": [ - "Mozi" - ], - "threatintel.abuseurl.threat": "malware_download", - "threatintel.abuseurl.url_status": "online", - "threatintel.indicator.first_seen": "2021-01-14T21:04:04.000Z", - "threatintel.indicator.ip": "27.218.15.209", - "threatintel.indicator.provider": "Gandylyan1", - "threatintel.indicator.reference": "https://urlhaus.abuse.ch/url/961509/", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "27.218.15.209", - "threatintel.indicator.url.extension": "m", - "threatintel.indicator.url.full": "http://27.218.15.209:47671/Mozi.m", - "threatintel.indicator.url.original": "http://27.218.15.209:47671/Mozi.m", - "threatintel.indicator.url.path": "/Mozi.m", - "threatintel.indicator.url.port": 47671, - "threatintel.indicator.url.scheme": "http" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] AbuseCH URL", + "threat.indicator.first_seen": "2021-01-14T21:04:04.000Z", + "threat.indicator.ip": "27.218.15.209", + "threat.indicator.provider": "Gandylyan1", + "threat.indicator.reference": "https://urlhaus.abuse.ch/url/961509/", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "27.218.15.209", + "threat.indicator.url.extension": "m", + "threat.indicator.url.full": "http://27.218.15.209:47671/Mozi.m", + "threat.indicator.url.original": "http://27.218.15.209:47671/Mozi.m", + "threat.indicator.url.path": "/Mozi.m", + "threat.indicator.url.port": 47671, + "threat.indicator.url.scheme": "http" }, { + "abusech.url.blacklists.spamhaus_dbl": "not listed", + "abusech.url.blacklists.surbl": "not listed", + "abusech.url.id": "961510", + "abusech.url.larted": true, + "abusech.url.tags": [ + "Mozi" + ], + "abusech.url.threat": "malware_download", + "abusech.url.url_status": "online", "event.category": "threat", "event.dataset": "threatintel.abuseurl", "event.kind": "enrichment", @@ -1373,29 +1456,33 @@ "forwarded", "threatintel-abuseurls" ], - "threatintel.abuseurl.blacklists.spamhaus_dbl": "not listed", - "threatintel.abuseurl.blacklists.surbl": "not listed", - "threatintel.abuseurl.id": "961510", - "threatintel.abuseurl.larted": true, - "threatintel.abuseurl.tags": [ - "Mozi" - ], - "threatintel.abuseurl.threat": "malware_download", - "threatintel.abuseurl.url_status": "online", - "threatintel.indicator.first_seen": "2021-01-14T21:04:04.000Z", - "threatintel.indicator.ip": "120.85.171.210", - "threatintel.indicator.provider": "Gandylyan1", - "threatintel.indicator.reference": "https://urlhaus.abuse.ch/url/961510/", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "120.85.171.210", - "threatintel.indicator.url.extension": "m", - "threatintel.indicator.url.full": "http://120.85.171.210:57690/Mozi.m", - "threatintel.indicator.url.original": "http://120.85.171.210:57690/Mozi.m", - "threatintel.indicator.url.path": "/Mozi.m", - "threatintel.indicator.url.port": 57690, - "threatintel.indicator.url.scheme": "http" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] AbuseCH URL", + "threat.indicator.first_seen": "2021-01-14T21:04:04.000Z", + "threat.indicator.ip": "120.85.171.210", + "threat.indicator.provider": "Gandylyan1", + "threat.indicator.reference": "https://urlhaus.abuse.ch/url/961510/", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "120.85.171.210", + "threat.indicator.url.extension": "m", + "threat.indicator.url.full": "http://120.85.171.210:57690/Mozi.m", + "threat.indicator.url.original": "http://120.85.171.210:57690/Mozi.m", + "threat.indicator.url.path": "/Mozi.m", + "threat.indicator.url.port": 57690, + "threat.indicator.url.scheme": "http" }, { + "abusech.url.blacklists.spamhaus_dbl": "not listed", + "abusech.url.blacklists.surbl": "not listed", + "abusech.url.id": "961511", + "abusech.url.larted": true, + "abusech.url.tags": [ + "32-bit", + "elf", + "mips" + ], + "abusech.url.threat": "malware_download", + "abusech.url.url_status": "online", "event.category": "threat", "event.dataset": "threatintel.abuseurl", "event.kind": "enrichment", @@ -1409,30 +1496,30 @@ "forwarded", "threatintel-abuseurls" ], - "threatintel.abuseurl.blacklists.spamhaus_dbl": "not listed", - "threatintel.abuseurl.blacklists.surbl": "not listed", - "threatintel.abuseurl.id": "961511", - "threatintel.abuseurl.larted": true, - "threatintel.abuseurl.tags": [ - "32-bit", - "elf", - "mips" - ], - "threatintel.abuseurl.threat": "malware_download", - "threatintel.abuseurl.url_status": "online", - "threatintel.indicator.first_seen": "2021-01-14T21:04:04.000Z", - "threatintel.indicator.ip": "117.251.59.53", - "threatintel.indicator.provider": "geenensp", - "threatintel.indicator.reference": "https://urlhaus.abuse.ch/url/961511/", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "117.251.59.53", - "threatintel.indicator.url.full": "http://117.251.59.53:50611/i", - "threatintel.indicator.url.original": "http://117.251.59.53:50611/i", - "threatintel.indicator.url.path": "/i", - "threatintel.indicator.url.port": 50611, - "threatintel.indicator.url.scheme": "http" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] AbuseCH URL", + "threat.indicator.first_seen": "2021-01-14T21:04:04.000Z", + "threat.indicator.ip": "117.251.59.53", + "threat.indicator.provider": "geenensp", + "threat.indicator.reference": "https://urlhaus.abuse.ch/url/961511/", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "117.251.59.53", + "threat.indicator.url.full": "http://117.251.59.53:50611/i", + "threat.indicator.url.original": "http://117.251.59.53:50611/i", + "threat.indicator.url.path": "/i", + "threat.indicator.url.port": 50611, + "threat.indicator.url.scheme": "http" }, { + "abusech.url.blacklists.spamhaus_dbl": "not listed", + "abusech.url.blacklists.surbl": "not listed", + "abusech.url.id": "961512", + "abusech.url.larted": true, + "abusech.url.tags": [ + "Mozi" + ], + "abusech.url.threat": "malware_download", + "abusech.url.url_status": "online", "event.category": "threat", "event.dataset": "threatintel.abuseurl", "event.kind": "enrichment", @@ -1446,29 +1533,32 @@ "forwarded", "threatintel-abuseurls" ], - "threatintel.abuseurl.blacklists.spamhaus_dbl": "not listed", - "threatintel.abuseurl.blacklists.surbl": "not listed", - "threatintel.abuseurl.id": "961512", - "threatintel.abuseurl.larted": true, - "threatintel.abuseurl.tags": [ - "Mozi" - ], - "threatintel.abuseurl.threat": "malware_download", - "threatintel.abuseurl.url_status": "online", - "threatintel.indicator.first_seen": "2021-01-14T21:04:04.000Z", - "threatintel.indicator.ip": "115.58.83.167", - "threatintel.indicator.provider": "Gandylyan1", - "threatintel.indicator.reference": "https://urlhaus.abuse.ch/url/961512/", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "115.58.83.167", - "threatintel.indicator.url.extension": "m", - "threatintel.indicator.url.full": "http://115.58.83.167:34141/Mozi.m", - "threatintel.indicator.url.original": "http://115.58.83.167:34141/Mozi.m", - "threatintel.indicator.url.path": "/Mozi.m", - "threatintel.indicator.url.port": 34141, - "threatintel.indicator.url.scheme": "http" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] AbuseCH URL", + "threat.indicator.first_seen": "2021-01-14T21:04:04.000Z", + "threat.indicator.ip": "115.58.83.167", + "threat.indicator.provider": "Gandylyan1", + "threat.indicator.reference": "https://urlhaus.abuse.ch/url/961512/", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "115.58.83.167", + "threat.indicator.url.extension": "m", + "threat.indicator.url.full": "http://115.58.83.167:34141/Mozi.m", + "threat.indicator.url.original": "http://115.58.83.167:34141/Mozi.m", + "threat.indicator.url.path": "/Mozi.m", + "threat.indicator.url.port": 34141, + "threat.indicator.url.scheme": "http" }, { + "abusech.url.blacklists.spamhaus_dbl": "not listed", + "abusech.url.blacklists.surbl": "not listed", + "abusech.url.id": "961507", + "abusech.url.larted": true, + "abusech.url.tags": [ + "Mozi", + "elf" + ], + "abusech.url.threat": "malware_download", + "abusech.url.url_status": "online", "event.category": "threat", "event.dataset": "threatintel.abuseurl", "event.kind": "enrichment", @@ -1482,30 +1572,32 @@ "forwarded", "threatintel-abuseurls" ], - "threatintel.abuseurl.blacklists.spamhaus_dbl": "not listed", - "threatintel.abuseurl.blacklists.surbl": "not listed", - "threatintel.abuseurl.id": "961507", - "threatintel.abuseurl.larted": true, - "threatintel.abuseurl.tags": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] AbuseCH URL", + "threat.indicator.first_seen": "2021-01-14T20:52:08.000Z", + "threat.indicator.ip": "94.178.124.83", + "threat.indicator.provider": "lrz_urlhaus", + "threat.indicator.reference": "https://urlhaus.abuse.ch/url/961507/", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "94.178.124.83", + "threat.indicator.url.extension": "m", + "threat.indicator.url.full": "http://94.178.124.83:44399/Mozi.m", + "threat.indicator.url.original": "http://94.178.124.83:44399/Mozi.m", + "threat.indicator.url.path": "/Mozi.m", + "threat.indicator.url.port": 44399, + "threat.indicator.url.scheme": "http" + }, + { + "abusech.url.blacklists.spamhaus_dbl": "not listed", + "abusech.url.blacklists.surbl": "not listed", + "abusech.url.id": "961508", + "abusech.url.larted": true, + "abusech.url.tags": [ "Mozi", "elf" ], - "threatintel.abuseurl.threat": "malware_download", - "threatintel.abuseurl.url_status": "online", - "threatintel.indicator.first_seen": "2021-01-14T20:52:08.000Z", - "threatintel.indicator.ip": "94.178.124.83", - "threatintel.indicator.provider": "lrz_urlhaus", - "threatintel.indicator.reference": "https://urlhaus.abuse.ch/url/961507/", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "94.178.124.83", - "threatintel.indicator.url.extension": "m", - "threatintel.indicator.url.full": "http://94.178.124.83:44399/Mozi.m", - "threatintel.indicator.url.original": "http://94.178.124.83:44399/Mozi.m", - "threatintel.indicator.url.path": "/Mozi.m", - "threatintel.indicator.url.port": 44399, - "threatintel.indicator.url.scheme": "http" - }, - { + "abusech.url.threat": "malware_download", + "abusech.url.url_status": "online", "event.category": "threat", "event.dataset": "threatintel.abuseurl", "event.kind": "enrichment", @@ -1519,30 +1611,32 @@ "forwarded", "threatintel-abuseurls" ], - "threatintel.abuseurl.blacklists.spamhaus_dbl": "not listed", - "threatintel.abuseurl.blacklists.surbl": "not listed", - "threatintel.abuseurl.id": "961508", - "threatintel.abuseurl.larted": true, - "threatintel.abuseurl.tags": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] AbuseCH URL", + "threat.indicator.first_seen": "2021-01-14T20:52:08.000Z", + "threat.indicator.ip": "182.122.75.232", + "threat.indicator.provider": "lrz_urlhaus", + "threat.indicator.reference": "https://urlhaus.abuse.ch/url/961508/", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "182.122.75.232", + "threat.indicator.url.extension": "m", + "threat.indicator.url.full": "http://182.122.75.232:49120/Mozi.m", + "threat.indicator.url.original": "http://182.122.75.232:49120/Mozi.m", + "threat.indicator.url.path": "/Mozi.m", + "threat.indicator.url.port": 49120, + "threat.indicator.url.scheme": "http" + }, + { + "abusech.url.blacklists.spamhaus_dbl": "not listed", + "abusech.url.blacklists.surbl": "not listed", + "abusech.url.id": "961506", + "abusech.url.larted": true, + "abusech.url.tags": [ "Mozi", "elf" ], - "threatintel.abuseurl.threat": "malware_download", - "threatintel.abuseurl.url_status": "online", - "threatintel.indicator.first_seen": "2021-01-14T20:52:08.000Z", - "threatintel.indicator.ip": "182.122.75.232", - "threatintel.indicator.provider": "lrz_urlhaus", - "threatintel.indicator.reference": "https://urlhaus.abuse.ch/url/961508/", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "182.122.75.232", - "threatintel.indicator.url.extension": "m", - "threatintel.indicator.url.full": "http://182.122.75.232:49120/Mozi.m", - "threatintel.indicator.url.original": "http://182.122.75.232:49120/Mozi.m", - "threatintel.indicator.url.path": "/Mozi.m", - "threatintel.indicator.url.port": 49120, - "threatintel.indicator.url.scheme": "http" - }, - { + "abusech.url.threat": "malware_download", + "abusech.url.url_status": "online", "event.category": "threat", "event.dataset": "threatintel.abuseurl", "event.kind": "enrichment", @@ -1556,30 +1650,32 @@ "forwarded", "threatintel-abuseurls" ], - "threatintel.abuseurl.blacklists.spamhaus_dbl": "not listed", - "threatintel.abuseurl.blacklists.surbl": "not listed", - "threatintel.abuseurl.id": "961506", - "threatintel.abuseurl.larted": true, - "threatintel.abuseurl.tags": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] AbuseCH URL", + "threat.indicator.first_seen": "2021-01-14T20:52:07.000Z", + "threat.indicator.ip": "115.63.202.43", + "threat.indicator.provider": "lrz_urlhaus", + "threat.indicator.reference": "https://urlhaus.abuse.ch/url/961506/", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "115.63.202.43", + "threat.indicator.url.extension": "m", + "threat.indicator.url.full": "http://115.63.202.43:51136/Mozi.m", + "threat.indicator.url.original": "http://115.63.202.43:51136/Mozi.m", + "threat.indicator.url.path": "/Mozi.m", + "threat.indicator.url.port": 51136, + "threat.indicator.url.scheme": "http" + }, + { + "abusech.url.blacklists.spamhaus_dbl": "not listed", + "abusech.url.blacklists.surbl": "not listed", + "abusech.url.id": "961504", + "abusech.url.larted": true, + "abusech.url.tags": [ "Mozi", "elf" ], - "threatintel.abuseurl.threat": "malware_download", - "threatintel.abuseurl.url_status": "online", - "threatintel.indicator.first_seen": "2021-01-14T20:52:07.000Z", - "threatintel.indicator.ip": "115.63.202.43", - "threatintel.indicator.provider": "lrz_urlhaus", - "threatintel.indicator.reference": "https://urlhaus.abuse.ch/url/961506/", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "115.63.202.43", - "threatintel.indicator.url.extension": "m", - "threatintel.indicator.url.full": "http://115.63.202.43:51136/Mozi.m", - "threatintel.indicator.url.original": "http://115.63.202.43:51136/Mozi.m", - "threatintel.indicator.url.path": "/Mozi.m", - "threatintel.indicator.url.port": 51136, - "threatintel.indicator.url.scheme": "http" - }, - { + "abusech.url.threat": "malware_download", + "abusech.url.url_status": "online", "event.category": "threat", "event.dataset": "threatintel.abuseurl", "event.kind": "enrichment", @@ -1593,30 +1689,32 @@ "forwarded", "threatintel-abuseurls" ], - "threatintel.abuseurl.blacklists.spamhaus_dbl": "not listed", - "threatintel.abuseurl.blacklists.surbl": "not listed", - "threatintel.abuseurl.id": "961504", - "threatintel.abuseurl.larted": true, - "threatintel.abuseurl.tags": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] AbuseCH URL", + "threat.indicator.first_seen": "2021-01-14T20:52:06.000Z", + "threat.indicator.ip": "59.99.40.204", + "threat.indicator.provider": "lrz_urlhaus", + "threat.indicator.reference": "https://urlhaus.abuse.ch/url/961504/", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "59.99.40.204", + "threat.indicator.url.extension": "m", + "threat.indicator.url.full": "http://59.99.40.204:45773/Mozi.m", + "threat.indicator.url.original": "http://59.99.40.204:45773/Mozi.m", + "threat.indicator.url.path": "/Mozi.m", + "threat.indicator.url.port": 45773, + "threat.indicator.url.scheme": "http" + }, + { + "abusech.url.blacklists.spamhaus_dbl": "not listed", + "abusech.url.blacklists.surbl": "not listed", + "abusech.url.id": "961505", + "abusech.url.larted": true, + "abusech.url.tags": [ "Mozi", "elf" ], - "threatintel.abuseurl.threat": "malware_download", - "threatintel.abuseurl.url_status": "online", - "threatintel.indicator.first_seen": "2021-01-14T20:52:06.000Z", - "threatintel.indicator.ip": "59.99.40.204", - "threatintel.indicator.provider": "lrz_urlhaus", - "threatintel.indicator.reference": "https://urlhaus.abuse.ch/url/961504/", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "59.99.40.204", - "threatintel.indicator.url.extension": "m", - "threatintel.indicator.url.full": "http://59.99.40.204:45773/Mozi.m", - "threatintel.indicator.url.original": "http://59.99.40.204:45773/Mozi.m", - "threatintel.indicator.url.path": "/Mozi.m", - "threatintel.indicator.url.port": 45773, - "threatintel.indicator.url.scheme": "http" - }, - { + "abusech.url.threat": "malware_download", + "abusech.url.url_status": "online", "event.category": "threat", "event.dataset": "threatintel.abuseurl", "event.kind": "enrichment", @@ -1630,30 +1728,32 @@ "forwarded", "threatintel-abuseurls" ], - "threatintel.abuseurl.blacklists.spamhaus_dbl": "not listed", - "threatintel.abuseurl.blacklists.surbl": "not listed", - "threatintel.abuseurl.id": "961505", - "threatintel.abuseurl.larted": true, - "threatintel.abuseurl.tags": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] AbuseCH URL", + "threat.indicator.first_seen": "2021-01-14T20:52:06.000Z", + "threat.indicator.ip": "117.247.128.213", + "threat.indicator.provider": "lrz_urlhaus", + "threat.indicator.reference": "https://urlhaus.abuse.ch/url/961505/", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "117.247.128.213", + "threat.indicator.url.extension": "m", + "threat.indicator.url.full": "http://117.247.128.213:56528/Mozi.m", + "threat.indicator.url.original": "http://117.247.128.213:56528/Mozi.m", + "threat.indicator.url.path": "/Mozi.m", + "threat.indicator.url.port": 56528, + "threat.indicator.url.scheme": "http" + }, + { + "abusech.url.blacklists.spamhaus_dbl": "not listed", + "abusech.url.blacklists.surbl": "not listed", + "abusech.url.id": "961500", + "abusech.url.larted": true, + "abusech.url.tags": [ "Mozi", "elf" ], - "threatintel.abuseurl.threat": "malware_download", - "threatintel.abuseurl.url_status": "online", - "threatintel.indicator.first_seen": "2021-01-14T20:52:06.000Z", - "threatintel.indicator.ip": "117.247.128.213", - "threatintel.indicator.provider": "lrz_urlhaus", - "threatintel.indicator.reference": "https://urlhaus.abuse.ch/url/961505/", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "117.247.128.213", - "threatintel.indicator.url.extension": "m", - "threatintel.indicator.url.full": "http://117.247.128.213:56528/Mozi.m", - "threatintel.indicator.url.original": "http://117.247.128.213:56528/Mozi.m", - "threatintel.indicator.url.path": "/Mozi.m", - "threatintel.indicator.url.port": 56528, - "threatintel.indicator.url.scheme": "http" - }, - { + "abusech.url.threat": "malware_download", + "abusech.url.url_status": "online", "event.category": "threat", "event.dataset": "threatintel.abuseurl", "event.kind": "enrichment", @@ -1667,30 +1767,32 @@ "forwarded", "threatintel-abuseurls" ], - "threatintel.abuseurl.blacklists.spamhaus_dbl": "not listed", - "threatintel.abuseurl.blacklists.surbl": "not listed", - "threatintel.abuseurl.id": "961500", - "threatintel.abuseurl.larted": true, - "threatintel.abuseurl.tags": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] AbuseCH URL", + "threat.indicator.first_seen": "2021-01-14T20:52:05.000Z", + "threat.indicator.ip": "14.137.219.132", + "threat.indicator.provider": "lrz_urlhaus", + "threat.indicator.reference": "https://urlhaus.abuse.ch/url/961500/", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "14.137.219.132", + "threat.indicator.url.extension": "a", + "threat.indicator.url.full": "http://14.137.219.132:44427/Mozi.a", + "threat.indicator.url.original": "http://14.137.219.132:44427/Mozi.a", + "threat.indicator.url.path": "/Mozi.a", + "threat.indicator.url.port": 44427, + "threat.indicator.url.scheme": "http" + }, + { + "abusech.url.blacklists.spamhaus_dbl": "not listed", + "abusech.url.blacklists.surbl": "not listed", + "abusech.url.id": "961501", + "abusech.url.larted": true, + "abusech.url.tags": [ "Mozi", "elf" ], - "threatintel.abuseurl.threat": "malware_download", - "threatintel.abuseurl.url_status": "online", - "threatintel.indicator.first_seen": "2021-01-14T20:52:05.000Z", - "threatintel.indicator.ip": "14.137.219.132", - "threatintel.indicator.provider": "lrz_urlhaus", - "threatintel.indicator.reference": "https://urlhaus.abuse.ch/url/961500/", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "14.137.219.132", - "threatintel.indicator.url.extension": "a", - "threatintel.indicator.url.full": "http://14.137.219.132:44427/Mozi.a", - "threatintel.indicator.url.original": "http://14.137.219.132:44427/Mozi.a", - "threatintel.indicator.url.path": "/Mozi.a", - "threatintel.indicator.url.port": 44427, - "threatintel.indicator.url.scheme": "http" - }, - { + "abusech.url.threat": "malware_download", + "abusech.url.url_status": "online", "event.category": "threat", "event.dataset": "threatintel.abuseurl", "event.kind": "enrichment", @@ -1704,30 +1806,32 @@ "forwarded", "threatintel-abuseurls" ], - "threatintel.abuseurl.blacklists.spamhaus_dbl": "not listed", - "threatintel.abuseurl.blacklists.surbl": "not listed", - "threatintel.abuseurl.id": "961501", - "threatintel.abuseurl.larted": true, - "threatintel.abuseurl.tags": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] AbuseCH URL", + "threat.indicator.first_seen": "2021-01-14T20:52:05.000Z", + "threat.indicator.ip": "42.224.40.14", + "threat.indicator.provider": "lrz_urlhaus", + "threat.indicator.reference": "https://urlhaus.abuse.ch/url/961501/", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "42.224.40.14", + "threat.indicator.url.extension": "m", + "threat.indicator.url.full": "http://42.224.40.14:36134/Mozi.m", + "threat.indicator.url.original": "http://42.224.40.14:36134/Mozi.m", + "threat.indicator.url.path": "/Mozi.m", + "threat.indicator.url.port": 36134, + "threat.indicator.url.scheme": "http" + }, + { + "abusech.url.blacklists.spamhaus_dbl": "not listed", + "abusech.url.blacklists.surbl": "not listed", + "abusech.url.id": "961502", + "abusech.url.larted": true, + "abusech.url.tags": [ "Mozi", "elf" ], - "threatintel.abuseurl.threat": "malware_download", - "threatintel.abuseurl.url_status": "online", - "threatintel.indicator.first_seen": "2021-01-14T20:52:05.000Z", - "threatintel.indicator.ip": "42.224.40.14", - "threatintel.indicator.provider": "lrz_urlhaus", - "threatintel.indicator.reference": "https://urlhaus.abuse.ch/url/961501/", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "42.224.40.14", - "threatintel.indicator.url.extension": "m", - "threatintel.indicator.url.full": "http://42.224.40.14:36134/Mozi.m", - "threatintel.indicator.url.original": "http://42.224.40.14:36134/Mozi.m", - "threatintel.indicator.url.path": "/Mozi.m", - "threatintel.indicator.url.port": 36134, - "threatintel.indicator.url.scheme": "http" - }, - { + "abusech.url.threat": "malware_download", + "abusech.url.url_status": "online", "event.category": "threat", "event.dataset": "threatintel.abuseurl", "event.kind": "enrichment", @@ -1741,30 +1845,32 @@ "forwarded", "threatintel-abuseurls" ], - "threatintel.abuseurl.blacklists.spamhaus_dbl": "not listed", - "threatintel.abuseurl.blacklists.surbl": "not listed", - "threatintel.abuseurl.id": "961502", - "threatintel.abuseurl.larted": true, - "threatintel.abuseurl.tags": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] AbuseCH URL", + "threat.indicator.first_seen": "2021-01-14T20:52:05.000Z", + "threat.indicator.ip": "186.33.104.107", + "threat.indicator.provider": "lrz_urlhaus", + "threat.indicator.reference": "https://urlhaus.abuse.ch/url/961502/", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "186.33.104.107", + "threat.indicator.url.extension": "m", + "threat.indicator.url.full": "http://186.33.104.107:43973/Mozi.m", + "threat.indicator.url.original": "http://186.33.104.107:43973/Mozi.m", + "threat.indicator.url.path": "/Mozi.m", + "threat.indicator.url.port": 43973, + "threat.indicator.url.scheme": "http" + }, + { + "abusech.url.blacklists.spamhaus_dbl": "not listed", + "abusech.url.blacklists.surbl": "not listed", + "abusech.url.id": "961503", + "abusech.url.larted": true, + "abusech.url.tags": [ "Mozi", "elf" ], - "threatintel.abuseurl.threat": "malware_download", - "threatintel.abuseurl.url_status": "online", - "threatintel.indicator.first_seen": "2021-01-14T20:52:05.000Z", - "threatintel.indicator.ip": "186.33.104.107", - "threatintel.indicator.provider": "lrz_urlhaus", - "threatintel.indicator.reference": "https://urlhaus.abuse.ch/url/961502/", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "186.33.104.107", - "threatintel.indicator.url.extension": "m", - "threatintel.indicator.url.full": "http://186.33.104.107:43973/Mozi.m", - "threatintel.indicator.url.original": "http://186.33.104.107:43973/Mozi.m", - "threatintel.indicator.url.path": "/Mozi.m", - "threatintel.indicator.url.port": 43973, - "threatintel.indicator.url.scheme": "http" - }, - { + "abusech.url.threat": "malware_download", + "abusech.url.url_status": "online", "event.category": "threat", "event.dataset": "threatintel.abuseurl", "event.kind": "enrichment", @@ -1778,30 +1884,32 @@ "forwarded", "threatintel-abuseurls" ], - "threatintel.abuseurl.blacklists.spamhaus_dbl": "not listed", - "threatintel.abuseurl.blacklists.surbl": "not listed", - "threatintel.abuseurl.id": "961503", - "threatintel.abuseurl.larted": true, - "threatintel.abuseurl.tags": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] AbuseCH URL", + "threat.indicator.first_seen": "2021-01-14T20:52:05.000Z", + "threat.indicator.ip": "85.105.16.154", + "threat.indicator.provider": "lrz_urlhaus", + "threat.indicator.reference": "https://urlhaus.abuse.ch/url/961503/", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "85.105.16.154", + "threat.indicator.url.extension": "m", + "threat.indicator.url.full": "http://85.105.16.154:41319/Mozi.m", + "threat.indicator.url.original": "http://85.105.16.154:41319/Mozi.m", + "threat.indicator.url.path": "/Mozi.m", + "threat.indicator.url.port": 41319, + "threat.indicator.url.scheme": "http" + }, + { + "abusech.url.blacklists.spamhaus_dbl": "not listed", + "abusech.url.blacklists.surbl": "not listed", + "abusech.url.id": "961496", + "abusech.url.larted": true, + "abusech.url.tags": [ "Mozi", "elf" ], - "threatintel.abuseurl.threat": "malware_download", - "threatintel.abuseurl.url_status": "online", - "threatintel.indicator.first_seen": "2021-01-14T20:52:05.000Z", - "threatintel.indicator.ip": "85.105.16.154", - "threatintel.indicator.provider": "lrz_urlhaus", - "threatintel.indicator.reference": "https://urlhaus.abuse.ch/url/961503/", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "85.105.16.154", - "threatintel.indicator.url.extension": "m", - "threatintel.indicator.url.full": "http://85.105.16.154:41319/Mozi.m", - "threatintel.indicator.url.original": "http://85.105.16.154:41319/Mozi.m", - "threatintel.indicator.url.path": "/Mozi.m", - "threatintel.indicator.url.port": 41319, - "threatintel.indicator.url.scheme": "http" - }, - { + "abusech.url.threat": "malware_download", + "abusech.url.url_status": "online", "event.category": "threat", "event.dataset": "threatintel.abuseurl", "event.kind": "enrichment", @@ -1815,30 +1923,32 @@ "forwarded", "threatintel-abuseurls" ], - "threatintel.abuseurl.blacklists.spamhaus_dbl": "not listed", - "threatintel.abuseurl.blacklists.surbl": "not listed", - "threatintel.abuseurl.id": "961496", - "threatintel.abuseurl.larted": true, - "threatintel.abuseurl.tags": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] AbuseCH URL", + "threat.indicator.first_seen": "2021-01-14T20:52:04.000Z", + "threat.indicator.ip": "178.141.73.115", + "threat.indicator.provider": "lrz_urlhaus", + "threat.indicator.reference": "https://urlhaus.abuse.ch/url/961496/", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "178.141.73.115", + "threat.indicator.url.extension": "a", + "threat.indicator.url.full": "http://178.141.73.115:51847/Mozi.a", + "threat.indicator.url.original": "http://178.141.73.115:51847/Mozi.a", + "threat.indicator.url.path": "/Mozi.a", + "threat.indicator.url.port": 51847, + "threat.indicator.url.scheme": "http" + }, + { + "abusech.url.blacklists.spamhaus_dbl": "not listed", + "abusech.url.blacklists.surbl": "not listed", + "abusech.url.id": "961497", + "abusech.url.larted": true, + "abusech.url.tags": [ "Mozi", "elf" ], - "threatintel.abuseurl.threat": "malware_download", - "threatintel.abuseurl.url_status": "online", - "threatintel.indicator.first_seen": "2021-01-14T20:52:04.000Z", - "threatintel.indicator.ip": "178.141.73.115", - "threatintel.indicator.provider": "lrz_urlhaus", - "threatintel.indicator.reference": "https://urlhaus.abuse.ch/url/961496/", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "178.141.73.115", - "threatintel.indicator.url.extension": "a", - "threatintel.indicator.url.full": "http://178.141.73.115:51847/Mozi.a", - "threatintel.indicator.url.original": "http://178.141.73.115:51847/Mozi.a", - "threatintel.indicator.url.path": "/Mozi.a", - "threatintel.indicator.url.port": 51847, - "threatintel.indicator.url.scheme": "http" - }, - { + "abusech.url.threat": "malware_download", + "abusech.url.url_status": "online", "event.category": "threat", "event.dataset": "threatintel.abuseurl", "event.kind": "enrichment", @@ -1852,30 +1962,32 @@ "forwarded", "threatintel-abuseurls" ], - "threatintel.abuseurl.blacklists.spamhaus_dbl": "not listed", - "threatintel.abuseurl.blacklists.surbl": "not listed", - "threatintel.abuseurl.id": "961497", - "threatintel.abuseurl.larted": true, - "threatintel.abuseurl.tags": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] AbuseCH URL", + "threat.indicator.first_seen": "2021-01-14T20:52:04.000Z", + "threat.indicator.ip": "186.33.104.135", + "threat.indicator.provider": "lrz_urlhaus", + "threat.indicator.reference": "https://urlhaus.abuse.ch/url/961497/", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "186.33.104.135", + "threat.indicator.url.extension": "m", + "threat.indicator.url.full": "http://186.33.104.135:54469/Mozi.m", + "threat.indicator.url.original": "http://186.33.104.135:54469/Mozi.m", + "threat.indicator.url.path": "/Mozi.m", + "threat.indicator.url.port": 54469, + "threat.indicator.url.scheme": "http" + }, + { + "abusech.url.blacklists.spamhaus_dbl": "not listed", + "abusech.url.blacklists.surbl": "not listed", + "abusech.url.id": "961498", + "abusech.url.larted": true, + "abusech.url.tags": [ "Mozi", "elf" ], - "threatintel.abuseurl.threat": "malware_download", - "threatintel.abuseurl.url_status": "online", - "threatintel.indicator.first_seen": "2021-01-14T20:52:04.000Z", - "threatintel.indicator.ip": "186.33.104.135", - "threatintel.indicator.provider": "lrz_urlhaus", - "threatintel.indicator.reference": "https://urlhaus.abuse.ch/url/961497/", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "186.33.104.135", - "threatintel.indicator.url.extension": "m", - "threatintel.indicator.url.full": "http://186.33.104.135:54469/Mozi.m", - "threatintel.indicator.url.original": "http://186.33.104.135:54469/Mozi.m", - "threatintel.indicator.url.path": "/Mozi.m", - "threatintel.indicator.url.port": 54469, - "threatintel.indicator.url.scheme": "http" - }, - { + "abusech.url.threat": "malware_download", + "abusech.url.url_status": "online", "event.category": "threat", "event.dataset": "threatintel.abuseurl", "event.kind": "enrichment", @@ -1889,30 +2001,32 @@ "forwarded", "threatintel-abuseurls" ], - "threatintel.abuseurl.blacklists.spamhaus_dbl": "not listed", - "threatintel.abuseurl.blacklists.surbl": "not listed", - "threatintel.abuseurl.id": "961498", - "threatintel.abuseurl.larted": true, - "threatintel.abuseurl.tags": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] AbuseCH URL", + "threat.indicator.first_seen": "2021-01-14T20:52:04.000Z", + "threat.indicator.ip": "115.56.159.43", + "threat.indicator.provider": "lrz_urlhaus", + "threat.indicator.reference": "https://urlhaus.abuse.ch/url/961498/", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "115.56.159.43", + "threat.indicator.url.extension": "m", + "threat.indicator.url.full": "http://115.56.159.43:34547/Mozi.m", + "threat.indicator.url.original": "http://115.56.159.43:34547/Mozi.m", + "threat.indicator.url.path": "/Mozi.m", + "threat.indicator.url.port": 34547, + "threat.indicator.url.scheme": "http" + }, + { + "abusech.url.blacklists.spamhaus_dbl": "not listed", + "abusech.url.blacklists.surbl": "not listed", + "abusech.url.id": "961499", + "abusech.url.larted": true, + "abusech.url.tags": [ "Mozi", "elf" ], - "threatintel.abuseurl.threat": "malware_download", - "threatintel.abuseurl.url_status": "online", - "threatintel.indicator.first_seen": "2021-01-14T20:52:04.000Z", - "threatintel.indicator.ip": "115.56.159.43", - "threatintel.indicator.provider": "lrz_urlhaus", - "threatintel.indicator.reference": "https://urlhaus.abuse.ch/url/961498/", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "115.56.159.43", - "threatintel.indicator.url.extension": "m", - "threatintel.indicator.url.full": "http://115.56.159.43:34547/Mozi.m", - "threatintel.indicator.url.original": "http://115.56.159.43:34547/Mozi.m", - "threatintel.indicator.url.path": "/Mozi.m", - "threatintel.indicator.url.port": 34547, - "threatintel.indicator.url.scheme": "http" - }, - { + "abusech.url.threat": "malware_download", + "abusech.url.url_status": "online", "event.category": "threat", "event.dataset": "threatintel.abuseurl", "event.kind": "enrichment", @@ -1926,30 +2040,31 @@ "forwarded", "threatintel-abuseurls" ], - "threatintel.abuseurl.blacklists.spamhaus_dbl": "not listed", - "threatintel.abuseurl.blacklists.surbl": "not listed", - "threatintel.abuseurl.id": "961499", - "threatintel.abuseurl.larted": true, - "threatintel.abuseurl.tags": [ - "Mozi", - "elf" - ], - "threatintel.abuseurl.threat": "malware_download", - "threatintel.abuseurl.url_status": "online", - "threatintel.indicator.first_seen": "2021-01-14T20:52:04.000Z", - "threatintel.indicator.ip": "42.230.138.170", - "threatintel.indicator.provider": "lrz_urlhaus", - "threatintel.indicator.reference": "https://urlhaus.abuse.ch/url/961499/", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "42.230.138.170", - "threatintel.indicator.url.extension": "m", - "threatintel.indicator.url.full": "http://42.230.138.170:33932/Mozi.m", - "threatintel.indicator.url.original": "http://42.230.138.170:33932/Mozi.m", - "threatintel.indicator.url.path": "/Mozi.m", - "threatintel.indicator.url.port": 33932, - "threatintel.indicator.url.scheme": "http" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] AbuseCH URL", + "threat.indicator.first_seen": "2021-01-14T20:52:04.000Z", + "threat.indicator.ip": "42.230.138.170", + "threat.indicator.provider": "lrz_urlhaus", + "threat.indicator.reference": "https://urlhaus.abuse.ch/url/961499/", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "42.230.138.170", + "threat.indicator.url.extension": "m", + "threat.indicator.url.full": "http://42.230.138.170:33932/Mozi.m", + "threat.indicator.url.original": "http://42.230.138.170:33932/Mozi.m", + "threat.indicator.url.path": "/Mozi.m", + "threat.indicator.url.port": 33932, + "threat.indicator.url.scheme": "http" }, { + "abusech.url.blacklists.spamhaus_dbl": "not listed", + "abusech.url.blacklists.surbl": "not listed", + "abusech.url.id": "961494", + "abusech.url.larted": false, + "abusech.url.tags": [ + "sLoad" + ], + "abusech.url.threat": "malware_download", + "abusech.url.url_status": "offline", "event.category": "threat", "event.dataset": "threatintel.abuseurl", "event.kind": "enrichment", @@ -1963,27 +2078,29 @@ "forwarded", "threatintel-abuseurls" ], - "threatintel.abuseurl.blacklists.spamhaus_dbl": "not listed", - "threatintel.abuseurl.blacklists.surbl": "not listed", - "threatintel.abuseurl.id": "961494", - "threatintel.abuseurl.larted": false, - "threatintel.abuseurl.tags": [ - "sLoad" - ], - "threatintel.abuseurl.threat": "malware_download", - "threatintel.abuseurl.url_status": "offline", - "threatintel.indicator.first_seen": "2021-01-14T20:51:47.000Z", - "threatintel.indicator.provider": "Cryptolaemus1", - "threatintel.indicator.reference": "https://urlhaus.abuse.ch/url/961494/", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "univirtek.com", - "threatintel.indicator.url.extension": "jpg", - "threatintel.indicator.url.full": "https://univirtek.com/viro/02478080035/blank.jpg", - "threatintel.indicator.url.original": "https://univirtek.com/viro/02478080035/blank.jpg", - "threatintel.indicator.url.path": "/viro/02478080035/blank.jpg", - "threatintel.indicator.url.scheme": "https" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] AbuseCH URL", + "threat.indicator.first_seen": "2021-01-14T20:51:47.000Z", + "threat.indicator.provider": "Cryptolaemus1", + "threat.indicator.reference": "https://urlhaus.abuse.ch/url/961494/", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "univirtek.com", + "threat.indicator.url.extension": "jpg", + "threat.indicator.url.full": "https://univirtek.com/viro/02478080035/blank.jpg", + "threat.indicator.url.original": "https://univirtek.com/viro/02478080035/blank.jpg", + "threat.indicator.url.path": "/viro/02478080035/blank.jpg", + "threat.indicator.url.scheme": "https" }, { + "abusech.url.blacklists.spamhaus_dbl": "not listed", + "abusech.url.blacklists.surbl": "not listed", + "abusech.url.id": "961495", + "abusech.url.larted": false, + "abusech.url.tags": [ + "sLoad" + ], + "abusech.url.threat": "malware_download", + "abusech.url.url_status": "offline", "event.category": "threat", "event.dataset": "threatintel.abuseurl", "event.kind": "enrichment", @@ -1997,27 +2114,29 @@ "forwarded", "threatintel-abuseurls" ], - "threatintel.abuseurl.blacklists.spamhaus_dbl": "not listed", - "threatintel.abuseurl.blacklists.surbl": "not listed", - "threatintel.abuseurl.id": "961495", - "threatintel.abuseurl.larted": false, - "threatintel.abuseurl.tags": [ - "sLoad" - ], - "threatintel.abuseurl.threat": "malware_download", - "threatintel.abuseurl.url_status": "offline", - "threatintel.indicator.first_seen": "2021-01-14T20:51:47.000Z", - "threatintel.indicator.provider": "Cryptolaemus1", - "threatintel.indicator.reference": "https://urlhaus.abuse.ch/url/961495/", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "univirtek.com", - "threatintel.indicator.url.extension": "png", - "threatintel.indicator.url.full": "https://univirtek.com/viro/FRRNDR77C25D325O/map.png", - "threatintel.indicator.url.original": "https://univirtek.com/viro/FRRNDR77C25D325O/map.png", - "threatintel.indicator.url.path": "/viro/FRRNDR77C25D325O/map.png", - "threatintel.indicator.url.scheme": "https" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] AbuseCH URL", + "threat.indicator.first_seen": "2021-01-14T20:51:47.000Z", + "threat.indicator.provider": "Cryptolaemus1", + "threat.indicator.reference": "https://urlhaus.abuse.ch/url/961495/", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "univirtek.com", + "threat.indicator.url.extension": "png", + "threat.indicator.url.full": "https://univirtek.com/viro/FRRNDR77C25D325O/map.png", + "threat.indicator.url.original": "https://univirtek.com/viro/FRRNDR77C25D325O/map.png", + "threat.indicator.url.path": "/viro/FRRNDR77C25D325O/map.png", + "threat.indicator.url.scheme": "https" }, { + "abusech.url.blacklists.spamhaus_dbl": "not listed", + "abusech.url.blacklists.surbl": "not listed", + "abusech.url.id": "961492", + "abusech.url.larted": false, + "abusech.url.tags": [ + "sLoad" + ], + "abusech.url.threat": "malware_download", + "abusech.url.url_status": "offline", "event.category": "threat", "event.dataset": "threatintel.abuseurl", "event.kind": "enrichment", @@ -2031,27 +2150,29 @@ "forwarded", "threatintel-abuseurls" ], - "threatintel.abuseurl.blacklists.spamhaus_dbl": "not listed", - "threatintel.abuseurl.blacklists.surbl": "not listed", - "threatintel.abuseurl.id": "961492", - "threatintel.abuseurl.larted": false, - "threatintel.abuseurl.tags": [ - "sLoad" - ], - "threatintel.abuseurl.threat": "malware_download", - "threatintel.abuseurl.url_status": "offline", - "threatintel.indicator.first_seen": "2021-01-14T20:51:45.000Z", - "threatintel.indicator.provider": "Cryptolaemus1", - "threatintel.indicator.reference": "https://urlhaus.abuse.ch/url/961492/", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "ladiesincode.com", - "threatintel.indicator.url.extension": "jpg", - "threatintel.indicator.url.full": "https://ladiesincode.com/ladi/CNNSRG83H04F158R/blank.jpg", - "threatintel.indicator.url.original": "https://ladiesincode.com/ladi/CNNSRG83H04F158R/blank.jpg", - "threatintel.indicator.url.path": "/ladi/CNNSRG83H04F158R/blank.jpg", - "threatintel.indicator.url.scheme": "https" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] AbuseCH URL", + "threat.indicator.first_seen": "2021-01-14T20:51:45.000Z", + "threat.indicator.provider": "Cryptolaemus1", + "threat.indicator.reference": "https://urlhaus.abuse.ch/url/961492/", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "ladiesincode.com", + "threat.indicator.url.extension": "jpg", + "threat.indicator.url.full": "https://ladiesincode.com/ladi/CNNSRG83H04F158R/blank.jpg", + "threat.indicator.url.original": "https://ladiesincode.com/ladi/CNNSRG83H04F158R/blank.jpg", + "threat.indicator.url.path": "/ladi/CNNSRG83H04F158R/blank.jpg", + "threat.indicator.url.scheme": "https" }, { + "abusech.url.blacklists.spamhaus_dbl": "not listed", + "abusech.url.blacklists.surbl": "not listed", + "abusech.url.id": "961493", + "abusech.url.larted": false, + "abusech.url.tags": [ + "sLoad" + ], + "abusech.url.threat": "malware_download", + "abusech.url.url_status": "offline", "event.category": "threat", "event.dataset": "threatintel.abuseurl", "event.kind": "enrichment", @@ -2065,27 +2186,29 @@ "forwarded", "threatintel-abuseurls" ], - "threatintel.abuseurl.blacklists.spamhaus_dbl": "not listed", - "threatintel.abuseurl.blacklists.surbl": "not listed", - "threatintel.abuseurl.id": "961493", - "threatintel.abuseurl.larted": false, - "threatintel.abuseurl.tags": [ - "sLoad" - ], - "threatintel.abuseurl.threat": "malware_download", - "threatintel.abuseurl.url_status": "offline", - "threatintel.indicator.first_seen": "2021-01-14T20:51:45.000Z", - "threatintel.indicator.provider": "Cryptolaemus1", - "threatintel.indicator.reference": "https://urlhaus.abuse.ch/url/961493/", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "letonguesc.com", - "threatintel.indicator.url.extension": "css", - "threatintel.indicator.url.full": "https://letonguesc.com/leto/02328510512/logo.css", - "threatintel.indicator.url.original": "https://letonguesc.com/leto/02328510512/logo.css", - "threatintel.indicator.url.path": "/leto/02328510512/logo.css", - "threatintel.indicator.url.scheme": "https" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] AbuseCH URL", + "threat.indicator.first_seen": "2021-01-14T20:51:45.000Z", + "threat.indicator.provider": "Cryptolaemus1", + "threat.indicator.reference": "https://urlhaus.abuse.ch/url/961493/", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "letonguesc.com", + "threat.indicator.url.extension": "css", + "threat.indicator.url.full": "https://letonguesc.com/leto/02328510512/logo.css", + "threat.indicator.url.original": "https://letonguesc.com/leto/02328510512/logo.css", + "threat.indicator.url.path": "/leto/02328510512/logo.css", + "threat.indicator.url.scheme": "https" }, { + "abusech.url.blacklists.spamhaus_dbl": "not listed", + "abusech.url.blacklists.surbl": "not listed", + "abusech.url.id": "961490", + "abusech.url.larted": false, + "abusech.url.tags": [ + "sLoad" + ], + "abusech.url.threat": "malware_download", + "abusech.url.url_status": "offline", "event.category": "threat", "event.dataset": "threatintel.abuseurl", "event.kind": "enrichment", @@ -2099,27 +2222,29 @@ "forwarded", "threatintel-abuseurls" ], - "threatintel.abuseurl.blacklists.spamhaus_dbl": "not listed", - "threatintel.abuseurl.blacklists.surbl": "not listed", - "threatintel.abuseurl.id": "961490", - "threatintel.abuseurl.larted": false, - "threatintel.abuseurl.tags": [ - "sLoad" - ], - "threatintel.abuseurl.threat": "malware_download", - "threatintel.abuseurl.url_status": "offline", - "threatintel.indicator.first_seen": "2021-01-14T20:51:44.000Z", - "threatintel.indicator.provider": "Cryptolaemus1", - "threatintel.indicator.reference": "https://urlhaus.abuse.ch/url/961490/", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "cxminute.com", - "threatintel.indicator.url.extension": "png", - "threatintel.indicator.url.full": "https://cxminute.com/minu/MLILSN74B21E507L/uk.png", - "threatintel.indicator.url.original": "https://cxminute.com/minu/MLILSN74B21E507L/uk.png", - "threatintel.indicator.url.path": "/minu/MLILSN74B21E507L/uk.png", - "threatintel.indicator.url.scheme": "https" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] AbuseCH URL", + "threat.indicator.first_seen": "2021-01-14T20:51:44.000Z", + "threat.indicator.provider": "Cryptolaemus1", + "threat.indicator.reference": "https://urlhaus.abuse.ch/url/961490/", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "cxminute.com", + "threat.indicator.url.extension": "png", + "threat.indicator.url.full": "https://cxminute.com/minu/MLILSN74B21E507L/uk.png", + "threat.indicator.url.original": "https://cxminute.com/minu/MLILSN74B21E507L/uk.png", + "threat.indicator.url.path": "/minu/MLILSN74B21E507L/uk.png", + "threat.indicator.url.scheme": "https" }, { + "abusech.url.blacklists.spamhaus_dbl": "not listed", + "abusech.url.blacklists.surbl": "not listed", + "abusech.url.id": "961491", + "abusech.url.larted": false, + "abusech.url.tags": [ + "sLoad" + ], + "abusech.url.threat": "malware_download", + "abusech.url.url_status": "offline", "event.category": "threat", "event.dataset": "threatintel.abuseurl", "event.kind": "enrichment", @@ -2133,27 +2258,29 @@ "forwarded", "threatintel-abuseurls" ], - "threatintel.abuseurl.blacklists.spamhaus_dbl": "not listed", - "threatintel.abuseurl.blacklists.surbl": "not listed", - "threatintel.abuseurl.id": "961491", - "threatintel.abuseurl.larted": false, - "threatintel.abuseurl.tags": [ - "sLoad" - ], - "threatintel.abuseurl.threat": "malware_download", - "threatintel.abuseurl.url_status": "offline", - "threatintel.indicator.first_seen": "2021-01-14T20:51:44.000Z", - "threatintel.indicator.provider": "Cryptolaemus1", - "threatintel.indicator.reference": "https://urlhaus.abuse.ch/url/961491/", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "cxminute.com", - "threatintel.indicator.url.extension": "css", - "threatintel.indicator.url.full": "https://cxminute.com/minu/12875710159/blank.css", - "threatintel.indicator.url.original": "https://cxminute.com/minu/12875710159/blank.css", - "threatintel.indicator.url.path": "/minu/12875710159/blank.css", - "threatintel.indicator.url.scheme": "https" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] AbuseCH URL", + "threat.indicator.first_seen": "2021-01-14T20:51:44.000Z", + "threat.indicator.provider": "Cryptolaemus1", + "threat.indicator.reference": "https://urlhaus.abuse.ch/url/961491/", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "cxminute.com", + "threat.indicator.url.extension": "css", + "threat.indicator.url.full": "https://cxminute.com/minu/12875710159/blank.css", + "threat.indicator.url.original": "https://cxminute.com/minu/12875710159/blank.css", + "threat.indicator.url.path": "/minu/12875710159/blank.css", + "threat.indicator.url.scheme": "https" }, { + "abusech.url.blacklists.spamhaus_dbl": "not listed", + "abusech.url.blacklists.surbl": "not listed", + "abusech.url.id": "961489", + "abusech.url.larted": false, + "abusech.url.tags": [ + "sLoad" + ], + "abusech.url.threat": "malware_download", + "abusech.url.url_status": "offline", "event.category": "threat", "event.dataset": "threatintel.abuseurl", "event.kind": "enrichment", @@ -2167,27 +2294,29 @@ "forwarded", "threatintel-abuseurls" ], - "threatintel.abuseurl.blacklists.spamhaus_dbl": "not listed", - "threatintel.abuseurl.blacklists.surbl": "not listed", - "threatintel.abuseurl.id": "961489", - "threatintel.abuseurl.larted": false, - "threatintel.abuseurl.tags": [ - "sLoad" - ], - "threatintel.abuseurl.threat": "malware_download", - "threatintel.abuseurl.url_status": "offline", - "threatintel.indicator.first_seen": "2021-01-14T20:51:41.000Z", - "threatintel.indicator.provider": "Cryptolaemus1", - "threatintel.indicator.reference": "https://urlhaus.abuse.ch/url/961489/", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "cxminute.com", - "threatintel.indicator.url.extension": "gif", - "threatintel.indicator.url.full": "https://cxminute.com/minu/CPNLNZ65M20A200N/maps.gif", - "threatintel.indicator.url.original": "https://cxminute.com/minu/CPNLNZ65M20A200N/maps.gif", - "threatintel.indicator.url.path": "/minu/CPNLNZ65M20A200N/maps.gif", - "threatintel.indicator.url.scheme": "https" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] AbuseCH URL", + "threat.indicator.first_seen": "2021-01-14T20:51:41.000Z", + "threat.indicator.provider": "Cryptolaemus1", + "threat.indicator.reference": "https://urlhaus.abuse.ch/url/961489/", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "cxminute.com", + "threat.indicator.url.extension": "gif", + "threat.indicator.url.full": "https://cxminute.com/minu/CPNLNZ65M20A200N/maps.gif", + "threat.indicator.url.original": "https://cxminute.com/minu/CPNLNZ65M20A200N/maps.gif", + "threat.indicator.url.path": "/minu/CPNLNZ65M20A200N/maps.gif", + "threat.indicator.url.scheme": "https" }, { + "abusech.url.blacklists.spamhaus_dbl": "not listed", + "abusech.url.blacklists.surbl": "not listed", + "abusech.url.id": "961488", + "abusech.url.larted": false, + "abusech.url.tags": [ + "sLoad" + ], + "abusech.url.threat": "malware_download", + "abusech.url.url_status": "offline", "event.category": "threat", "event.dataset": "threatintel.abuseurl", "event.kind": "enrichment", @@ -2201,27 +2330,29 @@ "forwarded", "threatintel-abuseurls" ], - "threatintel.abuseurl.blacklists.spamhaus_dbl": "not listed", - "threatintel.abuseurl.blacklists.surbl": "not listed", - "threatintel.abuseurl.id": "961488", - "threatintel.abuseurl.larted": false, - "threatintel.abuseurl.tags": [ - "sLoad" - ], - "threatintel.abuseurl.threat": "malware_download", - "threatintel.abuseurl.url_status": "offline", - "threatintel.indicator.first_seen": "2021-01-14T20:51:40.000Z", - "threatintel.indicator.provider": "Cryptolaemus1", - "threatintel.indicator.reference": "https://urlhaus.abuse.ch/url/961488/", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "belfetproduction.com", - "threatintel.indicator.url.extension": "png", - "threatintel.indicator.url.full": "https://belfetproduction.com/bella/DLPCMN64D02D789E/logo.png", - "threatintel.indicator.url.original": "https://belfetproduction.com/bella/DLPCMN64D02D789E/logo.png", - "threatintel.indicator.url.path": "/bella/DLPCMN64D02D789E/logo.png", - "threatintel.indicator.url.scheme": "https" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] AbuseCH URL", + "threat.indicator.first_seen": "2021-01-14T20:51:40.000Z", + "threat.indicator.provider": "Cryptolaemus1", + "threat.indicator.reference": "https://urlhaus.abuse.ch/url/961488/", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "belfetproduction.com", + "threat.indicator.url.extension": "png", + "threat.indicator.url.full": "https://belfetproduction.com/bella/DLPCMN64D02D789E/logo.png", + "threat.indicator.url.original": "https://belfetproduction.com/bella/DLPCMN64D02D789E/logo.png", + "threat.indicator.url.path": "/bella/DLPCMN64D02D789E/logo.png", + "threat.indicator.url.scheme": "https" }, { + "abusech.url.blacklists.spamhaus_dbl": "not listed", + "abusech.url.blacklists.surbl": "not listed", + "abusech.url.id": "961487", + "abusech.url.larted": false, + "abusech.url.tags": [ + "sLoad" + ], + "abusech.url.threat": "malware_download", + "abusech.url.url_status": "offline", "event.category": "threat", "event.dataset": "threatintel.abuseurl", "event.kind": "enrichment", @@ -2235,27 +2366,29 @@ "forwarded", "threatintel-abuseurls" ], - "threatintel.abuseurl.blacklists.spamhaus_dbl": "not listed", - "threatintel.abuseurl.blacklists.surbl": "not listed", - "threatintel.abuseurl.id": "961487", - "threatintel.abuseurl.larted": false, - "threatintel.abuseurl.tags": [ - "sLoad" - ], - "threatintel.abuseurl.threat": "malware_download", - "threatintel.abuseurl.url_status": "offline", - "threatintel.indicator.first_seen": "2021-01-14T20:51:17.000Z", - "threatintel.indicator.provider": "Cryptolaemus1", - "threatintel.indicator.reference": "https://urlhaus.abuse.ch/url/961487/", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "belfetproduction.com", - "threatintel.indicator.url.extension": "jpg", - "threatintel.indicator.url.full": "https://belfetproduction.com/bella/01844510469/1x1.jpg", - "threatintel.indicator.url.original": "https://belfetproduction.com/bella/01844510469/1x1.jpg", - "threatintel.indicator.url.path": "/bella/01844510469/1x1.jpg", - "threatintel.indicator.url.scheme": "https" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] AbuseCH URL", + "threat.indicator.first_seen": "2021-01-14T20:51:17.000Z", + "threat.indicator.provider": "Cryptolaemus1", + "threat.indicator.reference": "https://urlhaus.abuse.ch/url/961487/", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "belfetproduction.com", + "threat.indicator.url.extension": "jpg", + "threat.indicator.url.full": "https://belfetproduction.com/bella/01844510469/1x1.jpg", + "threat.indicator.url.original": "https://belfetproduction.com/bella/01844510469/1x1.jpg", + "threat.indicator.url.path": "/bella/01844510469/1x1.jpg", + "threat.indicator.url.scheme": "https" }, { + "abusech.url.blacklists.spamhaus_dbl": "not listed", + "abusech.url.blacklists.surbl": "not listed", + "abusech.url.id": "961485", + "abusech.url.larted": false, + "abusech.url.tags": [ + "sLoad" + ], + "abusech.url.threat": "malware_download", + "abusech.url.url_status": "offline", "event.category": "threat", "event.dataset": "threatintel.abuseurl", "event.kind": "enrichment", @@ -2269,27 +2402,29 @@ "forwarded", "threatintel-abuseurls" ], - "threatintel.abuseurl.blacklists.spamhaus_dbl": "not listed", - "threatintel.abuseurl.blacklists.surbl": "not listed", - "threatintel.abuseurl.id": "961485", - "threatintel.abuseurl.larted": false, - "threatintel.abuseurl.tags": [ - "sLoad" - ], - "threatintel.abuseurl.threat": "malware_download", - "threatintel.abuseurl.url_status": "offline", - "threatintel.indicator.first_seen": "2021-01-14T20:51:16.000Z", - "threatintel.indicator.provider": "Cryptolaemus1", - "threatintel.indicator.reference": "https://urlhaus.abuse.ch/url/961485/", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "ladiesincode.com", - "threatintel.indicator.url.extension": "css", - "threatintel.indicator.url.full": "https://ladiesincode.com/ladi/FRRDNI52M71E522D/logo.css", - "threatintel.indicator.url.original": "https://ladiesincode.com/ladi/FRRDNI52M71E522D/logo.css", - "threatintel.indicator.url.path": "/ladi/FRRDNI52M71E522D/logo.css", - "threatintel.indicator.url.scheme": "https" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] AbuseCH URL", + "threat.indicator.first_seen": "2021-01-14T20:51:16.000Z", + "threat.indicator.provider": "Cryptolaemus1", + "threat.indicator.reference": "https://urlhaus.abuse.ch/url/961485/", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "ladiesincode.com", + "threat.indicator.url.extension": "css", + "threat.indicator.url.full": "https://ladiesincode.com/ladi/FRRDNI52M71E522D/logo.css", + "threat.indicator.url.original": "https://ladiesincode.com/ladi/FRRDNI52M71E522D/logo.css", + "threat.indicator.url.path": "/ladi/FRRDNI52M71E522D/logo.css", + "threat.indicator.url.scheme": "https" }, { + "abusech.url.blacklists.spamhaus_dbl": "not listed", + "abusech.url.blacklists.surbl": "not listed", + "abusech.url.id": "961486", + "abusech.url.larted": false, + "abusech.url.tags": [ + "sLoad" + ], + "abusech.url.threat": "malware_download", + "abusech.url.url_status": "offline", "event.category": "threat", "event.dataset": "threatintel.abuseurl", "event.kind": "enrichment", @@ -2303,27 +2438,29 @@ "forwarded", "threatintel-abuseurls" ], - "threatintel.abuseurl.blacklists.spamhaus_dbl": "not listed", - "threatintel.abuseurl.blacklists.surbl": "not listed", - "threatintel.abuseurl.id": "961486", - "threatintel.abuseurl.larted": false, - "threatintel.abuseurl.tags": [ - "sLoad" - ], - "threatintel.abuseurl.threat": "malware_download", - "threatintel.abuseurl.url_status": "offline", - "threatintel.indicator.first_seen": "2021-01-14T20:51:16.000Z", - "threatintel.indicator.provider": "Cryptolaemus1", - "threatintel.indicator.reference": "https://urlhaus.abuse.ch/url/961486/", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "letonguesc.com", - "threatintel.indicator.url.extension": "gif", - "threatintel.indicator.url.full": "https://letonguesc.com/leto/CPPMRC65E04H980Q/it.gif", - "threatintel.indicator.url.original": "https://letonguesc.com/leto/CPPMRC65E04H980Q/it.gif", - "threatintel.indicator.url.path": "/leto/CPPMRC65E04H980Q/it.gif", - "threatintel.indicator.url.scheme": "https" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] AbuseCH URL", + "threat.indicator.first_seen": "2021-01-14T20:51:16.000Z", + "threat.indicator.provider": "Cryptolaemus1", + "threat.indicator.reference": "https://urlhaus.abuse.ch/url/961486/", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "letonguesc.com", + "threat.indicator.url.extension": "gif", + "threat.indicator.url.full": "https://letonguesc.com/leto/CPPMRC65E04H980Q/it.gif", + "threat.indicator.url.original": "https://letonguesc.com/leto/CPPMRC65E04H980Q/it.gif", + "threat.indicator.url.path": "/leto/CPPMRC65E04H980Q/it.gif", + "threat.indicator.url.scheme": "https" }, { + "abusech.url.blacklists.spamhaus_dbl": "not listed", + "abusech.url.blacklists.surbl": "not listed", + "abusech.url.id": "961482", + "abusech.url.larted": false, + "abusech.url.tags": [ + "sLoad" + ], + "abusech.url.threat": "malware_download", + "abusech.url.url_status": "offline", "event.category": "threat", "event.dataset": "threatintel.abuseurl", "event.kind": "enrichment", @@ -2337,27 +2474,29 @@ "forwarded", "threatintel-abuseurls" ], - "threatintel.abuseurl.blacklists.spamhaus_dbl": "not listed", - "threatintel.abuseurl.blacklists.surbl": "not listed", - "threatintel.abuseurl.id": "961482", - "threatintel.abuseurl.larted": false, - "threatintel.abuseurl.tags": [ - "sLoad" - ], - "threatintel.abuseurl.threat": "malware_download", - "threatintel.abuseurl.url_status": "offline", - "threatintel.indicator.first_seen": "2021-01-14T20:51:15.000Z", - "threatintel.indicator.provider": "Cryptolaemus1", - "threatintel.indicator.reference": "https://urlhaus.abuse.ch/url/961482/", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "univirtek.com", - "threatintel.indicator.url.extension": "css", - "threatintel.indicator.url.full": "https://univirtek.com/viro/06389650018/it.css", - "threatintel.indicator.url.original": "https://univirtek.com/viro/06389650018/it.css", - "threatintel.indicator.url.path": "/viro/06389650018/it.css", - "threatintel.indicator.url.scheme": "https" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] AbuseCH URL", + "threat.indicator.first_seen": "2021-01-14T20:51:15.000Z", + "threat.indicator.provider": "Cryptolaemus1", + "threat.indicator.reference": "https://urlhaus.abuse.ch/url/961482/", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "univirtek.com", + "threat.indicator.url.extension": "css", + "threat.indicator.url.full": "https://univirtek.com/viro/06389650018/it.css", + "threat.indicator.url.original": "https://univirtek.com/viro/06389650018/it.css", + "threat.indicator.url.path": "/viro/06389650018/it.css", + "threat.indicator.url.scheme": "https" }, { + "abusech.url.blacklists.spamhaus_dbl": "not listed", + "abusech.url.blacklists.surbl": "not listed", + "abusech.url.id": "961483", + "abusech.url.larted": false, + "abusech.url.tags": [ + "sLoad" + ], + "abusech.url.threat": "malware_download", + "abusech.url.url_status": "offline", "event.category": "threat", "event.dataset": "threatintel.abuseurl", "event.kind": "enrichment", @@ -2371,27 +2510,29 @@ "forwarded", "threatintel-abuseurls" ], - "threatintel.abuseurl.blacklists.spamhaus_dbl": "not listed", - "threatintel.abuseurl.blacklists.surbl": "not listed", - "threatintel.abuseurl.id": "961483", - "threatintel.abuseurl.larted": false, - "threatintel.abuseurl.tags": [ - "sLoad" - ], - "threatintel.abuseurl.threat": "malware_download", - "threatintel.abuseurl.url_status": "offline", - "threatintel.indicator.first_seen": "2021-01-14T20:51:15.000Z", - "threatintel.indicator.provider": "Cryptolaemus1", - "threatintel.indicator.reference": "https://urlhaus.abuse.ch/url/961483/", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "belfetproduction.com", - "threatintel.indicator.url.extension": "png", - "threatintel.indicator.url.full": "https://belfetproduction.com/bella/CRSRRT61E15H501H/logo.png", - "threatintel.indicator.url.original": "https://belfetproduction.com/bella/CRSRRT61E15H501H/logo.png", - "threatintel.indicator.url.path": "/bella/CRSRRT61E15H501H/logo.png", - "threatintel.indicator.url.scheme": "https" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] AbuseCH URL", + "threat.indicator.first_seen": "2021-01-14T20:51:15.000Z", + "threat.indicator.provider": "Cryptolaemus1", + "threat.indicator.reference": "https://urlhaus.abuse.ch/url/961483/", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "belfetproduction.com", + "threat.indicator.url.extension": "png", + "threat.indicator.url.full": "https://belfetproduction.com/bella/CRSRRT61E15H501H/logo.png", + "threat.indicator.url.original": "https://belfetproduction.com/bella/CRSRRT61E15H501H/logo.png", + "threat.indicator.url.path": "/bella/CRSRRT61E15H501H/logo.png", + "threat.indicator.url.scheme": "https" }, { + "abusech.url.blacklists.spamhaus_dbl": "not listed", + "abusech.url.blacklists.surbl": "not listed", + "abusech.url.id": "961484", + "abusech.url.larted": false, + "abusech.url.tags": [ + "sLoad" + ], + "abusech.url.threat": "malware_download", + "abusech.url.url_status": "offline", "event.category": "threat", "event.dataset": "threatintel.abuseurl", "event.kind": "enrichment", @@ -2405,27 +2546,29 @@ "forwarded", "threatintel-abuseurls" ], - "threatintel.abuseurl.blacklists.spamhaus_dbl": "not listed", - "threatintel.abuseurl.blacklists.surbl": "not listed", - "threatintel.abuseurl.id": "961484", - "threatintel.abuseurl.larted": false, - "threatintel.abuseurl.tags": [ - "sLoad" - ], - "threatintel.abuseurl.threat": "malware_download", - "threatintel.abuseurl.url_status": "offline", - "threatintel.indicator.first_seen": "2021-01-14T20:51:15.000Z", - "threatintel.indicator.provider": "Cryptolaemus1", - "threatintel.indicator.reference": "https://urlhaus.abuse.ch/url/961484/", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "cxminute.com", - "threatintel.indicator.url.extension": "jpg", - "threatintel.indicator.url.full": "https://cxminute.com/minu/SMPMSM67P05F205U/it.jpg", - "threatintel.indicator.url.original": "https://cxminute.com/minu/SMPMSM67P05F205U/it.jpg", - "threatintel.indicator.url.path": "/minu/SMPMSM67P05F205U/it.jpg", - "threatintel.indicator.url.scheme": "https" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] AbuseCH URL", + "threat.indicator.first_seen": "2021-01-14T20:51:15.000Z", + "threat.indicator.provider": "Cryptolaemus1", + "threat.indicator.reference": "https://urlhaus.abuse.ch/url/961484/", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "cxminute.com", + "threat.indicator.url.extension": "jpg", + "threat.indicator.url.full": "https://cxminute.com/minu/SMPMSM67P05F205U/it.jpg", + "threat.indicator.url.original": "https://cxminute.com/minu/SMPMSM67P05F205U/it.jpg", + "threat.indicator.url.path": "/minu/SMPMSM67P05F205U/it.jpg", + "threat.indicator.url.scheme": "https" }, { + "abusech.url.blacklists.spamhaus_dbl": "not listed", + "abusech.url.blacklists.surbl": "not listed", + "abusech.url.id": "961480", + "abusech.url.larted": false, + "abusech.url.tags": [ + "sLoad" + ], + "abusech.url.threat": "malware_download", + "abusech.url.url_status": "offline", "event.category": "threat", "event.dataset": "threatintel.abuseurl", "event.kind": "enrichment", @@ -2439,27 +2582,29 @@ "forwarded", "threatintel-abuseurls" ], - "threatintel.abuseurl.blacklists.spamhaus_dbl": "not listed", - "threatintel.abuseurl.blacklists.surbl": "not listed", - "threatintel.abuseurl.id": "961480", - "threatintel.abuseurl.larted": false, - "threatintel.abuseurl.tags": [ - "sLoad" - ], - "threatintel.abuseurl.threat": "malware_download", - "threatintel.abuseurl.url_status": "offline", - "threatintel.indicator.first_seen": "2021-01-14T20:51:13.000Z", - "threatintel.indicator.provider": "Cryptolaemus1", - "threatintel.indicator.reference": "https://urlhaus.abuse.ch/url/961480/", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "univirtek.com", - "threatintel.indicator.url.extension": "png", - "threatintel.indicator.url.full": "https://univirtek.com/viro/SBNPQL78A24A783E/uk.png", - "threatintel.indicator.url.original": "https://univirtek.com/viro/SBNPQL78A24A783E/uk.png", - "threatintel.indicator.url.path": "/viro/SBNPQL78A24A783E/uk.png", - "threatintel.indicator.url.scheme": "https" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] AbuseCH URL", + "threat.indicator.first_seen": "2021-01-14T20:51:13.000Z", + "threat.indicator.provider": "Cryptolaemus1", + "threat.indicator.reference": "https://urlhaus.abuse.ch/url/961480/", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "univirtek.com", + "threat.indicator.url.extension": "png", + "threat.indicator.url.full": "https://univirtek.com/viro/SBNPQL78A24A783E/uk.png", + "threat.indicator.url.original": "https://univirtek.com/viro/SBNPQL78A24A783E/uk.png", + "threat.indicator.url.path": "/viro/SBNPQL78A24A783E/uk.png", + "threat.indicator.url.scheme": "https" }, { + "abusech.url.blacklists.spamhaus_dbl": "not listed", + "abusech.url.blacklists.surbl": "not listed", + "abusech.url.id": "961481", + "abusech.url.larted": false, + "abusech.url.tags": [ + "sLoad" + ], + "abusech.url.threat": "malware_download", + "abusech.url.url_status": "offline", "event.category": "threat", "event.dataset": "threatintel.abuseurl", "event.kind": "enrichment", @@ -2473,27 +2618,29 @@ "forwarded", "threatintel-abuseurls" ], - "threatintel.abuseurl.blacklists.spamhaus_dbl": "not listed", - "threatintel.abuseurl.blacklists.surbl": "not listed", - "threatintel.abuseurl.id": "961481", - "threatintel.abuseurl.larted": false, - "threatintel.abuseurl.tags": [ - "sLoad" - ], - "threatintel.abuseurl.threat": "malware_download", - "threatintel.abuseurl.url_status": "offline", - "threatintel.indicator.first_seen": "2021-01-14T20:51:13.000Z", - "threatintel.indicator.provider": "Cryptolaemus1", - "threatintel.indicator.reference": "https://urlhaus.abuse.ch/url/961481/", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "cxminute.com", - "threatintel.indicator.url.extension": "jpg", - "threatintel.indicator.url.full": "https://cxminute.com/minu/15578761007/maps.jpg", - "threatintel.indicator.url.original": "https://cxminute.com/minu/15578761007/maps.jpg", - "threatintel.indicator.url.path": "/minu/15578761007/maps.jpg", - "threatintel.indicator.url.scheme": "https" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] AbuseCH URL", + "threat.indicator.first_seen": "2021-01-14T20:51:13.000Z", + "threat.indicator.provider": "Cryptolaemus1", + "threat.indicator.reference": "https://urlhaus.abuse.ch/url/961481/", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "cxminute.com", + "threat.indicator.url.extension": "jpg", + "threat.indicator.url.full": "https://cxminute.com/minu/15578761007/maps.jpg", + "threat.indicator.url.original": "https://cxminute.com/minu/15578761007/maps.jpg", + "threat.indicator.url.path": "/minu/15578761007/maps.jpg", + "threat.indicator.url.scheme": "https" }, { + "abusech.url.blacklists.spamhaus_dbl": "not listed", + "abusech.url.blacklists.surbl": "not listed", + "abusech.url.id": "961478", + "abusech.url.larted": false, + "abusech.url.tags": [ + "sLoad" + ], + "abusech.url.threat": "malware_download", + "abusech.url.url_status": "offline", "event.category": "threat", "event.dataset": "threatintel.abuseurl", "event.kind": "enrichment", @@ -2507,27 +2654,29 @@ "forwarded", "threatintel-abuseurls" ], - "threatintel.abuseurl.blacklists.spamhaus_dbl": "not listed", - "threatintel.abuseurl.blacklists.surbl": "not listed", - "threatintel.abuseurl.id": "961478", - "threatintel.abuseurl.larted": false, - "threatintel.abuseurl.tags": [ - "sLoad" - ], - "threatintel.abuseurl.threat": "malware_download", - "threatintel.abuseurl.url_status": "offline", - "threatintel.indicator.first_seen": "2021-01-14T20:51:10.000Z", - "threatintel.indicator.provider": "Cryptolaemus1", - "threatintel.indicator.reference": "https://urlhaus.abuse.ch/url/961478/", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "univirtek.com", - "threatintel.indicator.url.extension": "png", - "threatintel.indicator.url.full": "https://univirtek.com/viro/03079590133/1x1.png", - "threatintel.indicator.url.original": "https://univirtek.com/viro/03079590133/1x1.png", - "threatintel.indicator.url.path": "/viro/03079590133/1x1.png", - "threatintel.indicator.url.scheme": "https" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] AbuseCH URL", + "threat.indicator.first_seen": "2021-01-14T20:51:10.000Z", + "threat.indicator.provider": "Cryptolaemus1", + "threat.indicator.reference": "https://urlhaus.abuse.ch/url/961478/", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "univirtek.com", + "threat.indicator.url.extension": "png", + "threat.indicator.url.full": "https://univirtek.com/viro/03079590133/1x1.png", + "threat.indicator.url.original": "https://univirtek.com/viro/03079590133/1x1.png", + "threat.indicator.url.path": "/viro/03079590133/1x1.png", + "threat.indicator.url.scheme": "https" }, { + "abusech.url.blacklists.spamhaus_dbl": "not listed", + "abusech.url.blacklists.surbl": "not listed", + "abusech.url.id": "961479", + "abusech.url.larted": false, + "abusech.url.tags": [ + "sLoad" + ], + "abusech.url.threat": "malware_download", + "abusech.url.url_status": "offline", "event.category": "threat", "event.dataset": "threatintel.abuseurl", "event.kind": "enrichment", @@ -2541,27 +2690,29 @@ "forwarded", "threatintel-abuseurls" ], - "threatintel.abuseurl.blacklists.spamhaus_dbl": "not listed", - "threatintel.abuseurl.blacklists.surbl": "not listed", - "threatintel.abuseurl.id": "961479", - "threatintel.abuseurl.larted": false, - "threatintel.abuseurl.tags": [ - "sLoad" - ], - "threatintel.abuseurl.threat": "malware_download", - "threatintel.abuseurl.url_status": "offline", - "threatintel.indicator.first_seen": "2021-01-14T20:51:10.000Z", - "threatintel.indicator.provider": "Cryptolaemus1", - "threatintel.indicator.reference": "https://urlhaus.abuse.ch/url/961479/", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "ladiesincode.com", - "threatintel.indicator.url.extension": "gif", - "threatintel.indicator.url.full": "https://ladiesincode.com/ladi/BNCLNR77T56M082U/it.gif", - "threatintel.indicator.url.original": "https://ladiesincode.com/ladi/BNCLNR77T56M082U/it.gif", - "threatintel.indicator.url.path": "/ladi/BNCLNR77T56M082U/it.gif", - "threatintel.indicator.url.scheme": "https" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] AbuseCH URL", + "threat.indicator.first_seen": "2021-01-14T20:51:10.000Z", + "threat.indicator.provider": "Cryptolaemus1", + "threat.indicator.reference": "https://urlhaus.abuse.ch/url/961479/", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "ladiesincode.com", + "threat.indicator.url.extension": "gif", + "threat.indicator.url.full": "https://ladiesincode.com/ladi/BNCLNR77T56M082U/it.gif", + "threat.indicator.url.original": "https://ladiesincode.com/ladi/BNCLNR77T56M082U/it.gif", + "threat.indicator.url.path": "/ladi/BNCLNR77T56M082U/it.gif", + "threat.indicator.url.scheme": "https" }, { + "abusech.url.blacklists.spamhaus_dbl": "not listed", + "abusech.url.blacklists.surbl": "not listed", + "abusech.url.id": "961476", + "abusech.url.larted": false, + "abusech.url.tags": [ + "sLoad" + ], + "abusech.url.threat": "malware_download", + "abusech.url.url_status": "offline", "event.category": "threat", "event.dataset": "threatintel.abuseurl", "event.kind": "enrichment", @@ -2575,27 +2726,29 @@ "forwarded", "threatintel-abuseurls" ], - "threatintel.abuseurl.blacklists.spamhaus_dbl": "not listed", - "threatintel.abuseurl.blacklists.surbl": "not listed", - "threatintel.abuseurl.id": "961476", - "threatintel.abuseurl.larted": false, - "threatintel.abuseurl.tags": [ - "sLoad" - ], - "threatintel.abuseurl.threat": "malware_download", - "threatintel.abuseurl.url_status": "offline", - "threatintel.indicator.first_seen": "2021-01-14T20:50:45.000Z", - "threatintel.indicator.provider": "Cryptolaemus1", - "threatintel.indicator.reference": "https://urlhaus.abuse.ch/url/961476/", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "cxminute.com", - "threatintel.indicator.url.extension": "css", - "threatintel.indicator.url.full": "https://cxminute.com/minu/JNKMTJ64B29L424O/uk.css", - "threatintel.indicator.url.original": "https://cxminute.com/minu/JNKMTJ64B29L424O/uk.css", - "threatintel.indicator.url.path": "/minu/JNKMTJ64B29L424O/uk.css", - "threatintel.indicator.url.scheme": "https" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] AbuseCH URL", + "threat.indicator.first_seen": "2021-01-14T20:50:45.000Z", + "threat.indicator.provider": "Cryptolaemus1", + "threat.indicator.reference": "https://urlhaus.abuse.ch/url/961476/", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "cxminute.com", + "threat.indicator.url.extension": "css", + "threat.indicator.url.full": "https://cxminute.com/minu/JNKMTJ64B29L424O/uk.css", + "threat.indicator.url.original": "https://cxminute.com/minu/JNKMTJ64B29L424O/uk.css", + "threat.indicator.url.path": "/minu/JNKMTJ64B29L424O/uk.css", + "threat.indicator.url.scheme": "https" }, { + "abusech.url.blacklists.spamhaus_dbl": "not listed", + "abusech.url.blacklists.surbl": "not listed", + "abusech.url.id": "961477", + "abusech.url.larted": false, + "abusech.url.tags": [ + "sLoad" + ], + "abusech.url.threat": "malware_download", + "abusech.url.url_status": "offline", "event.category": "threat", "event.dataset": "threatintel.abuseurl", "event.kind": "enrichment", @@ -2609,27 +2762,29 @@ "forwarded", "threatintel-abuseurls" ], - "threatintel.abuseurl.blacklists.spamhaus_dbl": "not listed", - "threatintel.abuseurl.blacklists.surbl": "not listed", - "threatintel.abuseurl.id": "961477", - "threatintel.abuseurl.larted": false, - "threatintel.abuseurl.tags": [ - "sLoad" - ], - "threatintel.abuseurl.threat": "malware_download", - "threatintel.abuseurl.url_status": "offline", - "threatintel.indicator.first_seen": "2021-01-14T20:50:45.000Z", - "threatintel.indicator.provider": "Cryptolaemus1", - "threatintel.indicator.reference": "https://urlhaus.abuse.ch/url/961477/", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "belfetproduction.com", - "threatintel.indicator.url.extension": "png", - "threatintel.indicator.url.full": "https://belfetproduction.com/bella/PGNMRA64S22I608Z/en.png", - "threatintel.indicator.url.original": "https://belfetproduction.com/bella/PGNMRA64S22I608Z/en.png", - "threatintel.indicator.url.path": "/bella/PGNMRA64S22I608Z/en.png", - "threatintel.indicator.url.scheme": "https" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] AbuseCH URL", + "threat.indicator.first_seen": "2021-01-14T20:50:45.000Z", + "threat.indicator.provider": "Cryptolaemus1", + "threat.indicator.reference": "https://urlhaus.abuse.ch/url/961477/", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "belfetproduction.com", + "threat.indicator.url.extension": "png", + "threat.indicator.url.full": "https://belfetproduction.com/bella/PGNMRA64S22I608Z/en.png", + "threat.indicator.url.original": "https://belfetproduction.com/bella/PGNMRA64S22I608Z/en.png", + "threat.indicator.url.path": "/bella/PGNMRA64S22I608Z/en.png", + "threat.indicator.url.scheme": "https" }, { + "abusech.url.blacklists.spamhaus_dbl": "not listed", + "abusech.url.blacklists.surbl": "not listed", + "abusech.url.id": "961470", + "abusech.url.larted": false, + "abusech.url.tags": [ + "sLoad" + ], + "abusech.url.threat": "malware_download", + "abusech.url.url_status": "offline", "event.category": "threat", "event.dataset": "threatintel.abuseurl", "event.kind": "enrichment", @@ -2643,27 +2798,29 @@ "forwarded", "threatintel-abuseurls" ], - "threatintel.abuseurl.blacklists.spamhaus_dbl": "not listed", - "threatintel.abuseurl.blacklists.surbl": "not listed", - "threatintel.abuseurl.id": "961470", - "threatintel.abuseurl.larted": false, - "threatintel.abuseurl.tags": [ - "sLoad" - ], - "threatintel.abuseurl.threat": "malware_download", - "threatintel.abuseurl.url_status": "offline", - "threatintel.indicator.first_seen": "2021-01-14T20:50:43.000Z", - "threatintel.indicator.provider": "Cryptolaemus1", - "threatintel.indicator.reference": "https://urlhaus.abuse.ch/url/961470/", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "cxminute.com", - "threatintel.indicator.url.extension": "jpg", - "threatintel.indicator.url.full": "https://cxminute.com/minu/RZKDRD77T23Z229T/logo.jpg", - "threatintel.indicator.url.original": "https://cxminute.com/minu/RZKDRD77T23Z229T/logo.jpg", - "threatintel.indicator.url.path": "/minu/RZKDRD77T23Z229T/logo.jpg", - "threatintel.indicator.url.scheme": "https" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] AbuseCH URL", + "threat.indicator.first_seen": "2021-01-14T20:50:43.000Z", + "threat.indicator.provider": "Cryptolaemus1", + "threat.indicator.reference": "https://urlhaus.abuse.ch/url/961470/", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "cxminute.com", + "threat.indicator.url.extension": "jpg", + "threat.indicator.url.full": "https://cxminute.com/minu/RZKDRD77T23Z229T/logo.jpg", + "threat.indicator.url.original": "https://cxminute.com/minu/RZKDRD77T23Z229T/logo.jpg", + "threat.indicator.url.path": "/minu/RZKDRD77T23Z229T/logo.jpg", + "threat.indicator.url.scheme": "https" }, { + "abusech.url.blacklists.spamhaus_dbl": "not listed", + "abusech.url.blacklists.surbl": "not listed", + "abusech.url.id": "961471", + "abusech.url.larted": false, + "abusech.url.tags": [ + "sLoad" + ], + "abusech.url.threat": "malware_download", + "abusech.url.url_status": "offline", "event.category": "threat", "event.dataset": "threatintel.abuseurl", "event.kind": "enrichment", @@ -2677,27 +2834,29 @@ "forwarded", "threatintel-abuseurls" ], - "threatintel.abuseurl.blacklists.spamhaus_dbl": "not listed", - "threatintel.abuseurl.blacklists.surbl": "not listed", - "threatintel.abuseurl.id": "961471", - "threatintel.abuseurl.larted": false, - "threatintel.abuseurl.tags": [ - "sLoad" - ], - "threatintel.abuseurl.threat": "malware_download", - "threatintel.abuseurl.url_status": "offline", - "threatintel.indicator.first_seen": "2021-01-14T20:50:43.000Z", - "threatintel.indicator.provider": "Cryptolaemus1", - "threatintel.indicator.reference": "https://urlhaus.abuse.ch/url/961471/", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "fhivelifestyle.online", - "threatintel.indicator.url.extension": "jpg", - "threatintel.indicator.url.full": "https://fhivelifestyle.online/nhbrwvdffsgt/adf/maps.jpg", - "threatintel.indicator.url.original": "https://fhivelifestyle.online/nhbrwvdffsgt/adf/maps.jpg", - "threatintel.indicator.url.path": "/nhbrwvdffsgt/adf/maps.jpg", - "threatintel.indicator.url.scheme": "https" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] AbuseCH URL", + "threat.indicator.first_seen": "2021-01-14T20:50:43.000Z", + "threat.indicator.provider": "Cryptolaemus1", + "threat.indicator.reference": "https://urlhaus.abuse.ch/url/961471/", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "fhivelifestyle.online", + "threat.indicator.url.extension": "jpg", + "threat.indicator.url.full": "https://fhivelifestyle.online/nhbrwvdffsgt/adf/maps.jpg", + "threat.indicator.url.original": "https://fhivelifestyle.online/nhbrwvdffsgt/adf/maps.jpg", + "threat.indicator.url.path": "/nhbrwvdffsgt/adf/maps.jpg", + "threat.indicator.url.scheme": "https" }, { + "abusech.url.blacklists.spamhaus_dbl": "not listed", + "abusech.url.blacklists.surbl": "not listed", + "abusech.url.id": "961472", + "abusech.url.larted": false, + "abusech.url.tags": [ + "sLoad" + ], + "abusech.url.threat": "malware_download", + "abusech.url.url_status": "offline", "event.category": "threat", "event.dataset": "threatintel.abuseurl", "event.kind": "enrichment", @@ -2711,27 +2870,29 @@ "forwarded", "threatintel-abuseurls" ], - "threatintel.abuseurl.blacklists.spamhaus_dbl": "not listed", - "threatintel.abuseurl.blacklists.surbl": "not listed", - "threatintel.abuseurl.id": "961472", - "threatintel.abuseurl.larted": false, - "threatintel.abuseurl.tags": [ - "sLoad" - ], - "threatintel.abuseurl.threat": "malware_download", - "threatintel.abuseurl.url_status": "offline", - "threatintel.indicator.first_seen": "2021-01-14T20:50:43.000Z", - "threatintel.indicator.provider": "Cryptolaemus1", - "threatintel.indicator.reference": "https://urlhaus.abuse.ch/url/961472/", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "belfetproduction.com", - "threatintel.indicator.url.extension": "css", - "threatintel.indicator.url.full": "https://belfetproduction.com/bella/05739900487/1x1.css", - "threatintel.indicator.url.original": "https://belfetproduction.com/bella/05739900487/1x1.css", - "threatintel.indicator.url.path": "/bella/05739900487/1x1.css", - "threatintel.indicator.url.scheme": "https" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] AbuseCH URL", + "threat.indicator.first_seen": "2021-01-14T20:50:43.000Z", + "threat.indicator.provider": "Cryptolaemus1", + "threat.indicator.reference": "https://urlhaus.abuse.ch/url/961472/", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "belfetproduction.com", + "threat.indicator.url.extension": "css", + "threat.indicator.url.full": "https://belfetproduction.com/bella/05739900487/1x1.css", + "threat.indicator.url.original": "https://belfetproduction.com/bella/05739900487/1x1.css", + "threat.indicator.url.path": "/bella/05739900487/1x1.css", + "threat.indicator.url.scheme": "https" }, { + "abusech.url.blacklists.spamhaus_dbl": "not listed", + "abusech.url.blacklists.surbl": "not listed", + "abusech.url.id": "961473", + "abusech.url.larted": false, + "abusech.url.tags": [ + "sLoad" + ], + "abusech.url.threat": "malware_download", + "abusech.url.url_status": "offline", "event.category": "threat", "event.dataset": "threatintel.abuseurl", "event.kind": "enrichment", @@ -2745,27 +2906,29 @@ "forwarded", "threatintel-abuseurls" ], - "threatintel.abuseurl.blacklists.spamhaus_dbl": "not listed", - "threatintel.abuseurl.blacklists.surbl": "not listed", - "threatintel.abuseurl.id": "961473", - "threatintel.abuseurl.larted": false, - "threatintel.abuseurl.tags": [ - "sLoad" - ], - "threatintel.abuseurl.threat": "malware_download", - "threatintel.abuseurl.url_status": "offline", - "threatintel.indicator.first_seen": "2021-01-14T20:50:43.000Z", - "threatintel.indicator.provider": "Cryptolaemus1", - "threatintel.indicator.reference": "https://urlhaus.abuse.ch/url/961473/", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "belfetproduction.com", - "threatintel.indicator.url.extension": "css", - "threatintel.indicator.url.full": "https://belfetproduction.com/bella/01767180597/map.css", - "threatintel.indicator.url.original": "https://belfetproduction.com/bella/01767180597/map.css", - "threatintel.indicator.url.path": "/bella/01767180597/map.css", - "threatintel.indicator.url.scheme": "https" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] AbuseCH URL", + "threat.indicator.first_seen": "2021-01-14T20:50:43.000Z", + "threat.indicator.provider": "Cryptolaemus1", + "threat.indicator.reference": "https://urlhaus.abuse.ch/url/961473/", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "belfetproduction.com", + "threat.indicator.url.extension": "css", + "threat.indicator.url.full": "https://belfetproduction.com/bella/01767180597/map.css", + "threat.indicator.url.original": "https://belfetproduction.com/bella/01767180597/map.css", + "threat.indicator.url.path": "/bella/01767180597/map.css", + "threat.indicator.url.scheme": "https" }, { + "abusech.url.blacklists.spamhaus_dbl": "not listed", + "abusech.url.blacklists.surbl": "not listed", + "abusech.url.id": "961474", + "abusech.url.larted": false, + "abusech.url.tags": [ + "sLoad" + ], + "abusech.url.threat": "malware_download", + "abusech.url.url_status": "offline", "event.category": "threat", "event.dataset": "threatintel.abuseurl", "event.kind": "enrichment", @@ -2779,27 +2942,29 @@ "forwarded", "threatintel-abuseurls" ], - "threatintel.abuseurl.blacklists.spamhaus_dbl": "not listed", - "threatintel.abuseurl.blacklists.surbl": "not listed", - "threatintel.abuseurl.id": "961474", - "threatintel.abuseurl.larted": false, - "threatintel.abuseurl.tags": [ - "sLoad" - ], - "threatintel.abuseurl.threat": "malware_download", - "threatintel.abuseurl.url_status": "offline", - "threatintel.indicator.first_seen": "2021-01-14T20:50:43.000Z", - "threatintel.indicator.provider": "Cryptolaemus1", - "threatintel.indicator.reference": "https://urlhaus.abuse.ch/url/961474/", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "belfetproduction.com", - "threatintel.indicator.url.extension": "css", - "threatintel.indicator.url.full": "https://belfetproduction.com/bella/BRNGRG55D21F394K/map.css", - "threatintel.indicator.url.original": "https://belfetproduction.com/bella/BRNGRG55D21F394K/map.css", - "threatintel.indicator.url.path": "/bella/BRNGRG55D21F394K/map.css", - "threatintel.indicator.url.scheme": "https" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] AbuseCH URL", + "threat.indicator.first_seen": "2021-01-14T20:50:43.000Z", + "threat.indicator.provider": "Cryptolaemus1", + "threat.indicator.reference": "https://urlhaus.abuse.ch/url/961474/", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "belfetproduction.com", + "threat.indicator.url.extension": "css", + "threat.indicator.url.full": "https://belfetproduction.com/bella/BRNGRG55D21F394K/map.css", + "threat.indicator.url.original": "https://belfetproduction.com/bella/BRNGRG55D21F394K/map.css", + "threat.indicator.url.path": "/bella/BRNGRG55D21F394K/map.css", + "threat.indicator.url.scheme": "https" }, { + "abusech.url.blacklists.spamhaus_dbl": "not listed", + "abusech.url.blacklists.surbl": "not listed", + "abusech.url.id": "961475", + "abusech.url.larted": false, + "abusech.url.tags": [ + "sLoad" + ], + "abusech.url.threat": "malware_download", + "abusech.url.url_status": "offline", "event.category": "threat", "event.dataset": "threatintel.abuseurl", "event.kind": "enrichment", @@ -2813,27 +2978,29 @@ "forwarded", "threatintel-abuseurls" ], - "threatintel.abuseurl.blacklists.spamhaus_dbl": "not listed", - "threatintel.abuseurl.blacklists.surbl": "not listed", - "threatintel.abuseurl.id": "961475", - "threatintel.abuseurl.larted": false, - "threatintel.abuseurl.tags": [ - "sLoad" - ], - "threatintel.abuseurl.threat": "malware_download", - "threatintel.abuseurl.url_status": "offline", - "threatintel.indicator.first_seen": "2021-01-14T20:50:43.000Z", - "threatintel.indicator.provider": "Cryptolaemus1", - "threatintel.indicator.reference": "https://urlhaus.abuse.ch/url/961475/", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "cxminute.com", - "threatintel.indicator.url.extension": "css", - "threatintel.indicator.url.full": "https://cxminute.com/minu/DLLTZN67L20L157J/1x1.css", - "threatintel.indicator.url.original": "https://cxminute.com/minu/DLLTZN67L20L157J/1x1.css", - "threatintel.indicator.url.path": "/minu/DLLTZN67L20L157J/1x1.css", - "threatintel.indicator.url.scheme": "https" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] AbuseCH URL", + "threat.indicator.first_seen": "2021-01-14T20:50:43.000Z", + "threat.indicator.provider": "Cryptolaemus1", + "threat.indicator.reference": "https://urlhaus.abuse.ch/url/961475/", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "cxminute.com", + "threat.indicator.url.extension": "css", + "threat.indicator.url.full": "https://cxminute.com/minu/DLLTZN67L20L157J/1x1.css", + "threat.indicator.url.original": "https://cxminute.com/minu/DLLTZN67L20L157J/1x1.css", + "threat.indicator.url.path": "/minu/DLLTZN67L20L157J/1x1.css", + "threat.indicator.url.scheme": "https" }, { + "abusech.url.blacklists.spamhaus_dbl": "not listed", + "abusech.url.blacklists.surbl": "not listed", + "abusech.url.id": "961468", + "abusech.url.larted": false, + "abusech.url.tags": [ + "sLoad" + ], + "abusech.url.threat": "malware_download", + "abusech.url.url_status": "offline", "event.category": "threat", "event.dataset": "threatintel.abuseurl", "event.kind": "enrichment", @@ -2847,27 +3014,29 @@ "forwarded", "threatintel-abuseurls" ], - "threatintel.abuseurl.blacklists.spamhaus_dbl": "not listed", - "threatintel.abuseurl.blacklists.surbl": "not listed", - "threatintel.abuseurl.id": "961468", - "threatintel.abuseurl.larted": false, - "threatintel.abuseurl.tags": [ - "sLoad" - ], - "threatintel.abuseurl.threat": "malware_download", - "threatintel.abuseurl.url_status": "offline", - "threatintel.indicator.first_seen": "2021-01-14T20:50:38.000Z", - "threatintel.indicator.provider": "Cryptolaemus1", - "threatintel.indicator.reference": "https://urlhaus.abuse.ch/url/961468/", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "cxminute.com", - "threatintel.indicator.url.extension": "jpg", - "threatintel.indicator.url.full": "https://cxminute.com/minu/08035410722/logo.jpg", - "threatintel.indicator.url.original": "https://cxminute.com/minu/08035410722/logo.jpg", - "threatintel.indicator.url.path": "/minu/08035410722/logo.jpg", - "threatintel.indicator.url.scheme": "https" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] AbuseCH URL", + "threat.indicator.first_seen": "2021-01-14T20:50:38.000Z", + "threat.indicator.provider": "Cryptolaemus1", + "threat.indicator.reference": "https://urlhaus.abuse.ch/url/961468/", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "cxminute.com", + "threat.indicator.url.extension": "jpg", + "threat.indicator.url.full": "https://cxminute.com/minu/08035410722/logo.jpg", + "threat.indicator.url.original": "https://cxminute.com/minu/08035410722/logo.jpg", + "threat.indicator.url.path": "/minu/08035410722/logo.jpg", + "threat.indicator.url.scheme": "https" }, { + "abusech.url.blacklists.spamhaus_dbl": "not listed", + "abusech.url.blacklists.surbl": "not listed", + "abusech.url.id": "961469", + "abusech.url.larted": false, + "abusech.url.tags": [ + "sLoad" + ], + "abusech.url.threat": "malware_download", + "abusech.url.url_status": "offline", "event.category": "threat", "event.dataset": "threatintel.abuseurl", "event.kind": "enrichment", @@ -2881,27 +3050,29 @@ "forwarded", "threatintel-abuseurls" ], - "threatintel.abuseurl.blacklists.spamhaus_dbl": "not listed", - "threatintel.abuseurl.blacklists.surbl": "not listed", - "threatintel.abuseurl.id": "961469", - "threatintel.abuseurl.larted": false, - "threatintel.abuseurl.tags": [ - "sLoad" - ], - "threatintel.abuseurl.threat": "malware_download", - "threatintel.abuseurl.url_status": "offline", - "threatintel.indicator.first_seen": "2021-01-14T20:50:38.000Z", - "threatintel.indicator.provider": "Cryptolaemus1", - "threatintel.indicator.reference": "https://urlhaus.abuse.ch/url/961469/", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "univirtek.com", - "threatintel.indicator.url.extension": "css", - "threatintel.indicator.url.full": "https://univirtek.com/viro/GRNZEI60M13G346L/en.css", - "threatintel.indicator.url.original": "https://univirtek.com/viro/GRNZEI60M13G346L/en.css", - "threatintel.indicator.url.path": "/viro/GRNZEI60M13G346L/en.css", - "threatintel.indicator.url.scheme": "https" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] AbuseCH URL", + "threat.indicator.first_seen": "2021-01-14T20:50:38.000Z", + "threat.indicator.provider": "Cryptolaemus1", + "threat.indicator.reference": "https://urlhaus.abuse.ch/url/961469/", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "univirtek.com", + "threat.indicator.url.extension": "css", + "threat.indicator.url.full": "https://univirtek.com/viro/GRNZEI60M13G346L/en.css", + "threat.indicator.url.original": "https://univirtek.com/viro/GRNZEI60M13G346L/en.css", + "threat.indicator.url.path": "/viro/GRNZEI60M13G346L/en.css", + "threat.indicator.url.scheme": "https" }, { + "abusech.url.blacklists.spamhaus_dbl": "not listed", + "abusech.url.blacklists.surbl": "not listed", + "abusech.url.id": "961467", + "abusech.url.larted": false, + "abusech.url.tags": [ + "sLoad" + ], + "abusech.url.threat": "malware_download", + "abusech.url.url_status": "offline", "event.category": "threat", "event.dataset": "threatintel.abuseurl", "event.kind": "enrichment", @@ -2915,27 +3086,29 @@ "forwarded", "threatintel-abuseurls" ], - "threatintel.abuseurl.blacklists.spamhaus_dbl": "not listed", - "threatintel.abuseurl.blacklists.surbl": "not listed", - "threatintel.abuseurl.id": "961467", - "threatintel.abuseurl.larted": false, - "threatintel.abuseurl.tags": [ - "sLoad" - ], - "threatintel.abuseurl.threat": "malware_download", - "threatintel.abuseurl.url_status": "offline", - "threatintel.indicator.first_seen": "2021-01-14T20:50:13.000Z", - "threatintel.indicator.provider": "Cryptolaemus1", - "threatintel.indicator.reference": "https://urlhaus.abuse.ch/url/961467/", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "letonguesc.com", - "threatintel.indicator.url.extension": "png", - "threatintel.indicator.url.full": "https://letonguesc.com/leto/03253350239/1x1.png", - "threatintel.indicator.url.original": "https://letonguesc.com/leto/03253350239/1x1.png", - "threatintel.indicator.url.path": "/leto/03253350239/1x1.png", - "threatintel.indicator.url.scheme": "https" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] AbuseCH URL", + "threat.indicator.first_seen": "2021-01-14T20:50:13.000Z", + "threat.indicator.provider": "Cryptolaemus1", + "threat.indicator.reference": "https://urlhaus.abuse.ch/url/961467/", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "letonguesc.com", + "threat.indicator.url.extension": "png", + "threat.indicator.url.full": "https://letonguesc.com/leto/03253350239/1x1.png", + "threat.indicator.url.original": "https://letonguesc.com/leto/03253350239/1x1.png", + "threat.indicator.url.path": "/leto/03253350239/1x1.png", + "threat.indicator.url.scheme": "https" }, { + "abusech.url.blacklists.spamhaus_dbl": "not listed", + "abusech.url.blacklists.surbl": "not listed", + "abusech.url.id": "961464", + "abusech.url.larted": false, + "abusech.url.tags": [ + "sLoad" + ], + "abusech.url.threat": "malware_download", + "abusech.url.url_status": "offline", "event.category": "threat", "event.dataset": "threatintel.abuseurl", "event.kind": "enrichment", @@ -2949,27 +3122,29 @@ "forwarded", "threatintel-abuseurls" ], - "threatintel.abuseurl.blacklists.spamhaus_dbl": "not listed", - "threatintel.abuseurl.blacklists.surbl": "not listed", - "threatintel.abuseurl.id": "961464", - "threatintel.abuseurl.larted": false, - "threatintel.abuseurl.tags": [ - "sLoad" - ], - "threatintel.abuseurl.threat": "malware_download", - "threatintel.abuseurl.url_status": "offline", - "threatintel.indicator.first_seen": "2021-01-14T20:50:09.000Z", - "threatintel.indicator.provider": "Cryptolaemus1", - "threatintel.indicator.reference": "https://urlhaus.abuse.ch/url/961464/", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "ladiesincode.com", - "threatintel.indicator.url.extension": "css", - "threatintel.indicator.url.full": "https://ladiesincode.com/ladi/10582470158/uk.css", - "threatintel.indicator.url.original": "https://ladiesincode.com/ladi/10582470158/uk.css", - "threatintel.indicator.url.path": "/ladi/10582470158/uk.css", - "threatintel.indicator.url.scheme": "https" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] AbuseCH URL", + "threat.indicator.first_seen": "2021-01-14T20:50:09.000Z", + "threat.indicator.provider": "Cryptolaemus1", + "threat.indicator.reference": "https://urlhaus.abuse.ch/url/961464/", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "ladiesincode.com", + "threat.indicator.url.extension": "css", + "threat.indicator.url.full": "https://ladiesincode.com/ladi/10582470158/uk.css", + "threat.indicator.url.original": "https://ladiesincode.com/ladi/10582470158/uk.css", + "threat.indicator.url.path": "/ladi/10582470158/uk.css", + "threat.indicator.url.scheme": "https" }, { + "abusech.url.blacklists.spamhaus_dbl": "not listed", + "abusech.url.blacklists.surbl": "not listed", + "abusech.url.id": "961465", + "abusech.url.larted": false, + "abusech.url.tags": [ + "sLoad" + ], + "abusech.url.threat": "malware_download", + "abusech.url.url_status": "offline", "event.category": "threat", "event.dataset": "threatintel.abuseurl", "event.kind": "enrichment", @@ -2983,27 +3158,29 @@ "forwarded", "threatintel-abuseurls" ], - "threatintel.abuseurl.blacklists.spamhaus_dbl": "not listed", - "threatintel.abuseurl.blacklists.surbl": "not listed", - "threatintel.abuseurl.id": "961465", - "threatintel.abuseurl.larted": false, - "threatintel.abuseurl.tags": [ - "sLoad" - ], - "threatintel.abuseurl.threat": "malware_download", - "threatintel.abuseurl.url_status": "offline", - "threatintel.indicator.first_seen": "2021-01-14T20:50:09.000Z", - "threatintel.indicator.provider": "Cryptolaemus1", - "threatintel.indicator.reference": "https://urlhaus.abuse.ch/url/961465/", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "ladiesincode.com", - "threatintel.indicator.url.extension": "css", - "threatintel.indicator.url.full": "https://ladiesincode.com/ladi/BTTLNZ68A56D325C/map.css", - "threatintel.indicator.url.original": "https://ladiesincode.com/ladi/BTTLNZ68A56D325C/map.css", - "threatintel.indicator.url.path": "/ladi/BTTLNZ68A56D325C/map.css", - "threatintel.indicator.url.scheme": "https" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] AbuseCH URL", + "threat.indicator.first_seen": "2021-01-14T20:50:09.000Z", + "threat.indicator.provider": "Cryptolaemus1", + "threat.indicator.reference": "https://urlhaus.abuse.ch/url/961465/", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "ladiesincode.com", + "threat.indicator.url.extension": "css", + "threat.indicator.url.full": "https://ladiesincode.com/ladi/BTTLNZ68A56D325C/map.css", + "threat.indicator.url.original": "https://ladiesincode.com/ladi/BTTLNZ68A56D325C/map.css", + "threat.indicator.url.path": "/ladi/BTTLNZ68A56D325C/map.css", + "threat.indicator.url.scheme": "https" }, { + "abusech.url.blacklists.spamhaus_dbl": "not listed", + "abusech.url.blacklists.surbl": "not listed", + "abusech.url.id": "961466", + "abusech.url.larted": false, + "abusech.url.tags": [ + "sLoad" + ], + "abusech.url.threat": "malware_download", + "abusech.url.url_status": "offline", "event.category": "threat", "event.dataset": "threatintel.abuseurl", "event.kind": "enrichment", @@ -3017,27 +3194,29 @@ "forwarded", "threatintel-abuseurls" ], - "threatintel.abuseurl.blacklists.spamhaus_dbl": "not listed", - "threatintel.abuseurl.blacklists.surbl": "not listed", - "threatintel.abuseurl.id": "961466", - "threatintel.abuseurl.larted": false, - "threatintel.abuseurl.tags": [ - "sLoad" - ], - "threatintel.abuseurl.threat": "malware_download", - "threatintel.abuseurl.url_status": "offline", - "threatintel.indicator.first_seen": "2021-01-14T20:50:09.000Z", - "threatintel.indicator.provider": "Cryptolaemus1", - "threatintel.indicator.reference": "https://urlhaus.abuse.ch/url/961466/", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "letonguesc.com", - "threatintel.indicator.url.extension": "jpg", - "threatintel.indicator.url.full": "https://letonguesc.com/leto/NNTLRT68P28A717L/en.jpg", - "threatintel.indicator.url.original": "https://letonguesc.com/leto/NNTLRT68P28A717L/en.jpg", - "threatintel.indicator.url.path": "/leto/NNTLRT68P28A717L/en.jpg", - "threatintel.indicator.url.scheme": "https" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] AbuseCH URL", + "threat.indicator.first_seen": "2021-01-14T20:50:09.000Z", + "threat.indicator.provider": "Cryptolaemus1", + "threat.indicator.reference": "https://urlhaus.abuse.ch/url/961466/", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "letonguesc.com", + "threat.indicator.url.extension": "jpg", + "threat.indicator.url.full": "https://letonguesc.com/leto/NNTLRT68P28A717L/en.jpg", + "threat.indicator.url.original": "https://letonguesc.com/leto/NNTLRT68P28A717L/en.jpg", + "threat.indicator.url.path": "/leto/NNTLRT68P28A717L/en.jpg", + "threat.indicator.url.scheme": "https" }, { + "abusech.url.blacklists.spamhaus_dbl": "not listed", + "abusech.url.blacklists.surbl": "not listed", + "abusech.url.id": "961461", + "abusech.url.larted": false, + "abusech.url.tags": [ + "sLoad" + ], + "abusech.url.threat": "malware_download", + "abusech.url.url_status": "offline", "event.category": "threat", "event.dataset": "threatintel.abuseurl", "event.kind": "enrichment", @@ -3051,27 +3230,29 @@ "forwarded", "threatintel-abuseurls" ], - "threatintel.abuseurl.blacklists.spamhaus_dbl": "not listed", - "threatintel.abuseurl.blacklists.surbl": "not listed", - "threatintel.abuseurl.id": "961461", - "threatintel.abuseurl.larted": false, - "threatintel.abuseurl.tags": [ - "sLoad" - ], - "threatintel.abuseurl.threat": "malware_download", - "threatintel.abuseurl.url_status": "offline", - "threatintel.indicator.first_seen": "2021-01-14T20:50:08.000Z", - "threatintel.indicator.provider": "Cryptolaemus1", - "threatintel.indicator.reference": "https://urlhaus.abuse.ch/url/961461/", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "univirtek.com", - "threatintel.indicator.url.extension": "png", - "threatintel.indicator.url.full": "https://univirtek.com/viro/CTTNDR89A19B149W/maps.png", - "threatintel.indicator.url.original": "https://univirtek.com/viro/CTTNDR89A19B149W/maps.png", - "threatintel.indicator.url.path": "/viro/CTTNDR89A19B149W/maps.png", - "threatintel.indicator.url.scheme": "https" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] AbuseCH URL", + "threat.indicator.first_seen": "2021-01-14T20:50:08.000Z", + "threat.indicator.provider": "Cryptolaemus1", + "threat.indicator.reference": "https://urlhaus.abuse.ch/url/961461/", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "univirtek.com", + "threat.indicator.url.extension": "png", + "threat.indicator.url.full": "https://univirtek.com/viro/CTTNDR89A19B149W/maps.png", + "threat.indicator.url.original": "https://univirtek.com/viro/CTTNDR89A19B149W/maps.png", + "threat.indicator.url.path": "/viro/CTTNDR89A19B149W/maps.png", + "threat.indicator.url.scheme": "https" }, { + "abusech.url.blacklists.spamhaus_dbl": "not listed", + "abusech.url.blacklists.surbl": "not listed", + "abusech.url.id": "961462", + "abusech.url.larted": false, + "abusech.url.tags": [ + "sLoad" + ], + "abusech.url.threat": "malware_download", + "abusech.url.url_status": "offline", "event.category": "threat", "event.dataset": "threatintel.abuseurl", "event.kind": "enrichment", @@ -3085,27 +3266,29 @@ "forwarded", "threatintel-abuseurls" ], - "threatintel.abuseurl.blacklists.spamhaus_dbl": "not listed", - "threatintel.abuseurl.blacklists.surbl": "not listed", - "threatintel.abuseurl.id": "961462", - "threatintel.abuseurl.larted": false, - "threatintel.abuseurl.tags": [ - "sLoad" - ], - "threatintel.abuseurl.threat": "malware_download", - "threatintel.abuseurl.url_status": "offline", - "threatintel.indicator.first_seen": "2021-01-14T20:50:08.000Z", - "threatintel.indicator.provider": "Cryptolaemus1", - "threatintel.indicator.reference": "https://urlhaus.abuse.ch/url/961462/", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "cxminute.com", - "threatintel.indicator.url.extension": "css", - "threatintel.indicator.url.full": "https://cxminute.com/minu/DRSNTN77B16I197U/logo.css", - "threatintel.indicator.url.original": "https://cxminute.com/minu/DRSNTN77B16I197U/logo.css", - "threatintel.indicator.url.path": "/minu/DRSNTN77B16I197U/logo.css", - "threatintel.indicator.url.scheme": "https" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] AbuseCH URL", + "threat.indicator.first_seen": "2021-01-14T20:50:08.000Z", + "threat.indicator.provider": "Cryptolaemus1", + "threat.indicator.reference": "https://urlhaus.abuse.ch/url/961462/", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "cxminute.com", + "threat.indicator.url.extension": "css", + "threat.indicator.url.full": "https://cxminute.com/minu/DRSNTN77B16I197U/logo.css", + "threat.indicator.url.original": "https://cxminute.com/minu/DRSNTN77B16I197U/logo.css", + "threat.indicator.url.path": "/minu/DRSNTN77B16I197U/logo.css", + "threat.indicator.url.scheme": "https" }, { + "abusech.url.blacklists.spamhaus_dbl": "not listed", + "abusech.url.blacklists.surbl": "not listed", + "abusech.url.id": "961463", + "abusech.url.larted": false, + "abusech.url.tags": [ + "sLoad" + ], + "abusech.url.threat": "malware_download", + "abusech.url.url_status": "offline", "event.category": "threat", "event.dataset": "threatintel.abuseurl", "event.kind": "enrichment", @@ -3119,27 +3302,29 @@ "forwarded", "threatintel-abuseurls" ], - "threatintel.abuseurl.blacklists.spamhaus_dbl": "not listed", - "threatintel.abuseurl.blacklists.surbl": "not listed", - "threatintel.abuseurl.id": "961463", - "threatintel.abuseurl.larted": false, - "threatintel.abuseurl.tags": [ - "sLoad" - ], - "threatintel.abuseurl.threat": "malware_download", - "threatintel.abuseurl.url_status": "offline", - "threatintel.indicator.first_seen": "2021-01-14T20:50:08.000Z", - "threatintel.indicator.provider": "Cryptolaemus1", - "threatintel.indicator.reference": "https://urlhaus.abuse.ch/url/961463/", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "univirtek.com", - "threatintel.indicator.url.extension": "css", - "threatintel.indicator.url.full": "https://univirtek.com/viro/02941830735/uk.css", - "threatintel.indicator.url.original": "https://univirtek.com/viro/02941830735/uk.css", - "threatintel.indicator.url.path": "/viro/02941830735/uk.css", - "threatintel.indicator.url.scheme": "https" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] AbuseCH URL", + "threat.indicator.first_seen": "2021-01-14T20:50:08.000Z", + "threat.indicator.provider": "Cryptolaemus1", + "threat.indicator.reference": "https://urlhaus.abuse.ch/url/961463/", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "univirtek.com", + "threat.indicator.url.extension": "css", + "threat.indicator.url.full": "https://univirtek.com/viro/02941830735/uk.css", + "threat.indicator.url.original": "https://univirtek.com/viro/02941830735/uk.css", + "threat.indicator.url.path": "/viro/02941830735/uk.css", + "threat.indicator.url.scheme": "https" }, { + "abusech.url.blacklists.spamhaus_dbl": "not listed", + "abusech.url.blacklists.surbl": "not listed", + "abusech.url.id": "961458", + "abusech.url.larted": false, + "abusech.url.tags": [ + "sLoad" + ], + "abusech.url.threat": "malware_download", + "abusech.url.url_status": "offline", "event.category": "threat", "event.dataset": "threatintel.abuseurl", "event.kind": "enrichment", @@ -3153,27 +3338,29 @@ "forwarded", "threatintel-abuseurls" ], - "threatintel.abuseurl.blacklists.spamhaus_dbl": "not listed", - "threatintel.abuseurl.blacklists.surbl": "not listed", - "threatintel.abuseurl.id": "961458", - "threatintel.abuseurl.larted": false, - "threatintel.abuseurl.tags": [ - "sLoad" - ], - "threatintel.abuseurl.threat": "malware_download", - "threatintel.abuseurl.url_status": "offline", - "threatintel.indicator.first_seen": "2021-01-14T20:50:07.000Z", - "threatintel.indicator.provider": "Cryptolaemus1", - "threatintel.indicator.reference": "https://urlhaus.abuse.ch/url/961458/", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "belfetproduction.com", - "threatintel.indicator.url.extension": "css", - "threatintel.indicator.url.full": "https://belfetproduction.com/bella/MNSGCM91A04G240K/it.css", - "threatintel.indicator.url.original": "https://belfetproduction.com/bella/MNSGCM91A04G240K/it.css", - "threatintel.indicator.url.path": "/bella/MNSGCM91A04G240K/it.css", - "threatintel.indicator.url.scheme": "https" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] AbuseCH URL", + "threat.indicator.first_seen": "2021-01-14T20:50:07.000Z", + "threat.indicator.provider": "Cryptolaemus1", + "threat.indicator.reference": "https://urlhaus.abuse.ch/url/961458/", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "belfetproduction.com", + "threat.indicator.url.extension": "css", + "threat.indicator.url.full": "https://belfetproduction.com/bella/MNSGCM91A04G240K/it.css", + "threat.indicator.url.original": "https://belfetproduction.com/bella/MNSGCM91A04G240K/it.css", + "threat.indicator.url.path": "/bella/MNSGCM91A04G240K/it.css", + "threat.indicator.url.scheme": "https" }, { + "abusech.url.blacklists.spamhaus_dbl": "not listed", + "abusech.url.blacklists.surbl": "not listed", + "abusech.url.id": "961459", + "abusech.url.larted": false, + "abusech.url.tags": [ + "sLoad" + ], + "abusech.url.threat": "malware_download", + "abusech.url.url_status": "offline", "event.category": "threat", "event.dataset": "threatintel.abuseurl", "event.kind": "enrichment", @@ -3187,27 +3374,29 @@ "forwarded", "threatintel-abuseurls" ], - "threatintel.abuseurl.blacklists.spamhaus_dbl": "not listed", - "threatintel.abuseurl.blacklists.surbl": "not listed", - "threatintel.abuseurl.id": "961459", - "threatintel.abuseurl.larted": false, - "threatintel.abuseurl.tags": [ - "sLoad" - ], - "threatintel.abuseurl.threat": "malware_download", - "threatintel.abuseurl.url_status": "offline", - "threatintel.indicator.first_seen": "2021-01-14T20:50:07.000Z", - "threatintel.indicator.provider": "Cryptolaemus1", - "threatintel.indicator.reference": "https://urlhaus.abuse.ch/url/961459/", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "ladiesincode.com", - "threatintel.indicator.url.extension": "jpg", - "threatintel.indicator.url.full": "https://ladiesincode.com/ladi/03108100615/it.jpg", - "threatintel.indicator.url.original": "https://ladiesincode.com/ladi/03108100615/it.jpg", - "threatintel.indicator.url.path": "/ladi/03108100615/it.jpg", - "threatintel.indicator.url.scheme": "https" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] AbuseCH URL", + "threat.indicator.first_seen": "2021-01-14T20:50:07.000Z", + "threat.indicator.provider": "Cryptolaemus1", + "threat.indicator.reference": "https://urlhaus.abuse.ch/url/961459/", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "ladiesincode.com", + "threat.indicator.url.extension": "jpg", + "threat.indicator.url.full": "https://ladiesincode.com/ladi/03108100615/it.jpg", + "threat.indicator.url.original": "https://ladiesincode.com/ladi/03108100615/it.jpg", + "threat.indicator.url.path": "/ladi/03108100615/it.jpg", + "threat.indicator.url.scheme": "https" }, { + "abusech.url.blacklists.spamhaus_dbl": "not listed", + "abusech.url.blacklists.surbl": "not listed", + "abusech.url.id": "961460", + "abusech.url.larted": false, + "abusech.url.tags": [ + "sLoad" + ], + "abusech.url.threat": "malware_download", + "abusech.url.url_status": "offline", "event.category": "threat", "event.dataset": "threatintel.abuseurl", "event.kind": "enrichment", @@ -3221,27 +3410,29 @@ "forwarded", "threatintel-abuseurls" ], - "threatintel.abuseurl.blacklists.spamhaus_dbl": "not listed", - "threatintel.abuseurl.blacklists.surbl": "not listed", - "threatintel.abuseurl.id": "961460", - "threatintel.abuseurl.larted": false, - "threatintel.abuseurl.tags": [ - "sLoad" - ], - "threatintel.abuseurl.threat": "malware_download", - "threatintel.abuseurl.url_status": "offline", - "threatintel.indicator.first_seen": "2021-01-14T20:50:07.000Z", - "threatintel.indicator.provider": "Cryptolaemus1", - "threatintel.indicator.reference": "https://urlhaus.abuse.ch/url/961460/", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "cxminute.com", - "threatintel.indicator.url.extension": "png", - "threatintel.indicator.url.full": "https://cxminute.com/minu/PTACSM56A31F604X/en.png", - "threatintel.indicator.url.original": "https://cxminute.com/minu/PTACSM56A31F604X/en.png", - "threatintel.indicator.url.path": "/minu/PTACSM56A31F604X/en.png", - "threatintel.indicator.url.scheme": "https" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] AbuseCH URL", + "threat.indicator.first_seen": "2021-01-14T20:50:07.000Z", + "threat.indicator.provider": "Cryptolaemus1", + "threat.indicator.reference": "https://urlhaus.abuse.ch/url/961460/", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "cxminute.com", + "threat.indicator.url.extension": "png", + "threat.indicator.url.full": "https://cxminute.com/minu/PTACSM56A31F604X/en.png", + "threat.indicator.url.original": "https://cxminute.com/minu/PTACSM56A31F604X/en.png", + "threat.indicator.url.path": "/minu/PTACSM56A31F604X/en.png", + "threat.indicator.url.scheme": "https" }, { + "abusech.url.blacklists.spamhaus_dbl": "not listed", + "abusech.url.blacklists.surbl": "not listed", + "abusech.url.id": "961455", + "abusech.url.larted": false, + "abusech.url.tags": [ + "sLoad" + ], + "abusech.url.threat": "malware_download", + "abusech.url.url_status": "offline", "event.category": "threat", "event.dataset": "threatintel.abuseurl", "event.kind": "enrichment", @@ -3255,27 +3446,29 @@ "forwarded", "threatintel-abuseurls" ], - "threatintel.abuseurl.blacklists.spamhaus_dbl": "not listed", - "threatintel.abuseurl.blacklists.surbl": "not listed", - "threatintel.abuseurl.id": "961455", - "threatintel.abuseurl.larted": false, - "threatintel.abuseurl.tags": [ - "sLoad" - ], - "threatintel.abuseurl.threat": "malware_download", - "threatintel.abuseurl.url_status": "offline", - "threatintel.indicator.first_seen": "2021-01-14T20:49:39.000Z", - "threatintel.indicator.provider": "Cryptolaemus1", - "threatintel.indicator.reference": "https://urlhaus.abuse.ch/url/961455/", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "univirtek.com", - "threatintel.indicator.url.extension": "gif", - "threatintel.indicator.url.full": "https://univirtek.com/viro/00183050368/en.gif", - "threatintel.indicator.url.original": "https://univirtek.com/viro/00183050368/en.gif", - "threatintel.indicator.url.path": "/viro/00183050368/en.gif", - "threatintel.indicator.url.scheme": "https" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] AbuseCH URL", + "threat.indicator.first_seen": "2021-01-14T20:49:39.000Z", + "threat.indicator.provider": "Cryptolaemus1", + "threat.indicator.reference": "https://urlhaus.abuse.ch/url/961455/", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "univirtek.com", + "threat.indicator.url.extension": "gif", + "threat.indicator.url.full": "https://univirtek.com/viro/00183050368/en.gif", + "threat.indicator.url.original": "https://univirtek.com/viro/00183050368/en.gif", + "threat.indicator.url.path": "/viro/00183050368/en.gif", + "threat.indicator.url.scheme": "https" }, { + "abusech.url.blacklists.spamhaus_dbl": "not listed", + "abusech.url.blacklists.surbl": "not listed", + "abusech.url.id": "961456", + "abusech.url.larted": false, + "abusech.url.tags": [ + "sLoad" + ], + "abusech.url.threat": "malware_download", + "abusech.url.url_status": "offline", "event.category": "threat", "event.dataset": "threatintel.abuseurl", "event.kind": "enrichment", @@ -3289,27 +3482,29 @@ "forwarded", "threatintel-abuseurls" ], - "threatintel.abuseurl.blacklists.spamhaus_dbl": "not listed", - "threatintel.abuseurl.blacklists.surbl": "not listed", - "threatintel.abuseurl.id": "961456", - "threatintel.abuseurl.larted": false, - "threatintel.abuseurl.tags": [ - "sLoad" - ], - "threatintel.abuseurl.threat": "malware_download", - "threatintel.abuseurl.url_status": "offline", - "threatintel.indicator.first_seen": "2021-01-14T20:49:39.000Z", - "threatintel.indicator.provider": "Cryptolaemus1", - "threatintel.indicator.reference": "https://urlhaus.abuse.ch/url/961456/", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "cxminute.com", - "threatintel.indicator.url.extension": "gif", - "threatintel.indicator.url.full": "https://cxminute.com/minu/TSNLSN58H30G912H/uk.gif", - "threatintel.indicator.url.original": "https://cxminute.com/minu/TSNLSN58H30G912H/uk.gif", - "threatintel.indicator.url.path": "/minu/TSNLSN58H30G912H/uk.gif", - "threatintel.indicator.url.scheme": "https" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] AbuseCH URL", + "threat.indicator.first_seen": "2021-01-14T20:49:39.000Z", + "threat.indicator.provider": "Cryptolaemus1", + "threat.indicator.reference": "https://urlhaus.abuse.ch/url/961456/", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "cxminute.com", + "threat.indicator.url.extension": "gif", + "threat.indicator.url.full": "https://cxminute.com/minu/TSNLSN58H30G912H/uk.gif", + "threat.indicator.url.original": "https://cxminute.com/minu/TSNLSN58H30G912H/uk.gif", + "threat.indicator.url.path": "/minu/TSNLSN58H30G912H/uk.gif", + "threat.indicator.url.scheme": "https" }, { + "abusech.url.blacklists.spamhaus_dbl": "not listed", + "abusech.url.blacklists.surbl": "not listed", + "abusech.url.id": "961457", + "abusech.url.larted": false, + "abusech.url.tags": [ + "sLoad" + ], + "abusech.url.threat": "malware_download", + "abusech.url.url_status": "offline", "event.category": "threat", "event.dataset": "threatintel.abuseurl", "event.kind": "enrichment", @@ -3323,27 +3518,29 @@ "forwarded", "threatintel-abuseurls" ], - "threatintel.abuseurl.blacklists.spamhaus_dbl": "not listed", - "threatintel.abuseurl.blacklists.surbl": "not listed", - "threatintel.abuseurl.id": "961457", - "threatintel.abuseurl.larted": false, - "threatintel.abuseurl.tags": [ - "sLoad" - ], - "threatintel.abuseurl.threat": "malware_download", - "threatintel.abuseurl.url_status": "offline", - "threatintel.indicator.first_seen": "2021-01-14T20:49:39.000Z", - "threatintel.indicator.provider": "Cryptolaemus1", - "threatintel.indicator.reference": "https://urlhaus.abuse.ch/url/961457/", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "letonguesc.com", - "threatintel.indicator.url.extension": "gif", - "threatintel.indicator.url.full": "https://letonguesc.com/leto/08658331007/blank.gif", - "threatintel.indicator.url.original": "https://letonguesc.com/leto/08658331007/blank.gif", - "threatintel.indicator.url.path": "/leto/08658331007/blank.gif", - "threatintel.indicator.url.scheme": "https" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] AbuseCH URL", + "threat.indicator.first_seen": "2021-01-14T20:49:39.000Z", + "threat.indicator.provider": "Cryptolaemus1", + "threat.indicator.reference": "https://urlhaus.abuse.ch/url/961457/", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "letonguesc.com", + "threat.indicator.url.extension": "gif", + "threat.indicator.url.full": "https://letonguesc.com/leto/08658331007/blank.gif", + "threat.indicator.url.original": "https://letonguesc.com/leto/08658331007/blank.gif", + "threat.indicator.url.path": "/leto/08658331007/blank.gif", + "threat.indicator.url.scheme": "https" }, { + "abusech.url.blacklists.spamhaus_dbl": "not listed", + "abusech.url.blacklists.surbl": "not listed", + "abusech.url.id": "961450", + "abusech.url.larted": false, + "abusech.url.tags": [ + "sLoad" + ], + "abusech.url.threat": "malware_download", + "abusech.url.url_status": "offline", "event.category": "threat", "event.dataset": "threatintel.abuseurl", "event.kind": "enrichment", @@ -3357,27 +3554,29 @@ "forwarded", "threatintel-abuseurls" ], - "threatintel.abuseurl.blacklists.spamhaus_dbl": "not listed", - "threatintel.abuseurl.blacklists.surbl": "not listed", - "threatintel.abuseurl.id": "961450", - "threatintel.abuseurl.larted": false, - "threatintel.abuseurl.tags": [ - "sLoad" - ], - "threatintel.abuseurl.threat": "malware_download", - "threatintel.abuseurl.url_status": "offline", - "threatintel.indicator.first_seen": "2021-01-14T20:49:37.000Z", - "threatintel.indicator.provider": "Cryptolaemus1", - "threatintel.indicator.reference": "https://urlhaus.abuse.ch/url/961450/", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "cxminute.com", - "threatintel.indicator.url.extension": "png", - "threatintel.indicator.url.full": "https://cxminute.com/minu/01098910324/blank.png", - "threatintel.indicator.url.original": "https://cxminute.com/minu/01098910324/blank.png", - "threatintel.indicator.url.path": "/minu/01098910324/blank.png", - "threatintel.indicator.url.scheme": "https" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] AbuseCH URL", + "threat.indicator.first_seen": "2021-01-14T20:49:37.000Z", + "threat.indicator.provider": "Cryptolaemus1", + "threat.indicator.reference": "https://urlhaus.abuse.ch/url/961450/", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "cxminute.com", + "threat.indicator.url.extension": "png", + "threat.indicator.url.full": "https://cxminute.com/minu/01098910324/blank.png", + "threat.indicator.url.original": "https://cxminute.com/minu/01098910324/blank.png", + "threat.indicator.url.path": "/minu/01098910324/blank.png", + "threat.indicator.url.scheme": "https" }, { + "abusech.url.blacklists.spamhaus_dbl": "not listed", + "abusech.url.blacklists.surbl": "not listed", + "abusech.url.id": "961451", + "abusech.url.larted": false, + "abusech.url.tags": [ + "sLoad" + ], + "abusech.url.threat": "malware_download", + "abusech.url.url_status": "offline", "event.category": "threat", "event.dataset": "threatintel.abuseurl", "event.kind": "enrichment", @@ -3391,27 +3590,29 @@ "forwarded", "threatintel-abuseurls" ], - "threatintel.abuseurl.blacklists.spamhaus_dbl": "not listed", - "threatintel.abuseurl.blacklists.surbl": "not listed", - "threatintel.abuseurl.id": "961451", - "threatintel.abuseurl.larted": false, - "threatintel.abuseurl.tags": [ - "sLoad" - ], - "threatintel.abuseurl.threat": "malware_download", - "threatintel.abuseurl.url_status": "offline", - "threatintel.indicator.first_seen": "2021-01-14T20:49:37.000Z", - "threatintel.indicator.provider": "Cryptolaemus1", - "threatintel.indicator.reference": "https://urlhaus.abuse.ch/url/961451/", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "univirtek.com", - "threatintel.indicator.url.extension": "css", - "threatintel.indicator.url.full": "https://univirtek.com/viro/02794390233/uk.css", - "threatintel.indicator.url.original": "https://univirtek.com/viro/02794390233/uk.css", - "threatintel.indicator.url.path": "/viro/02794390233/uk.css", - "threatintel.indicator.url.scheme": "https" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] AbuseCH URL", + "threat.indicator.first_seen": "2021-01-14T20:49:37.000Z", + "threat.indicator.provider": "Cryptolaemus1", + "threat.indicator.reference": "https://urlhaus.abuse.ch/url/961451/", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "univirtek.com", + "threat.indicator.url.extension": "css", + "threat.indicator.url.full": "https://univirtek.com/viro/02794390233/uk.css", + "threat.indicator.url.original": "https://univirtek.com/viro/02794390233/uk.css", + "threat.indicator.url.path": "/viro/02794390233/uk.css", + "threat.indicator.url.scheme": "https" }, { + "abusech.url.blacklists.spamhaus_dbl": "not listed", + "abusech.url.blacklists.surbl": "not listed", + "abusech.url.id": "961452", + "abusech.url.larted": false, + "abusech.url.tags": [ + "sLoad" + ], + "abusech.url.threat": "malware_download", + "abusech.url.url_status": "offline", "event.category": "threat", "event.dataset": "threatintel.abuseurl", "event.kind": "enrichment", @@ -3425,27 +3626,29 @@ "forwarded", "threatintel-abuseurls" ], - "threatintel.abuseurl.blacklists.spamhaus_dbl": "not listed", - "threatintel.abuseurl.blacklists.surbl": "not listed", - "threatintel.abuseurl.id": "961452", - "threatintel.abuseurl.larted": false, - "threatintel.abuseurl.tags": [ - "sLoad" - ], - "threatintel.abuseurl.threat": "malware_download", - "threatintel.abuseurl.url_status": "offline", - "threatintel.indicator.first_seen": "2021-01-14T20:49:37.000Z", - "threatintel.indicator.provider": "Cryptolaemus1", - "threatintel.indicator.reference": "https://urlhaus.abuse.ch/url/961452/", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "univirtek.com", - "threatintel.indicator.url.extension": "css", - "threatintel.indicator.url.full": "https://univirtek.com/viro/CSTDNT69D63F754D/en.css", - "threatintel.indicator.url.original": "https://univirtek.com/viro/CSTDNT69D63F754D/en.css", - "threatintel.indicator.url.path": "/viro/CSTDNT69D63F754D/en.css", - "threatintel.indicator.url.scheme": "https" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] AbuseCH URL", + "threat.indicator.first_seen": "2021-01-14T20:49:37.000Z", + "threat.indicator.provider": "Cryptolaemus1", + "threat.indicator.reference": "https://urlhaus.abuse.ch/url/961452/", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "univirtek.com", + "threat.indicator.url.extension": "css", + "threat.indicator.url.full": "https://univirtek.com/viro/CSTDNT69D63F754D/en.css", + "threat.indicator.url.original": "https://univirtek.com/viro/CSTDNT69D63F754D/en.css", + "threat.indicator.url.path": "/viro/CSTDNT69D63F754D/en.css", + "threat.indicator.url.scheme": "https" }, { + "abusech.url.blacklists.spamhaus_dbl": "not listed", + "abusech.url.blacklists.surbl": "not listed", + "abusech.url.id": "961453", + "abusech.url.larted": false, + "abusech.url.tags": [ + "sLoad" + ], + "abusech.url.threat": "malware_download", + "abusech.url.url_status": "offline", "event.category": "threat", "event.dataset": "threatintel.abuseurl", "event.kind": "enrichment", @@ -3459,27 +3662,29 @@ "forwarded", "threatintel-abuseurls" ], - "threatintel.abuseurl.blacklists.spamhaus_dbl": "not listed", - "threatintel.abuseurl.blacklists.surbl": "not listed", - "threatintel.abuseurl.id": "961453", - "threatintel.abuseurl.larted": false, - "threatintel.abuseurl.tags": [ - "sLoad" - ], - "threatintel.abuseurl.threat": "malware_download", - "threatintel.abuseurl.url_status": "offline", - "threatintel.indicator.first_seen": "2021-01-14T20:49:37.000Z", - "threatintel.indicator.provider": "Cryptolaemus1", - "threatintel.indicator.reference": "https://urlhaus.abuse.ch/url/961453/", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "univirtek.com", - "threatintel.indicator.url.extension": "jpg", - "threatintel.indicator.url.full": "https://univirtek.com/viro/GSTGNE91B06L219W/1x1.jpg", - "threatintel.indicator.url.original": "https://univirtek.com/viro/GSTGNE91B06L219W/1x1.jpg", - "threatintel.indicator.url.path": "/viro/GSTGNE91B06L219W/1x1.jpg", - "threatintel.indicator.url.scheme": "https" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] AbuseCH URL", + "threat.indicator.first_seen": "2021-01-14T20:49:37.000Z", + "threat.indicator.provider": "Cryptolaemus1", + "threat.indicator.reference": "https://urlhaus.abuse.ch/url/961453/", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "univirtek.com", + "threat.indicator.url.extension": "jpg", + "threat.indicator.url.full": "https://univirtek.com/viro/GSTGNE91B06L219W/1x1.jpg", + "threat.indicator.url.original": "https://univirtek.com/viro/GSTGNE91B06L219W/1x1.jpg", + "threat.indicator.url.path": "/viro/GSTGNE91B06L219W/1x1.jpg", + "threat.indicator.url.scheme": "https" }, { + "abusech.url.blacklists.spamhaus_dbl": "not listed", + "abusech.url.blacklists.surbl": "not listed", + "abusech.url.id": "961454", + "abusech.url.larted": false, + "abusech.url.tags": [ + "sLoad" + ], + "abusech.url.threat": "malware_download", + "abusech.url.url_status": "offline", "event.category": "threat", "event.dataset": "threatintel.abuseurl", "event.kind": "enrichment", @@ -3493,27 +3698,29 @@ "forwarded", "threatintel-abuseurls" ], - "threatintel.abuseurl.blacklists.spamhaus_dbl": "not listed", - "threatintel.abuseurl.blacklists.surbl": "not listed", - "threatintel.abuseurl.id": "961454", - "threatintel.abuseurl.larted": false, - "threatintel.abuseurl.tags": [ - "sLoad" - ], - "threatintel.abuseurl.threat": "malware_download", - "threatintel.abuseurl.url_status": "offline", - "threatintel.indicator.first_seen": "2021-01-14T20:49:37.000Z", - "threatintel.indicator.provider": "Cryptolaemus1", - "threatintel.indicator.reference": "https://urlhaus.abuse.ch/url/961454/", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "univirtek.com", - "threatintel.indicator.url.extension": "jpg", - "threatintel.indicator.url.full": "https://univirtek.com/viro/03610140125/map.jpg", - "threatintel.indicator.url.original": "https://univirtek.com/viro/03610140125/map.jpg", - "threatintel.indicator.url.path": "/viro/03610140125/map.jpg", - "threatintel.indicator.url.scheme": "https" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] AbuseCH URL", + "threat.indicator.first_seen": "2021-01-14T20:49:37.000Z", + "threat.indicator.provider": "Cryptolaemus1", + "threat.indicator.reference": "https://urlhaus.abuse.ch/url/961454/", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "univirtek.com", + "threat.indicator.url.extension": "jpg", + "threat.indicator.url.full": "https://univirtek.com/viro/03610140125/map.jpg", + "threat.indicator.url.original": "https://univirtek.com/viro/03610140125/map.jpg", + "threat.indicator.url.path": "/viro/03610140125/map.jpg", + "threat.indicator.url.scheme": "https" }, { + "abusech.url.blacklists.spamhaus_dbl": "not listed", + "abusech.url.blacklists.surbl": "not listed", + "abusech.url.id": "961448", + "abusech.url.larted": false, + "abusech.url.tags": [ + "sLoad" + ], + "abusech.url.threat": "malware_download", + "abusech.url.url_status": "offline", "event.category": "threat", "event.dataset": "threatintel.abuseurl", "event.kind": "enrichment", @@ -3527,24 +3734,17 @@ "forwarded", "threatintel-abuseurls" ], - "threatintel.abuseurl.blacklists.spamhaus_dbl": "not listed", - "threatintel.abuseurl.blacklists.surbl": "not listed", - "threatintel.abuseurl.id": "961448", - "threatintel.abuseurl.larted": false, - "threatintel.abuseurl.tags": [ - "sLoad" - ], - "threatintel.abuseurl.threat": "malware_download", - "threatintel.abuseurl.url_status": "offline", - "threatintel.indicator.first_seen": "2021-01-14T20:49:36.000Z", - "threatintel.indicator.provider": "Cryptolaemus1", - "threatintel.indicator.reference": "https://urlhaus.abuse.ch/url/961448/", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "belfetproduction.com", - "threatintel.indicator.url.extension": "png", - "threatintel.indicator.url.full": "https://belfetproduction.com/bella/CRRLRD74E09A462T/blank.png", - "threatintel.indicator.url.original": "https://belfetproduction.com/bella/CRRLRD74E09A462T/blank.png", - "threatintel.indicator.url.path": "/bella/CRRLRD74E09A462T/blank.png", - "threatintel.indicator.url.scheme": "https" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] AbuseCH URL", + "threat.indicator.first_seen": "2021-01-14T20:49:36.000Z", + "threat.indicator.provider": "Cryptolaemus1", + "threat.indicator.reference": "https://urlhaus.abuse.ch/url/961448/", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "belfetproduction.com", + "threat.indicator.url.extension": "png", + "threat.indicator.url.full": "https://belfetproduction.com/bella/CRRLRD74E09A462T/blank.png", + "threat.indicator.url.original": "https://belfetproduction.com/bella/CRRLRD74E09A462T/blank.png", + "threat.indicator.url.path": "/bella/CRRLRD74E09A462T/blank.png", + "threat.indicator.url.scheme": "https" } ] \ No newline at end of file diff --git a/x-pack/filebeat/module/threatintel/anomali/_meta/fields.yml b/x-pack/filebeat/module/threatintel/anomali/_meta/fields.yml index 69ab6e22e9b..696b062b6b2 100644 --- a/x-pack/filebeat/module/threatintel/anomali/_meta/fields.yml +++ b/x-pack/filebeat/module/threatintel/anomali/_meta/fields.yml @@ -1,4 +1,4 @@ -- name: anomali +- name: anomali.limo type: group description: > Fields for Anomali Threat Intel @@ -50,4 +50,4 @@ - name: object_marking_refs type: keyword description: > - The STIX reference object. \ No newline at end of file + The STIX reference object. diff --git a/x-pack/filebeat/module/threatintel/anomali/config/config.yml b/x-pack/filebeat/module/threatintel/anomali/config/config.yml index a268ddb7559..1a30d874635 100644 --- a/x-pack/filebeat/module/threatintel/anomali/config/config.yml +++ b/x-pack/filebeat/module/threatintel/anomali/config/config.yml @@ -30,7 +30,7 @@ request.transforms: value: items 0-10000 - set: target: url.params.match[type] - value: {{ .types }} + value: indicator - set: target: url.params.added_after value: '[[.cursor.timestamp]]' @@ -54,17 +54,12 @@ exclude_files: [".gz$"] {{ end }} -tags: {{.tags | tojson}} -publisher_pipeline.disable_host: {{ inList .tags "forwarded" }} +tags: +{{if .preserve_original_event}} + - preserve_original_event +{{end}} +{{range $val := .tags}} + - {{$val}} +{{end}} -processors: - - decode_json_fields: - fields: [message] - target: json - - fingerprint: - fields: ["json.id"] - target_field: "@metadata._id" - - add_fields: - target: '' - fields: - ecs.version: 1.12.0 +publisher_pipeline.disable_host: {{ inList .tags "forwarded" }} diff --git a/x-pack/filebeat/module/threatintel/anomali/ingest/pipeline.yml b/x-pack/filebeat/module/threatintel/anomali/ingest/pipeline.yml index eccbf5e9826..94ca3a84751 100644 --- a/x-pack/filebeat/module/threatintel/anomali/ingest/pipeline.yml +++ b/x-pack/filebeat/module/threatintel/anomali/ingest/pipeline.yml @@ -1,4 +1,5 @@ -description: Pipeline for parsing Anomali Threat Intel +--- +description: Pipeline for parsing Anomali Limo indicators processors: #################### # Event ECS fields # @@ -6,6 +7,9 @@ processors: - set: field: event.ingested value: "{{_ingest.timestamp}}" + - set: + field: ecs.version + value: "1.12" - set: field: event.kind value: enrichment @@ -20,16 +24,30 @@ processors: # General ECS fields # ###################### - rename: - field: json - target_field: threatintel.anomali + field: message + target_field: event.original + ignore_missing: true + - json: + field: event.original + target_field: anomali.limo + - fingerprint: + fields: + - anomali.limo.id + target_field: "_id" ignore_missing: true ##################### # Threat ECS Fields # ##################### + - set: + field: threat.feed.name + value: "[Filebeat] Anomali Limo" + - set: + field: threat.feed.dashboard_id + value: "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f" ## File indicator operations - date: - field: threatintel.anomali.created + field: anomali.limo.created formats: - "yyyy-MM-dd'T'HH:mm:ssz" - "yyyy-MM-dd'T'HH:mm:ssZ" @@ -39,68 +57,73 @@ processors: - "yyyy-MM-dd'T'HH:mm:ss.SSZ" - "yyyy-MM-dd'T'HH:mm:ss.SSSz" - "yyyy-MM-dd'T'HH:mm:ss.SSSZ" - if: "ctx?.threatintel?.anomali?.created != null" + if: "ctx.anomali?.limo?.created != null" - date: - field: threatintel.anomali.modified - target_field: threatintel.anomali.modified + field: anomali.limo.modified + target_field: anomali.limo.modified formats: + - "yyyy-MM-dd'T'HH:mm:ssz" + - "yyyy-MM-dd'T'HH:mm:ssZ" - "yyyy-MM-dd'T'HH:mm:ss.Sz" - "yyyy-MM-dd'T'HH:mm:ss.SZ" - "yyyy-MM-dd'T'HH:mm:ss.SSz" - "yyyy-MM-dd'T'HH:mm:ss.SSZ" - "yyyy-MM-dd'T'HH:mm:ss.SSSz" - "yyyy-MM-dd'T'HH:mm:ss.SSSZ" - if: "ctx?.threatintel?.anomali?.modified != null" + if: "ctx.anomali?.limo?.modified != null" - date: - field: threatintel.anomali.valid_from - target_field: threatintel.indicator.first_seen + field: anomali.limo.valid_from + target_field: threat.indicator.first_seen formats: + - "yyyy-MM-dd'T'HH:mm:ssz" + - "yyyy-MM-dd'T'HH:mm:ssZ" - "yyyy-MM-dd'T'HH:mm:ss.Sz" - "yyyy-MM-dd'T'HH:mm:ss.SZ" - "yyyy-MM-dd'T'HH:mm:ss.SSz" - "yyyy-MM-dd'T'HH:mm:ss.SSZ" - "yyyy-MM-dd'T'HH:mm:ss.SSSz" - "yyyy-MM-dd'T'HH:mm:ss.SSSZ" - if: "ctx?.threatintel?.anomali?.valid_from != null" + if: "ctx.anomali?.limo?.valid_from != null" - grok: - field: threatintel.anomali.pattern + field: anomali.limo.pattern patterns: - "^\\[%{DATA:_tmp.threattype}:value%{SPACE}=%{SPACE}'%{DATA:_tmp.threatvalue}'\\]" + if: ctx.anomali?.limo?.pattern != null - rename: field: _tmp.threattype - target_field: threatintel.indicator.type + target_field: threat.indicator.type ignore_missing: true - rename: field: _tmp.threatvalue - target_field: threatintel.indicator.ip + target_field: threat.indicator.ip ignore_missing: true - if: "['ipv4-addr', 'ipv6-addr'].contains(ctx?.threatintel?.indicator?.type)" + if: "['ipv4-addr', 'ipv6-addr'].contains(ctx.threat?.indicator?.type)" - uri_parts: field: _tmp.threatvalue - target_field: threatintel.indicator.url + target_field: threat.indicator.url keep_original: true remove_if_successful: true - if: ctx?.threatintel?.indicator?.type == 'url' + if: ctx.threat?.indicator?.type == 'url' - set: - field: threatintel.indicator.url.full - value: "{{{threatintel.indicator.url.original}}}" + field: threat.indicator.url.full + value: "{{{threat.indicator.url.original}}}" ignore_empty_value: true - rename: field: _tmp.threatvalue - target_field: threatintel.indicator.email.address + target_field: threat.indicator.email.address ignore_missing: true - if: ctx?.threatintel?.indicator?.type == 'email-addr' + if: ctx.threat?.indicator?.type == 'email-addr' - rename: field: _tmp.threatvalue - target_field: threatintel.indicator.url.domain + target_field: threat.indicator.url.domain ignore_missing: true - if: ctx?.threatintel?.indicator?.type == 'domain-name' + if: ctx.threat?.indicator?.type == 'domain-name' - set: - field: threatintel.indicator.type + field: threat.indicator.type value: unknown - if: ctx?.threatintel?.indicator?.type == null + if: ctx.threat?.indicator?.type == null - foreach: - field: threatintel.anomali.labels + field: anomali.limo.labels ignore_missing: true processor: append: @@ -108,9 +131,9 @@ processors: value: "{{_ingest._value}}" allow_duplicates: false - grok: - field: threatintel.anomali.description + field: anomali.limo.description patterns: - - "^%{GREEDYDATA}Source: %{GREEDYDATA:threatintel.indicator.provider}" + - "^%{GREEDYDATA}Source: %{GREEDYDATA:threat.indicator.provider}" ignore_missing: true ignore_failure: true ###################### @@ -140,9 +163,14 @@ processors: } } handleMap(ctx); + - remove: + field: event.original + if: "ctx?.tags == null || !(ctx.tags.contains('preserve_original_event'))" + ignore_failure: true + ignore_missing: true - remove: field: - - threatintel.anomali.created + - anomali.limo.created - message - _tmp ignore_missing: true diff --git a/x-pack/filebeat/module/threatintel/anomali/manifest.yml b/x-pack/filebeat/module/threatintel/anomali/manifest.yml index 1087e00df8a..bdfcf20a3ad 100644 --- a/x-pack/filebeat/module/threatintel/anomali/manifest.yml +++ b/x-pack/filebeat/module/threatintel/anomali/manifest.yml @@ -8,8 +8,6 @@ var: - name: first_interval default: 24h - name: ssl - - name: types - default: indicators - name: username - name: password - name: url @@ -17,6 +15,8 @@ var: - name: tags default: [threatintel-anomali, forwarded] - name: proxy_url + - name: preserve_original_event + default: false ingest_pipeline: - ingest/pipeline.yml diff --git a/x-pack/filebeat/module/threatintel/anomali/test/anomali_limo.ndjson.log-expected.json b/x-pack/filebeat/module/threatintel/anomali/test/anomali_limo.ndjson.log-expected.json index f527da1ed98..7f998f8c778 100644 --- a/x-pack/filebeat/module/threatintel/anomali/test/anomali_limo.ndjson.log-expected.json +++ b/x-pack/filebeat/module/threatintel/anomali/test/anomali_limo.ndjson.log-expected.json @@ -1,5 +1,20 @@ [ { + "anomali.limo.description": "TS ID: 55241332361; iType: mal_url; State: active; Org: Cloudflare; Source: CyberCrime", + "anomali.limo.id": "indicator--44c85d4f-45ca-4977-b693-c810bbfb7a28", + "anomali.limo.labels": [ + "malicious-activity", + "threatstream-confidence-76", + "threatstream-severity-medium" + ], + "anomali.limo.modified": "2020-01-22T02:58:57.431Z", + "anomali.limo.name": "mal_url: http://chol.cc/Work6/PvqDq929BSx_A_D_M1n_a.php", + "anomali.limo.object_marking_refs": [ + "marking-definition--34098fce-860f-48ae-8e50-ebd3cc5e41da" + ], + "anomali.limo.pattern": "[url:value = 'http://chol.cc/Work6/PvqDq929BSx_A_D_M1n_a.php']", + "anomali.limo.type": "indicator", + "anomali.limo.valid_from": "2020-01-22T02:58:57.431Z", "event.category": "threat", "event.dataset": "threatintel.anomali", "event.kind": "enrichment", @@ -16,32 +31,34 @@ "threatstream-confidence-76", "threatstream-severity-medium" ], - "threatintel.anomali.description": "TS ID: 55241332361; iType: mal_url; State: active; Org: Cloudflare; Source: CyberCrime", - "threatintel.anomali.id": "indicator--44c85d4f-45ca-4977-b693-c810bbfb7a28", - "threatintel.anomali.labels": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali Limo", + "threat.indicator.first_seen": "2020-01-22T02:58:57.431Z", + "threat.indicator.provider": "CyberCrime", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "chol.cc", + "threat.indicator.url.extension": "php", + "threat.indicator.url.full": "http://chol.cc/Work6/PvqDq929BSx_A_D_M1n_a.php", + "threat.indicator.url.original": "http://chol.cc/Work6/PvqDq929BSx_A_D_M1n_a.php", + "threat.indicator.url.path": "/Work6/PvqDq929BSx_A_D_M1n_a.php", + "threat.indicator.url.scheme": "http" + }, + { + "anomali.limo.description": "TS ID: 55241332307; iType: mal_url; State: active; Org: ServerMania; Source: CyberCrime", + "anomali.limo.id": "indicator--f9fe5c81-6869-4247-af81-62b7c8aba209", + "anomali.limo.labels": [ "malicious-activity", - "threatstream-confidence-76", + "threatstream-confidence-68", "threatstream-severity-medium" ], - "threatintel.anomali.modified": "2020-01-22T02:58:57.431Z", - "threatintel.anomali.name": "mal_url: http://chol.cc/Work6/PvqDq929BSx_A_D_M1n_a.php", - "threatintel.anomali.object_marking_refs": [ + "anomali.limo.modified": "2020-01-22T02:58:57.503Z", + "anomali.limo.name": "mal_url: http://worldatdoor.in/lewis/Panel/five/PvqDq929BSx_A_D_M1n_a.php", + "anomali.limo.object_marking_refs": [ "marking-definition--34098fce-860f-48ae-8e50-ebd3cc5e41da" ], - "threatintel.anomali.pattern": "[url:value = 'http://chol.cc/Work6/PvqDq929BSx_A_D_M1n_a.php']", - "threatintel.anomali.type": "indicator", - "threatintel.anomali.valid_from": "2020-01-22T02:58:57.431Z", - "threatintel.indicator.first_seen": "2020-01-22T02:58:57.431Z", - "threatintel.indicator.provider": "CyberCrime", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "chol.cc", - "threatintel.indicator.url.extension": "php", - "threatintel.indicator.url.full": "http://chol.cc/Work6/PvqDq929BSx_A_D_M1n_a.php", - "threatintel.indicator.url.original": "http://chol.cc/Work6/PvqDq929BSx_A_D_M1n_a.php", - "threatintel.indicator.url.path": "/Work6/PvqDq929BSx_A_D_M1n_a.php", - "threatintel.indicator.url.scheme": "http" - }, - { + "anomali.limo.pattern": "[url:value = 'http://worldatdoor.in/lewis/Panel/five/PvqDq929BSx_A_D_M1n_a.php']", + "anomali.limo.type": "indicator", + "anomali.limo.valid_from": "2020-01-22T02:58:57.503Z", "event.category": "threat", "event.dataset": "threatintel.anomali", "event.kind": "enrichment", @@ -58,32 +75,34 @@ "threatstream-confidence-68", "threatstream-severity-medium" ], - "threatintel.anomali.description": "TS ID: 55241332307; iType: mal_url; State: active; Org: ServerMania; Source: CyberCrime", - "threatintel.anomali.id": "indicator--f9fe5c81-6869-4247-af81-62b7c8aba209", - "threatintel.anomali.labels": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali Limo", + "threat.indicator.first_seen": "2020-01-22T02:58:57.503Z", + "threat.indicator.provider": "CyberCrime", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "worldatdoor.in", + "threat.indicator.url.extension": "php", + "threat.indicator.url.full": "http://worldatdoor.in/lewis/Panel/five/PvqDq929BSx_A_D_M1n_a.php", + "threat.indicator.url.original": "http://worldatdoor.in/lewis/Panel/five/PvqDq929BSx_A_D_M1n_a.php", + "threat.indicator.url.path": "/lewis/Panel/five/PvqDq929BSx_A_D_M1n_a.php", + "threat.indicator.url.scheme": "http" + }, + { + "anomali.limo.description": "TS ID: 55241332302; iType: mal_url; State: active; Org: SPRINTHOST.RU - shared/premium hosting, VDS, dedic; Source: CyberCrime", + "anomali.limo.id": "indicator--b0e14122-9005-4776-99fc-00872476c6d1", + "anomali.limo.labels": [ "malicious-activity", - "threatstream-confidence-68", + "threatstream-confidence-71", "threatstream-severity-medium" ], - "threatintel.anomali.modified": "2020-01-22T02:58:57.503Z", - "threatintel.anomali.name": "mal_url: http://worldatdoor.in/lewis/Panel/five/PvqDq929BSx_A_D_M1n_a.php", - "threatintel.anomali.object_marking_refs": [ + "anomali.limo.modified": "2020-01-22T02:58:57.570Z", + "anomali.limo.name": "mal_url: http://f0387770.xsph.ru/login", + "anomali.limo.object_marking_refs": [ "marking-definition--34098fce-860f-48ae-8e50-ebd3cc5e41da" ], - "threatintel.anomali.pattern": "[url:value = 'http://worldatdoor.in/lewis/Panel/five/PvqDq929BSx_A_D_M1n_a.php']", - "threatintel.anomali.type": "indicator", - "threatintel.anomali.valid_from": "2020-01-22T02:58:57.503Z", - "threatintel.indicator.first_seen": "2020-01-22T02:58:57.503Z", - "threatintel.indicator.provider": "CyberCrime", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "worldatdoor.in", - "threatintel.indicator.url.extension": "php", - "threatintel.indicator.url.full": "http://worldatdoor.in/lewis/Panel/five/PvqDq929BSx_A_D_M1n_a.php", - "threatintel.indicator.url.original": "http://worldatdoor.in/lewis/Panel/five/PvqDq929BSx_A_D_M1n_a.php", - "threatintel.indicator.url.path": "/lewis/Panel/five/PvqDq929BSx_A_D_M1n_a.php", - "threatintel.indicator.url.scheme": "http" - }, - { + "anomali.limo.pattern": "[url:value = 'http://f0387770.xsph.ru/login']", + "anomali.limo.type": "indicator", + "anomali.limo.valid_from": "2020-01-22T02:58:57.57Z", "event.category": "threat", "event.dataset": "threatintel.anomali", "event.kind": "enrichment", @@ -100,31 +119,33 @@ "threatstream-confidence-71", "threatstream-severity-medium" ], - "threatintel.anomali.description": "TS ID: 55241332302; iType: mal_url; State: active; Org: SPRINTHOST.RU - shared/premium hosting, VDS, dedic; Source: CyberCrime", - "threatintel.anomali.id": "indicator--b0e14122-9005-4776-99fc-00872476c6d1", - "threatintel.anomali.labels": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali Limo", + "threat.indicator.first_seen": "2020-01-22T02:58:57.570Z", + "threat.indicator.provider": "CyberCrime", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "f0387770.xsph.ru", + "threat.indicator.url.full": "http://f0387770.xsph.ru/login", + "threat.indicator.url.original": "http://f0387770.xsph.ru/login", + "threat.indicator.url.path": "/login", + "threat.indicator.url.scheme": "http" + }, + { + "anomali.limo.description": "TS ID: 55241332312; iType: mal_url; State: active; Org: Digital Ocean; Source: CyberCrime", + "anomali.limo.id": "indicator--111ec76f-616d-4aa8-80fd-e11ef0066aba", + "anomali.limo.labels": [ "malicious-activity", - "threatstream-confidence-71", + "threatstream-confidence-50", "threatstream-severity-medium" ], - "threatintel.anomali.modified": "2020-01-22T02:58:57.570Z", - "threatintel.anomali.name": "mal_url: http://f0387770.xsph.ru/login", - "threatintel.anomali.object_marking_refs": [ + "anomali.limo.modified": "2020-01-22T02:58:59.366Z", + "anomali.limo.name": "mal_url: http://178.62.187.103/login", + "anomali.limo.object_marking_refs": [ "marking-definition--34098fce-860f-48ae-8e50-ebd3cc5e41da" ], - "threatintel.anomali.pattern": "[url:value = 'http://f0387770.xsph.ru/login']", - "threatintel.anomali.type": "indicator", - "threatintel.anomali.valid_from": "2020-01-22T02:58:57.57Z", - "threatintel.indicator.first_seen": "2020-01-22T02:58:57.570Z", - "threatintel.indicator.provider": "CyberCrime", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "f0387770.xsph.ru", - "threatintel.indicator.url.full": "http://f0387770.xsph.ru/login", - "threatintel.indicator.url.original": "http://f0387770.xsph.ru/login", - "threatintel.indicator.url.path": "/login", - "threatintel.indicator.url.scheme": "http" - }, - { + "anomali.limo.pattern": "[url:value = 'http://178.62.187.103/login']", + "anomali.limo.type": "indicator", + "anomali.limo.valid_from": "2020-01-22T02:58:59.366Z", "event.category": "threat", "event.dataset": "threatintel.anomali", "event.kind": "enrichment", @@ -141,31 +162,33 @@ "threatstream-confidence-50", "threatstream-severity-medium" ], - "threatintel.anomali.description": "TS ID: 55241332312; iType: mal_url; State: active; Org: Digital Ocean; Source: CyberCrime", - "threatintel.anomali.id": "indicator--111ec76f-616d-4aa8-80fd-e11ef0066aba", - "threatintel.anomali.labels": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali Limo", + "threat.indicator.first_seen": "2020-01-22T02:58:59.366Z", + "threat.indicator.provider": "CyberCrime", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "178.62.187.103", + "threat.indicator.url.full": "http://178.62.187.103/login", + "threat.indicator.url.original": "http://178.62.187.103/login", + "threat.indicator.url.path": "/login", + "threat.indicator.url.scheme": "http" + }, + { + "anomali.limo.description": "TS ID: 55241332386; iType: mal_url; State: active; Source: CyberCrime", + "anomali.limo.id": "indicator--189ce776-6d7e-4e85-9222-de5876644988", + "anomali.limo.labels": [ "malicious-activity", - "threatstream-confidence-50", + "threatstream-confidence-66", "threatstream-severity-medium" ], - "threatintel.anomali.modified": "2020-01-22T02:58:59.366Z", - "threatintel.anomali.name": "mal_url: http://178.62.187.103/login", - "threatintel.anomali.object_marking_refs": [ + "anomali.limo.modified": "2020-01-22T02:58:59.457Z", + "anomali.limo.name": "mal_url: http://appareluea.com/panel/admin.php", + "anomali.limo.object_marking_refs": [ "marking-definition--34098fce-860f-48ae-8e50-ebd3cc5e41da" ], - "threatintel.anomali.pattern": "[url:value = 'http://178.62.187.103/login']", - "threatintel.anomali.type": "indicator", - "threatintel.anomali.valid_from": "2020-01-22T02:58:59.366Z", - "threatintel.indicator.first_seen": "2020-01-22T02:58:59.366Z", - "threatintel.indicator.provider": "CyberCrime", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "178.62.187.103", - "threatintel.indicator.url.full": "http://178.62.187.103/login", - "threatintel.indicator.url.original": "http://178.62.187.103/login", - "threatintel.indicator.url.path": "/login", - "threatintel.indicator.url.scheme": "http" - }, - { + "anomali.limo.pattern": "[url:value = 'http://appareluea.com/panel/admin.php']", + "anomali.limo.type": "indicator", + "anomali.limo.valid_from": "2020-01-22T02:58:59.457Z", "event.category": "threat", "event.dataset": "threatintel.anomali", "event.kind": "enrichment", @@ -182,32 +205,34 @@ "threatstream-confidence-66", "threatstream-severity-medium" ], - "threatintel.anomali.description": "TS ID: 55241332386; iType: mal_url; State: active; Source: CyberCrime", - "threatintel.anomali.id": "indicator--189ce776-6d7e-4e85-9222-de5876644988", - "threatintel.anomali.labels": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali Limo", + "threat.indicator.first_seen": "2020-01-22T02:58:59.457Z", + "threat.indicator.provider": "CyberCrime", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "appareluea.com", + "threat.indicator.url.extension": "php", + "threat.indicator.url.full": "http://appareluea.com/panel/admin.php", + "threat.indicator.url.original": "http://appareluea.com/panel/admin.php", + "threat.indicator.url.path": "/panel/admin.php", + "threat.indicator.url.scheme": "http" + }, + { + "anomali.limo.description": "TS ID: 55241332391; iType: mal_url; State: active; Org: Cloudflare; Source: CyberCrime", + "anomali.limo.id": "indicator--a4144d34-b86d-475e-8047-eb46b48ee325", + "anomali.limo.labels": [ "malicious-activity", - "threatstream-confidence-66", + "threatstream-confidence-93", "threatstream-severity-medium" ], - "threatintel.anomali.modified": "2020-01-22T02:58:59.457Z", - "threatintel.anomali.name": "mal_url: http://appareluea.com/panel/admin.php", - "threatintel.anomali.object_marking_refs": [ + "anomali.limo.modified": "2020-01-22T02:59:06.402Z", + "anomali.limo.name": "mal_url: http://nkpotu.xyz/Kpot3/login.php", + "anomali.limo.object_marking_refs": [ "marking-definition--34098fce-860f-48ae-8e50-ebd3cc5e41da" ], - "threatintel.anomali.pattern": "[url:value = 'http://appareluea.com/panel/admin.php']", - "threatintel.anomali.type": "indicator", - "threatintel.anomali.valid_from": "2020-01-22T02:58:59.457Z", - "threatintel.indicator.first_seen": "2020-01-22T02:58:59.457Z", - "threatintel.indicator.provider": "CyberCrime", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "appareluea.com", - "threatintel.indicator.url.extension": "php", - "threatintel.indicator.url.full": "http://appareluea.com/panel/admin.php", - "threatintel.indicator.url.original": "http://appareluea.com/panel/admin.php", - "threatintel.indicator.url.path": "/panel/admin.php", - "threatintel.indicator.url.scheme": "http" - }, - { + "anomali.limo.pattern": "[url:value = 'http://nkpotu.xyz/Kpot3/login.php']", + "anomali.limo.type": "indicator", + "anomali.limo.valid_from": "2020-01-22T02:59:06.402Z", "event.category": "threat", "event.dataset": "threatintel.anomali", "event.kind": "enrichment", @@ -224,32 +249,34 @@ "threatstream-confidence-93", "threatstream-severity-medium" ], - "threatintel.anomali.description": "TS ID: 55241332391; iType: mal_url; State: active; Org: Cloudflare; Source: CyberCrime", - "threatintel.anomali.id": "indicator--a4144d34-b86d-475e-8047-eb46b48ee325", - "threatintel.anomali.labels": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali Limo", + "threat.indicator.first_seen": "2020-01-22T02:59:06.402Z", + "threat.indicator.provider": "CyberCrime", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "nkpotu.xyz", + "threat.indicator.url.extension": "php", + "threat.indicator.url.full": "http://nkpotu.xyz/Kpot3/login.php", + "threat.indicator.url.original": "http://nkpotu.xyz/Kpot3/login.php", + "threat.indicator.url.path": "/Kpot3/login.php", + "threat.indicator.url.scheme": "http" + }, + { + "anomali.limo.description": "TS ID: 55241332372; iType: mal_ip; State: active; Org: Unified Layer; Source: CyberCrime", + "anomali.limo.id": "indicator--983d9c3d-b7f8-4345-b643-b1d18e6ac6b2", + "anomali.limo.labels": [ "malicious-activity", - "threatstream-confidence-93", + "threatstream-confidence-49", "threatstream-severity-medium" ], - "threatintel.anomali.modified": "2020-01-22T02:59:06.402Z", - "threatintel.anomali.name": "mal_url: http://nkpotu.xyz/Kpot3/login.php", - "threatintel.anomali.object_marking_refs": [ + "anomali.limo.modified": "2020-01-22T02:59:19.990Z", + "anomali.limo.name": "mal_ip: 162.144.128.116", + "anomali.limo.object_marking_refs": [ "marking-definition--34098fce-860f-48ae-8e50-ebd3cc5e41da" ], - "threatintel.anomali.pattern": "[url:value = 'http://nkpotu.xyz/Kpot3/login.php']", - "threatintel.anomali.type": "indicator", - "threatintel.anomali.valid_from": "2020-01-22T02:59:06.402Z", - "threatintel.indicator.first_seen": "2020-01-22T02:59:06.402Z", - "threatintel.indicator.provider": "CyberCrime", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "nkpotu.xyz", - "threatintel.indicator.url.extension": "php", - "threatintel.indicator.url.full": "http://nkpotu.xyz/Kpot3/login.php", - "threatintel.indicator.url.original": "http://nkpotu.xyz/Kpot3/login.php", - "threatintel.indicator.url.path": "/Kpot3/login.php", - "threatintel.indicator.url.scheme": "http" - }, - { + "anomali.limo.pattern": "[ipv4-addr:value = '162.144.128.116']", + "anomali.limo.type": "indicator", + "anomali.limo.valid_from": "2020-01-22T02:59:19.99Z", "event.category": "threat", "event.dataset": "threatintel.anomali", "event.kind": "enrichment", @@ -266,27 +293,29 @@ "threatstream-confidence-49", "threatstream-severity-medium" ], - "threatintel.anomali.description": "TS ID: 55241332372; iType: mal_ip; State: active; Org: Unified Layer; Source: CyberCrime", - "threatintel.anomali.id": "indicator--983d9c3d-b7f8-4345-b643-b1d18e6ac6b2", - "threatintel.anomali.labels": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali Limo", + "threat.indicator.first_seen": "2020-01-22T02:59:19.990Z", + "threat.indicator.ip": "162.144.128.116", + "threat.indicator.provider": "CyberCrime", + "threat.indicator.type": "ipv4-addr" + }, + { + "anomali.limo.description": "TS ID: 55241332313; iType: mal_url; State: active; Org: ServerMania; Source: CyberCrime", + "anomali.limo.id": "indicator--f9c6386b-dba2-41f9-8160-d307671e5c8e", + "anomali.limo.labels": [ "malicious-activity", - "threatstream-confidence-49", + "threatstream-confidence-79", "threatstream-severity-medium" ], - "threatintel.anomali.modified": "2020-01-22T02:59:19.990Z", - "threatintel.anomali.name": "mal_ip: 162.144.128.116", - "threatintel.anomali.object_marking_refs": [ + "anomali.limo.modified": "2020-01-22T02:59:20.155Z", + "anomali.limo.name": "mal_url: http://ntrcgroup.com/nze/panel/admin.php", + "anomali.limo.object_marking_refs": [ "marking-definition--34098fce-860f-48ae-8e50-ebd3cc5e41da" ], - "threatintel.anomali.pattern": "[ipv4-addr:value = '162.144.128.116']", - "threatintel.anomali.type": "indicator", - "threatintel.anomali.valid_from": "2020-01-22T02:59:19.99Z", - "threatintel.indicator.first_seen": "2020-01-22T02:59:19.990Z", - "threatintel.indicator.ip": "162.144.128.116", - "threatintel.indicator.provider": "CyberCrime", - "threatintel.indicator.type": "ipv4-addr" - }, - { + "anomali.limo.pattern": "[url:value = 'http://ntrcgroup.com/nze/panel/admin.php']", + "anomali.limo.type": "indicator", + "anomali.limo.valid_from": "2020-01-22T02:59:20.155Z", "event.category": "threat", "event.dataset": "threatintel.anomali", "event.kind": "enrichment", @@ -303,32 +332,34 @@ "threatstream-confidence-79", "threatstream-severity-medium" ], - "threatintel.anomali.description": "TS ID: 55241332313; iType: mal_url; State: active; Org: ServerMania; Source: CyberCrime", - "threatintel.anomali.id": "indicator--f9c6386b-dba2-41f9-8160-d307671e5c8e", - "threatintel.anomali.labels": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali Limo", + "threat.indicator.first_seen": "2020-01-22T02:59:20.155Z", + "threat.indicator.provider": "CyberCrime", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "ntrcgroup.com", + "threat.indicator.url.extension": "php", + "threat.indicator.url.full": "http://ntrcgroup.com/nze/panel/admin.php", + "threat.indicator.url.original": "http://ntrcgroup.com/nze/panel/admin.php", + "threat.indicator.url.path": "/nze/panel/admin.php", + "threat.indicator.url.scheme": "http" + }, + { + "anomali.limo.description": "TS ID: 55241332350; iType: mal_url; State: active; Org: Cloudflare; Source: CyberCrime", + "anomali.limo.id": "indicator--98fad53e-5389-47f7-a3ff-44d334af2d6b", + "anomali.limo.labels": [ "malicious-activity", - "threatstream-confidence-79", + "threatstream-confidence-76", "threatstream-severity-medium" ], - "threatintel.anomali.modified": "2020-01-22T02:59:20.155Z", - "threatintel.anomali.name": "mal_url: http://ntrcgroup.com/nze/panel/admin.php", - "threatintel.anomali.object_marking_refs": [ + "anomali.limo.modified": "2020-01-22T02:59:25.521Z", + "anomali.limo.name": "mal_url: http://chol.cc/Work8/PvqDq929BSx_A_D_M1n_a.php", + "anomali.limo.object_marking_refs": [ "marking-definition--34098fce-860f-48ae-8e50-ebd3cc5e41da" ], - "threatintel.anomali.pattern": "[url:value = 'http://ntrcgroup.com/nze/panel/admin.php']", - "threatintel.anomali.type": "indicator", - "threatintel.anomali.valid_from": "2020-01-22T02:59:20.155Z", - "threatintel.indicator.first_seen": "2020-01-22T02:59:20.155Z", - "threatintel.indicator.provider": "CyberCrime", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "ntrcgroup.com", - "threatintel.indicator.url.extension": "php", - "threatintel.indicator.url.full": "http://ntrcgroup.com/nze/panel/admin.php", - "threatintel.indicator.url.original": "http://ntrcgroup.com/nze/panel/admin.php", - "threatintel.indicator.url.path": "/nze/panel/admin.php", - "threatintel.indicator.url.scheme": "http" - }, - { + "anomali.limo.pattern": "[url:value = 'http://chol.cc/Work8/PvqDq929BSx_A_D_M1n_a.php']", + "anomali.limo.type": "indicator", + "anomali.limo.valid_from": "2020-01-22T02:59:25.521Z", "event.category": "threat", "event.dataset": "threatintel.anomali", "event.kind": "enrichment", @@ -345,32 +376,34 @@ "threatstream-confidence-76", "threatstream-severity-medium" ], - "threatintel.anomali.description": "TS ID: 55241332350; iType: mal_url; State: active; Org: Cloudflare; Source: CyberCrime", - "threatintel.anomali.id": "indicator--98fad53e-5389-47f7-a3ff-44d334af2d6b", - "threatintel.anomali.labels": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali Limo", + "threat.indicator.first_seen": "2020-01-22T02:59:25.521Z", + "threat.indicator.provider": "CyberCrime", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "chol.cc", + "threat.indicator.url.extension": "php", + "threat.indicator.url.full": "http://chol.cc/Work8/PvqDq929BSx_A_D_M1n_a.php", + "threat.indicator.url.original": "http://chol.cc/Work8/PvqDq929BSx_A_D_M1n_a.php", + "threat.indicator.url.path": "/Work8/PvqDq929BSx_A_D_M1n_a.php", + "threat.indicator.url.scheme": "http" + }, + { + "anomali.limo.description": "TS ID: 55241332291; iType: mal_url; State: active; Org: SPRINTHOST.RU - shared/premium hosting, VDS, dedic; Source: CyberCrime", + "anomali.limo.id": "indicator--76c01735-fb76-463d-9609-9ea3aedf3f4f", + "anomali.limo.labels": [ "malicious-activity", - "threatstream-confidence-76", + "threatstream-confidence-68", "threatstream-severity-medium" ], - "threatintel.anomali.modified": "2020-01-22T02:59:25.521Z", - "threatintel.anomali.name": "mal_url: http://chol.cc/Work8/PvqDq929BSx_A_D_M1n_a.php", - "threatintel.anomali.object_marking_refs": [ + "anomali.limo.modified": "2020-01-22T02:59:25.626Z", + "anomali.limo.name": "mal_url: http://f0390764.xsph.ru/login", + "anomali.limo.object_marking_refs": [ "marking-definition--34098fce-860f-48ae-8e50-ebd3cc5e41da" ], - "threatintel.anomali.pattern": "[url:value = 'http://chol.cc/Work8/PvqDq929BSx_A_D_M1n_a.php']", - "threatintel.anomali.type": "indicator", - "threatintel.anomali.valid_from": "2020-01-22T02:59:25.521Z", - "threatintel.indicator.first_seen": "2020-01-22T02:59:25.521Z", - "threatintel.indicator.provider": "CyberCrime", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "chol.cc", - "threatintel.indicator.url.extension": "php", - "threatintel.indicator.url.full": "http://chol.cc/Work8/PvqDq929BSx_A_D_M1n_a.php", - "threatintel.indicator.url.original": "http://chol.cc/Work8/PvqDq929BSx_A_D_M1n_a.php", - "threatintel.indicator.url.path": "/Work8/PvqDq929BSx_A_D_M1n_a.php", - "threatintel.indicator.url.scheme": "http" - }, - { + "anomali.limo.pattern": "[url:value = 'http://f0390764.xsph.ru/login']", + "anomali.limo.type": "indicator", + "anomali.limo.valid_from": "2020-01-22T02:59:25.626Z", "event.category": "threat", "event.dataset": "threatintel.anomali", "event.kind": "enrichment", @@ -387,31 +420,33 @@ "threatstream-confidence-68", "threatstream-severity-medium" ], - "threatintel.anomali.description": "TS ID: 55241332291; iType: mal_url; State: active; Org: SPRINTHOST.RU - shared/premium hosting, VDS, dedic; Source: CyberCrime", - "threatintel.anomali.id": "indicator--76c01735-fb76-463d-9609-9ea3aedf3f4f", - "threatintel.anomali.labels": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali Limo", + "threat.indicator.first_seen": "2020-01-22T02:59:25.626Z", + "threat.indicator.provider": "CyberCrime", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "f0390764.xsph.ru", + "threat.indicator.url.full": "http://f0390764.xsph.ru/login", + "threat.indicator.url.original": "http://f0390764.xsph.ru/login", + "threat.indicator.url.path": "/login", + "threat.indicator.url.scheme": "http" + }, + { + "anomali.limo.description": "TS ID: 55241332343; iType: mal_ip; State: active; Source: CyberCrime", + "anomali.limo.id": "indicator--e0a812dc-63c8-4949-b038-2241b2dbfcdc", + "anomali.limo.labels": [ "malicious-activity", - "threatstream-confidence-68", + "threatstream-confidence-85", "threatstream-severity-medium" ], - "threatintel.anomali.modified": "2020-01-22T02:59:25.626Z", - "threatintel.anomali.name": "mal_url: http://f0390764.xsph.ru/login", - "threatintel.anomali.object_marking_refs": [ + "anomali.limo.modified": "2020-01-22T02:59:36.461Z", + "anomali.limo.name": "mal_ip: 45.143.138.39", + "anomali.limo.object_marking_refs": [ "marking-definition--34098fce-860f-48ae-8e50-ebd3cc5e41da" ], - "threatintel.anomali.pattern": "[url:value = 'http://f0390764.xsph.ru/login']", - "threatintel.anomali.type": "indicator", - "threatintel.anomali.valid_from": "2020-01-22T02:59:25.626Z", - "threatintel.indicator.first_seen": "2020-01-22T02:59:25.626Z", - "threatintel.indicator.provider": "CyberCrime", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "f0390764.xsph.ru", - "threatintel.indicator.url.full": "http://f0390764.xsph.ru/login", - "threatintel.indicator.url.original": "http://f0390764.xsph.ru/login", - "threatintel.indicator.url.path": "/login", - "threatintel.indicator.url.scheme": "http" - }, - { + "anomali.limo.pattern": "[ipv4-addr:value = '45.143.138.39']", + "anomali.limo.type": "indicator", + "anomali.limo.valid_from": "2020-01-22T02:59:36.461Z", "event.category": "threat", "event.dataset": "threatintel.anomali", "event.kind": "enrichment", @@ -428,27 +463,29 @@ "threatstream-confidence-85", "threatstream-severity-medium" ], - "threatintel.anomali.description": "TS ID: 55241332343; iType: mal_ip; State: active; Source: CyberCrime", - "threatintel.anomali.id": "indicator--e0a812dc-63c8-4949-b038-2241b2dbfcdc", - "threatintel.anomali.labels": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali Limo", + "threat.indicator.first_seen": "2020-01-22T02:59:36.461Z", + "threat.indicator.ip": "45.143.138.39", + "threat.indicator.provider": "CyberCrime", + "threat.indicator.type": "ipv4-addr" + }, + { + "anomali.limo.description": "TS ID: 55241332316; iType: mal_url; State: active; Org: Sksa Technology Sdn Bhd; Source: CyberCrime", + "anomali.limo.id": "indicator--6f0d8607-21cb-4738-9712-f4fd91a37f7d", + "anomali.limo.labels": [ "malicious-activity", - "threatstream-confidence-85", + "threatstream-confidence-82", "threatstream-severity-medium" ], - "threatintel.anomali.modified": "2020-01-22T02:59:36.461Z", - "threatintel.anomali.name": "mal_ip: 45.143.138.39", - "threatintel.anomali.object_marking_refs": [ + "anomali.limo.modified": "2020-01-22T02:59:41.193Z", + "anomali.limo.name": "mal_url: http://aglfreight.com.my/inc/js/jstree/biu/panel/admin.php", + "anomali.limo.object_marking_refs": [ "marking-definition--34098fce-860f-48ae-8e50-ebd3cc5e41da" ], - "threatintel.anomali.pattern": "[ipv4-addr:value = '45.143.138.39']", - "threatintel.anomali.type": "indicator", - "threatintel.anomali.valid_from": "2020-01-22T02:59:36.461Z", - "threatintel.indicator.first_seen": "2020-01-22T02:59:36.461Z", - "threatintel.indicator.ip": "45.143.138.39", - "threatintel.indicator.provider": "CyberCrime", - "threatintel.indicator.type": "ipv4-addr" - }, - { + "anomali.limo.pattern": "[url:value = 'http://aglfreight.com.my/inc/js/jstree/biu/panel/admin.php']", + "anomali.limo.type": "indicator", + "anomali.limo.valid_from": "2020-01-22T02:59:41.193Z", "event.category": "threat", "event.dataset": "threatintel.anomali", "event.kind": "enrichment", @@ -465,32 +502,34 @@ "threatstream-confidence-82", "threatstream-severity-medium" ], - "threatintel.anomali.description": "TS ID: 55241332316; iType: mal_url; State: active; Org: Sksa Technology Sdn Bhd; Source: CyberCrime", - "threatintel.anomali.id": "indicator--6f0d8607-21cb-4738-9712-f4fd91a37f7d", - "threatintel.anomali.labels": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali Limo", + "threat.indicator.first_seen": "2020-01-22T02:59:41.193Z", + "threat.indicator.provider": "CyberCrime", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "aglfreight.com.my", + "threat.indicator.url.extension": "php", + "threat.indicator.url.full": "http://aglfreight.com.my/inc/js/jstree/biu/panel/admin.php", + "threat.indicator.url.original": "http://aglfreight.com.my/inc/js/jstree/biu/panel/admin.php", + "threat.indicator.url.path": "/inc/js/jstree/biu/panel/admin.php", + "threat.indicator.url.scheme": "http" + }, + { + "anomali.limo.description": "TS ID: 55241332284; iType: mal_url; State: active; Org: Oltelecom Jsc; Source: CyberCrime", + "anomali.limo.id": "indicator--c649d6d4-87c4-4b76-bfc2-75a509ccb187", + "anomali.limo.labels": [ "malicious-activity", - "threatstream-confidence-82", + "threatstream-confidence-61", "threatstream-severity-medium" ], - "threatintel.anomali.modified": "2020-01-22T02:59:41.193Z", - "threatintel.anomali.name": "mal_url: http://aglfreight.com.my/inc/js/jstree/biu/panel/admin.php", - "threatintel.anomali.object_marking_refs": [ + "anomali.limo.modified": "2020-01-22T02:59:41.228Z", + "anomali.limo.name": "mal_url: http://95.182.122.184/", + "anomali.limo.object_marking_refs": [ "marking-definition--34098fce-860f-48ae-8e50-ebd3cc5e41da" ], - "threatintel.anomali.pattern": "[url:value = 'http://aglfreight.com.my/inc/js/jstree/biu/panel/admin.php']", - "threatintel.anomali.type": "indicator", - "threatintel.anomali.valid_from": "2020-01-22T02:59:41.193Z", - "threatintel.indicator.first_seen": "2020-01-22T02:59:41.193Z", - "threatintel.indicator.provider": "CyberCrime", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "aglfreight.com.my", - "threatintel.indicator.url.extension": "php", - "threatintel.indicator.url.full": "http://aglfreight.com.my/inc/js/jstree/biu/panel/admin.php", - "threatintel.indicator.url.original": "http://aglfreight.com.my/inc/js/jstree/biu/panel/admin.php", - "threatintel.indicator.url.path": "/inc/js/jstree/biu/panel/admin.php", - "threatintel.indicator.url.scheme": "http" - }, - { + "anomali.limo.pattern": "[url:value = 'http://95.182.122.184/']", + "anomali.limo.type": "indicator", + "anomali.limo.valid_from": "2020-01-22T02:59:41.228Z", "event.category": "threat", "event.dataset": "threatintel.anomali", "event.kind": "enrichment", @@ -507,31 +546,33 @@ "threatstream-confidence-61", "threatstream-severity-medium" ], - "threatintel.anomali.description": "TS ID: 55241332284; iType: mal_url; State: active; Org: Oltelecom Jsc; Source: CyberCrime", - "threatintel.anomali.id": "indicator--c649d6d4-87c4-4b76-bfc2-75a509ccb187", - "threatintel.anomali.labels": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali Limo", + "threat.indicator.first_seen": "2020-01-22T02:59:41.228Z", + "threat.indicator.provider": "CyberCrime", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "95.182.122.184", + "threat.indicator.url.full": "http://95.182.122.184/", + "threat.indicator.url.original": "http://95.182.122.184/", + "threat.indicator.url.path": "/", + "threat.indicator.url.scheme": "http" + }, + { + "anomali.limo.description": "TS ID: 55241332337; iType: mal_ip; State: active; Org: Namecheap; Source: CyberCrime", + "anomali.limo.id": "indicator--408ebd2d-063f-4646-b2e7-c00519869736", + "anomali.limo.labels": [ "malicious-activity", - "threatstream-confidence-61", + "threatstream-confidence-62", "threatstream-severity-medium" ], - "threatintel.anomali.modified": "2020-01-22T02:59:41.228Z", - "threatintel.anomali.name": "mal_url: http://95.182.122.184/", - "threatintel.anomali.object_marking_refs": [ + "anomali.limo.modified": "2020-01-22T02:59:51.313Z", + "anomali.limo.name": "mal_ip: 198.54.115.121", + "anomali.limo.object_marking_refs": [ "marking-definition--34098fce-860f-48ae-8e50-ebd3cc5e41da" ], - "threatintel.anomali.pattern": "[url:value = 'http://95.182.122.184/']", - "threatintel.anomali.type": "indicator", - "threatintel.anomali.valid_from": "2020-01-22T02:59:41.228Z", - "threatintel.indicator.first_seen": "2020-01-22T02:59:41.228Z", - "threatintel.indicator.provider": "CyberCrime", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "95.182.122.184", - "threatintel.indicator.url.full": "http://95.182.122.184/", - "threatintel.indicator.url.original": "http://95.182.122.184/", - "threatintel.indicator.url.path": "/", - "threatintel.indicator.url.scheme": "http" - }, - { + "anomali.limo.pattern": "[ipv4-addr:value = '198.54.115.121']", + "anomali.limo.type": "indicator", + "anomali.limo.valid_from": "2020-01-22T02:59:51.313Z", "event.category": "threat", "event.dataset": "threatintel.anomali", "event.kind": "enrichment", @@ -548,27 +589,29 @@ "threatstream-confidence-62", "threatstream-severity-medium" ], - "threatintel.anomali.description": "TS ID: 55241332337; iType: mal_ip; State: active; Org: Namecheap; Source: CyberCrime", - "threatintel.anomali.id": "indicator--408ebd2d-063f-4646-b2e7-c00519869736", - "threatintel.anomali.labels": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali Limo", + "threat.indicator.first_seen": "2020-01-22T02:59:51.313Z", + "threat.indicator.ip": "198.54.115.121", + "threat.indicator.provider": "CyberCrime", + "threat.indicator.type": "ipv4-addr" + }, + { + "anomali.limo.description": "TS ID: 55241332324; iType: mal_ip; State: active; Org: CyrusOne LLC; Source: CyberCrime", + "anomali.limo.id": "indicator--e1d215cb-c7a5-40e0-bc53-8f92a2bcaba8", + "anomali.limo.labels": [ "malicious-activity", - "threatstream-confidence-62", + "threatstream-confidence-38", "threatstream-severity-medium" ], - "threatintel.anomali.modified": "2020-01-22T02:59:51.313Z", - "threatintel.anomali.name": "mal_ip: 198.54.115.121", - "threatintel.anomali.object_marking_refs": [ + "anomali.limo.modified": "2020-01-22T02:59:51.372Z", + "anomali.limo.name": "mal_ip: 192.185.119.172", + "anomali.limo.object_marking_refs": [ "marking-definition--34098fce-860f-48ae-8e50-ebd3cc5e41da" ], - "threatintel.anomali.pattern": "[ipv4-addr:value = '198.54.115.121']", - "threatintel.anomali.type": "indicator", - "threatintel.anomali.valid_from": "2020-01-22T02:59:51.313Z", - "threatintel.indicator.first_seen": "2020-01-22T02:59:51.313Z", - "threatintel.indicator.ip": "198.54.115.121", - "threatintel.indicator.provider": "CyberCrime", - "threatintel.indicator.type": "ipv4-addr" - }, - { + "anomali.limo.pattern": "[ipv4-addr:value = '192.185.119.172']", + "anomali.limo.type": "indicator", + "anomali.limo.valid_from": "2020-01-22T02:59:51.372Z", "event.category": "threat", "event.dataset": "threatintel.anomali", "event.kind": "enrichment", @@ -585,27 +628,29 @@ "threatstream-confidence-38", "threatstream-severity-medium" ], - "threatintel.anomali.description": "TS ID: 55241332324; iType: mal_ip; State: active; Org: CyrusOne LLC; Source: CyberCrime", - "threatintel.anomali.id": "indicator--e1d215cb-c7a5-40e0-bc53-8f92a2bcaba8", - "threatintel.anomali.labels": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali Limo", + "threat.indicator.first_seen": "2020-01-22T02:59:51.372Z", + "threat.indicator.ip": "192.185.119.172", + "threat.indicator.provider": "CyberCrime", + "threat.indicator.type": "ipv4-addr" + }, + { + "anomali.limo.description": "TS ID: 55241332296; iType: mal_url; State: active; Org: SPRINTHOST.RU - shared/premium hosting, VDS, dedic; Source: CyberCrime", + "anomali.limo.id": "indicator--6f3a4a2b-62e3-48ef-94ae-70103f09cf7e", + "anomali.limo.labels": [ "malicious-activity", - "threatstream-confidence-38", + "threatstream-confidence-61", "threatstream-severity-medium" ], - "threatintel.anomali.modified": "2020-01-22T02:59:51.372Z", - "threatintel.anomali.name": "mal_ip: 192.185.119.172", - "threatintel.anomali.object_marking_refs": [ + "anomali.limo.modified": "2020-01-22T02:59:51.442Z", + "anomali.limo.name": "mal_url: http://f0389246.xsph.ru/login", + "anomali.limo.object_marking_refs": [ "marking-definition--34098fce-860f-48ae-8e50-ebd3cc5e41da" ], - "threatintel.anomali.pattern": "[ipv4-addr:value = '192.185.119.172']", - "threatintel.anomali.type": "indicator", - "threatintel.anomali.valid_from": "2020-01-22T02:59:51.372Z", - "threatintel.indicator.first_seen": "2020-01-22T02:59:51.372Z", - "threatintel.indicator.ip": "192.185.119.172", - "threatintel.indicator.provider": "CyberCrime", - "threatintel.indicator.type": "ipv4-addr" - }, - { + "anomali.limo.pattern": "[url:value = 'http://f0389246.xsph.ru/login']", + "anomali.limo.type": "indicator", + "anomali.limo.valid_from": "2020-01-22T02:59:51.442Z", "event.category": "threat", "event.dataset": "threatintel.anomali", "event.kind": "enrichment", @@ -622,31 +667,33 @@ "threatstream-confidence-61", "threatstream-severity-medium" ], - "threatintel.anomali.description": "TS ID: 55241332296; iType: mal_url; State: active; Org: SPRINTHOST.RU - shared/premium hosting, VDS, dedic; Source: CyberCrime", - "threatintel.anomali.id": "indicator--6f3a4a2b-62e3-48ef-94ae-70103f09cf7e", - "threatintel.anomali.labels": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali Limo", + "threat.indicator.first_seen": "2020-01-22T02:59:51.442Z", + "threat.indicator.provider": "CyberCrime", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "f0389246.xsph.ru", + "threat.indicator.url.full": "http://f0389246.xsph.ru/login", + "threat.indicator.url.original": "http://f0389246.xsph.ru/login", + "threat.indicator.url.path": "/login", + "threat.indicator.url.scheme": "http" + }, + { + "anomali.limo.description": "TS ID: 55241332400; iType: mal_url; State: active; Source: CyberCrime", + "anomali.limo.id": "indicator--213519c9-f511-4188-89c8-159f35f08008", + "anomali.limo.labels": [ "malicious-activity", - "threatstream-confidence-61", + "threatstream-confidence-66", "threatstream-severity-medium" ], - "threatintel.anomali.modified": "2020-01-22T02:59:51.442Z", - "threatintel.anomali.name": "mal_url: http://f0389246.xsph.ru/login", - "threatintel.anomali.object_marking_refs": [ + "anomali.limo.modified": "2020-01-22T03:00:01.563Z", + "anomali.limo.name": "mal_url: http://appareluea.com/server/cp.php", + "anomali.limo.object_marking_refs": [ "marking-definition--34098fce-860f-48ae-8e50-ebd3cc5e41da" ], - "threatintel.anomali.pattern": "[url:value = 'http://f0389246.xsph.ru/login']", - "threatintel.anomali.type": "indicator", - "threatintel.anomali.valid_from": "2020-01-22T02:59:51.442Z", - "threatintel.indicator.first_seen": "2020-01-22T02:59:51.442Z", - "threatintel.indicator.provider": "CyberCrime", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "f0389246.xsph.ru", - "threatintel.indicator.url.full": "http://f0389246.xsph.ru/login", - "threatintel.indicator.url.original": "http://f0389246.xsph.ru/login", - "threatintel.indicator.url.path": "/login", - "threatintel.indicator.url.scheme": "http" - }, - { + "anomali.limo.pattern": "[url:value = 'http://appareluea.com/server/cp.php']", + "anomali.limo.type": "indicator", + "anomali.limo.valid_from": "2020-01-22T03:00:01.563Z", "event.category": "threat", "event.dataset": "threatintel.anomali", "event.kind": "enrichment", @@ -663,32 +710,34 @@ "threatstream-confidence-66", "threatstream-severity-medium" ], - "threatintel.anomali.description": "TS ID: 55241332400; iType: mal_url; State: active; Source: CyberCrime", - "threatintel.anomali.id": "indicator--213519c9-f511-4188-89c8-159f35f08008", - "threatintel.anomali.labels": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali Limo", + "threat.indicator.first_seen": "2020-01-22T03:00:01.563Z", + "threat.indicator.provider": "CyberCrime", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "appareluea.com", + "threat.indicator.url.extension": "php", + "threat.indicator.url.full": "http://appareluea.com/server/cp.php", + "threat.indicator.url.original": "http://appareluea.com/server/cp.php", + "threat.indicator.url.path": "/server/cp.php", + "threat.indicator.url.scheme": "http" + }, + { + "anomali.limo.description": "TS ID: 55241332396; iType: mal_url; State: active; Org: Cloudflare; Source: CyberCrime", + "anomali.limo.id": "indicator--5a563c85-c528-4e33-babe-2dcff34f73c4", + "anomali.limo.labels": [ "malicious-activity", - "threatstream-confidence-66", + "threatstream-confidence-93", "threatstream-severity-medium" ], - "threatintel.anomali.modified": "2020-01-22T03:00:01.563Z", - "threatintel.anomali.name": "mal_url: http://appareluea.com/server/cp.php", - "threatintel.anomali.object_marking_refs": [ + "anomali.limo.modified": "2020-01-22T03:00:03.138Z", + "anomali.limo.name": "mal_url: http://nkpotu.xyz/Kpot2/login.php", + "anomali.limo.object_marking_refs": [ "marking-definition--34098fce-860f-48ae-8e50-ebd3cc5e41da" ], - "threatintel.anomali.pattern": "[url:value = 'http://appareluea.com/server/cp.php']", - "threatintel.anomali.type": "indicator", - "threatintel.anomali.valid_from": "2020-01-22T03:00:01.563Z", - "threatintel.indicator.first_seen": "2020-01-22T03:00:01.563Z", - "threatintel.indicator.provider": "CyberCrime", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "appareluea.com", - "threatintel.indicator.url.extension": "php", - "threatintel.indicator.url.full": "http://appareluea.com/server/cp.php", - "threatintel.indicator.url.original": "http://appareluea.com/server/cp.php", - "threatintel.indicator.url.path": "/server/cp.php", - "threatintel.indicator.url.scheme": "http" - }, - { + "anomali.limo.pattern": "[url:value = 'http://nkpotu.xyz/Kpot2/login.php']", + "anomali.limo.type": "indicator", + "anomali.limo.valid_from": "2020-01-22T03:00:03.138Z", "event.category": "threat", "event.dataset": "threatintel.anomali", "event.kind": "enrichment", @@ -705,32 +754,34 @@ "threatstream-confidence-93", "threatstream-severity-medium" ], - "threatintel.anomali.description": "TS ID: 55241332396; iType: mal_url; State: active; Org: Cloudflare; Source: CyberCrime", - "threatintel.anomali.id": "indicator--5a563c85-c528-4e33-babe-2dcff34f73c4", - "threatintel.anomali.labels": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali Limo", + "threat.indicator.first_seen": "2020-01-22T03:00:03.138Z", + "threat.indicator.provider": "CyberCrime", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "nkpotu.xyz", + "threat.indicator.url.extension": "php", + "threat.indicator.url.full": "http://nkpotu.xyz/Kpot2/login.php", + "threat.indicator.url.original": "http://nkpotu.xyz/Kpot2/login.php", + "threat.indicator.url.path": "/Kpot2/login.php", + "threat.indicator.url.scheme": "http" + }, + { + "anomali.limo.description": "TS ID: 55241332363; iType: mal_url; State: active; Org: Cloudflare; Source: CyberCrime", + "anomali.limo.id": "indicator--f3e33aab-e2af-4c15-8cb9-f008a37cf986", + "anomali.limo.labels": [ "malicious-activity", - "threatstream-confidence-93", + "threatstream-confidence-76", "threatstream-severity-medium" ], - "threatintel.anomali.modified": "2020-01-22T03:00:03.138Z", - "threatintel.anomali.name": "mal_url: http://nkpotu.xyz/Kpot2/login.php", - "threatintel.anomali.object_marking_refs": [ + "anomali.limo.modified": "2020-01-22T03:00:03.396Z", + "anomali.limo.name": "mal_url: http://chol.cc/Work5/PvqDq929BSx_A_D_M1n_a.php", + "anomali.limo.object_marking_refs": [ "marking-definition--34098fce-860f-48ae-8e50-ebd3cc5e41da" ], - "threatintel.anomali.pattern": "[url:value = 'http://nkpotu.xyz/Kpot2/login.php']", - "threatintel.anomali.type": "indicator", - "threatintel.anomali.valid_from": "2020-01-22T03:00:03.138Z", - "threatintel.indicator.first_seen": "2020-01-22T03:00:03.138Z", - "threatintel.indicator.provider": "CyberCrime", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "nkpotu.xyz", - "threatintel.indicator.url.extension": "php", - "threatintel.indicator.url.full": "http://nkpotu.xyz/Kpot2/login.php", - "threatintel.indicator.url.original": "http://nkpotu.xyz/Kpot2/login.php", - "threatintel.indicator.url.path": "/Kpot2/login.php", - "threatintel.indicator.url.scheme": "http" - }, - { + "anomali.limo.pattern": "[url:value = 'http://chol.cc/Work5/PvqDq929BSx_A_D_M1n_a.php']", + "anomali.limo.type": "indicator", + "anomali.limo.valid_from": "2020-01-22T03:00:03.396Z", "event.category": "threat", "event.dataset": "threatintel.anomali", "event.kind": "enrichment", @@ -747,32 +798,34 @@ "threatstream-confidence-76", "threatstream-severity-medium" ], - "threatintel.anomali.description": "TS ID: 55241332363; iType: mal_url; State: active; Org: Cloudflare; Source: CyberCrime", - "threatintel.anomali.id": "indicator--f3e33aab-e2af-4c15-8cb9-f008a37cf986", - "threatintel.anomali.labels": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali Limo", + "threat.indicator.first_seen": "2020-01-22T03:00:03.396Z", + "threat.indicator.provider": "CyberCrime", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "chol.cc", + "threat.indicator.url.extension": "php", + "threat.indicator.url.full": "http://chol.cc/Work5/PvqDq929BSx_A_D_M1n_a.php", + "threat.indicator.url.original": "http://chol.cc/Work5/PvqDq929BSx_A_D_M1n_a.php", + "threat.indicator.url.path": "/Work5/PvqDq929BSx_A_D_M1n_a.php", + "threat.indicator.url.scheme": "http" + }, + { + "anomali.limo.description": "TS ID: 55241332320; iType: mal_url; State: active; Source: CyberCrime", + "anomali.limo.id": "indicator--f03f098d-2fa9-49e1-a7dd-02518aa105fa", + "anomali.limo.labels": [ "malicious-activity", - "threatstream-confidence-76", + "threatstream-confidence-87", "threatstream-severity-medium" ], - "threatintel.anomali.modified": "2020-01-22T03:00:03.396Z", - "threatintel.anomali.name": "mal_url: http://chol.cc/Work5/PvqDq929BSx_A_D_M1n_a.php", - "threatintel.anomali.object_marking_refs": [ + "anomali.limo.modified": "2020-01-22T03:00:03.642Z", + "anomali.limo.name": "mal_url: http://mecharnise.ir/ca4/panel/admin.php", + "anomali.limo.object_marking_refs": [ "marking-definition--34098fce-860f-48ae-8e50-ebd3cc5e41da" ], - "threatintel.anomali.pattern": "[url:value = 'http://chol.cc/Work5/PvqDq929BSx_A_D_M1n_a.php']", - "threatintel.anomali.type": "indicator", - "threatintel.anomali.valid_from": "2020-01-22T03:00:03.396Z", - "threatintel.indicator.first_seen": "2020-01-22T03:00:03.396Z", - "threatintel.indicator.provider": "CyberCrime", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "chol.cc", - "threatintel.indicator.url.extension": "php", - "threatintel.indicator.url.full": "http://chol.cc/Work5/PvqDq929BSx_A_D_M1n_a.php", - "threatintel.indicator.url.original": "http://chol.cc/Work5/PvqDq929BSx_A_D_M1n_a.php", - "threatintel.indicator.url.path": "/Work5/PvqDq929BSx_A_D_M1n_a.php", - "threatintel.indicator.url.scheme": "http" - }, - { + "anomali.limo.pattern": "[url:value = 'http://mecharnise.ir/ca4/panel/admin.php']", + "anomali.limo.type": "indicator", + "anomali.limo.valid_from": "2020-01-22T03:00:03.642Z", "event.category": "threat", "event.dataset": "threatintel.anomali", "event.kind": "enrichment", @@ -789,32 +842,34 @@ "threatstream-confidence-87", "threatstream-severity-medium" ], - "threatintel.anomali.description": "TS ID: 55241332320; iType: mal_url; State: active; Source: CyberCrime", - "threatintel.anomali.id": "indicator--f03f098d-2fa9-49e1-a7dd-02518aa105fa", - "threatintel.anomali.labels": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali Limo", + "threat.indicator.first_seen": "2020-01-22T03:00:03.642Z", + "threat.indicator.provider": "CyberCrime", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "mecharnise.ir", + "threat.indicator.url.extension": "php", + "threat.indicator.url.full": "http://mecharnise.ir/ca4/panel/admin.php", + "threat.indicator.url.original": "http://mecharnise.ir/ca4/panel/admin.php", + "threat.indicator.url.path": "/ca4/panel/admin.php", + "threat.indicator.url.scheme": "http" + }, + { + "anomali.limo.description": "TS ID: 55241332367; iType: mal_url; State: active; Org: Cloudflare; Source: CyberCrime", + "anomali.limo.id": "indicator--e72e3ba0-7de5-46bb-ab1e-efdf3e0a0b3b", + "anomali.limo.labels": [ "malicious-activity", - "threatstream-confidence-87", + "threatstream-confidence-76", "threatstream-severity-medium" ], - "threatintel.anomali.modified": "2020-01-22T03:00:03.642Z", - "threatintel.anomali.name": "mal_url: http://mecharnise.ir/ca4/panel/admin.php", - "threatintel.anomali.object_marking_refs": [ + "anomali.limo.modified": "2020-01-22T03:00:27.534Z", + "anomali.limo.name": "mal_url: http://chol.cc/Work4/PvqDq929BSx_A_D_M1n_a.php", + "anomali.limo.object_marking_refs": [ "marking-definition--34098fce-860f-48ae-8e50-ebd3cc5e41da" ], - "threatintel.anomali.pattern": "[url:value = 'http://mecharnise.ir/ca4/panel/admin.php']", - "threatintel.anomali.type": "indicator", - "threatintel.anomali.valid_from": "2020-01-22T03:00:03.642Z", - "threatintel.indicator.first_seen": "2020-01-22T03:00:03.642Z", - "threatintel.indicator.provider": "CyberCrime", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "mecharnise.ir", - "threatintel.indicator.url.extension": "php", - "threatintel.indicator.url.full": "http://mecharnise.ir/ca4/panel/admin.php", - "threatintel.indicator.url.original": "http://mecharnise.ir/ca4/panel/admin.php", - "threatintel.indicator.url.path": "/ca4/panel/admin.php", - "threatintel.indicator.url.scheme": "http" - }, - { + "anomali.limo.pattern": "[url:value = 'http://chol.cc/Work4/PvqDq929BSx_A_D_M1n_a.php']", + "anomali.limo.type": "indicator", + "anomali.limo.valid_from": "2020-01-22T03:00:27.534Z", "event.category": "threat", "event.dataset": "threatintel.anomali", "event.kind": "enrichment", @@ -831,32 +886,34 @@ "threatstream-confidence-76", "threatstream-severity-medium" ], - "threatintel.anomali.description": "TS ID: 55241332367; iType: mal_url; State: active; Org: Cloudflare; Source: CyberCrime", - "threatintel.anomali.id": "indicator--e72e3ba0-7de5-46bb-ab1e-efdf3e0a0b3b", - "threatintel.anomali.labels": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali Limo", + "threat.indicator.first_seen": "2020-01-22T03:00:27.534Z", + "threat.indicator.provider": "CyberCrime", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "chol.cc", + "threat.indicator.url.extension": "php", + "threat.indicator.url.full": "http://chol.cc/Work4/PvqDq929BSx_A_D_M1n_a.php", + "threat.indicator.url.original": "http://chol.cc/Work4/PvqDq929BSx_A_D_M1n_a.php", + "threat.indicator.url.path": "/Work4/PvqDq929BSx_A_D_M1n_a.php", + "threat.indicator.url.scheme": "http" + }, + { + "anomali.limo.description": "TS ID: 55241332317; iType: mal_url; State: active; Org: SoftLayer Technologies; Source: CyberCrime", + "anomali.limo.id": "indicator--d6b59b66-5020-4368-85a7-196026856ea9", + "anomali.limo.labels": [ "malicious-activity", - "threatstream-confidence-76", + "threatstream-confidence-78", "threatstream-severity-medium" ], - "threatintel.anomali.modified": "2020-01-22T03:00:27.534Z", - "threatintel.anomali.name": "mal_url: http://chol.cc/Work4/PvqDq929BSx_A_D_M1n_a.php", - "threatintel.anomali.object_marking_refs": [ + "anomali.limo.modified": "2020-01-22T03:00:27.591Z", + "anomali.limo.name": "mal_url: http://kironofer.com/webpanel/login.php", + "anomali.limo.object_marking_refs": [ "marking-definition--34098fce-860f-48ae-8e50-ebd3cc5e41da" ], - "threatintel.anomali.pattern": "[url:value = 'http://chol.cc/Work4/PvqDq929BSx_A_D_M1n_a.php']", - "threatintel.anomali.type": "indicator", - "threatintel.anomali.valid_from": "2020-01-22T03:00:27.534Z", - "threatintel.indicator.first_seen": "2020-01-22T03:00:27.534Z", - "threatintel.indicator.provider": "CyberCrime", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "chol.cc", - "threatintel.indicator.url.extension": "php", - "threatintel.indicator.url.full": "http://chol.cc/Work4/PvqDq929BSx_A_D_M1n_a.php", - "threatintel.indicator.url.original": "http://chol.cc/Work4/PvqDq929BSx_A_D_M1n_a.php", - "threatintel.indicator.url.path": "/Work4/PvqDq929BSx_A_D_M1n_a.php", - "threatintel.indicator.url.scheme": "http" - }, - { + "anomali.limo.pattern": "[url:value = 'http://kironofer.com/webpanel/login.php']", + "anomali.limo.type": "indicator", + "anomali.limo.valid_from": "2020-01-22T03:00:27.591Z", "event.category": "threat", "event.dataset": "threatintel.anomali", "event.kind": "enrichment", @@ -873,32 +930,34 @@ "threatstream-confidence-78", "threatstream-severity-medium" ], - "threatintel.anomali.description": "TS ID: 55241332317; iType: mal_url; State: active; Org: SoftLayer Technologies; Source: CyberCrime", - "threatintel.anomali.id": "indicator--d6b59b66-5020-4368-85a7-196026856ea9", - "threatintel.anomali.labels": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali Limo", + "threat.indicator.first_seen": "2020-01-22T03:00:27.591Z", + "threat.indicator.provider": "CyberCrime", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "kironofer.com", + "threat.indicator.url.extension": "php", + "threat.indicator.url.full": "http://kironofer.com/webpanel/login.php", + "threat.indicator.url.original": "http://kironofer.com/webpanel/login.php", + "threat.indicator.url.path": "/webpanel/login.php", + "threat.indicator.url.scheme": "http" + }, + { + "anomali.limo.description": "TS ID: 55241332309; iType: mal_url; State: active; Org: ServerMania; Source: CyberCrime", + "anomali.limo.id": "indicator--aff7b07f-acc7-4bec-ab19-1fce972bfd09", + "anomali.limo.labels": [ "malicious-activity", - "threatstream-confidence-78", + "threatstream-confidence-68", "threatstream-severity-medium" ], - "threatintel.anomali.modified": "2020-01-22T03:00:27.591Z", - "threatintel.anomali.name": "mal_url: http://kironofer.com/webpanel/login.php", - "threatintel.anomali.object_marking_refs": [ + "anomali.limo.modified": "2020-01-22T03:00:45.787Z", + "anomali.limo.name": "mal_url: http://worldatdoor.in/panel2/Panel/five/PvqDq929BSx_A_D_M1n_a.php", + "anomali.limo.object_marking_refs": [ "marking-definition--34098fce-860f-48ae-8e50-ebd3cc5e41da" ], - "threatintel.anomali.pattern": "[url:value = 'http://kironofer.com/webpanel/login.php']", - "threatintel.anomali.type": "indicator", - "threatintel.anomali.valid_from": "2020-01-22T03:00:27.591Z", - "threatintel.indicator.first_seen": "2020-01-22T03:00:27.591Z", - "threatintel.indicator.provider": "CyberCrime", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "kironofer.com", - "threatintel.indicator.url.extension": "php", - "threatintel.indicator.url.full": "http://kironofer.com/webpanel/login.php", - "threatintel.indicator.url.original": "http://kironofer.com/webpanel/login.php", - "threatintel.indicator.url.path": "/webpanel/login.php", - "threatintel.indicator.url.scheme": "http" - }, - { + "anomali.limo.pattern": "[url:value = 'http://worldatdoor.in/panel2/Panel/five/PvqDq929BSx_A_D_M1n_a.php']", + "anomali.limo.type": "indicator", + "anomali.limo.valid_from": "2020-01-22T03:00:45.787Z", "event.category": "threat", "event.dataset": "threatintel.anomali", "event.kind": "enrichment", @@ -915,32 +974,34 @@ "threatstream-confidence-68", "threatstream-severity-medium" ], - "threatintel.anomali.description": "TS ID: 55241332309; iType: mal_url; State: active; Org: ServerMania; Source: CyberCrime", - "threatintel.anomali.id": "indicator--aff7b07f-acc7-4bec-ab19-1fce972bfd09", - "threatintel.anomali.labels": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali Limo", + "threat.indicator.first_seen": "2020-01-22T03:00:45.787Z", + "threat.indicator.provider": "CyberCrime", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "worldatdoor.in", + "threat.indicator.url.extension": "php", + "threat.indicator.url.full": "http://worldatdoor.in/panel2/Panel/five/PvqDq929BSx_A_D_M1n_a.php", + "threat.indicator.url.original": "http://worldatdoor.in/panel2/Panel/five/PvqDq929BSx_A_D_M1n_a.php", + "threat.indicator.url.path": "/panel2/Panel/five/PvqDq929BSx_A_D_M1n_a.php", + "threat.indicator.url.scheme": "http" + }, + { + "anomali.limo.description": "TS ID: 55241332286; iType: mal_url; State: active; Org: Garanntor-Hosting; Source: CyberCrime", + "anomali.limo.id": "indicator--ba71ba3a-1efd-40da-ab0d-f4397d6fc337", + "anomali.limo.labels": [ "malicious-activity", - "threatstream-confidence-68", + "threatstream-confidence-91", "threatstream-severity-medium" ], - "threatintel.anomali.modified": "2020-01-22T03:00:45.787Z", - "threatintel.anomali.name": "mal_url: http://worldatdoor.in/panel2/Panel/five/PvqDq929BSx_A_D_M1n_a.php", - "threatintel.anomali.object_marking_refs": [ + "anomali.limo.modified": "2020-01-22T03:00:45.841Z", + "anomali.limo.name": "mal_url: http://smartlinktelecom.top/kings/panel/admin.php", + "anomali.limo.object_marking_refs": [ "marking-definition--34098fce-860f-48ae-8e50-ebd3cc5e41da" ], - "threatintel.anomali.pattern": "[url:value = 'http://worldatdoor.in/panel2/Panel/five/PvqDq929BSx_A_D_M1n_a.php']", - "threatintel.anomali.type": "indicator", - "threatintel.anomali.valid_from": "2020-01-22T03:00:45.787Z", - "threatintel.indicator.first_seen": "2020-01-22T03:00:45.787Z", - "threatintel.indicator.provider": "CyberCrime", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "worldatdoor.in", - "threatintel.indicator.url.extension": "php", - "threatintel.indicator.url.full": "http://worldatdoor.in/panel2/Panel/five/PvqDq929BSx_A_D_M1n_a.php", - "threatintel.indicator.url.original": "http://worldatdoor.in/panel2/Panel/five/PvqDq929BSx_A_D_M1n_a.php", - "threatintel.indicator.url.path": "/panel2/Panel/five/PvqDq929BSx_A_D_M1n_a.php", - "threatintel.indicator.url.scheme": "http" - }, - { + "anomali.limo.pattern": "[url:value = 'http://smartlinktelecom.top/kings/panel/admin.php']", + "anomali.limo.type": "indicator", + "anomali.limo.valid_from": "2020-01-22T03:00:45.841Z", "event.category": "threat", "event.dataset": "threatintel.anomali", "event.kind": "enrichment", @@ -957,32 +1018,34 @@ "threatstream-confidence-91", "threatstream-severity-medium" ], - "threatintel.anomali.description": "TS ID: 55241332286; iType: mal_url; State: active; Org: Garanntor-Hosting; Source: CyberCrime", - "threatintel.anomali.id": "indicator--ba71ba3a-1efd-40da-ab0d-f4397d6fc337", - "threatintel.anomali.labels": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali Limo", + "threat.indicator.first_seen": "2020-01-22T03:00:45.841Z", + "threat.indicator.provider": "CyberCrime", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "smartlinktelecom.top", + "threat.indicator.url.extension": "php", + "threat.indicator.url.full": "http://smartlinktelecom.top/kings/panel/admin.php", + "threat.indicator.url.original": "http://smartlinktelecom.top/kings/panel/admin.php", + "threat.indicator.url.path": "/kings/panel/admin.php", + "threat.indicator.url.scheme": "http" + }, + { + "anomali.limo.description": "TS ID: 55241332339; iType: mal_url; State: active; Org: Cloudflare; Source: CyberCrime", + "anomali.limo.id": "indicator--17777e7f-3e91-4446-a43d-79139de8a948", + "anomali.limo.labels": [ "malicious-activity", - "threatstream-confidence-91", + "threatstream-confidence-64", "threatstream-severity-medium" ], - "threatintel.anomali.modified": "2020-01-22T03:00:45.841Z", - "threatintel.anomali.name": "mal_url: http://smartlinktelecom.top/kings/panel/admin.php", - "threatintel.anomali.object_marking_refs": [ + "anomali.limo.modified": "2020-01-22T03:00:45.959Z", + "anomali.limo.name": "mal_url: http://carirero.net/login.php", + "anomali.limo.object_marking_refs": [ "marking-definition--34098fce-860f-48ae-8e50-ebd3cc5e41da" ], - "threatintel.anomali.pattern": "[url:value = 'http://smartlinktelecom.top/kings/panel/admin.php']", - "threatintel.anomali.type": "indicator", - "threatintel.anomali.valid_from": "2020-01-22T03:00:45.841Z", - "threatintel.indicator.first_seen": "2020-01-22T03:00:45.841Z", - "threatintel.indicator.provider": "CyberCrime", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "smartlinktelecom.top", - "threatintel.indicator.url.extension": "php", - "threatintel.indicator.url.full": "http://smartlinktelecom.top/kings/panel/admin.php", - "threatintel.indicator.url.original": "http://smartlinktelecom.top/kings/panel/admin.php", - "threatintel.indicator.url.path": "/kings/panel/admin.php", - "threatintel.indicator.url.scheme": "http" - }, - { + "anomali.limo.pattern": "[url:value = 'http://carirero.net/login.php']", + "anomali.limo.type": "indicator", + "anomali.limo.valid_from": "2020-01-22T03:00:45.959Z", "event.category": "threat", "event.dataset": "threatintel.anomali", "event.kind": "enrichment", @@ -999,32 +1062,34 @@ "threatstream-confidence-64", "threatstream-severity-medium" ], - "threatintel.anomali.description": "TS ID: 55241332339; iType: mal_url; State: active; Org: Cloudflare; Source: CyberCrime", - "threatintel.anomali.id": "indicator--17777e7f-3e91-4446-a43d-79139de8a948", - "threatintel.anomali.labels": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali Limo", + "threat.indicator.first_seen": "2020-01-22T03:00:45.959Z", + "threat.indicator.provider": "CyberCrime", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "carirero.net", + "threat.indicator.url.extension": "php", + "threat.indicator.url.full": "http://carirero.net/login.php", + "threat.indicator.url.original": "http://carirero.net/login.php", + "threat.indicator.url.path": "/login.php", + "threat.indicator.url.scheme": "http" + }, + { + "anomali.limo.description": "TS ID: 55241332319; iType: mal_ip; State: active; Org: SoftLayer Technologies; Source: CyberCrime", + "anomali.limo.id": "indicator--f6be1804-cfe4-4f41-9338-2b65f5b1dda1", + "anomali.limo.labels": [ "malicious-activity", - "threatstream-confidence-64", + "threatstream-confidence-30", "threatstream-severity-medium" ], - "threatintel.anomali.modified": "2020-01-22T03:00:45.959Z", - "threatintel.anomali.name": "mal_url: http://carirero.net/login.php", - "threatintel.anomali.object_marking_refs": [ + "anomali.limo.modified": "2020-01-22T03:00:46.025Z", + "anomali.limo.name": "mal_ip: 74.116.84.20", + "anomali.limo.object_marking_refs": [ "marking-definition--34098fce-860f-48ae-8e50-ebd3cc5e41da" ], - "threatintel.anomali.pattern": "[url:value = 'http://carirero.net/login.php']", - "threatintel.anomali.type": "indicator", - "threatintel.anomali.valid_from": "2020-01-22T03:00:45.959Z", - "threatintel.indicator.first_seen": "2020-01-22T03:00:45.959Z", - "threatintel.indicator.provider": "CyberCrime", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "carirero.net", - "threatintel.indicator.url.extension": "php", - "threatintel.indicator.url.full": "http://carirero.net/login.php", - "threatintel.indicator.url.original": "http://carirero.net/login.php", - "threatintel.indicator.url.path": "/login.php", - "threatintel.indicator.url.scheme": "http" - }, - { + "anomali.limo.pattern": "[ipv4-addr:value = '74.116.84.20']", + "anomali.limo.type": "indicator", + "anomali.limo.valid_from": "2020-01-22T03:00:46.025Z", "event.category": "threat", "event.dataset": "threatintel.anomali", "event.kind": "enrichment", @@ -1041,27 +1106,29 @@ "threatstream-confidence-30", "threatstream-severity-medium" ], - "threatintel.anomali.description": "TS ID: 55241332319; iType: mal_ip; State: active; Org: SoftLayer Technologies; Source: CyberCrime", - "threatintel.anomali.id": "indicator--f6be1804-cfe4-4f41-9338-2b65f5b1dda1", - "threatintel.anomali.labels": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali Limo", + "threat.indicator.first_seen": "2020-01-22T03:00:46.025Z", + "threat.indicator.ip": "74.116.84.20", + "threat.indicator.provider": "CyberCrime", + "threat.indicator.type": "ipv4-addr" + }, + { + "anomali.limo.description": "TS ID: 55241332305; iType: mal_url; State: active; Org: Cloudflare; Source: CyberCrime", + "anomali.limo.id": "indicator--b4fd8489-9589-4f70-996c-84989245a21b", + "anomali.limo.labels": [ "malicious-activity", - "threatstream-confidence-30", + "threatstream-confidence-43", "threatstream-severity-medium" ], - "threatintel.anomali.modified": "2020-01-22T03:00:46.025Z", - "threatintel.anomali.name": "mal_ip: 74.116.84.20", - "threatintel.anomali.object_marking_refs": [ + "anomali.limo.modified": "2020-01-22T03:00:57.729Z", + "anomali.limo.name": "mal_url: http://tuu.nu/login", + "anomali.limo.object_marking_refs": [ "marking-definition--34098fce-860f-48ae-8e50-ebd3cc5e41da" ], - "threatintel.anomali.pattern": "[ipv4-addr:value = '74.116.84.20']", - "threatintel.anomali.type": "indicator", - "threatintel.anomali.valid_from": "2020-01-22T03:00:46.025Z", - "threatintel.indicator.first_seen": "2020-01-22T03:00:46.025Z", - "threatintel.indicator.ip": "74.116.84.20", - "threatintel.indicator.provider": "CyberCrime", - "threatintel.indicator.type": "ipv4-addr" - }, - { + "anomali.limo.pattern": "[url:value = 'http://tuu.nu/login']", + "anomali.limo.type": "indicator", + "anomali.limo.valid_from": "2020-01-22T03:00:57.729Z", "event.category": "threat", "event.dataset": "threatintel.anomali", "event.kind": "enrichment", @@ -1078,31 +1145,33 @@ "threatstream-confidence-43", "threatstream-severity-medium" ], - "threatintel.anomali.description": "TS ID: 55241332305; iType: mal_url; State: active; Org: Cloudflare; Source: CyberCrime", - "threatintel.anomali.id": "indicator--b4fd8489-9589-4f70-996c-84989245a21b", - "threatintel.anomali.labels": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali Limo", + "threat.indicator.first_seen": "2020-01-22T03:00:57.729Z", + "threat.indicator.provider": "CyberCrime", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "tuu.nu", + "threat.indicator.url.full": "http://tuu.nu/login", + "threat.indicator.url.original": "http://tuu.nu/login", + "threat.indicator.url.path": "/login", + "threat.indicator.url.scheme": "http" + }, + { + "anomali.limo.description": "TS ID: 55241332346; iType: mal_url; State: active; Org: Ifx Networks Colombia; Source: CyberCrime", + "anomali.limo.id": "indicator--bc50c62f-a015-4460-87df-2137626877e3", + "anomali.limo.labels": [ "malicious-activity", - "threatstream-confidence-43", + "threatstream-confidence-36", "threatstream-severity-medium" ], - "threatintel.anomali.modified": "2020-01-22T03:00:57.729Z", - "threatintel.anomali.name": "mal_url: http://tuu.nu/login", - "threatintel.anomali.object_marking_refs": [ + "anomali.limo.modified": "2020-01-22T03:01:02.696Z", + "anomali.limo.name": "mal_url: http://dulfix.com/cgi-bins/dulfix/gustav57/PvqDq929BSx_A_D_M1n_a.php", + "anomali.limo.object_marking_refs": [ "marking-definition--34098fce-860f-48ae-8e50-ebd3cc5e41da" ], - "threatintel.anomali.pattern": "[url:value = 'http://tuu.nu/login']", - "threatintel.anomali.type": "indicator", - "threatintel.anomali.valid_from": "2020-01-22T03:00:57.729Z", - "threatintel.indicator.first_seen": "2020-01-22T03:00:57.729Z", - "threatintel.indicator.provider": "CyberCrime", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "tuu.nu", - "threatintel.indicator.url.full": "http://tuu.nu/login", - "threatintel.indicator.url.original": "http://tuu.nu/login", - "threatintel.indicator.url.path": "/login", - "threatintel.indicator.url.scheme": "http" - }, - { + "anomali.limo.pattern": "[url:value = 'http://dulfix.com/cgi-bins/dulfix/gustav57/PvqDq929BSx_A_D_M1n_a.php']", + "anomali.limo.type": "indicator", + "anomali.limo.valid_from": "2020-01-22T03:01:02.696Z", "event.category": "threat", "event.dataset": "threatintel.anomali", "event.kind": "enrichment", @@ -1119,32 +1188,34 @@ "threatstream-confidence-36", "threatstream-severity-medium" ], - "threatintel.anomali.description": "TS ID: 55241332346; iType: mal_url; State: active; Org: Ifx Networks Colombia; Source: CyberCrime", - "threatintel.anomali.id": "indicator--bc50c62f-a015-4460-87df-2137626877e3", - "threatintel.anomali.labels": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali Limo", + "threat.indicator.first_seen": "2020-01-22T03:01:02.696Z", + "threat.indicator.provider": "CyberCrime", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "dulfix.com", + "threat.indicator.url.extension": "php", + "threat.indicator.url.full": "http://dulfix.com/cgi-bins/dulfix/gustav57/PvqDq929BSx_A_D_M1n_a.php", + "threat.indicator.url.original": "http://dulfix.com/cgi-bins/dulfix/gustav57/PvqDq929BSx_A_D_M1n_a.php", + "threat.indicator.url.path": "/cgi-bins/dulfix/gustav57/PvqDq929BSx_A_D_M1n_a.php", + "threat.indicator.url.scheme": "http" + }, + { + "anomali.limo.description": "TS ID: 55241332323; iType: mal_url; State: active; Org: CyrusOne LLC; Source: CyberCrime", + "anomali.limo.id": "indicator--2765af4b-bfb7-4ac8-82d2-ab6ed8a52461", + "anomali.limo.labels": [ "malicious-activity", - "threatstream-confidence-36", + "threatstream-confidence-65", "threatstream-severity-medium" ], - "threatintel.anomali.modified": "2020-01-22T03:01:02.696Z", - "threatintel.anomali.name": "mal_url: http://dulfix.com/cgi-bins/dulfix/gustav57/PvqDq929BSx_A_D_M1n_a.php", - "threatintel.anomali.object_marking_refs": [ + "anomali.limo.modified": "2020-01-22T03:01:02.807Z", + "anomali.limo.name": "mal_url: http://deliciasdvally.com.pe/includes/gter/PvqDq929BSx_A_D_M1n_a.php", + "anomali.limo.object_marking_refs": [ "marking-definition--34098fce-860f-48ae-8e50-ebd3cc5e41da" ], - "threatintel.anomali.pattern": "[url:value = 'http://dulfix.com/cgi-bins/dulfix/gustav57/PvqDq929BSx_A_D_M1n_a.php']", - "threatintel.anomali.type": "indicator", - "threatintel.anomali.valid_from": "2020-01-22T03:01:02.696Z", - "threatintel.indicator.first_seen": "2020-01-22T03:01:02.696Z", - "threatintel.indicator.provider": "CyberCrime", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "dulfix.com", - "threatintel.indicator.url.extension": "php", - "threatintel.indicator.url.full": "http://dulfix.com/cgi-bins/dulfix/gustav57/PvqDq929BSx_A_D_M1n_a.php", - "threatintel.indicator.url.original": "http://dulfix.com/cgi-bins/dulfix/gustav57/PvqDq929BSx_A_D_M1n_a.php", - "threatintel.indicator.url.path": "/cgi-bins/dulfix/gustav57/PvqDq929BSx_A_D_M1n_a.php", - "threatintel.indicator.url.scheme": "http" - }, - { + "anomali.limo.pattern": "[url:value = 'http://deliciasdvally.com.pe/includes/gter/PvqDq929BSx_A_D_M1n_a.php']", + "anomali.limo.type": "indicator", + "anomali.limo.valid_from": "2020-01-22T03:01:02.807Z", "event.category": "threat", "event.dataset": "threatintel.anomali", "event.kind": "enrichment", @@ -1161,32 +1232,34 @@ "threatstream-confidence-65", "threatstream-severity-medium" ], - "threatintel.anomali.description": "TS ID: 55241332323; iType: mal_url; State: active; Org: CyrusOne LLC; Source: CyberCrime", - "threatintel.anomali.id": "indicator--2765af4b-bfb7-4ac8-82d2-ab6ed8a52461", - "threatintel.anomali.labels": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali Limo", + "threat.indicator.first_seen": "2020-01-22T03:01:02.807Z", + "threat.indicator.provider": "CyberCrime", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "deliciasdvally.com.pe", + "threat.indicator.url.extension": "php", + "threat.indicator.url.full": "http://deliciasdvally.com.pe/includes/gter/PvqDq929BSx_A_D_M1n_a.php", + "threat.indicator.url.original": "http://deliciasdvally.com.pe/includes/gter/PvqDq929BSx_A_D_M1n_a.php", + "threat.indicator.url.path": "/includes/gter/PvqDq929BSx_A_D_M1n_a.php", + "threat.indicator.url.scheme": "http" + }, + { + "anomali.limo.description": "TS ID: 55241332399; iType: mal_url; State: active; Org: Cloudflare; Source: CyberCrime", + "anomali.limo.id": "indicator--9c0e63a1-c32a-470a-bf09-51488e239c63", + "anomali.limo.labels": [ "malicious-activity", - "threatstream-confidence-65", + "threatstream-confidence-93", "threatstream-severity-medium" ], - "threatintel.anomali.modified": "2020-01-22T03:01:02.807Z", - "threatintel.anomali.name": "mal_url: http://deliciasdvally.com.pe/includes/gter/PvqDq929BSx_A_D_M1n_a.php", - "threatintel.anomali.object_marking_refs": [ + "anomali.limo.modified": "2020-01-22T03:01:24.810Z", + "anomali.limo.name": "mal_url: http://nkpotu.xyz/Kpot1/login.php", + "anomali.limo.object_marking_refs": [ "marking-definition--34098fce-860f-48ae-8e50-ebd3cc5e41da" ], - "threatintel.anomali.pattern": "[url:value = 'http://deliciasdvally.com.pe/includes/gter/PvqDq929BSx_A_D_M1n_a.php']", - "threatintel.anomali.type": "indicator", - "threatintel.anomali.valid_from": "2020-01-22T03:01:02.807Z", - "threatintel.indicator.first_seen": "2020-01-22T03:01:02.807Z", - "threatintel.indicator.provider": "CyberCrime", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "deliciasdvally.com.pe", - "threatintel.indicator.url.extension": "php", - "threatintel.indicator.url.full": "http://deliciasdvally.com.pe/includes/gter/PvqDq929BSx_A_D_M1n_a.php", - "threatintel.indicator.url.original": "http://deliciasdvally.com.pe/includes/gter/PvqDq929BSx_A_D_M1n_a.php", - "threatintel.indicator.url.path": "/includes/gter/PvqDq929BSx_A_D_M1n_a.php", - "threatintel.indicator.url.scheme": "http" - }, - { + "anomali.limo.pattern": "[url:value = 'http://nkpotu.xyz/Kpot1/login.php']", + "anomali.limo.type": "indicator", + "anomali.limo.valid_from": "2020-01-22T03:01:24.81Z", "event.category": "threat", "event.dataset": "threatintel.anomali", "event.kind": "enrichment", @@ -1203,32 +1276,34 @@ "threatstream-confidence-93", "threatstream-severity-medium" ], - "threatintel.anomali.description": "TS ID: 55241332399; iType: mal_url; State: active; Org: Cloudflare; Source: CyberCrime", - "threatintel.anomali.id": "indicator--9c0e63a1-c32a-470a-bf09-51488e239c63", - "threatintel.anomali.labels": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali Limo", + "threat.indicator.first_seen": "2020-01-22T03:01:24.810Z", + "threat.indicator.provider": "CyberCrime", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "nkpotu.xyz", + "threat.indicator.url.extension": "php", + "threat.indicator.url.full": "http://nkpotu.xyz/Kpot1/login.php", + "threat.indicator.url.original": "http://nkpotu.xyz/Kpot1/login.php", + "threat.indicator.url.path": "/Kpot1/login.php", + "threat.indicator.url.scheme": "http" + }, + { + "anomali.limo.description": "TS ID: 55241332328; iType: mal_ip; State: active; Org: RUCloud; Source: CyberCrime", + "anomali.limo.id": "indicator--8047678e-20be-4116-9bc4-7bb7c26554e0", + "anomali.limo.labels": [ "malicious-activity", - "threatstream-confidence-93", + "threatstream-confidence-87", "threatstream-severity-medium" ], - "threatintel.anomali.modified": "2020-01-22T03:01:24.810Z", - "threatintel.anomali.name": "mal_url: http://nkpotu.xyz/Kpot1/login.php", - "threatintel.anomali.object_marking_refs": [ + "anomali.limo.modified": "2020-01-22T03:01:41.158Z", + "anomali.limo.name": "mal_ip: 194.87.147.80", + "anomali.limo.object_marking_refs": [ "marking-definition--34098fce-860f-48ae-8e50-ebd3cc5e41da" ], - "threatintel.anomali.pattern": "[url:value = 'http://nkpotu.xyz/Kpot1/login.php']", - "threatintel.anomali.type": "indicator", - "threatintel.anomali.valid_from": "2020-01-22T03:01:24.81Z", - "threatintel.indicator.first_seen": "2020-01-22T03:01:24.810Z", - "threatintel.indicator.provider": "CyberCrime", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "nkpotu.xyz", - "threatintel.indicator.url.extension": "php", - "threatintel.indicator.url.full": "http://nkpotu.xyz/Kpot1/login.php", - "threatintel.indicator.url.original": "http://nkpotu.xyz/Kpot1/login.php", - "threatintel.indicator.url.path": "/Kpot1/login.php", - "threatintel.indicator.url.scheme": "http" - }, - { + "anomali.limo.pattern": "[ipv4-addr:value = '194.87.147.80']", + "anomali.limo.type": "indicator", + "anomali.limo.valid_from": "2020-01-22T03:01:41.158Z", "event.category": "threat", "event.dataset": "threatintel.anomali", "event.kind": "enrichment", @@ -1245,27 +1320,29 @@ "threatstream-confidence-87", "threatstream-severity-medium" ], - "threatintel.anomali.description": "TS ID: 55241332328; iType: mal_ip; State: active; Org: RUCloud; Source: CyberCrime", - "threatintel.anomali.id": "indicator--8047678e-20be-4116-9bc4-7bb7c26554e0", - "threatintel.anomali.labels": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali Limo", + "threat.indicator.first_seen": "2020-01-22T03:01:41.158Z", + "threat.indicator.ip": "194.87.147.80", + "threat.indicator.provider": "CyberCrime", + "threat.indicator.type": "ipv4-addr" + }, + { + "anomali.limo.description": "TS ID: 55241332377; iType: mal_url; State: active; Org: A100 ROW GmbH; Source: CyberCrime", + "anomali.limo.id": "indicator--c57a880c-1ce0-45de-9bab-fb2910454a61", + "anomali.limo.labels": [ "malicious-activity", - "threatstream-confidence-87", + "threatstream-confidence-85", "threatstream-severity-medium" ], - "threatintel.anomali.modified": "2020-01-22T03:01:41.158Z", - "threatintel.anomali.name": "mal_ip: 194.87.147.80", - "threatintel.anomali.object_marking_refs": [ + "anomali.limo.modified": "2020-01-22T03:01:57.189Z", + "anomali.limo.name": "mal_url: http://35.158.92.3/panel/admin.php", + "anomali.limo.object_marking_refs": [ "marking-definition--34098fce-860f-48ae-8e50-ebd3cc5e41da" ], - "threatintel.anomali.pattern": "[ipv4-addr:value = '194.87.147.80']", - "threatintel.anomali.type": "indicator", - "threatintel.anomali.valid_from": "2020-01-22T03:01:41.158Z", - "threatintel.indicator.first_seen": "2020-01-22T03:01:41.158Z", - "threatintel.indicator.ip": "194.87.147.80", - "threatintel.indicator.provider": "CyberCrime", - "threatintel.indicator.type": "ipv4-addr" - }, - { + "anomali.limo.pattern": "[url:value = 'http://35.158.92.3/panel/admin.php']", + "anomali.limo.type": "indicator", + "anomali.limo.valid_from": "2020-01-22T03:01:57.189Z", "event.category": "threat", "event.dataset": "threatintel.anomali", "event.kind": "enrichment", @@ -1282,32 +1359,34 @@ "threatstream-confidence-85", "threatstream-severity-medium" ], - "threatintel.anomali.description": "TS ID: 55241332377; iType: mal_url; State: active; Org: A100 ROW GmbH; Source: CyberCrime", - "threatintel.anomali.id": "indicator--c57a880c-1ce0-45de-9bab-fb2910454a61", - "threatintel.anomali.labels": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali Limo", + "threat.indicator.first_seen": "2020-01-22T03:01:57.189Z", + "threat.indicator.provider": "CyberCrime", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "35.158.92.3", + "threat.indicator.url.extension": "php", + "threat.indicator.url.full": "http://35.158.92.3/panel/admin.php", + "threat.indicator.url.original": "http://35.158.92.3/panel/admin.php", + "threat.indicator.url.path": "/panel/admin.php", + "threat.indicator.url.scheme": "http" + }, + { + "anomali.limo.description": "TS ID: 55241332101; iType: mal_ip; State: active; Source: CyberCrime", + "anomali.limo.id": "indicator--6056152c-0fa5-4e34-871a-3c8990f1ee46", + "anomali.limo.labels": [ "malicious-activity", - "threatstream-confidence-85", + "threatstream-confidence-42", "threatstream-severity-medium" ], - "threatintel.anomali.modified": "2020-01-22T03:01:57.189Z", - "threatintel.anomali.name": "mal_url: http://35.158.92.3/panel/admin.php", - "threatintel.anomali.object_marking_refs": [ + "anomali.limo.modified": "2020-01-22T03:01:57.279Z", + "anomali.limo.name": "mal_ip: 45.95.168.70", + "anomali.limo.object_marking_refs": [ "marking-definition--34098fce-860f-48ae-8e50-ebd3cc5e41da" ], - "threatintel.anomali.pattern": "[url:value = 'http://35.158.92.3/panel/admin.php']", - "threatintel.anomali.type": "indicator", - "threatintel.anomali.valid_from": "2020-01-22T03:01:57.189Z", - "threatintel.indicator.first_seen": "2020-01-22T03:01:57.189Z", - "threatintel.indicator.provider": "CyberCrime", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "35.158.92.3", - "threatintel.indicator.url.extension": "php", - "threatintel.indicator.url.full": "http://35.158.92.3/panel/admin.php", - "threatintel.indicator.url.original": "http://35.158.92.3/panel/admin.php", - "threatintel.indicator.url.path": "/panel/admin.php", - "threatintel.indicator.url.scheme": "http" - }, - { + "anomali.limo.pattern": "[ipv4-addr:value = '45.95.168.70']", + "anomali.limo.type": "indicator", + "anomali.limo.valid_from": "2020-01-22T03:01:57.279Z", "event.category": "threat", "event.dataset": "threatintel.anomali", "event.kind": "enrichment", @@ -1324,27 +1403,29 @@ "threatstream-confidence-42", "threatstream-severity-medium" ], - "threatintel.anomali.description": "TS ID: 55241332101; iType: mal_ip; State: active; Source: CyberCrime", - "threatintel.anomali.id": "indicator--6056152c-0fa5-4e34-871a-3c8990f1ee46", - "threatintel.anomali.labels": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali Limo", + "threat.indicator.first_seen": "2020-01-22T03:01:57.279Z", + "threat.indicator.ip": "45.95.168.70", + "threat.indicator.provider": "CyberCrime", + "threat.indicator.type": "ipv4-addr" + }, + { + "anomali.limo.description": "TS ID: 55241332357; iType: mal_url; State: active; Org: Cloudflare; Source: CyberCrime", + "anomali.limo.id": "indicator--23215acb-4989-4434-ac6d-8f9367734f0f", + "anomali.limo.labels": [ "malicious-activity", - "threatstream-confidence-42", + "threatstream-confidence-76", "threatstream-severity-medium" ], - "threatintel.anomali.modified": "2020-01-22T03:01:57.279Z", - "threatintel.anomali.name": "mal_ip: 45.95.168.70", - "threatintel.anomali.object_marking_refs": [ + "anomali.limo.modified": "2020-01-22T03:02:50.570Z", + "anomali.limo.name": "mal_url: http://chol.cc/Work7/PvqDq929BSx_A_D_M1n_a.php", + "anomali.limo.object_marking_refs": [ "marking-definition--34098fce-860f-48ae-8e50-ebd3cc5e41da" ], - "threatintel.anomali.pattern": "[ipv4-addr:value = '45.95.168.70']", - "threatintel.anomali.type": "indicator", - "threatintel.anomali.valid_from": "2020-01-22T03:01:57.279Z", - "threatintel.indicator.first_seen": "2020-01-22T03:01:57.279Z", - "threatintel.indicator.ip": "45.95.168.70", - "threatintel.indicator.provider": "CyberCrime", - "threatintel.indicator.type": "ipv4-addr" - }, - { + "anomali.limo.pattern": "[url:value = 'http://chol.cc/Work7/PvqDq929BSx_A_D_M1n_a.php']", + "anomali.limo.type": "indicator", + "anomali.limo.valid_from": "2020-01-22T03:02:50.57Z", "event.category": "threat", "event.dataset": "threatintel.anomali", "event.kind": "enrichment", @@ -1361,32 +1442,34 @@ "threatstream-confidence-76", "threatstream-severity-medium" ], - "threatintel.anomali.description": "TS ID: 55241332357; iType: mal_url; State: active; Org: Cloudflare; Source: CyberCrime", - "threatintel.anomali.id": "indicator--23215acb-4989-4434-ac6d-8f9367734f0f", - "threatintel.anomali.labels": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali Limo", + "threat.indicator.first_seen": "2020-01-22T03:02:50.570Z", + "threat.indicator.provider": "CyberCrime", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "chol.cc", + "threat.indicator.url.extension": "php", + "threat.indicator.url.full": "http://chol.cc/Work7/PvqDq929BSx_A_D_M1n_a.php", + "threat.indicator.url.original": "http://chol.cc/Work7/PvqDq929BSx_A_D_M1n_a.php", + "threat.indicator.url.path": "/Work7/PvqDq929BSx_A_D_M1n_a.php", + "threat.indicator.url.scheme": "http" + }, + { + "anomali.limo.description": "TS ID: 55241332289; iType: mal_url; State: active; Org: SPRINTHOST.RU - shared/premium hosting, VDS, dedic; Source: CyberCrime", + "anomali.limo.id": "indicator--452ece92-9ff2-4f99-8a7f-fd614ebea8cf", + "anomali.limo.labels": [ "malicious-activity", - "threatstream-confidence-76", + "threatstream-confidence-26", "threatstream-severity-medium" ], - "threatintel.anomali.modified": "2020-01-22T03:02:50.570Z", - "threatintel.anomali.name": "mal_url: http://chol.cc/Work7/PvqDq929BSx_A_D_M1n_a.php", - "threatintel.anomali.object_marking_refs": [ + "anomali.limo.modified": "2020-01-22T03:02:52.496Z", + "anomali.limo.name": "mal_url: http://f0391600.xsph.ru/login", + "anomali.limo.object_marking_refs": [ "marking-definition--34098fce-860f-48ae-8e50-ebd3cc5e41da" ], - "threatintel.anomali.pattern": "[url:value = 'http://chol.cc/Work7/PvqDq929BSx_A_D_M1n_a.php']", - "threatintel.anomali.type": "indicator", - "threatintel.anomali.valid_from": "2020-01-22T03:02:50.57Z", - "threatintel.indicator.first_seen": "2020-01-22T03:02:50.570Z", - "threatintel.indicator.provider": "CyberCrime", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "chol.cc", - "threatintel.indicator.url.extension": "php", - "threatintel.indicator.url.full": "http://chol.cc/Work7/PvqDq929BSx_A_D_M1n_a.php", - "threatintel.indicator.url.original": "http://chol.cc/Work7/PvqDq929BSx_A_D_M1n_a.php", - "threatintel.indicator.url.path": "/Work7/PvqDq929BSx_A_D_M1n_a.php", - "threatintel.indicator.url.scheme": "http" - }, - { + "anomali.limo.pattern": "[url:value = 'http://f0391600.xsph.ru/login']", + "anomali.limo.type": "indicator", + "anomali.limo.valid_from": "2020-01-22T03:02:52.496Z", "event.category": "threat", "event.dataset": "threatintel.anomali", "event.kind": "enrichment", @@ -1403,31 +1486,33 @@ "threatstream-confidence-26", "threatstream-severity-medium" ], - "threatintel.anomali.description": "TS ID: 55241332289; iType: mal_url; State: active; Org: SPRINTHOST.RU - shared/premium hosting, VDS, dedic; Source: CyberCrime", - "threatintel.anomali.id": "indicator--452ece92-9ff2-4f99-8a7f-fd614ebea8cf", - "threatintel.anomali.labels": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali Limo", + "threat.indicator.first_seen": "2020-01-22T03:02:52.496Z", + "threat.indicator.provider": "CyberCrime", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "f0391600.xsph.ru", + "threat.indicator.url.full": "http://f0391600.xsph.ru/login", + "threat.indicator.url.original": "http://f0391600.xsph.ru/login", + "threat.indicator.url.path": "/login", + "threat.indicator.url.scheme": "http" + }, + { + "anomali.limo.description": "TS ID: 55241332334; iType: mal_url; State: active; Org: Namecheap; Source: CyberCrime", + "anomali.limo.id": "indicator--10958d74-ec60-41af-a1ab-1613257e670f", + "anomali.limo.labels": [ "malicious-activity", - "threatstream-confidence-26", + "threatstream-confidence-94", "threatstream-severity-medium" ], - "threatintel.anomali.modified": "2020-01-22T03:02:52.496Z", - "threatintel.anomali.name": "mal_url: http://f0391600.xsph.ru/login", - "threatintel.anomali.object_marking_refs": [ + "anomali.limo.modified": "2020-01-22T03:03:42.819Z", + "anomali.limo.name": "mal_url: http://extraclick.space/login.php", + "anomali.limo.object_marking_refs": [ "marking-definition--34098fce-860f-48ae-8e50-ebd3cc5e41da" ], - "threatintel.anomali.pattern": "[url:value = 'http://f0391600.xsph.ru/login']", - "threatintel.anomali.type": "indicator", - "threatintel.anomali.valid_from": "2020-01-22T03:02:52.496Z", - "threatintel.indicator.first_seen": "2020-01-22T03:02:52.496Z", - "threatintel.indicator.provider": "CyberCrime", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "f0391600.xsph.ru", - "threatintel.indicator.url.full": "http://f0391600.xsph.ru/login", - "threatintel.indicator.url.original": "http://f0391600.xsph.ru/login", - "threatintel.indicator.url.path": "/login", - "threatintel.indicator.url.scheme": "http" - }, - { + "anomali.limo.pattern": "[url:value = 'http://extraclick.space/login.php']", + "anomali.limo.type": "indicator", + "anomali.limo.valid_from": "2020-01-22T03:03:42.819Z", "event.category": "threat", "event.dataset": "threatintel.anomali", "event.kind": "enrichment", @@ -1444,32 +1529,34 @@ "threatstream-confidence-94", "threatstream-severity-medium" ], - "threatintel.anomali.description": "TS ID: 55241332334; iType: mal_url; State: active; Org: Namecheap; Source: CyberCrime", - "threatintel.anomali.id": "indicator--10958d74-ec60-41af-a1ab-1613257e670f", - "threatintel.anomali.labels": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali Limo", + "threat.indicator.first_seen": "2020-01-22T03:03:42.819Z", + "threat.indicator.provider": "CyberCrime", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "extraclick.space", + "threat.indicator.url.extension": "php", + "threat.indicator.url.full": "http://extraclick.space/login.php", + "threat.indicator.url.original": "http://extraclick.space/login.php", + "threat.indicator.url.path": "/login.php", + "threat.indicator.url.scheme": "http" + }, + { + "anomali.limo.description": "TS ID: 55241332326; iType: mal_url; State: active; Org: RUCloud; Source: CyberCrime", + "anomali.limo.id": "indicator--19556daa-6293-400d-8706-d0baa6b16b7a", + "anomali.limo.labels": [ "malicious-activity", - "threatstream-confidence-94", + "threatstream-confidence-87", "threatstream-severity-medium" ], - "threatintel.anomali.modified": "2020-01-22T03:03:42.819Z", - "threatintel.anomali.name": "mal_url: http://extraclick.space/login.php", - "threatintel.anomali.object_marking_refs": [ + "anomali.limo.modified": "2020-01-22T03:03:52.044Z", + "anomali.limo.name": "mal_url: http://petrogarmani.pw/login.php", + "anomali.limo.object_marking_refs": [ "marking-definition--34098fce-860f-48ae-8e50-ebd3cc5e41da" ], - "threatintel.anomali.pattern": "[url:value = 'http://extraclick.space/login.php']", - "threatintel.anomali.type": "indicator", - "threatintel.anomali.valid_from": "2020-01-22T03:03:42.819Z", - "threatintel.indicator.first_seen": "2020-01-22T03:03:42.819Z", - "threatintel.indicator.provider": "CyberCrime", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "extraclick.space", - "threatintel.indicator.url.extension": "php", - "threatintel.indicator.url.full": "http://extraclick.space/login.php", - "threatintel.indicator.url.original": "http://extraclick.space/login.php", - "threatintel.indicator.url.path": "/login.php", - "threatintel.indicator.url.scheme": "http" - }, - { + "anomali.limo.pattern": "[url:value = 'http://petrogarmani.pw/login.php']", + "anomali.limo.type": "indicator", + "anomali.limo.valid_from": "2020-01-22T03:03:52.044Z", "event.category": "threat", "event.dataset": "threatintel.anomali", "event.kind": "enrichment", @@ -1486,32 +1573,34 @@ "threatstream-confidence-87", "threatstream-severity-medium" ], - "threatintel.anomali.description": "TS ID: 55241332326; iType: mal_url; State: active; Org: RUCloud; Source: CyberCrime", - "threatintel.anomali.id": "indicator--19556daa-6293-400d-8706-d0baa6b16b7a", - "threatintel.anomali.labels": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali Limo", + "threat.indicator.first_seen": "2020-01-22T03:03:52.044Z", + "threat.indicator.provider": "CyberCrime", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "petrogarmani.pw", + "threat.indicator.url.extension": "php", + "threat.indicator.url.full": "http://petrogarmani.pw/login.php", + "threat.indicator.url.original": "http://petrogarmani.pw/login.php", + "threat.indicator.url.path": "/login.php", + "threat.indicator.url.scheme": "http" + }, + { + "anomali.limo.description": "TS ID: 55241332311; iType: mal_url; State: active; Org: ServerMania; Source: CyberCrime", + "anomali.limo.id": "indicator--b09d9be9-6703-4a7d-a066-2baebb6418fc", + "anomali.limo.labels": [ "malicious-activity", - "threatstream-confidence-87", + "threatstream-confidence-68", "threatstream-severity-medium" ], - "threatintel.anomali.modified": "2020-01-22T03:03:52.044Z", - "threatintel.anomali.name": "mal_url: http://petrogarmani.pw/login.php", - "threatintel.anomali.object_marking_refs": [ + "anomali.limo.modified": "2020-01-22T03:04:01.650Z", + "anomali.limo.name": "mal_url: http://worldatdoor.in/mighty/32/panel/admin.php", + "anomali.limo.object_marking_refs": [ "marking-definition--34098fce-860f-48ae-8e50-ebd3cc5e41da" ], - "threatintel.anomali.pattern": "[url:value = 'http://petrogarmani.pw/login.php']", - "threatintel.anomali.type": "indicator", - "threatintel.anomali.valid_from": "2020-01-22T03:03:52.044Z", - "threatintel.indicator.first_seen": "2020-01-22T03:03:52.044Z", - "threatintel.indicator.provider": "CyberCrime", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "petrogarmani.pw", - "threatintel.indicator.url.extension": "php", - "threatintel.indicator.url.full": "http://petrogarmani.pw/login.php", - "threatintel.indicator.url.original": "http://petrogarmani.pw/login.php", - "threatintel.indicator.url.path": "/login.php", - "threatintel.indicator.url.scheme": "http" - }, - { + "anomali.limo.pattern": "[url:value = 'http://worldatdoor.in/mighty/32/panel/admin.php']", + "anomali.limo.type": "indicator", + "anomali.limo.valid_from": "2020-01-22T03:04:01.65Z", "event.category": "threat", "event.dataset": "threatintel.anomali", "event.kind": "enrichment", @@ -1528,32 +1617,34 @@ "threatstream-confidence-68", "threatstream-severity-medium" ], - "threatintel.anomali.description": "TS ID: 55241332311; iType: mal_url; State: active; Org: ServerMania; Source: CyberCrime", - "threatintel.anomali.id": "indicator--b09d9be9-6703-4a7d-a066-2baebb6418fc", - "threatintel.anomali.labels": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali Limo", + "threat.indicator.first_seen": "2020-01-22T03:04:01.650Z", + "threat.indicator.provider": "CyberCrime", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "worldatdoor.in", + "threat.indicator.url.extension": "php", + "threat.indicator.url.full": "http://worldatdoor.in/mighty/32/panel/admin.php", + "threat.indicator.url.original": "http://worldatdoor.in/mighty/32/panel/admin.php", + "threat.indicator.url.path": "/mighty/32/panel/admin.php", + "threat.indicator.url.scheme": "http" + }, + { + "anomali.limo.description": "TS ID: 55241332341; iType: mal_url; State: active; Org: Institute of Philosophy, Russian Academy of Scienc; Source: CyberCrime", + "anomali.limo.id": "indicator--43febf7d-4185-4a12-a868-e7be690b14aa", + "anomali.limo.labels": [ "malicious-activity", - "threatstream-confidence-68", + "threatstream-confidence-92", "threatstream-severity-medium" ], - "threatintel.anomali.modified": "2020-01-22T03:04:01.650Z", - "threatintel.anomali.name": "mal_url: http://worldatdoor.in/mighty/32/panel/admin.php", - "threatintel.anomali.object_marking_refs": [ + "anomali.limo.modified": "2020-01-22T03:04:32.717Z", + "anomali.limo.name": "mal_url: http://zanlma.com/login", + "anomali.limo.object_marking_refs": [ "marking-definition--34098fce-860f-48ae-8e50-ebd3cc5e41da" ], - "threatintel.anomali.pattern": "[url:value = 'http://worldatdoor.in/mighty/32/panel/admin.php']", - "threatintel.anomali.type": "indicator", - "threatintel.anomali.valid_from": "2020-01-22T03:04:01.65Z", - "threatintel.indicator.first_seen": "2020-01-22T03:04:01.650Z", - "threatintel.indicator.provider": "CyberCrime", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "worldatdoor.in", - "threatintel.indicator.url.extension": "php", - "threatintel.indicator.url.full": "http://worldatdoor.in/mighty/32/panel/admin.php", - "threatintel.indicator.url.original": "http://worldatdoor.in/mighty/32/panel/admin.php", - "threatintel.indicator.url.path": "/mighty/32/panel/admin.php", - "threatintel.indicator.url.scheme": "http" - }, - { + "anomali.limo.pattern": "[url:value = 'http://zanlma.com/login']", + "anomali.limo.type": "indicator", + "anomali.limo.valid_from": "2020-01-22T03:04:32.717Z", "event.category": "threat", "event.dataset": "threatintel.anomali", "event.kind": "enrichment", @@ -1570,31 +1661,33 @@ "threatstream-confidence-92", "threatstream-severity-medium" ], - "threatintel.anomali.description": "TS ID: 55241332341; iType: mal_url; State: active; Org: Institute of Philosophy, Russian Academy of Scienc; Source: CyberCrime", - "threatintel.anomali.id": "indicator--43febf7d-4185-4a12-a868-e7be690b14aa", - "threatintel.anomali.labels": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali Limo", + "threat.indicator.first_seen": "2020-01-22T03:04:32.717Z", + "threat.indicator.provider": "CyberCrime", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "zanlma.com", + "threat.indicator.url.full": "http://zanlma.com/login", + "threat.indicator.url.original": "http://zanlma.com/login", + "threat.indicator.url.path": "/login", + "threat.indicator.url.scheme": "http" + }, + { + "anomali.limo.description": "TS ID: 55241332303; iType: mal_url; State: active; Org: SPRINTHOST.RU - shared/premium hosting, VDS, dedic; Source: CyberCrime", + "anomali.limo.id": "indicator--a34728e6-f91d-47e6-a4d8-a69176299e45", + "anomali.limo.labels": [ "malicious-activity", - "threatstream-confidence-92", + "threatstream-confidence-84", "threatstream-severity-medium" ], - "threatintel.anomali.modified": "2020-01-22T03:04:32.717Z", - "threatintel.anomali.name": "mal_url: http://zanlma.com/login", - "threatintel.anomali.object_marking_refs": [ + "anomali.limo.modified": "2020-01-22T03:04:56.858Z", + "anomali.limo.name": "mal_url: http://f0369688.xsph.ru/login", + "anomali.limo.object_marking_refs": [ "marking-definition--34098fce-860f-48ae-8e50-ebd3cc5e41da" ], - "threatintel.anomali.pattern": "[url:value = 'http://zanlma.com/login']", - "threatintel.anomali.type": "indicator", - "threatintel.anomali.valid_from": "2020-01-22T03:04:32.717Z", - "threatintel.indicator.first_seen": "2020-01-22T03:04:32.717Z", - "threatintel.indicator.provider": "CyberCrime", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "zanlma.com", - "threatintel.indicator.url.full": "http://zanlma.com/login", - "threatintel.indicator.url.original": "http://zanlma.com/login", - "threatintel.indicator.url.path": "/login", - "threatintel.indicator.url.scheme": "http" - }, - { + "anomali.limo.pattern": "[url:value = 'http://f0369688.xsph.ru/login']", + "anomali.limo.type": "indicator", + "anomali.limo.valid_from": "2020-01-22T03:04:56.858Z", "event.category": "threat", "event.dataset": "threatintel.anomali", "event.kind": "enrichment", @@ -1611,31 +1704,33 @@ "threatstream-confidence-84", "threatstream-severity-medium" ], - "threatintel.anomali.description": "TS ID: 55241332303; iType: mal_url; State: active; Org: SPRINTHOST.RU - shared/premium hosting, VDS, dedic; Source: CyberCrime", - "threatintel.anomali.id": "indicator--a34728e6-f91d-47e6-a4d8-a69176299e45", - "threatintel.anomali.labels": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali Limo", + "threat.indicator.first_seen": "2020-01-22T03:04:56.858Z", + "threat.indicator.provider": "CyberCrime", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "f0369688.xsph.ru", + "threat.indicator.url.full": "http://f0369688.xsph.ru/login", + "threat.indicator.url.original": "http://f0369688.xsph.ru/login", + "threat.indicator.url.path": "/login", + "threat.indicator.url.scheme": "http" + }, + { + "anomali.limo.description": "TS ID: 55241332380; iType: mal_url; State: active; Org: Cloudflare; Source: CyberCrime", + "anomali.limo.id": "indicator--ac821704-5eb2-4f8f-a8b6-2a168dbd0e54", + "anomali.limo.labels": [ "malicious-activity", - "threatstream-confidence-84", + "threatstream-confidence-76", "threatstream-severity-medium" ], - "threatintel.anomali.modified": "2020-01-22T03:04:56.858Z", - "threatintel.anomali.name": "mal_url: http://f0369688.xsph.ru/login", - "threatintel.anomali.object_marking_refs": [ + "anomali.limo.modified": "2020-01-22T03:04:59.245Z", + "anomali.limo.name": "mal_url: http://chol.cc/Work2/PvqDq929BSx_A_D_M1n_a.php", + "anomali.limo.object_marking_refs": [ "marking-definition--34098fce-860f-48ae-8e50-ebd3cc5e41da" ], - "threatintel.anomali.pattern": "[url:value = 'http://f0369688.xsph.ru/login']", - "threatintel.anomali.type": "indicator", - "threatintel.anomali.valid_from": "2020-01-22T03:04:56.858Z", - "threatintel.indicator.first_seen": "2020-01-22T03:04:56.858Z", - "threatintel.indicator.provider": "CyberCrime", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "f0369688.xsph.ru", - "threatintel.indicator.url.full": "http://f0369688.xsph.ru/login", - "threatintel.indicator.url.original": "http://f0369688.xsph.ru/login", - "threatintel.indicator.url.path": "/login", - "threatintel.indicator.url.scheme": "http" - }, - { + "anomali.limo.pattern": "[url:value = 'http://chol.cc/Work2/PvqDq929BSx_A_D_M1n_a.php']", + "anomali.limo.type": "indicator", + "anomali.limo.valid_from": "2020-01-22T03:04:59.245Z", "event.category": "threat", "event.dataset": "threatintel.anomali", "event.kind": "enrichment", @@ -1652,32 +1747,34 @@ "threatstream-confidence-76", "threatstream-severity-medium" ], - "threatintel.anomali.description": "TS ID: 55241332380; iType: mal_url; State: active; Org: Cloudflare; Source: CyberCrime", - "threatintel.anomali.id": "indicator--ac821704-5eb2-4f8f-a8b6-2a168dbd0e54", - "threatintel.anomali.labels": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali Limo", + "threat.indicator.first_seen": "2020-01-22T03:04:59.245Z", + "threat.indicator.provider": "CyberCrime", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "chol.cc", + "threat.indicator.url.extension": "php", + "threat.indicator.url.full": "http://chol.cc/Work2/PvqDq929BSx_A_D_M1n_a.php", + "threat.indicator.url.original": "http://chol.cc/Work2/PvqDq929BSx_A_D_M1n_a.php", + "threat.indicator.url.path": "/Work2/PvqDq929BSx_A_D_M1n_a.php", + "threat.indicator.url.scheme": "http" + }, + { + "anomali.limo.description": "TS ID: 55245868747; iType: mal_ip; State: active; Org: CyrusOne LLC; Source: CyberCrime", + "anomali.limo.id": "indicator--0d3e1bd8-0f16-4c22-b8a1-663ec255ad79", + "anomali.limo.labels": [ "malicious-activity", - "threatstream-confidence-76", + "threatstream-confidence-57", "threatstream-severity-medium" ], - "threatintel.anomali.modified": "2020-01-22T03:04:59.245Z", - "threatintel.anomali.name": "mal_url: http://chol.cc/Work2/PvqDq929BSx_A_D_M1n_a.php", - "threatintel.anomali.object_marking_refs": [ + "anomali.limo.modified": "2020-01-23T03:00:22.287Z", + "anomali.limo.name": "mal_ip: 192.185.214.199", + "anomali.limo.object_marking_refs": [ "marking-definition--34098fce-860f-48ae-8e50-ebd3cc5e41da" ], - "threatintel.anomali.pattern": "[url:value = 'http://chol.cc/Work2/PvqDq929BSx_A_D_M1n_a.php']", - "threatintel.anomali.type": "indicator", - "threatintel.anomali.valid_from": "2020-01-22T03:04:59.245Z", - "threatintel.indicator.first_seen": "2020-01-22T03:04:59.245Z", - "threatintel.indicator.provider": "CyberCrime", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "chol.cc", - "threatintel.indicator.url.extension": "php", - "threatintel.indicator.url.full": "http://chol.cc/Work2/PvqDq929BSx_A_D_M1n_a.php", - "threatintel.indicator.url.original": "http://chol.cc/Work2/PvqDq929BSx_A_D_M1n_a.php", - "threatintel.indicator.url.path": "/Work2/PvqDq929BSx_A_D_M1n_a.php", - "threatintel.indicator.url.scheme": "http" - }, - { + "anomali.limo.pattern": "[ipv4-addr:value = '192.185.214.199']", + "anomali.limo.type": "indicator", + "anomali.limo.valid_from": "2020-01-23T03:00:22.287Z", "event.category": "threat", "event.dataset": "threatintel.anomali", "event.kind": "enrichment", @@ -1694,27 +1791,29 @@ "threatstream-confidence-57", "threatstream-severity-medium" ], - "threatintel.anomali.description": "TS ID: 55245868747; iType: mal_ip; State: active; Org: CyrusOne LLC; Source: CyberCrime", - "threatintel.anomali.id": "indicator--0d3e1bd8-0f16-4c22-b8a1-663ec255ad79", - "threatintel.anomali.labels": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali Limo", + "threat.indicator.first_seen": "2020-01-23T03:00:22.287Z", + "threat.indicator.ip": "192.185.214.199", + "threat.indicator.provider": "CyberCrime", + "threat.indicator.type": "ipv4-addr" + }, + { + "anomali.limo.description": "TS ID: 55245868770; iType: mal_url; State: active; Org: Mills College; Source: CyberCrime", + "anomali.limo.id": "indicator--2cdd130a-c884-402d-b63c-e03f9448f5d9", + "anomali.limo.labels": [ "malicious-activity", - "threatstream-confidence-57", + "threatstream-confidence-24", "threatstream-severity-medium" ], - "threatintel.anomali.modified": "2020-01-23T03:00:22.287Z", - "threatintel.anomali.name": "mal_ip: 192.185.214.199", - "threatintel.anomali.object_marking_refs": [ + "anomali.limo.modified": "2020-01-23T03:01:11.329Z", + "anomali.limo.name": "mal_url: http://softtouchcollars.com/Loki/Panel/five/PvqDq929BSx_A_D_M1n_a.php", + "anomali.limo.object_marking_refs": [ "marking-definition--34098fce-860f-48ae-8e50-ebd3cc5e41da" ], - "threatintel.anomali.pattern": "[ipv4-addr:value = '192.185.214.199']", - "threatintel.anomali.type": "indicator", - "threatintel.anomali.valid_from": "2020-01-23T03:00:22.287Z", - "threatintel.indicator.first_seen": "2020-01-23T03:00:22.287Z", - "threatintel.indicator.ip": "192.185.214.199", - "threatintel.indicator.provider": "CyberCrime", - "threatintel.indicator.type": "ipv4-addr" - }, - { + "anomali.limo.pattern": "[url:value = 'http://softtouchcollars.com/Loki/Panel/five/PvqDq929BSx_A_D_M1n_a.php']", + "anomali.limo.type": "indicator", + "anomali.limo.valid_from": "2020-01-23T03:01:11.329Z", "event.category": "threat", "event.dataset": "threatintel.anomali", "event.kind": "enrichment", @@ -1731,32 +1830,34 @@ "threatstream-confidence-24", "threatstream-severity-medium" ], - "threatintel.anomali.description": "TS ID: 55245868770; iType: mal_url; State: active; Org: Mills College; Source: CyberCrime", - "threatintel.anomali.id": "indicator--2cdd130a-c884-402d-b63c-e03f9448f5d9", - "threatintel.anomali.labels": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali Limo", + "threat.indicator.first_seen": "2020-01-23T03:01:11.329Z", + "threat.indicator.provider": "CyberCrime", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "softtouchcollars.com", + "threat.indicator.url.extension": "php", + "threat.indicator.url.full": "http://softtouchcollars.com/Loki/Panel/five/PvqDq929BSx_A_D_M1n_a.php", + "threat.indicator.url.original": "http://softtouchcollars.com/Loki/Panel/five/PvqDq929BSx_A_D_M1n_a.php", + "threat.indicator.url.path": "/Loki/Panel/five/PvqDq929BSx_A_D_M1n_a.php", + "threat.indicator.url.scheme": "http" + }, + { + "anomali.limo.description": "TS ID: 55245868769; iType: mal_url; State: active; Org: CyrusOne LLC; Source: CyberCrime", + "anomali.limo.id": "indicator--88e98e13-4bfd-4188-941a-f696a7b86b71", + "anomali.limo.labels": [ "malicious-activity", - "threatstream-confidence-24", + "threatstream-confidence-61", "threatstream-severity-medium" ], - "threatintel.anomali.modified": "2020-01-23T03:01:11.329Z", - "threatintel.anomali.name": "mal_url: http://softtouchcollars.com/Loki/Panel/five/PvqDq929BSx_A_D_M1n_a.php", - "threatintel.anomali.object_marking_refs": [ + "anomali.limo.modified": "2020-01-23T03:01:36.682Z", + "anomali.limo.name": "mal_url: http://imobiliariatirol.com/gh/panelnew/admin.php", + "anomali.limo.object_marking_refs": [ "marking-definition--34098fce-860f-48ae-8e50-ebd3cc5e41da" ], - "threatintel.anomali.pattern": "[url:value = 'http://softtouchcollars.com/Loki/Panel/five/PvqDq929BSx_A_D_M1n_a.php']", - "threatintel.anomali.type": "indicator", - "threatintel.anomali.valid_from": "2020-01-23T03:01:11.329Z", - "threatintel.indicator.first_seen": "2020-01-23T03:01:11.329Z", - "threatintel.indicator.provider": "CyberCrime", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "softtouchcollars.com", - "threatintel.indicator.url.extension": "php", - "threatintel.indicator.url.full": "http://softtouchcollars.com/Loki/Panel/five/PvqDq929BSx_A_D_M1n_a.php", - "threatintel.indicator.url.original": "http://softtouchcollars.com/Loki/Panel/five/PvqDq929BSx_A_D_M1n_a.php", - "threatintel.indicator.url.path": "/Loki/Panel/five/PvqDq929BSx_A_D_M1n_a.php", - "threatintel.indicator.url.scheme": "http" - }, - { + "anomali.limo.pattern": "[url:value = 'http://imobiliariatirol.com/gh/panelnew/admin.php']", + "anomali.limo.type": "indicator", + "anomali.limo.valid_from": "2020-01-23T03:01:36.682Z", "event.category": "threat", "event.dataset": "threatintel.anomali", "event.kind": "enrichment", @@ -1773,32 +1874,34 @@ "threatstream-confidence-61", "threatstream-severity-medium" ], - "threatintel.anomali.description": "TS ID: 55245868769; iType: mal_url; State: active; Org: CyrusOne LLC; Source: CyberCrime", - "threatintel.anomali.id": "indicator--88e98e13-4bfd-4188-941a-f696a7b86b71", - "threatintel.anomali.labels": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali Limo", + "threat.indicator.first_seen": "2020-01-23T03:01:36.682Z", + "threat.indicator.provider": "CyberCrime", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "imobiliariatirol.com", + "threat.indicator.url.extension": "php", + "threat.indicator.url.full": "http://imobiliariatirol.com/gh/panelnew/admin.php", + "threat.indicator.url.original": "http://imobiliariatirol.com/gh/panelnew/admin.php", + "threat.indicator.url.path": "/gh/panelnew/admin.php", + "threat.indicator.url.scheme": "http" + }, + { + "anomali.limo.description": "TS ID: 55245868772; iType: mal_url; State: active; Org: ServerMania; Source: CyberCrime", + "anomali.limo.id": "indicator--27323b7d-85d3-4e89-8249-b7696925a772", + "anomali.limo.labels": [ "malicious-activity", - "threatstream-confidence-61", + "threatstream-confidence-93", "threatstream-severity-medium" ], - "threatintel.anomali.modified": "2020-01-23T03:01:36.682Z", - "threatintel.anomali.name": "mal_url: http://imobiliariatirol.com/gh/panelnew/admin.php", - "threatintel.anomali.object_marking_refs": [ + "anomali.limo.modified": "2020-01-23T03:02:15.854Z", + "anomali.limo.name": "mal_url: http://deliveryexpressworld.xyz/five/PvqDq929BSx_A_D_M1n_a.php", + "anomali.limo.object_marking_refs": [ "marking-definition--34098fce-860f-48ae-8e50-ebd3cc5e41da" ], - "threatintel.anomali.pattern": "[url:value = 'http://imobiliariatirol.com/gh/panelnew/admin.php']", - "threatintel.anomali.type": "indicator", - "threatintel.anomali.valid_from": "2020-01-23T03:01:36.682Z", - "threatintel.indicator.first_seen": "2020-01-23T03:01:36.682Z", - "threatintel.indicator.provider": "CyberCrime", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "imobiliariatirol.com", - "threatintel.indicator.url.extension": "php", - "threatintel.indicator.url.full": "http://imobiliariatirol.com/gh/panelnew/admin.php", - "threatintel.indicator.url.original": "http://imobiliariatirol.com/gh/panelnew/admin.php", - "threatintel.indicator.url.path": "/gh/panelnew/admin.php", - "threatintel.indicator.url.scheme": "http" - }, - { + "anomali.limo.pattern": "[url:value = 'http://deliveryexpressworld.xyz/five/PvqDq929BSx_A_D_M1n_a.php']", + "anomali.limo.type": "indicator", + "anomali.limo.valid_from": "2020-01-23T03:02:15.854Z", "event.category": "threat", "event.dataset": "threatintel.anomali", "event.kind": "enrichment", @@ -1815,32 +1918,34 @@ "threatstream-confidence-93", "threatstream-severity-medium" ], - "threatintel.anomali.description": "TS ID: 55245868772; iType: mal_url; State: active; Org: ServerMania; Source: CyberCrime", - "threatintel.anomali.id": "indicator--27323b7d-85d3-4e89-8249-b7696925a772", - "threatintel.anomali.labels": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali Limo", + "threat.indicator.first_seen": "2020-01-23T03:02:15.854Z", + "threat.indicator.provider": "CyberCrime", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "deliveryexpressworld.xyz", + "threat.indicator.url.extension": "php", + "threat.indicator.url.full": "http://deliveryexpressworld.xyz/five/PvqDq929BSx_A_D_M1n_a.php", + "threat.indicator.url.original": "http://deliveryexpressworld.xyz/five/PvqDq929BSx_A_D_M1n_a.php", + "threat.indicator.url.path": "/five/PvqDq929BSx_A_D_M1n_a.php", + "threat.indicator.url.scheme": "http" + }, + { + "anomali.limo.description": "TS ID: 55245868766; iType: mal_url; State: active; Org: SPRINTHOST.RU - shared/premium hosting, VDS, dedic; Source: CyberCrime", + "anomali.limo.id": "indicator--b0639721-de55-48c6-b237-3859d61aecfb", + "anomali.limo.labels": [ "malicious-activity", - "threatstream-confidence-93", + "threatstream-confidence-62", "threatstream-severity-medium" ], - "threatintel.anomali.modified": "2020-01-23T03:02:15.854Z", - "threatintel.anomali.name": "mal_url: http://deliveryexpressworld.xyz/five/PvqDq929BSx_A_D_M1n_a.php", - "threatintel.anomali.object_marking_refs": [ + "anomali.limo.modified": "2020-01-23T03:02:47.364Z", + "anomali.limo.name": "mal_url: http://f0392261.xsph.ru/login", + "anomali.limo.object_marking_refs": [ "marking-definition--34098fce-860f-48ae-8e50-ebd3cc5e41da" ], - "threatintel.anomali.pattern": "[url:value = 'http://deliveryexpressworld.xyz/five/PvqDq929BSx_A_D_M1n_a.php']", - "threatintel.anomali.type": "indicator", - "threatintel.anomali.valid_from": "2020-01-23T03:02:15.854Z", - "threatintel.indicator.first_seen": "2020-01-23T03:02:15.854Z", - "threatintel.indicator.provider": "CyberCrime", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "deliveryexpressworld.xyz", - "threatintel.indicator.url.extension": "php", - "threatintel.indicator.url.full": "http://deliveryexpressworld.xyz/five/PvqDq929BSx_A_D_M1n_a.php", - "threatintel.indicator.url.original": "http://deliveryexpressworld.xyz/five/PvqDq929BSx_A_D_M1n_a.php", - "threatintel.indicator.url.path": "/five/PvqDq929BSx_A_D_M1n_a.php", - "threatintel.indicator.url.scheme": "http" - }, - { + "anomali.limo.pattern": "[url:value = 'http://f0392261.xsph.ru/login']", + "anomali.limo.type": "indicator", + "anomali.limo.valid_from": "2020-01-23T03:02:47.364Z", "event.category": "threat", "event.dataset": "threatintel.anomali", "event.kind": "enrichment", @@ -1857,31 +1962,33 @@ "threatstream-confidence-62", "threatstream-severity-medium" ], - "threatintel.anomali.description": "TS ID: 55245868766; iType: mal_url; State: active; Org: SPRINTHOST.RU - shared/premium hosting, VDS, dedic; Source: CyberCrime", - "threatintel.anomali.id": "indicator--b0639721-de55-48c6-b237-3859d61aecfb", - "threatintel.anomali.labels": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali Limo", + "threat.indicator.first_seen": "2020-01-23T03:02:47.364Z", + "threat.indicator.provider": "CyberCrime", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "f0392261.xsph.ru", + "threat.indicator.url.full": "http://f0392261.xsph.ru/login", + "threat.indicator.url.original": "http://f0392261.xsph.ru/login", + "threat.indicator.url.path": "/login", + "threat.indicator.url.scheme": "http" + }, + { + "anomali.limo.description": "TS ID: 55245868749; iType: mal_url; State: active; Org: ColoCrossing; Source: CyberCrime", + "anomali.limo.id": "indicator--677e714d-c237-42a1-b6b7-9145acd13eee", + "anomali.limo.labels": [ "malicious-activity", - "threatstream-confidence-62", + "threatstream-confidence-80", "threatstream-severity-medium" ], - "threatintel.anomali.modified": "2020-01-23T03:02:47.364Z", - "threatintel.anomali.name": "mal_url: http://f0392261.xsph.ru/login", - "threatintel.anomali.object_marking_refs": [ + "anomali.limo.modified": "2020-01-23T03:03:05.048Z", + "anomali.limo.name": "mal_url: http://104.168.99.168/panel/panel/admin.php", + "anomali.limo.object_marking_refs": [ "marking-definition--34098fce-860f-48ae-8e50-ebd3cc5e41da" ], - "threatintel.anomali.pattern": "[url:value = 'http://f0392261.xsph.ru/login']", - "threatintel.anomali.type": "indicator", - "threatintel.anomali.valid_from": "2020-01-23T03:02:47.364Z", - "threatintel.indicator.first_seen": "2020-01-23T03:02:47.364Z", - "threatintel.indicator.provider": "CyberCrime", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "f0392261.xsph.ru", - "threatintel.indicator.url.full": "http://f0392261.xsph.ru/login", - "threatintel.indicator.url.original": "http://f0392261.xsph.ru/login", - "threatintel.indicator.url.path": "/login", - "threatintel.indicator.url.scheme": "http" - }, - { + "anomali.limo.pattern": "[url:value = 'http://104.168.99.168/panel/panel/admin.php']", + "anomali.limo.type": "indicator", + "anomali.limo.valid_from": "2020-01-23T03:03:05.048Z", "event.category": "threat", "event.dataset": "threatintel.anomali", "event.kind": "enrichment", @@ -1898,32 +2005,34 @@ "threatstream-confidence-80", "threatstream-severity-medium" ], - "threatintel.anomali.description": "TS ID: 55245868749; iType: mal_url; State: active; Org: ColoCrossing; Source: CyberCrime", - "threatintel.anomali.id": "indicator--677e714d-c237-42a1-b6b7-9145acd13eee", - "threatintel.anomali.labels": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali Limo", + "threat.indicator.first_seen": "2020-01-23T03:03:05.048Z", + "threat.indicator.provider": "CyberCrime", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "104.168.99.168", + "threat.indicator.url.extension": "php", + "threat.indicator.url.full": "http://104.168.99.168/panel/panel/admin.php", + "threat.indicator.url.original": "http://104.168.99.168/panel/panel/admin.php", + "threat.indicator.url.path": "/panel/panel/admin.php", + "threat.indicator.url.scheme": "http" + }, + { + "anomali.limo.description": "TS ID: 55245868767; iType: mal_url; State: active; Org: SPRINTHOST.RU - shared/premium hosting, VDS, dedic; Source: CyberCrime", + "anomali.limo.id": "indicator--5baa1dbd-d74e-408c-92b5-0a9f97e4b87a", + "anomali.limo.labels": [ "malicious-activity", - "threatstream-confidence-80", + "threatstream-confidence-69", "threatstream-severity-medium" ], - "threatintel.anomali.modified": "2020-01-23T03:03:05.048Z", - "threatintel.anomali.name": "mal_url: http://104.168.99.168/panel/panel/admin.php", - "threatintel.anomali.object_marking_refs": [ + "anomali.limo.modified": "2020-01-23T03:03:15.734Z", + "anomali.limo.name": "mal_url: http://f0387404.xsph.ru/panel/admin.php", + "anomali.limo.object_marking_refs": [ "marking-definition--34098fce-860f-48ae-8e50-ebd3cc5e41da" ], - "threatintel.anomali.pattern": "[url:value = 'http://104.168.99.168/panel/panel/admin.php']", - "threatintel.anomali.type": "indicator", - "threatintel.anomali.valid_from": "2020-01-23T03:03:05.048Z", - "threatintel.indicator.first_seen": "2020-01-23T03:03:05.048Z", - "threatintel.indicator.provider": "CyberCrime", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "104.168.99.168", - "threatintel.indicator.url.extension": "php", - "threatintel.indicator.url.full": "http://104.168.99.168/panel/panel/admin.php", - "threatintel.indicator.url.original": "http://104.168.99.168/panel/panel/admin.php", - "threatintel.indicator.url.path": "/panel/panel/admin.php", - "threatintel.indicator.url.scheme": "http" - }, - { + "anomali.limo.pattern": "[url:value = 'http://f0387404.xsph.ru/panel/admin.php']", + "anomali.limo.type": "indicator", + "anomali.limo.valid_from": "2020-01-23T03:03:15.734Z", "event.category": "threat", "event.dataset": "threatintel.anomali", "event.kind": "enrichment", @@ -1940,32 +2049,34 @@ "threatstream-confidence-69", "threatstream-severity-medium" ], - "threatintel.anomali.description": "TS ID: 55245868767; iType: mal_url; State: active; Org: SPRINTHOST.RU - shared/premium hosting, VDS, dedic; Source: CyberCrime", - "threatintel.anomali.id": "indicator--5baa1dbd-d74e-408c-92b5-0a9f97e4b87a", - "threatintel.anomali.labels": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali Limo", + "threat.indicator.first_seen": "2020-01-23T03:03:15.734Z", + "threat.indicator.provider": "CyberCrime", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "f0387404.xsph.ru", + "threat.indicator.url.extension": "php", + "threat.indicator.url.full": "http://f0387404.xsph.ru/panel/admin.php", + "threat.indicator.url.original": "http://f0387404.xsph.ru/panel/admin.php", + "threat.indicator.url.path": "/panel/admin.php", + "threat.indicator.url.scheme": "http" + }, + { + "anomali.limo.description": "TS ID: 55245868768; iType: mal_url; State: active; Org: SPRINTHOST.RU - shared/premium hosting, VDS, dedic; Source: CyberCrime", + "anomali.limo.id": "indicator--4563241e-5d2f-41a7-adb9-3925a5eeb1b1", + "anomali.limo.labels": [ "malicious-activity", - "threatstream-confidence-69", + "threatstream-confidence-72", "threatstream-severity-medium" ], - "threatintel.anomali.modified": "2020-01-23T03:03:15.734Z", - "threatintel.anomali.name": "mal_url: http://f0387404.xsph.ru/panel/admin.php", - "threatintel.anomali.object_marking_refs": [ + "anomali.limo.modified": "2020-01-23T03:03:42.599Z", + "anomali.limo.name": "mal_url: http://a0386457.xsph.ru/panel/admin.php", + "anomali.limo.object_marking_refs": [ "marking-definition--34098fce-860f-48ae-8e50-ebd3cc5e41da" ], - "threatintel.anomali.pattern": "[url:value = 'http://f0387404.xsph.ru/panel/admin.php']", - "threatintel.anomali.type": "indicator", - "threatintel.anomali.valid_from": "2020-01-23T03:03:15.734Z", - "threatintel.indicator.first_seen": "2020-01-23T03:03:15.734Z", - "threatintel.indicator.provider": "CyberCrime", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "f0387404.xsph.ru", - "threatintel.indicator.url.extension": "php", - "threatintel.indicator.url.full": "http://f0387404.xsph.ru/panel/admin.php", - "threatintel.indicator.url.original": "http://f0387404.xsph.ru/panel/admin.php", - "threatintel.indicator.url.path": "/panel/admin.php", - "threatintel.indicator.url.scheme": "http" - }, - { + "anomali.limo.pattern": "[url:value = 'http://a0386457.xsph.ru/panel/admin.php']", + "anomali.limo.type": "indicator", + "anomali.limo.valid_from": "2020-01-23T03:03:42.599Z", "event.category": "threat", "event.dataset": "threatintel.anomali", "event.kind": "enrichment", @@ -1982,32 +2093,34 @@ "threatstream-confidence-72", "threatstream-severity-medium" ], - "threatintel.anomali.description": "TS ID: 55245868768; iType: mal_url; State: active; Org: SPRINTHOST.RU - shared/premium hosting, VDS, dedic; Source: CyberCrime", - "threatintel.anomali.id": "indicator--4563241e-5d2f-41a7-adb9-3925a5eeb1b1", - "threatintel.anomali.labels": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali Limo", + "threat.indicator.first_seen": "2020-01-23T03:03:42.599Z", + "threat.indicator.provider": "CyberCrime", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "a0386457.xsph.ru", + "threat.indicator.url.extension": "php", + "threat.indicator.url.full": "http://a0386457.xsph.ru/panel/admin.php", + "threat.indicator.url.original": "http://a0386457.xsph.ru/panel/admin.php", + "threat.indicator.url.path": "/panel/admin.php", + "threat.indicator.url.scheme": "http" + }, + { + "anomali.limo.description": "TS ID: 55250078037; iType: mal_url; State: active; Source: CyberCrime", + "anomali.limo.id": "indicator--70cb5d42-91d3-4efe-8c47-995fc0ac4141", + "anomali.limo.labels": [ "malicious-activity", - "threatstream-confidence-72", + "threatstream-confidence-74", "threatstream-severity-medium" ], - "threatintel.anomali.modified": "2020-01-23T03:03:42.599Z", - "threatintel.anomali.name": "mal_url: http://a0386457.xsph.ru/panel/admin.php", - "threatintel.anomali.object_marking_refs": [ + "anomali.limo.modified": "2020-01-24T02:57:04.821Z", + "anomali.limo.name": "mal_url: http://defenseisrael.com/dis/index.php", + "anomali.limo.object_marking_refs": [ "marking-definition--34098fce-860f-48ae-8e50-ebd3cc5e41da" ], - "threatintel.anomali.pattern": "[url:value = 'http://a0386457.xsph.ru/panel/admin.php']", - "threatintel.anomali.type": "indicator", - "threatintel.anomali.valid_from": "2020-01-23T03:03:42.599Z", - "threatintel.indicator.first_seen": "2020-01-23T03:03:42.599Z", - "threatintel.indicator.provider": "CyberCrime", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "a0386457.xsph.ru", - "threatintel.indicator.url.extension": "php", - "threatintel.indicator.url.full": "http://a0386457.xsph.ru/panel/admin.php", - "threatintel.indicator.url.original": "http://a0386457.xsph.ru/panel/admin.php", - "threatintel.indicator.url.path": "/panel/admin.php", - "threatintel.indicator.url.scheme": "http" - }, - { + "anomali.limo.pattern": "[url:value = 'http://defenseisrael.com/dis/index.php']", + "anomali.limo.type": "indicator", + "anomali.limo.valid_from": "2020-01-24T02:57:04.821Z", "event.category": "threat", "event.dataset": "threatintel.anomali", "event.kind": "enrichment", @@ -2024,32 +2137,34 @@ "threatstream-confidence-74", "threatstream-severity-medium" ], - "threatintel.anomali.description": "TS ID: 55250078037; iType: mal_url; State: active; Source: CyberCrime", - "threatintel.anomali.id": "indicator--70cb5d42-91d3-4efe-8c47-995fc0ac4141", - "threatintel.anomali.labels": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali Limo", + "threat.indicator.first_seen": "2020-01-24T02:57:04.821Z", + "threat.indicator.provider": "CyberCrime", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "defenseisrael.com", + "threat.indicator.url.extension": "php", + "threat.indicator.url.full": "http://defenseisrael.com/dis/index.php", + "threat.indicator.url.original": "http://defenseisrael.com/dis/index.php", + "threat.indicator.url.path": "/dis/index.php", + "threat.indicator.url.scheme": "http" + }, + { + "anomali.limo.description": "TS ID: 55250078030; iType: mal_ip; State: active; Org: Best-Hoster Group Co. Ltd.; Source: CyberCrime", + "anomali.limo.id": "indicator--3aa712bb-b5d4-4632-bf50-48a4aeeaeb6d", + "anomali.limo.labels": [ "malicious-activity", - "threatstream-confidence-74", + "threatstream-confidence-83", "threatstream-severity-medium" ], - "threatintel.anomali.modified": "2020-01-24T02:57:04.821Z", - "threatintel.anomali.name": "mal_url: http://defenseisrael.com/dis/index.php", - "threatintel.anomali.object_marking_refs": [ + "anomali.limo.modified": "2020-01-24T02:57:04.857Z", + "anomali.limo.name": "mal_ip: 91.215.170.249", + "anomali.limo.object_marking_refs": [ "marking-definition--34098fce-860f-48ae-8e50-ebd3cc5e41da" ], - "threatintel.anomali.pattern": "[url:value = 'http://defenseisrael.com/dis/index.php']", - "threatintel.anomali.type": "indicator", - "threatintel.anomali.valid_from": "2020-01-24T02:57:04.821Z", - "threatintel.indicator.first_seen": "2020-01-24T02:57:04.821Z", - "threatintel.indicator.provider": "CyberCrime", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "defenseisrael.com", - "threatintel.indicator.url.extension": "php", - "threatintel.indicator.url.full": "http://defenseisrael.com/dis/index.php", - "threatintel.indicator.url.original": "http://defenseisrael.com/dis/index.php", - "threatintel.indicator.url.path": "/dis/index.php", - "threatintel.indicator.url.scheme": "http" - }, - { + "anomali.limo.pattern": "[ipv4-addr:value = '91.215.170.249']", + "anomali.limo.type": "indicator", + "anomali.limo.valid_from": "2020-01-24T02:57:04.857Z", "event.category": "threat", "event.dataset": "threatintel.anomali", "event.kind": "enrichment", @@ -2066,27 +2181,29 @@ "threatstream-confidence-83", "threatstream-severity-medium" ], - "threatintel.anomali.description": "TS ID: 55250078030; iType: mal_ip; State: active; Org: Best-Hoster Group Co. Ltd.; Source: CyberCrime", - "threatintel.anomali.id": "indicator--3aa712bb-b5d4-4632-bf50-48a4aeeaeb6d", - "threatintel.anomali.labels": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali Limo", + "threat.indicator.first_seen": "2020-01-24T02:57:04.857Z", + "threat.indicator.ip": "91.215.170.249", + "threat.indicator.provider": "CyberCrime", + "threat.indicator.type": "ipv4-addr" + }, + { + "anomali.limo.description": "TS ID: 55250078019; iType: mal_url; State: active; Org: MoreneHost; Source: CyberCrime", + "anomali.limo.id": "indicator--64227c7d-86ea-4146-a868-3decb5aa5f1d", + "anomali.limo.labels": [ "malicious-activity", - "threatstream-confidence-83", + "threatstream-confidence-79", "threatstream-severity-medium" ], - "threatintel.anomali.modified": "2020-01-24T02:57:04.857Z", - "threatintel.anomali.name": "mal_ip: 91.215.170.249", - "threatintel.anomali.object_marking_refs": [ + "anomali.limo.modified": "2020-01-24T02:57:04.883Z", + "anomali.limo.name": "mal_url: http://lbfb3f03.justinstalledpanel.com/login", + "anomali.limo.object_marking_refs": [ "marking-definition--34098fce-860f-48ae-8e50-ebd3cc5e41da" ], - "threatintel.anomali.pattern": "[ipv4-addr:value = '91.215.170.249']", - "threatintel.anomali.type": "indicator", - "threatintel.anomali.valid_from": "2020-01-24T02:57:04.857Z", - "threatintel.indicator.first_seen": "2020-01-24T02:57:04.857Z", - "threatintel.indicator.ip": "91.215.170.249", - "threatintel.indicator.provider": "CyberCrime", - "threatintel.indicator.type": "ipv4-addr" - }, - { + "anomali.limo.pattern": "[url:value = 'http://lbfb3f03.justinstalledpanel.com/login']", + "anomali.limo.type": "indicator", + "anomali.limo.valid_from": "2020-01-24T02:57:04.883Z", "event.category": "threat", "event.dataset": "threatintel.anomali", "event.kind": "enrichment", @@ -2103,31 +2220,33 @@ "threatstream-confidence-79", "threatstream-severity-medium" ], - "threatintel.anomali.description": "TS ID: 55250078019; iType: mal_url; State: active; Org: MoreneHost; Source: CyberCrime", - "threatintel.anomali.id": "indicator--64227c7d-86ea-4146-a868-3decb5aa5f1d", - "threatintel.anomali.labels": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali Limo", + "threat.indicator.first_seen": "2020-01-24T02:57:04.883Z", + "threat.indicator.provider": "CyberCrime", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "lbfb3f03.justinstalledpanel.com", + "threat.indicator.url.full": "http://lbfb3f03.justinstalledpanel.com/login", + "threat.indicator.url.original": "http://lbfb3f03.justinstalledpanel.com/login", + "threat.indicator.url.path": "/login", + "threat.indicator.url.scheme": "http" + }, + { + "anomali.limo.description": "TS ID: 55250078035; iType: mal_url; State: active; Source: CyberCrime", + "anomali.limo.id": "indicator--37fcf9a7-1a90-4d81-be0a-e824a4fa938e", + "anomali.limo.labels": [ "malicious-activity", - "threatstream-confidence-79", + "threatstream-confidence-93", "threatstream-severity-medium" ], - "threatintel.anomali.modified": "2020-01-24T02:57:04.883Z", - "threatintel.anomali.name": "mal_url: http://lbfb3f03.justinstalledpanel.com/login", - "threatintel.anomali.object_marking_refs": [ + "anomali.limo.modified": "2020-01-24T02:57:12.997Z", + "anomali.limo.name": "mal_url: http://byedtronchgroup.yt/jik/Panel/five/PvqDq929BSx_A_D_M1n_a.php", + "anomali.limo.object_marking_refs": [ "marking-definition--34098fce-860f-48ae-8e50-ebd3cc5e41da" ], - "threatintel.anomali.pattern": "[url:value = 'http://lbfb3f03.justinstalledpanel.com/login']", - "threatintel.anomali.type": "indicator", - "threatintel.anomali.valid_from": "2020-01-24T02:57:04.883Z", - "threatintel.indicator.first_seen": "2020-01-24T02:57:04.883Z", - "threatintel.indicator.provider": "CyberCrime", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "lbfb3f03.justinstalledpanel.com", - "threatintel.indicator.url.full": "http://lbfb3f03.justinstalledpanel.com/login", - "threatintel.indicator.url.original": "http://lbfb3f03.justinstalledpanel.com/login", - "threatintel.indicator.url.path": "/login", - "threatintel.indicator.url.scheme": "http" - }, - { + "anomali.limo.pattern": "[url:value = 'http://byedtronchgroup.yt/jik/Panel/five/PvqDq929BSx_A_D_M1n_a.php']", + "anomali.limo.type": "indicator", + "anomali.limo.valid_from": "2020-01-24T02:57:12.997Z", "event.category": "threat", "event.dataset": "threatintel.anomali", "event.kind": "enrichment", @@ -2144,32 +2263,34 @@ "threatstream-confidence-93", "threatstream-severity-medium" ], - "threatintel.anomali.description": "TS ID: 55250078035; iType: mal_url; State: active; Source: CyberCrime", - "threatintel.anomali.id": "indicator--37fcf9a7-1a90-4d81-be0a-e824a4fa938e", - "threatintel.anomali.labels": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali Limo", + "threat.indicator.first_seen": "2020-01-24T02:57:12.997Z", + "threat.indicator.provider": "CyberCrime", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "byedtronchgroup.yt", + "threat.indicator.url.extension": "php", + "threat.indicator.url.full": "http://byedtronchgroup.yt/jik/Panel/five/PvqDq929BSx_A_D_M1n_a.php", + "threat.indicator.url.original": "http://byedtronchgroup.yt/jik/Panel/five/PvqDq929BSx_A_D_M1n_a.php", + "threat.indicator.url.path": "/jik/Panel/five/PvqDq929BSx_A_D_M1n_a.php", + "threat.indicator.url.scheme": "http" + }, + { + "anomali.limo.description": "TS ID: 55250078008; iType: mal_url; State: active; Org: Namecheap; Source: CyberCrime", + "anomali.limo.id": "indicator--5a38786f-107e-4060-a7c9-ea8a5ded6aac", + "anomali.limo.labels": [ "malicious-activity", - "threatstream-confidence-93", + "threatstream-confidence-87", "threatstream-severity-medium" ], - "threatintel.anomali.modified": "2020-01-24T02:57:12.997Z", - "threatintel.anomali.name": "mal_url: http://byedtronchgroup.yt/jik/Panel/five/PvqDq929BSx_A_D_M1n_a.php", - "threatintel.anomali.object_marking_refs": [ + "anomali.limo.modified": "2020-01-24T02:57:13.025Z", + "anomali.limo.name": "mal_url: http://199.192.28.11/panel/admin.php", + "anomali.limo.object_marking_refs": [ "marking-definition--34098fce-860f-48ae-8e50-ebd3cc5e41da" ], - "threatintel.anomali.pattern": "[url:value = 'http://byedtronchgroup.yt/jik/Panel/five/PvqDq929BSx_A_D_M1n_a.php']", - "threatintel.anomali.type": "indicator", - "threatintel.anomali.valid_from": "2020-01-24T02:57:12.997Z", - "threatintel.indicator.first_seen": "2020-01-24T02:57:12.997Z", - "threatintel.indicator.provider": "CyberCrime", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "byedtronchgroup.yt", - "threatintel.indicator.url.extension": "php", - "threatintel.indicator.url.full": "http://byedtronchgroup.yt/jik/Panel/five/PvqDq929BSx_A_D_M1n_a.php", - "threatintel.indicator.url.original": "http://byedtronchgroup.yt/jik/Panel/five/PvqDq929BSx_A_D_M1n_a.php", - "threatintel.indicator.url.path": "/jik/Panel/five/PvqDq929BSx_A_D_M1n_a.php", - "threatintel.indicator.url.scheme": "http" - }, - { + "anomali.limo.pattern": "[url:value = 'http://199.192.28.11/panel/admin.php']", + "anomali.limo.type": "indicator", + "anomali.limo.valid_from": "2020-01-24T02:57:13.025Z", "event.category": "threat", "event.dataset": "threatintel.anomali", "event.kind": "enrichment", @@ -2186,32 +2307,34 @@ "threatstream-confidence-87", "threatstream-severity-medium" ], - "threatintel.anomali.description": "TS ID: 55250078008; iType: mal_url; State: active; Org: Namecheap; Source: CyberCrime", - "threatintel.anomali.id": "indicator--5a38786f-107e-4060-a7c9-ea8a5ded6aac", - "threatintel.anomali.labels": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali Limo", + "threat.indicator.first_seen": "2020-01-24T02:57:13.025Z", + "threat.indicator.provider": "CyberCrime", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "199.192.28.11", + "threat.indicator.url.extension": "php", + "threat.indicator.url.full": "http://199.192.28.11/panel/admin.php", + "threat.indicator.url.original": "http://199.192.28.11/panel/admin.php", + "threat.indicator.url.path": "/panel/admin.php", + "threat.indicator.url.scheme": "http" + }, + { + "anomali.limo.description": "TS ID: 55250078038; iType: mal_url; State: active; Source: CyberCrime", + "anomali.limo.id": "indicator--3eb79b31-1d6d-438c-a848-24a3407f6e32", + "anomali.limo.labels": [ "malicious-activity", - "threatstream-confidence-87", + "threatstream-confidence-82", "threatstream-severity-medium" ], - "threatintel.anomali.modified": "2020-01-24T02:57:13.025Z", - "threatintel.anomali.name": "mal_url: http://199.192.28.11/panel/admin.php", - "threatintel.anomali.object_marking_refs": [ + "anomali.limo.modified": "2020-01-24T02:57:32.901Z", + "anomali.limo.name": "mal_url: http://217.8.117.51/aW8bVds1/login.php", + "anomali.limo.object_marking_refs": [ "marking-definition--34098fce-860f-48ae-8e50-ebd3cc5e41da" ], - "threatintel.anomali.pattern": "[url:value = 'http://199.192.28.11/panel/admin.php']", - "threatintel.anomali.type": "indicator", - "threatintel.anomali.valid_from": "2020-01-24T02:57:13.025Z", - "threatintel.indicator.first_seen": "2020-01-24T02:57:13.025Z", - "threatintel.indicator.provider": "CyberCrime", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "199.192.28.11", - "threatintel.indicator.url.extension": "php", - "threatintel.indicator.url.full": "http://199.192.28.11/panel/admin.php", - "threatintel.indicator.url.original": "http://199.192.28.11/panel/admin.php", - "threatintel.indicator.url.path": "/panel/admin.php", - "threatintel.indicator.url.scheme": "http" - }, - { + "anomali.limo.pattern": "[url:value = 'http://217.8.117.51/aW8bVds1/login.php']", + "anomali.limo.type": "indicator", + "anomali.limo.valid_from": "2020-01-24T02:57:32.901Z", "event.category": "threat", "event.dataset": "threatintel.anomali", "event.kind": "enrichment", @@ -2228,32 +2351,34 @@ "threatstream-confidence-82", "threatstream-severity-medium" ], - "threatintel.anomali.description": "TS ID: 55250078038; iType: mal_url; State: active; Source: CyberCrime", - "threatintel.anomali.id": "indicator--3eb79b31-1d6d-438c-a848-24a3407f6e32", - "threatintel.anomali.labels": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali Limo", + "threat.indicator.first_seen": "2020-01-24T02:57:32.901Z", + "threat.indicator.provider": "CyberCrime", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "217.8.117.51", + "threat.indicator.url.extension": "php", + "threat.indicator.url.full": "http://217.8.117.51/aW8bVds1/login.php", + "threat.indicator.url.original": "http://217.8.117.51/aW8bVds1/login.php", + "threat.indicator.url.path": "/aW8bVds1/login.php", + "threat.indicator.url.scheme": "http" + }, + { + "anomali.limo.description": "TS ID: 55250078026; iType: mal_url; State: active; Org: IT DeLuxe Ltd.; Source: CyberCrime", + "anomali.limo.id": "indicator--a050832c-db6e-49a0-8470-7a3cd8f17178", + "anomali.limo.labels": [ "malicious-activity", - "threatstream-confidence-82", + "threatstream-confidence-93", "threatstream-severity-medium" ], - "threatintel.anomali.modified": "2020-01-24T02:57:32.901Z", - "threatintel.anomali.name": "mal_url: http://217.8.117.51/aW8bVds1/login.php", - "threatintel.anomali.object_marking_refs": [ + "anomali.limo.modified": "2020-01-24T02:57:32.929Z", + "anomali.limo.name": "mal_url: http://lansome.site/login", + "anomali.limo.object_marking_refs": [ "marking-definition--34098fce-860f-48ae-8e50-ebd3cc5e41da" ], - "threatintel.anomali.pattern": "[url:value = 'http://217.8.117.51/aW8bVds1/login.php']", - "threatintel.anomali.type": "indicator", - "threatintel.anomali.valid_from": "2020-01-24T02:57:32.901Z", - "threatintel.indicator.first_seen": "2020-01-24T02:57:32.901Z", - "threatintel.indicator.provider": "CyberCrime", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "217.8.117.51", - "threatintel.indicator.url.extension": "php", - "threatintel.indicator.url.full": "http://217.8.117.51/aW8bVds1/login.php", - "threatintel.indicator.url.original": "http://217.8.117.51/aW8bVds1/login.php", - "threatintel.indicator.url.path": "/aW8bVds1/login.php", - "threatintel.indicator.url.scheme": "http" - }, - { + "anomali.limo.pattern": "[url:value = 'http://lansome.site/login']", + "anomali.limo.type": "indicator", + "anomali.limo.valid_from": "2020-01-24T02:57:32.929Z", "event.category": "threat", "event.dataset": "threatintel.anomali", "event.kind": "enrichment", @@ -2270,31 +2395,33 @@ "threatstream-confidence-93", "threatstream-severity-medium" ], - "threatintel.anomali.description": "TS ID: 55250078026; iType: mal_url; State: active; Org: IT DeLuxe Ltd.; Source: CyberCrime", - "threatintel.anomali.id": "indicator--a050832c-db6e-49a0-8470-7a3cd8f17178", - "threatintel.anomali.labels": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali Limo", + "threat.indicator.first_seen": "2020-01-24T02:57:32.929Z", + "threat.indicator.provider": "CyberCrime", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "lansome.site", + "threat.indicator.url.full": "http://lansome.site/login", + "threat.indicator.url.original": "http://lansome.site/login", + "threat.indicator.url.path": "/login", + "threat.indicator.url.scheme": "http" + }, + { + "anomali.limo.description": "TS ID: 55250078034; iType: mal_url; State: active; Org: Branch of BachKim Network solutions jsc; Source: CyberCrime", + "anomali.limo.id": "indicator--e88008f4-76fc-428d-831a-4b389e48b712", + "anomali.limo.labels": [ "malicious-activity", - "threatstream-confidence-93", + "threatstream-confidence-83", "threatstream-severity-medium" ], - "threatintel.anomali.modified": "2020-01-24T02:57:32.929Z", - "threatintel.anomali.name": "mal_url: http://lansome.site/login", - "threatintel.anomali.object_marking_refs": [ + "anomali.limo.modified": "2020-01-24T02:57:49.028Z", + "anomali.limo.name": "mal_url: http://iplusvietnam.com.vn/jo/playbook/onelove/PvqDq929BSx_A_D_M1n_a.php", + "anomali.limo.object_marking_refs": [ "marking-definition--34098fce-860f-48ae-8e50-ebd3cc5e41da" ], - "threatintel.anomali.pattern": "[url:value = 'http://lansome.site/login']", - "threatintel.anomali.type": "indicator", - "threatintel.anomali.valid_from": "2020-01-24T02:57:32.929Z", - "threatintel.indicator.first_seen": "2020-01-24T02:57:32.929Z", - "threatintel.indicator.provider": "CyberCrime", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "lansome.site", - "threatintel.indicator.url.full": "http://lansome.site/login", - "threatintel.indicator.url.original": "http://lansome.site/login", - "threatintel.indicator.url.path": "/login", - "threatintel.indicator.url.scheme": "http" - }, - { + "anomali.limo.pattern": "[url:value = 'http://iplusvietnam.com.vn/jo/playbook/onelove/PvqDq929BSx_A_D_M1n_a.php']", + "anomali.limo.type": "indicator", + "anomali.limo.valid_from": "2020-01-24T02:57:49.028Z", "event.category": "threat", "event.dataset": "threatintel.anomali", "event.kind": "enrichment", @@ -2311,32 +2438,34 @@ "threatstream-confidence-83", "threatstream-severity-medium" ], - "threatintel.anomali.description": "TS ID: 55250078034; iType: mal_url; State: active; Org: Branch of BachKim Network solutions jsc; Source: CyberCrime", - "threatintel.anomali.id": "indicator--e88008f4-76fc-428d-831a-4b389e48b712", - "threatintel.anomali.labels": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali Limo", + "threat.indicator.first_seen": "2020-01-24T02:57:49.028Z", + "threat.indicator.provider": "CyberCrime", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "iplusvietnam.com.vn", + "threat.indicator.url.extension": "php", + "threat.indicator.url.full": "http://iplusvietnam.com.vn/jo/playbook/onelove/PvqDq929BSx_A_D_M1n_a.php", + "threat.indicator.url.original": "http://iplusvietnam.com.vn/jo/playbook/onelove/PvqDq929BSx_A_D_M1n_a.php", + "threat.indicator.url.path": "/jo/playbook/onelove/PvqDq929BSx_A_D_M1n_a.php", + "threat.indicator.url.scheme": "http" + }, + { + "anomali.limo.description": "TS ID: 55250078032; iType: mal_url; State: active; Org: ColoCrossing; Source: CyberCrime", + "anomali.limo.id": "indicator--dafe91cf-787c-471c-9afe-f7bb20a1b93f", + "anomali.limo.labels": [ "malicious-activity", - "threatstream-confidence-83", + "threatstream-confidence-94", "threatstream-severity-medium" ], - "threatintel.anomali.modified": "2020-01-24T02:57:49.028Z", - "threatintel.anomali.name": "mal_url: http://iplusvietnam.com.vn/jo/playbook/onelove/PvqDq929BSx_A_D_M1n_a.php", - "threatintel.anomali.object_marking_refs": [ + "anomali.limo.modified": "2020-01-24T02:58:03.345Z", + "anomali.limo.name": "mal_url: http://leakaryadeen.com/parl/id345/PvqDq929BSx_A_D_M1n_a.php", + "anomali.limo.object_marking_refs": [ "marking-definition--34098fce-860f-48ae-8e50-ebd3cc5e41da" ], - "threatintel.anomali.pattern": "[url:value = 'http://iplusvietnam.com.vn/jo/playbook/onelove/PvqDq929BSx_A_D_M1n_a.php']", - "threatintel.anomali.type": "indicator", - "threatintel.anomali.valid_from": "2020-01-24T02:57:49.028Z", - "threatintel.indicator.first_seen": "2020-01-24T02:57:49.028Z", - "threatintel.indicator.provider": "CyberCrime", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "iplusvietnam.com.vn", - "threatintel.indicator.url.extension": "php", - "threatintel.indicator.url.full": "http://iplusvietnam.com.vn/jo/playbook/onelove/PvqDq929BSx_A_D_M1n_a.php", - "threatintel.indicator.url.original": "http://iplusvietnam.com.vn/jo/playbook/onelove/PvqDq929BSx_A_D_M1n_a.php", - "threatintel.indicator.url.path": "/jo/playbook/onelove/PvqDq929BSx_A_D_M1n_a.php", - "threatintel.indicator.url.scheme": "http" - }, - { + "anomali.limo.pattern": "[url:value = 'http://leakaryadeen.com/parl/id345/PvqDq929BSx_A_D_M1n_a.php']", + "anomali.limo.type": "indicator", + "anomali.limo.valid_from": "2020-01-24T02:58:03.345Z", "event.category": "threat", "event.dataset": "threatintel.anomali", "event.kind": "enrichment", @@ -2353,32 +2482,34 @@ "threatstream-confidence-94", "threatstream-severity-medium" ], - "threatintel.anomali.description": "TS ID: 55250078032; iType: mal_url; State: active; Org: ColoCrossing; Source: CyberCrime", - "threatintel.anomali.id": "indicator--dafe91cf-787c-471c-9afe-f7bb20a1b93f", - "threatintel.anomali.labels": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali Limo", + "threat.indicator.first_seen": "2020-01-24T02:58:03.345Z", + "threat.indicator.provider": "CyberCrime", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "leakaryadeen.com", + "threat.indicator.url.extension": "php", + "threat.indicator.url.full": "http://leakaryadeen.com/parl/id345/PvqDq929BSx_A_D_M1n_a.php", + "threat.indicator.url.original": "http://leakaryadeen.com/parl/id345/PvqDq929BSx_A_D_M1n_a.php", + "threat.indicator.url.path": "/parl/id345/PvqDq929BSx_A_D_M1n_a.php", + "threat.indicator.url.scheme": "http" + }, + { + "anomali.limo.description": "TS ID: 55250078031; iType: mal_url; State: active; Org: IT House, Ltd; Source: CyberCrime", + "anomali.limo.id": "indicator--232bdc34-44cb-4f41-af52-f6f1cd28818e", + "anomali.limo.labels": [ "malicious-activity", - "threatstream-confidence-94", + "threatstream-confidence-81", "threatstream-severity-medium" ], - "threatintel.anomali.modified": "2020-01-24T02:58:03.345Z", - "threatintel.anomali.name": "mal_url: http://leakaryadeen.com/parl/id345/PvqDq929BSx_A_D_M1n_a.php", - "threatintel.anomali.object_marking_refs": [ + "anomali.limo.modified": "2020-01-24T02:58:16.318Z", + "anomali.limo.name": "mal_url: http://oaa-my.com/clap/five/PvqDq929BSx_A_D_M1n_a.php", + "anomali.limo.object_marking_refs": [ "marking-definition--34098fce-860f-48ae-8e50-ebd3cc5e41da" ], - "threatintel.anomali.pattern": "[url:value = 'http://leakaryadeen.com/parl/id345/PvqDq929BSx_A_D_M1n_a.php']", - "threatintel.anomali.type": "indicator", - "threatintel.anomali.valid_from": "2020-01-24T02:58:03.345Z", - "threatintel.indicator.first_seen": "2020-01-24T02:58:03.345Z", - "threatintel.indicator.provider": "CyberCrime", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "leakaryadeen.com", - "threatintel.indicator.url.extension": "php", - "threatintel.indicator.url.full": "http://leakaryadeen.com/parl/id345/PvqDq929BSx_A_D_M1n_a.php", - "threatintel.indicator.url.original": "http://leakaryadeen.com/parl/id345/PvqDq929BSx_A_D_M1n_a.php", - "threatintel.indicator.url.path": "/parl/id345/PvqDq929BSx_A_D_M1n_a.php", - "threatintel.indicator.url.scheme": "http" - }, - { + "anomali.limo.pattern": "[url:value = 'http://oaa-my.com/clap/five/PvqDq929BSx_A_D_M1n_a.php']", + "anomali.limo.type": "indicator", + "anomali.limo.valid_from": "2020-01-24T02:58:16.318Z", "event.category": "threat", "event.dataset": "threatintel.anomali", "event.kind": "enrichment", @@ -2395,32 +2526,34 @@ "threatstream-confidence-81", "threatstream-severity-medium" ], - "threatintel.anomali.description": "TS ID: 55250078031; iType: mal_url; State: active; Org: IT House, Ltd; Source: CyberCrime", - "threatintel.anomali.id": "indicator--232bdc34-44cb-4f41-af52-f6f1cd28818e", - "threatintel.anomali.labels": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali Limo", + "threat.indicator.first_seen": "2020-01-24T02:58:16.318Z", + "threat.indicator.provider": "CyberCrime", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "oaa-my.com", + "threat.indicator.url.extension": "php", + "threat.indicator.url.full": "http://oaa-my.com/clap/five/PvqDq929BSx_A_D_M1n_a.php", + "threat.indicator.url.original": "http://oaa-my.com/clap/five/PvqDq929BSx_A_D_M1n_a.php", + "threat.indicator.url.path": "/clap/five/PvqDq929BSx_A_D_M1n_a.php", + "threat.indicator.url.scheme": "http" + }, + { + "anomali.limo.description": "TS ID: 55250078027; iType: mal_url; State: active; Org: Branch of BachKim Network solutions jsc; Source: CyberCrime", + "anomali.limo.id": "indicator--4adabe80-3be4-401a-948a-f9724c872374", + "anomali.limo.labels": [ "malicious-activity", - "threatstream-confidence-81", + "threatstream-confidence-66", "threatstream-severity-medium" ], - "threatintel.anomali.modified": "2020-01-24T02:58:16.318Z", - "threatintel.anomali.name": "mal_url: http://oaa-my.com/clap/five/PvqDq929BSx_A_D_M1n_a.php", - "threatintel.anomali.object_marking_refs": [ + "anomali.limo.modified": "2020-01-24T02:58:16.358Z", + "anomali.limo.name": "mal_url: http://thaubenuocngam.com/go/playbook/onelove/PvqDq929BSx_A_D_M1n_a.php", + "anomali.limo.object_marking_refs": [ "marking-definition--34098fce-860f-48ae-8e50-ebd3cc5e41da" ], - "threatintel.anomali.pattern": "[url:value = 'http://oaa-my.com/clap/five/PvqDq929BSx_A_D_M1n_a.php']", - "threatintel.anomali.type": "indicator", - "threatintel.anomali.valid_from": "2020-01-24T02:58:16.318Z", - "threatintel.indicator.first_seen": "2020-01-24T02:58:16.318Z", - "threatintel.indicator.provider": "CyberCrime", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "oaa-my.com", - "threatintel.indicator.url.extension": "php", - "threatintel.indicator.url.full": "http://oaa-my.com/clap/five/PvqDq929BSx_A_D_M1n_a.php", - "threatintel.indicator.url.original": "http://oaa-my.com/clap/five/PvqDq929BSx_A_D_M1n_a.php", - "threatintel.indicator.url.path": "/clap/five/PvqDq929BSx_A_D_M1n_a.php", - "threatintel.indicator.url.scheme": "http" - }, - { + "anomali.limo.pattern": "[url:value = 'http://thaubenuocngam.com/go/playbook/onelove/PvqDq929BSx_A_D_M1n_a.php']", + "anomali.limo.type": "indicator", + "anomali.limo.valid_from": "2020-01-24T02:58:16.358Z", "event.category": "threat", "event.dataset": "threatintel.anomali", "event.kind": "enrichment", @@ -2437,32 +2570,34 @@ "threatstream-confidence-66", "threatstream-severity-medium" ], - "threatintel.anomali.description": "TS ID: 55250078027; iType: mal_url; State: active; Org: Branch of BachKim Network solutions jsc; Source: CyberCrime", - "threatintel.anomali.id": "indicator--4adabe80-3be4-401a-948a-f9724c872374", - "threatintel.anomali.labels": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali Limo", + "threat.indicator.first_seen": "2020-01-24T02:58:16.358Z", + "threat.indicator.provider": "CyberCrime", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "thaubenuocngam.com", + "threat.indicator.url.extension": "php", + "threat.indicator.url.full": "http://thaubenuocngam.com/go/playbook/onelove/PvqDq929BSx_A_D_M1n_a.php", + "threat.indicator.url.original": "http://thaubenuocngam.com/go/playbook/onelove/PvqDq929BSx_A_D_M1n_a.php", + "threat.indicator.url.path": "/go/playbook/onelove/PvqDq929BSx_A_D_M1n_a.php", + "threat.indicator.url.scheme": "http" + }, + { + "anomali.limo.description": "TS ID: 55250078013; iType: mal_url; State: active; Source: CyberCrime", + "anomali.limo.id": "indicator--1d7051c0-a42b-4801-bd7f-f0abf2cc125c", + "anomali.limo.labels": [ "malicious-activity", - "threatstream-confidence-66", + "threatstream-confidence-82", "threatstream-severity-medium" ], - "threatintel.anomali.modified": "2020-01-24T02:58:16.358Z", - "threatintel.anomali.name": "mal_url: http://thaubenuocngam.com/go/playbook/onelove/PvqDq929BSx_A_D_M1n_a.php", - "threatintel.anomali.object_marking_refs": [ + "anomali.limo.modified": "2020-01-24T02:58:32.126Z", + "anomali.limo.name": "mal_url: http://suspiciousactivity.xyz/login", + "anomali.limo.object_marking_refs": [ "marking-definition--34098fce-860f-48ae-8e50-ebd3cc5e41da" ], - "threatintel.anomali.pattern": "[url:value = 'http://thaubenuocngam.com/go/playbook/onelove/PvqDq929BSx_A_D_M1n_a.php']", - "threatintel.anomali.type": "indicator", - "threatintel.anomali.valid_from": "2020-01-24T02:58:16.358Z", - "threatintel.indicator.first_seen": "2020-01-24T02:58:16.358Z", - "threatintel.indicator.provider": "CyberCrime", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "thaubenuocngam.com", - "threatintel.indicator.url.extension": "php", - "threatintel.indicator.url.full": "http://thaubenuocngam.com/go/playbook/onelove/PvqDq929BSx_A_D_M1n_a.php", - "threatintel.indicator.url.original": "http://thaubenuocngam.com/go/playbook/onelove/PvqDq929BSx_A_D_M1n_a.php", - "threatintel.indicator.url.path": "/go/playbook/onelove/PvqDq929BSx_A_D_M1n_a.php", - "threatintel.indicator.url.scheme": "http" - }, - { + "anomali.limo.pattern": "[url:value = 'http://suspiciousactivity.xyz/login']", + "anomali.limo.type": "indicator", + "anomali.limo.valid_from": "2020-01-24T02:58:32.126Z", "event.category": "threat", "event.dataset": "threatintel.anomali", "event.kind": "enrichment", @@ -2479,31 +2614,33 @@ "threatstream-confidence-82", "threatstream-severity-medium" ], - "threatintel.anomali.description": "TS ID: 55250078013; iType: mal_url; State: active; Source: CyberCrime", - "threatintel.anomali.id": "indicator--1d7051c0-a42b-4801-bd7f-f0abf2cc125c", - "threatintel.anomali.labels": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali Limo", + "threat.indicator.first_seen": "2020-01-24T02:58:32.126Z", + "threat.indicator.provider": "CyberCrime", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "suspiciousactivity.xyz", + "threat.indicator.url.full": "http://suspiciousactivity.xyz/login", + "threat.indicator.url.original": "http://suspiciousactivity.xyz/login", + "threat.indicator.url.path": "/login", + "threat.indicator.url.scheme": "http" + }, + { + "anomali.limo.description": "TS ID: 55250078017; iType: mal_url; State: active; Source: CyberCrime", + "anomali.limo.id": "indicator--fb06856c-8aad-4fae-92fc-b73aae4f6dc7", + "anomali.limo.labels": [ "malicious-activity", "threatstream-confidence-82", "threatstream-severity-medium" ], - "threatintel.anomali.modified": "2020-01-24T02:58:32.126Z", - "threatintel.anomali.name": "mal_url: http://suspiciousactivity.xyz/login", - "threatintel.anomali.object_marking_refs": [ + "anomali.limo.modified": "2020-01-24T02:58:37.603Z", + "anomali.limo.name": "mal_url: http://217.8.117.8/login", + "anomali.limo.object_marking_refs": [ "marking-definition--34098fce-860f-48ae-8e50-ebd3cc5e41da" ], - "threatintel.anomali.pattern": "[url:value = 'http://suspiciousactivity.xyz/login']", - "threatintel.anomali.type": "indicator", - "threatintel.anomali.valid_from": "2020-01-24T02:58:32.126Z", - "threatintel.indicator.first_seen": "2020-01-24T02:58:32.126Z", - "threatintel.indicator.provider": "CyberCrime", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "suspiciousactivity.xyz", - "threatintel.indicator.url.full": "http://suspiciousactivity.xyz/login", - "threatintel.indicator.url.original": "http://suspiciousactivity.xyz/login", - "threatintel.indicator.url.path": "/login", - "threatintel.indicator.url.scheme": "http" - }, - { + "anomali.limo.pattern": "[url:value = 'http://217.8.117.8/login']", + "anomali.limo.type": "indicator", + "anomali.limo.valid_from": "2020-01-24T02:58:37.603Z", "event.category": "threat", "event.dataset": "threatintel.anomali", "event.kind": "enrichment", @@ -2520,31 +2657,33 @@ "threatstream-confidence-82", "threatstream-severity-medium" ], - "threatintel.anomali.description": "TS ID: 55250078017; iType: mal_url; State: active; Source: CyberCrime", - "threatintel.anomali.id": "indicator--fb06856c-8aad-4fae-92fc-b73aae4f6dc7", - "threatintel.anomali.labels": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali Limo", + "threat.indicator.first_seen": "2020-01-24T02:58:37.603Z", + "threat.indicator.provider": "CyberCrime", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "217.8.117.8", + "threat.indicator.url.full": "http://217.8.117.8/login", + "threat.indicator.url.original": "http://217.8.117.8/login", + "threat.indicator.url.path": "/login", + "threat.indicator.url.scheme": "http" + }, + { + "anomali.limo.description": "TS ID: 55250078012; iType: mal_url; State: active; Org: SPRINTHOST.RU - shared/premium hosting, VDS, dedic; Source: CyberCrime", + "anomali.limo.id": "indicator--33e674f5-a64a-48f4-9d8c-248348356135", + "anomali.limo.labels": [ "malicious-activity", - "threatstream-confidence-82", + "threatstream-confidence-71", "threatstream-severity-medium" ], - "threatintel.anomali.modified": "2020-01-24T02:58:37.603Z", - "threatintel.anomali.name": "mal_url: http://217.8.117.8/login", - "threatintel.anomali.object_marking_refs": [ + "anomali.limo.modified": "2020-01-24T02:58:37.643Z", + "anomali.limo.name": "mal_url: http://f0387550.xsph.ru/login", + "anomali.limo.object_marking_refs": [ "marking-definition--34098fce-860f-48ae-8e50-ebd3cc5e41da" ], - "threatintel.anomali.pattern": "[url:value = 'http://217.8.117.8/login']", - "threatintel.anomali.type": "indicator", - "threatintel.anomali.valid_from": "2020-01-24T02:58:37.603Z", - "threatintel.indicator.first_seen": "2020-01-24T02:58:37.603Z", - "threatintel.indicator.provider": "CyberCrime", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "217.8.117.8", - "threatintel.indicator.url.full": "http://217.8.117.8/login", - "threatintel.indicator.url.original": "http://217.8.117.8/login", - "threatintel.indicator.url.path": "/login", - "threatintel.indicator.url.scheme": "http" - }, - { + "anomali.limo.pattern": "[url:value = 'http://f0387550.xsph.ru/login']", + "anomali.limo.type": "indicator", + "anomali.limo.valid_from": "2020-01-24T02:58:37.643Z", "event.category": "threat", "event.dataset": "threatintel.anomali", "event.kind": "enrichment", @@ -2561,31 +2700,33 @@ "threatstream-confidence-71", "threatstream-severity-medium" ], - "threatintel.anomali.description": "TS ID: 55250078012; iType: mal_url; State: active; Org: SPRINTHOST.RU - shared/premium hosting, VDS, dedic; Source: CyberCrime", - "threatintel.anomali.id": "indicator--33e674f5-a64a-48f4-9d8c-248348356135", - "threatintel.anomali.labels": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali Limo", + "threat.indicator.first_seen": "2020-01-24T02:58:37.643Z", + "threat.indicator.provider": "CyberCrime", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "f0387550.xsph.ru", + "threat.indicator.url.full": "http://f0387550.xsph.ru/login", + "threat.indicator.url.original": "http://f0387550.xsph.ru/login", + "threat.indicator.url.path": "/login", + "threat.indicator.url.scheme": "http" + }, + { + "anomali.limo.description": "TS ID: 55250078018; iType: mal_url; State: active; Org: MoreneHost; Source: CyberCrime", + "anomali.limo.id": "indicator--6311f539-1d5d-423f-a238-d0c1dc167432", + "anomali.limo.labels": [ "malicious-activity", - "threatstream-confidence-71", + "threatstream-confidence-84", "threatstream-severity-medium" ], - "threatintel.anomali.modified": "2020-01-24T02:58:37.643Z", - "threatintel.anomali.name": "mal_url: http://f0387550.xsph.ru/login", - "threatintel.anomali.object_marking_refs": [ + "anomali.limo.modified": "2020-01-24T02:58:39.465Z", + "anomali.limo.name": "mal_url: http://lf4e4abf.justinstalledpanel.com/login", + "anomali.limo.object_marking_refs": [ "marking-definition--34098fce-860f-48ae-8e50-ebd3cc5e41da" ], - "threatintel.anomali.pattern": "[url:value = 'http://f0387550.xsph.ru/login']", - "threatintel.anomali.type": "indicator", - "threatintel.anomali.valid_from": "2020-01-24T02:58:37.643Z", - "threatintel.indicator.first_seen": "2020-01-24T02:58:37.643Z", - "threatintel.indicator.provider": "CyberCrime", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "f0387550.xsph.ru", - "threatintel.indicator.url.full": "http://f0387550.xsph.ru/login", - "threatintel.indicator.url.original": "http://f0387550.xsph.ru/login", - "threatintel.indicator.url.path": "/login", - "threatintel.indicator.url.scheme": "http" - }, - { + "anomali.limo.pattern": "[url:value = 'http://lf4e4abf.justinstalledpanel.com/login']", + "anomali.limo.type": "indicator", + "anomali.limo.valid_from": "2020-01-24T02:58:39.465Z", "event.category": "threat", "event.dataset": "threatintel.anomali", "event.kind": "enrichment", @@ -2602,31 +2743,33 @@ "threatstream-confidence-84", "threatstream-severity-medium" ], - "threatintel.anomali.description": "TS ID: 55250078018; iType: mal_url; State: active; Org: MoreneHost; Source: CyberCrime", - "threatintel.anomali.id": "indicator--6311f539-1d5d-423f-a238-d0c1dc167432", - "threatintel.anomali.labels": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali Limo", + "threat.indicator.first_seen": "2020-01-24T02:58:39.465Z", + "threat.indicator.provider": "CyberCrime", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "lf4e4abf.justinstalledpanel.com", + "threat.indicator.url.full": "http://lf4e4abf.justinstalledpanel.com/login", + "threat.indicator.url.original": "http://lf4e4abf.justinstalledpanel.com/login", + "threat.indicator.url.path": "/login", + "threat.indicator.url.scheme": "http" + }, + { + "anomali.limo.description": "TS ID: 55250078033; iType: mal_ip; State: active; Org: ColoCrossing; Source: CyberCrime", + "anomali.limo.id": "indicator--1c91f219-cfa6-44c7-a5ee-1c760489b43c", + "anomali.limo.labels": [ "malicious-activity", - "threatstream-confidence-84", + "threatstream-confidence-81", "threatstream-severity-medium" ], - "threatintel.anomali.modified": "2020-01-24T02:58:39.465Z", - "threatintel.anomali.name": "mal_url: http://lf4e4abf.justinstalledpanel.com/login", - "threatintel.anomali.object_marking_refs": [ + "anomali.limo.modified": "2020-01-24T02:59:02.031Z", + "anomali.limo.name": "mal_ip: 206.217.131.245", + "anomali.limo.object_marking_refs": [ "marking-definition--34098fce-860f-48ae-8e50-ebd3cc5e41da" ], - "threatintel.anomali.pattern": "[url:value = 'http://lf4e4abf.justinstalledpanel.com/login']", - "threatintel.anomali.type": "indicator", - "threatintel.anomali.valid_from": "2020-01-24T02:58:39.465Z", - "threatintel.indicator.first_seen": "2020-01-24T02:58:39.465Z", - "threatintel.indicator.provider": "CyberCrime", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "lf4e4abf.justinstalledpanel.com", - "threatintel.indicator.url.full": "http://lf4e4abf.justinstalledpanel.com/login", - "threatintel.indicator.url.original": "http://lf4e4abf.justinstalledpanel.com/login", - "threatintel.indicator.url.path": "/login", - "threatintel.indicator.url.scheme": "http" - }, - { + "anomali.limo.pattern": "[ipv4-addr:value = '206.217.131.245']", + "anomali.limo.type": "indicator", + "anomali.limo.valid_from": "2020-01-24T02:59:02.031Z", "event.category": "threat", "event.dataset": "threatintel.anomali", "event.kind": "enrichment", @@ -2643,27 +2786,29 @@ "threatstream-confidence-81", "threatstream-severity-medium" ], - "threatintel.anomali.description": "TS ID: 55250078033; iType: mal_ip; State: active; Org: ColoCrossing; Source: CyberCrime", - "threatintel.anomali.id": "indicator--1c91f219-cfa6-44c7-a5ee-1c760489b43c", - "threatintel.anomali.labels": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali Limo", + "threat.indicator.first_seen": "2020-01-24T02:59:02.031Z", + "threat.indicator.ip": "206.217.131.245", + "threat.indicator.provider": "CyberCrime", + "threat.indicator.type": "ipv4-addr" + }, + { + "anomali.limo.description": "TS ID: 55250078010; iType: mal_url; State: active; Org: QuadraNet; Source: CyberCrime", + "anomali.limo.id": "indicator--c58983e2-18fd-47b8-aab4-6c8a2e2dcb35", + "anomali.limo.labels": [ "malicious-activity", - "threatstream-confidence-81", + "threatstream-confidence-52", "threatstream-severity-medium" ], - "threatintel.anomali.modified": "2020-01-24T02:59:02.031Z", - "threatintel.anomali.name": "mal_ip: 206.217.131.245", - "threatintel.anomali.object_marking_refs": [ + "anomali.limo.modified": "2020-01-24T02:59:15.878Z", + "anomali.limo.name": "mal_url: http://67.215.224.101/a1/panel/admin.php", + "anomali.limo.object_marking_refs": [ "marking-definition--34098fce-860f-48ae-8e50-ebd3cc5e41da" ], - "threatintel.anomali.pattern": "[ipv4-addr:value = '206.217.131.245']", - "threatintel.anomali.type": "indicator", - "threatintel.anomali.valid_from": "2020-01-24T02:59:02.031Z", - "threatintel.indicator.first_seen": "2020-01-24T02:59:02.031Z", - "threatintel.indicator.ip": "206.217.131.245", - "threatintel.indicator.provider": "CyberCrime", - "threatintel.indicator.type": "ipv4-addr" - }, - { + "anomali.limo.pattern": "[url:value = 'http://67.215.224.101/a1/panel/admin.php']", + "anomali.limo.type": "indicator", + "anomali.limo.valid_from": "2020-01-24T02:59:15.878Z", "event.category": "threat", "event.dataset": "threatintel.anomali", "event.kind": "enrichment", @@ -2680,32 +2825,34 @@ "threatstream-confidence-52", "threatstream-severity-medium" ], - "threatintel.anomali.description": "TS ID: 55250078010; iType: mal_url; State: active; Org: QuadraNet; Source: CyberCrime", - "threatintel.anomali.id": "indicator--c58983e2-18fd-47b8-aab4-6c8a2e2dcb35", - "threatintel.anomali.labels": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali Limo", + "threat.indicator.first_seen": "2020-01-24T02:59:15.878Z", + "threat.indicator.provider": "CyberCrime", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "67.215.224.101", + "threat.indicator.url.extension": "php", + "threat.indicator.url.full": "http://67.215.224.101/a1/panel/admin.php", + "threat.indicator.url.original": "http://67.215.224.101/a1/panel/admin.php", + "threat.indicator.url.path": "/a1/panel/admin.php", + "threat.indicator.url.scheme": "http" + }, + { + "anomali.limo.description": "TS ID: 55250078000; iType: mal_ip; State: active; Org: CyrusOne LLC; Source: CyberCrime", + "anomali.limo.id": "indicator--1ab178a8-7991-4879-b9aa-8da49f40e92e", + "anomali.limo.labels": [ "malicious-activity", - "threatstream-confidence-52", + "threatstream-confidence-58", "threatstream-severity-medium" ], - "threatintel.anomali.modified": "2020-01-24T02:59:15.878Z", - "threatintel.anomali.name": "mal_url: http://67.215.224.101/a1/panel/admin.php", - "threatintel.anomali.object_marking_refs": [ + "anomali.limo.modified": "2020-01-24T02:59:29.155Z", + "anomali.limo.name": "mal_ip: 162.241.73.163", + "anomali.limo.object_marking_refs": [ "marking-definition--34098fce-860f-48ae-8e50-ebd3cc5e41da" ], - "threatintel.anomali.pattern": "[url:value = 'http://67.215.224.101/a1/panel/admin.php']", - "threatintel.anomali.type": "indicator", - "threatintel.anomali.valid_from": "2020-01-24T02:59:15.878Z", - "threatintel.indicator.first_seen": "2020-01-24T02:59:15.878Z", - "threatintel.indicator.provider": "CyberCrime", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "67.215.224.101", - "threatintel.indicator.url.extension": "php", - "threatintel.indicator.url.full": "http://67.215.224.101/a1/panel/admin.php", - "threatintel.indicator.url.original": "http://67.215.224.101/a1/panel/admin.php", - "threatintel.indicator.url.path": "/a1/panel/admin.php", - "threatintel.indicator.url.scheme": "http" - }, - { + "anomali.limo.pattern": "[ipv4-addr:value = '162.241.73.163']", + "anomali.limo.type": "indicator", + "anomali.limo.valid_from": "2020-01-24T02:59:29.155Z", "event.category": "threat", "event.dataset": "threatintel.anomali", "event.kind": "enrichment", @@ -2722,27 +2869,29 @@ "threatstream-confidence-58", "threatstream-severity-medium" ], - "threatintel.anomali.description": "TS ID: 55250078000; iType: mal_ip; State: active; Org: CyrusOne LLC; Source: CyberCrime", - "threatintel.anomali.id": "indicator--1ab178a8-7991-4879-b9aa-8da49f40e92e", - "threatintel.anomali.labels": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali Limo", + "threat.indicator.first_seen": "2020-01-24T02:59:29.155Z", + "threat.indicator.ip": "162.241.73.163", + "threat.indicator.provider": "CyberCrime", + "threat.indicator.type": "ipv4-addr" + }, + { + "anomali.limo.description": "TS ID: 55250078020; iType: mal_url; State: active; Org: MoreneHost; Source: CyberCrime", + "anomali.limo.id": "indicator--d5bdff38-6939-4a47-8e11-b910520565c4", + "anomali.limo.labels": [ "malicious-activity", - "threatstream-confidence-58", + "threatstream-confidence-78", "threatstream-severity-medium" ], - "threatintel.anomali.modified": "2020-01-24T02:59:29.155Z", - "threatintel.anomali.name": "mal_ip: 162.241.73.163", - "threatintel.anomali.object_marking_refs": [ + "anomali.limo.modified": "2020-01-24T02:59:50.233Z", + "anomali.limo.name": "mal_url: http://l60bdd58.justinstalledpanel.com/login", + "anomali.limo.object_marking_refs": [ "marking-definition--34098fce-860f-48ae-8e50-ebd3cc5e41da" ], - "threatintel.anomali.pattern": "[ipv4-addr:value = '162.241.73.163']", - "threatintel.anomali.type": "indicator", - "threatintel.anomali.valid_from": "2020-01-24T02:59:29.155Z", - "threatintel.indicator.first_seen": "2020-01-24T02:59:29.155Z", - "threatintel.indicator.ip": "162.241.73.163", - "threatintel.indicator.provider": "CyberCrime", - "threatintel.indicator.type": "ipv4-addr" - }, - { + "anomali.limo.pattern": "[url:value = 'http://l60bdd58.justinstalledpanel.com/login']", + "anomali.limo.type": "indicator", + "anomali.limo.valid_from": "2020-01-24T02:59:50.233Z", "event.category": "threat", "event.dataset": "threatintel.anomali", "event.kind": "enrichment", @@ -2759,31 +2908,33 @@ "threatstream-confidence-78", "threatstream-severity-medium" ], - "threatintel.anomali.description": "TS ID: 55250078020; iType: mal_url; State: active; Org: MoreneHost; Source: CyberCrime", - "threatintel.anomali.id": "indicator--d5bdff38-6939-4a47-8e11-b910520565c4", - "threatintel.anomali.labels": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali Limo", + "threat.indicator.first_seen": "2020-01-24T02:59:50.233Z", + "threat.indicator.provider": "CyberCrime", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "l60bdd58.justinstalledpanel.com", + "threat.indicator.url.full": "http://l60bdd58.justinstalledpanel.com/login", + "threat.indicator.url.original": "http://l60bdd58.justinstalledpanel.com/login", + "threat.indicator.url.path": "/login", + "threat.indicator.url.scheme": "http" + }, + { + "anomali.limo.description": "TS ID: 55250078009; iType: mal_url; State: active; Org: ColoCrossing; Source: CyberCrime", + "anomali.limo.id": "indicator--1be74977-5aa6-4175-99dd-32b54863a06b", + "anomali.limo.labels": [ "malicious-activity", - "threatstream-confidence-78", + "threatstream-confidence-25", "threatstream-severity-medium" ], - "threatintel.anomali.modified": "2020-01-24T02:59:50.233Z", - "threatintel.anomali.name": "mal_url: http://l60bdd58.justinstalledpanel.com/login", - "threatintel.anomali.object_marking_refs": [ + "anomali.limo.modified": "2020-01-24T02:59:50.255Z", + "anomali.limo.name": "mal_url: http://107.175.150.73/~giftioz/.azma/panel/admin.php", + "anomali.limo.object_marking_refs": [ "marking-definition--34098fce-860f-48ae-8e50-ebd3cc5e41da" ], - "threatintel.anomali.pattern": "[url:value = 'http://l60bdd58.justinstalledpanel.com/login']", - "threatintel.anomali.type": "indicator", - "threatintel.anomali.valid_from": "2020-01-24T02:59:50.233Z", - "threatintel.indicator.first_seen": "2020-01-24T02:59:50.233Z", - "threatintel.indicator.provider": "CyberCrime", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "l60bdd58.justinstalledpanel.com", - "threatintel.indicator.url.full": "http://l60bdd58.justinstalledpanel.com/login", - "threatintel.indicator.url.original": "http://l60bdd58.justinstalledpanel.com/login", - "threatintel.indicator.url.path": "/login", - "threatintel.indicator.url.scheme": "http" - }, - { + "anomali.limo.pattern": "[url:value = 'http://107.175.150.73/~giftioz/.azma/panel/admin.php']", + "anomali.limo.type": "indicator", + "anomali.limo.valid_from": "2020-01-24T02:59:50.255Z", "event.category": "threat", "event.dataset": "threatintel.anomali", "event.kind": "enrichment", @@ -2800,32 +2951,34 @@ "threatstream-confidence-25", "threatstream-severity-medium" ], - "threatintel.anomali.description": "TS ID: 55250078009; iType: mal_url; State: active; Org: ColoCrossing; Source: CyberCrime", - "threatintel.anomali.id": "indicator--1be74977-5aa6-4175-99dd-32b54863a06b", - "threatintel.anomali.labels": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali Limo", + "threat.indicator.first_seen": "2020-01-24T02:59:50.255Z", + "threat.indicator.provider": "CyberCrime", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "107.175.150.73", + "threat.indicator.url.extension": "php", + "threat.indicator.url.full": "http://107.175.150.73/~giftioz/.azma/panel/admin.php", + "threat.indicator.url.original": "http://107.175.150.73/~giftioz/.azma/panel/admin.php", + "threat.indicator.url.path": "/~giftioz/.azma/panel/admin.php", + "threat.indicator.url.scheme": "http" + }, + { + "anomali.limo.description": "TS ID: 55250078023; iType: mal_url; State: active; Org: MoreneHost; Source: CyberCrime", + "anomali.limo.id": "indicator--eacc25ce-584c-4b40-98ab-7935dabd5cb1", + "anomali.limo.labels": [ "malicious-activity", - "threatstream-confidence-25", + "threatstream-confidence-78", "threatstream-severity-medium" ], - "threatintel.anomali.modified": "2020-01-24T02:59:50.255Z", - "threatintel.anomali.name": "mal_url: http://107.175.150.73/~giftioz/.azma/panel/admin.php", - "threatintel.anomali.object_marking_refs": [ + "anomali.limo.modified": "2020-01-24T02:59:52.536Z", + "anomali.limo.name": "mal_url: http://5.188.60.52/login", + "anomali.limo.object_marking_refs": [ "marking-definition--34098fce-860f-48ae-8e50-ebd3cc5e41da" ], - "threatintel.anomali.pattern": "[url:value = 'http://107.175.150.73/~giftioz/.azma/panel/admin.php']", - "threatintel.anomali.type": "indicator", - "threatintel.anomali.valid_from": "2020-01-24T02:59:50.255Z", - "threatintel.indicator.first_seen": "2020-01-24T02:59:50.255Z", - "threatintel.indicator.provider": "CyberCrime", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "107.175.150.73", - "threatintel.indicator.url.extension": "php", - "threatintel.indicator.url.full": "http://107.175.150.73/~giftioz/.azma/panel/admin.php", - "threatintel.indicator.url.original": "http://107.175.150.73/~giftioz/.azma/panel/admin.php", - "threatintel.indicator.url.path": "/~giftioz/.azma/panel/admin.php", - "threatintel.indicator.url.scheme": "http" - }, - { + "anomali.limo.pattern": "[url:value = 'http://5.188.60.52/login']", + "anomali.limo.type": "indicator", + "anomali.limo.valid_from": "2020-01-24T02:59:52.536Z", "event.category": "threat", "event.dataset": "threatintel.anomali", "event.kind": "enrichment", @@ -2842,31 +2995,33 @@ "threatstream-confidence-78", "threatstream-severity-medium" ], - "threatintel.anomali.description": "TS ID: 55250078023; iType: mal_url; State: active; Org: MoreneHost; Source: CyberCrime", - "threatintel.anomali.id": "indicator--eacc25ce-584c-4b40-98ab-7935dabd5cb1", - "threatintel.anomali.labels": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali Limo", + "threat.indicator.first_seen": "2020-01-24T02:59:52.536Z", + "threat.indicator.provider": "CyberCrime", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "5.188.60.52", + "threat.indicator.url.full": "http://5.188.60.52/login", + "threat.indicator.url.original": "http://5.188.60.52/login", + "threat.indicator.url.path": "/login", + "threat.indicator.url.scheme": "http" + }, + { + "anomali.limo.description": "TS ID: 55250078025; iType: mal_url; State: active; Org: Cloudflare; Source: CyberCrime", + "anomali.limo.id": "indicator--504f4011-eaea-4921-aad5-f102bef7c798", + "anomali.limo.labels": [ "malicious-activity", - "threatstream-confidence-78", + "threatstream-confidence-85", "threatstream-severity-medium" ], - "threatintel.anomali.modified": "2020-01-24T02:59:52.536Z", - "threatintel.anomali.name": "mal_url: http://5.188.60.52/login", - "threatintel.anomali.object_marking_refs": [ + "anomali.limo.modified": "2020-01-24T02:59:54.784Z", + "anomali.limo.name": "mal_url: http://trotdeiman.ga/login", + "anomali.limo.object_marking_refs": [ "marking-definition--34098fce-860f-48ae-8e50-ebd3cc5e41da" ], - "threatintel.anomali.pattern": "[url:value = 'http://5.188.60.52/login']", - "threatintel.anomali.type": "indicator", - "threatintel.anomali.valid_from": "2020-01-24T02:59:52.536Z", - "threatintel.indicator.first_seen": "2020-01-24T02:59:52.536Z", - "threatintel.indicator.provider": "CyberCrime", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "5.188.60.52", - "threatintel.indicator.url.full": "http://5.188.60.52/login", - "threatintel.indicator.url.original": "http://5.188.60.52/login", - "threatintel.indicator.url.path": "/login", - "threatintel.indicator.url.scheme": "http" - }, - { + "anomali.limo.pattern": "[url:value = 'http://trotdeiman.ga/login']", + "anomali.limo.type": "indicator", + "anomali.limo.valid_from": "2020-01-24T02:59:54.784Z", "event.category": "threat", "event.dataset": "threatintel.anomali", "event.kind": "enrichment", @@ -2883,31 +3038,33 @@ "threatstream-confidence-85", "threatstream-severity-medium" ], - "threatintel.anomali.description": "TS ID: 55250078025; iType: mal_url; State: active; Org: Cloudflare; Source: CyberCrime", - "threatintel.anomali.id": "indicator--504f4011-eaea-4921-aad5-f102bef7c798", - "threatintel.anomali.labels": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali Limo", + "threat.indicator.first_seen": "2020-01-24T02:59:54.784Z", + "threat.indicator.provider": "CyberCrime", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "trotdeiman.ga", + "threat.indicator.url.full": "http://trotdeiman.ga/login", + "threat.indicator.url.original": "http://trotdeiman.ga/login", + "threat.indicator.url.path": "/login", + "threat.indicator.url.scheme": "http" + }, + { + "anomali.limo.description": "TS ID: 55250078014; iType: mal_ip; State: active; Source: CyberCrime", + "anomali.limo.id": "indicator--e3ffb953-6c59-461a-8242-0d26c2b5c358", + "anomali.limo.labels": [ "malicious-activity", - "threatstream-confidence-85", + "threatstream-confidence-82", "threatstream-severity-medium" ], - "threatintel.anomali.modified": "2020-01-24T02:59:54.784Z", - "threatintel.anomali.name": "mal_url: http://trotdeiman.ga/login", - "threatintel.anomali.object_marking_refs": [ + "anomali.limo.modified": "2020-01-24T02:59:54.815Z", + "anomali.limo.name": "mal_ip: 217.8.117.8", + "anomali.limo.object_marking_refs": [ "marking-definition--34098fce-860f-48ae-8e50-ebd3cc5e41da" ], - "threatintel.anomali.pattern": "[url:value = 'http://trotdeiman.ga/login']", - "threatintel.anomali.type": "indicator", - "threatintel.anomali.valid_from": "2020-01-24T02:59:54.784Z", - "threatintel.indicator.first_seen": "2020-01-24T02:59:54.784Z", - "threatintel.indicator.provider": "CyberCrime", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "trotdeiman.ga", - "threatintel.indicator.url.full": "http://trotdeiman.ga/login", - "threatintel.indicator.url.original": "http://trotdeiman.ga/login", - "threatintel.indicator.url.path": "/login", - "threatintel.indicator.url.scheme": "http" - }, - { + "anomali.limo.pattern": "[ipv4-addr:value = '217.8.117.8']", + "anomali.limo.type": "indicator", + "anomali.limo.valid_from": "2020-01-24T02:59:54.815Z", "event.category": "threat", "event.dataset": "threatintel.anomali", "event.kind": "enrichment", @@ -2924,27 +3081,29 @@ "threatstream-confidence-82", "threatstream-severity-medium" ], - "threatintel.anomali.description": "TS ID: 55250078014; iType: mal_ip; State: active; Source: CyberCrime", - "threatintel.anomali.id": "indicator--e3ffb953-6c59-461a-8242-0d26c2b5c358", - "threatintel.anomali.labels": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali Limo", + "threat.indicator.first_seen": "2020-01-24T02:59:54.815Z", + "threat.indicator.ip": "217.8.117.8", + "threat.indicator.provider": "CyberCrime", + "threat.indicator.type": "ipv4-addr" + }, + { + "anomali.limo.description": "TS ID: 55250078036; iType: mal_ip; State: active; Org: Global Frag Networks; Source: CyberCrime", + "anomali.limo.id": "indicator--3a47ad46-930d-4ced-b0e7-dc9d0776153e", + "anomali.limo.labels": [ "malicious-activity", - "threatstream-confidence-82", + "threatstream-confidence-83", "threatstream-severity-medium" ], - "threatintel.anomali.modified": "2020-01-24T02:59:54.815Z", - "threatintel.anomali.name": "mal_ip: 217.8.117.8", - "threatintel.anomali.object_marking_refs": [ + "anomali.limo.modified": "2020-01-24T03:00:01.726Z", + "anomali.limo.name": "mal_ip: 104.223.170.113", + "anomali.limo.object_marking_refs": [ "marking-definition--34098fce-860f-48ae-8e50-ebd3cc5e41da" ], - "threatintel.anomali.pattern": "[ipv4-addr:value = '217.8.117.8']", - "threatintel.anomali.type": "indicator", - "threatintel.anomali.valid_from": "2020-01-24T02:59:54.815Z", - "threatintel.indicator.first_seen": "2020-01-24T02:59:54.815Z", - "threatintel.indicator.ip": "217.8.117.8", - "threatintel.indicator.provider": "CyberCrime", - "threatintel.indicator.type": "ipv4-addr" - }, - { + "anomali.limo.pattern": "[ipv4-addr:value = '104.223.170.113']", + "anomali.limo.type": "indicator", + "anomali.limo.valid_from": "2020-01-24T03:00:01.726Z", "event.category": "threat", "event.dataset": "threatintel.anomali", "event.kind": "enrichment", @@ -2961,27 +3120,29 @@ "threatstream-confidence-83", "threatstream-severity-medium" ], - "threatintel.anomali.description": "TS ID: 55250078036; iType: mal_ip; State: active; Org: Global Frag Networks; Source: CyberCrime", - "threatintel.anomali.id": "indicator--3a47ad46-930d-4ced-b0e7-dc9d0776153e", - "threatintel.anomali.labels": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali Limo", + "threat.indicator.first_seen": "2020-01-24T03:00:01.726Z", + "threat.indicator.ip": "104.223.170.113", + "threat.indicator.provider": "CyberCrime", + "threat.indicator.type": "ipv4-addr" + }, + { + "anomali.limo.description": "TS ID: 55250078011; iType: mal_url; State: active; Org: CyrusOne LLC; Source: CyberCrime", + "anomali.limo.id": "indicator--0e10924c-745c-4a58-8e27-ab3a6bacd666", + "anomali.limo.labels": [ "malicious-activity", - "threatstream-confidence-83", + "threatstream-confidence-58", "threatstream-severity-medium" ], - "threatintel.anomali.modified": "2020-01-24T03:00:01.726Z", - "threatintel.anomali.name": "mal_ip: 104.223.170.113", - "threatintel.anomali.object_marking_refs": [ + "anomali.limo.modified": "2020-01-24T03:00:01.762Z", + "anomali.limo.name": "mal_url: http://tavim.org/includes/firmino/admin.php", + "anomali.limo.object_marking_refs": [ "marking-definition--34098fce-860f-48ae-8e50-ebd3cc5e41da" ], - "threatintel.anomali.pattern": "[ipv4-addr:value = '104.223.170.113']", - "threatintel.anomali.type": "indicator", - "threatintel.anomali.valid_from": "2020-01-24T03:00:01.726Z", - "threatintel.indicator.first_seen": "2020-01-24T03:00:01.726Z", - "threatintel.indicator.ip": "104.223.170.113", - "threatintel.indicator.provider": "CyberCrime", - "threatintel.indicator.type": "ipv4-addr" - }, - { + "anomali.limo.pattern": "[url:value = 'http://tavim.org/includes/firmino/admin.php']", + "anomali.limo.type": "indicator", + "anomali.limo.valid_from": "2020-01-24T03:00:01.762Z", "event.category": "threat", "event.dataset": "threatintel.anomali", "event.kind": "enrichment", @@ -2998,32 +3159,34 @@ "threatstream-confidence-58", "threatstream-severity-medium" ], - "threatintel.anomali.description": "TS ID: 55250078011; iType: mal_url; State: active; Org: CyrusOne LLC; Source: CyberCrime", - "threatintel.anomali.id": "indicator--0e10924c-745c-4a58-8e27-ab3a6bacd666", - "threatintel.anomali.labels": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali Limo", + "threat.indicator.first_seen": "2020-01-24T03:00:01.762Z", + "threat.indicator.provider": "CyberCrime", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "tavim.org", + "threat.indicator.url.extension": "php", + "threat.indicator.url.full": "http://tavim.org/includes/firmino/admin.php", + "threat.indicator.url.original": "http://tavim.org/includes/firmino/admin.php", + "threat.indicator.url.path": "/includes/firmino/admin.php", + "threat.indicator.url.scheme": "http" + }, + { + "anomali.limo.description": "TS ID: 55250078015; iType: mal_url; State: active; Source: CyberCrime", + "anomali.limo.id": "indicator--c3fb816a-cc3b-4442-be4d-d62113ae5168", + "anomali.limo.labels": [ "malicious-activity", - "threatstream-confidence-58", + "threatstream-confidence-84", "threatstream-severity-medium" ], - "threatintel.anomali.modified": "2020-01-24T03:00:01.762Z", - "threatintel.anomali.name": "mal_url: http://tavim.org/includes/firmino/admin.php", - "threatintel.anomali.object_marking_refs": [ + "anomali.limo.modified": "2020-01-24T03:00:10.928Z", + "anomali.limo.name": "mal_url: http://onlinesecuritycenter.xyz/login", + "anomali.limo.object_marking_refs": [ "marking-definition--34098fce-860f-48ae-8e50-ebd3cc5e41da" ], - "threatintel.anomali.pattern": "[url:value = 'http://tavim.org/includes/firmino/admin.php']", - "threatintel.anomali.type": "indicator", - "threatintel.anomali.valid_from": "2020-01-24T03:00:01.762Z", - "threatintel.indicator.first_seen": "2020-01-24T03:00:01.762Z", - "threatintel.indicator.provider": "CyberCrime", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "tavim.org", - "threatintel.indicator.url.extension": "php", - "threatintel.indicator.url.full": "http://tavim.org/includes/firmino/admin.php", - "threatintel.indicator.url.original": "http://tavim.org/includes/firmino/admin.php", - "threatintel.indicator.url.path": "/includes/firmino/admin.php", - "threatintel.indicator.url.scheme": "http" - }, - { + "anomali.limo.pattern": "[url:value = 'http://onlinesecuritycenter.xyz/login']", + "anomali.limo.type": "indicator", + "anomali.limo.valid_from": "2020-01-24T03:00:10.928Z", "event.category": "threat", "event.dataset": "threatintel.anomali", "event.kind": "enrichment", @@ -3040,31 +3203,33 @@ "threatstream-confidence-84", "threatstream-severity-medium" ], - "threatintel.anomali.description": "TS ID: 55250078015; iType: mal_url; State: active; Source: CyberCrime", - "threatintel.anomali.id": "indicator--c3fb816a-cc3b-4442-be4d-d62113ae5168", - "threatintel.anomali.labels": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali Limo", + "threat.indicator.first_seen": "2020-01-24T03:00:10.928Z", + "threat.indicator.provider": "CyberCrime", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "onlinesecuritycenter.xyz", + "threat.indicator.url.full": "http://onlinesecuritycenter.xyz/login", + "threat.indicator.url.original": "http://onlinesecuritycenter.xyz/login", + "threat.indicator.url.path": "/login", + "threat.indicator.url.scheme": "http" + }, + { + "anomali.limo.description": "TS ID: 55250078029; iType: mal_url; State: active; Org: IT House, Ltd; Source: CyberCrime", + "anomali.limo.id": "indicator--9159e46d-f3a4-464b-ac68-8beaf87e1a8f", + "anomali.limo.labels": [ "malicious-activity", - "threatstream-confidence-84", + "threatstream-confidence-81", "threatstream-severity-medium" ], - "threatintel.anomali.modified": "2020-01-24T03:00:10.928Z", - "threatintel.anomali.name": "mal_url: http://onlinesecuritycenter.xyz/login", - "threatintel.anomali.object_marking_refs": [ + "anomali.limo.modified": "2020-01-24T03:00:20.166Z", + "anomali.limo.name": "mal_url: http://oaa-my.com/cutter/five/PvqDq929BSx_A_D_M1n_a.php", + "anomali.limo.object_marking_refs": [ "marking-definition--34098fce-860f-48ae-8e50-ebd3cc5e41da" ], - "threatintel.anomali.pattern": "[url:value = 'http://onlinesecuritycenter.xyz/login']", - "threatintel.anomali.type": "indicator", - "threatintel.anomali.valid_from": "2020-01-24T03:00:10.928Z", - "threatintel.indicator.first_seen": "2020-01-24T03:00:10.928Z", - "threatintel.indicator.provider": "CyberCrime", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "onlinesecuritycenter.xyz", - "threatintel.indicator.url.full": "http://onlinesecuritycenter.xyz/login", - "threatintel.indicator.url.original": "http://onlinesecuritycenter.xyz/login", - "threatintel.indicator.url.path": "/login", - "threatintel.indicator.url.scheme": "http" - }, - { + "anomali.limo.pattern": "[url:value = 'http://oaa-my.com/cutter/five/PvqDq929BSx_A_D_M1n_a.php']", + "anomali.limo.type": "indicator", + "anomali.limo.valid_from": "2020-01-24T03:00:20.166Z", "event.category": "threat", "event.dataset": "threatintel.anomali", "event.kind": "enrichment", @@ -3081,32 +3246,34 @@ "threatstream-confidence-81", "threatstream-severity-medium" ], - "threatintel.anomali.description": "TS ID: 55250078029; iType: mal_url; State: active; Org: IT House, Ltd; Source: CyberCrime", - "threatintel.anomali.id": "indicator--9159e46d-f3a4-464b-ac68-8beaf87e1a8f", - "threatintel.anomali.labels": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali Limo", + "threat.indicator.first_seen": "2020-01-24T03:00:20.166Z", + "threat.indicator.provider": "CyberCrime", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "oaa-my.com", + "threat.indicator.url.extension": "php", + "threat.indicator.url.full": "http://oaa-my.com/cutter/five/PvqDq929BSx_A_D_M1n_a.php", + "threat.indicator.url.original": "http://oaa-my.com/cutter/five/PvqDq929BSx_A_D_M1n_a.php", + "threat.indicator.url.path": "/cutter/five/PvqDq929BSx_A_D_M1n_a.php", + "threat.indicator.url.scheme": "http" + }, + { + "anomali.limo.description": "TS ID: 55250078016; iType: mal_url; State: active; Source: CyberCrime", + "anomali.limo.id": "indicator--fefa8e76-ae0f-41ab-84e7-ea43ab055573", + "anomali.limo.labels": [ "malicious-activity", - "threatstream-confidence-81", + "threatstream-confidence-90", "threatstream-severity-medium" ], - "threatintel.anomali.modified": "2020-01-24T03:00:20.166Z", - "threatintel.anomali.name": "mal_url: http://oaa-my.com/cutter/five/PvqDq929BSx_A_D_M1n_a.php", - "threatintel.anomali.object_marking_refs": [ + "anomali.limo.modified": "2020-01-24T03:00:24.048Z", + "anomali.limo.name": "mal_url: http://jumbajumbadun.fun/login", + "anomali.limo.object_marking_refs": [ "marking-definition--34098fce-860f-48ae-8e50-ebd3cc5e41da" ], - "threatintel.anomali.pattern": "[url:value = 'http://oaa-my.com/cutter/five/PvqDq929BSx_A_D_M1n_a.php']", - "threatintel.anomali.type": "indicator", - "threatintel.anomali.valid_from": "2020-01-24T03:00:20.166Z", - "threatintel.indicator.first_seen": "2020-01-24T03:00:20.166Z", - "threatintel.indicator.provider": "CyberCrime", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "oaa-my.com", - "threatintel.indicator.url.extension": "php", - "threatintel.indicator.url.full": "http://oaa-my.com/cutter/five/PvqDq929BSx_A_D_M1n_a.php", - "threatintel.indicator.url.original": "http://oaa-my.com/cutter/five/PvqDq929BSx_A_D_M1n_a.php", - "threatintel.indicator.url.path": "/cutter/five/PvqDq929BSx_A_D_M1n_a.php", - "threatintel.indicator.url.scheme": "http" - }, - { + "anomali.limo.pattern": "[url:value = 'http://jumbajumbadun.fun/login']", + "anomali.limo.type": "indicator", + "anomali.limo.valid_from": "2020-01-24T03:00:24.048Z", "event.category": "threat", "event.dataset": "threatintel.anomali", "event.kind": "enrichment", @@ -3123,31 +3290,33 @@ "threatstream-confidence-90", "threatstream-severity-medium" ], - "threatintel.anomali.description": "TS ID: 55250078016; iType: mal_url; State: active; Source: CyberCrime", - "threatintel.anomali.id": "indicator--fefa8e76-ae0f-41ab-84e7-ea43ab055573", - "threatintel.anomali.labels": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali Limo", + "threat.indicator.first_seen": "2020-01-24T03:00:24.048Z", + "threat.indicator.provider": "CyberCrime", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "jumbajumbadun.fun", + "threat.indicator.url.full": "http://jumbajumbadun.fun/login", + "threat.indicator.url.original": "http://jumbajumbadun.fun/login", + "threat.indicator.url.path": "/login", + "threat.indicator.url.scheme": "http" + }, + { + "anomali.limo.description": "TS ID: 55250078024; iType: mal_url; State: active; Org: CyrusOne LLC; Source: CyberCrime", + "anomali.limo.id": "indicator--6a76fa89-4d5f-40d0-9b03-671bdb2d5b4b", + "anomali.limo.labels": [ "malicious-activity", - "threatstream-confidence-90", + "threatstream-confidence-58", "threatstream-severity-medium" ], - "threatintel.anomali.modified": "2020-01-24T03:00:24.048Z", - "threatintel.anomali.name": "mal_url: http://jumbajumbadun.fun/login", - "threatintel.anomali.object_marking_refs": [ + "anomali.limo.modified": "2020-01-24T03:00:55.816Z", + "anomali.limo.name": "mal_url: http://tavim.org/includes/salah/admin.php", + "anomali.limo.object_marking_refs": [ "marking-definition--34098fce-860f-48ae-8e50-ebd3cc5e41da" ], - "threatintel.anomali.pattern": "[url:value = 'http://jumbajumbadun.fun/login']", - "threatintel.anomali.type": "indicator", - "threatintel.anomali.valid_from": "2020-01-24T03:00:24.048Z", - "threatintel.indicator.first_seen": "2020-01-24T03:00:24.048Z", - "threatintel.indicator.provider": "CyberCrime", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "jumbajumbadun.fun", - "threatintel.indicator.url.full": "http://jumbajumbadun.fun/login", - "threatintel.indicator.url.original": "http://jumbajumbadun.fun/login", - "threatintel.indicator.url.path": "/login", - "threatintel.indicator.url.scheme": "http" - }, - { + "anomali.limo.pattern": "[url:value = 'http://tavim.org/includes/salah/admin.php']", + "anomali.limo.type": "indicator", + "anomali.limo.valid_from": "2020-01-24T03:00:55.816Z", "event.category": "threat", "event.dataset": "threatintel.anomali", "event.kind": "enrichment", @@ -3164,32 +3333,34 @@ "threatstream-confidence-58", "threatstream-severity-medium" ], - "threatintel.anomali.description": "TS ID: 55250078024; iType: mal_url; State: active; Org: CyrusOne LLC; Source: CyberCrime", - "threatintel.anomali.id": "indicator--6a76fa89-4d5f-40d0-9b03-671bdb2d5b4b", - "threatintel.anomali.labels": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali Limo", + "threat.indicator.first_seen": "2020-01-24T03:00:55.816Z", + "threat.indicator.provider": "CyberCrime", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "tavim.org", + "threat.indicator.url.extension": "php", + "threat.indicator.url.full": "http://tavim.org/includes/salah/admin.php", + "threat.indicator.url.original": "http://tavim.org/includes/salah/admin.php", + "threat.indicator.url.path": "/includes/salah/admin.php", + "threat.indicator.url.scheme": "http" + }, + { + "anomali.limo.description": "TS ID: 55250078022; iType: mal_url; State: active; Org: MoreneHost; Source: CyberCrime", + "anomali.limo.id": "indicator--21055dfd-d0cb-42ec-93bd-ffaeadd11d80", + "anomali.limo.labels": [ "malicious-activity", - "threatstream-confidence-58", + "threatstream-confidence-80", "threatstream-severity-medium" ], - "threatintel.anomali.modified": "2020-01-24T03:00:55.816Z", - "threatintel.anomali.name": "mal_url: http://tavim.org/includes/salah/admin.php", - "threatintel.anomali.object_marking_refs": [ + "anomali.limo.modified": "2020-01-24T03:01:10.501Z", + "anomali.limo.name": "mal_url: http://l0c23205.justinstalledpanel.com/login", + "anomali.limo.object_marking_refs": [ "marking-definition--34098fce-860f-48ae-8e50-ebd3cc5e41da" ], - "threatintel.anomali.pattern": "[url:value = 'http://tavim.org/includes/salah/admin.php']", - "threatintel.anomali.type": "indicator", - "threatintel.anomali.valid_from": "2020-01-24T03:00:55.816Z", - "threatintel.indicator.first_seen": "2020-01-24T03:00:55.816Z", - "threatintel.indicator.provider": "CyberCrime", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "tavim.org", - "threatintel.indicator.url.extension": "php", - "threatintel.indicator.url.full": "http://tavim.org/includes/salah/admin.php", - "threatintel.indicator.url.original": "http://tavim.org/includes/salah/admin.php", - "threatintel.indicator.url.path": "/includes/salah/admin.php", - "threatintel.indicator.url.scheme": "http" - }, - { + "anomali.limo.pattern": "[url:value = 'http://l0c23205.justinstalledpanel.com/login']", + "anomali.limo.type": "indicator", + "anomali.limo.valid_from": "2020-01-24T03:01:10.501Z", "event.category": "threat", "event.dataset": "threatintel.anomali", "event.kind": "enrichment", @@ -3206,31 +3377,33 @@ "threatstream-confidence-80", "threatstream-severity-medium" ], - "threatintel.anomali.description": "TS ID: 55250078022; iType: mal_url; State: active; Org: MoreneHost; Source: CyberCrime", - "threatintel.anomali.id": "indicator--21055dfd-d0cb-42ec-93bd-ffaeadd11d80", - "threatintel.anomali.labels": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali Limo", + "threat.indicator.first_seen": "2020-01-24T03:01:10.501Z", + "threat.indicator.provider": "CyberCrime", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "l0c23205.justinstalledpanel.com", + "threat.indicator.url.full": "http://l0c23205.justinstalledpanel.com/login", + "threat.indicator.url.original": "http://l0c23205.justinstalledpanel.com/login", + "threat.indicator.url.path": "/login", + "threat.indicator.url.scheme": "http" + }, + { + "anomali.limo.description": "TS ID: 55250078021; iType: mal_url; State: active; Org: MoreneHost; Source: CyberCrime", + "anomali.limo.id": "indicator--7471a595-e8b0-4c41-be4c-0a3e55675630", + "anomali.limo.labels": [ "malicious-activity", - "threatstream-confidence-80", + "threatstream-confidence-83", "threatstream-severity-medium" ], - "threatintel.anomali.modified": "2020-01-24T03:01:10.501Z", - "threatintel.anomali.name": "mal_url: http://l0c23205.justinstalledpanel.com/login", - "threatintel.anomali.object_marking_refs": [ + "anomali.limo.modified": "2020-01-24T03:01:10.518Z", + "anomali.limo.name": "mal_url: http://l535e9e5.justinstalledpanel.com/login", + "anomali.limo.object_marking_refs": [ "marking-definition--34098fce-860f-48ae-8e50-ebd3cc5e41da" ], - "threatintel.anomali.pattern": "[url:value = 'http://l0c23205.justinstalledpanel.com/login']", - "threatintel.anomali.type": "indicator", - "threatintel.anomali.valid_from": "2020-01-24T03:01:10.501Z", - "threatintel.indicator.first_seen": "2020-01-24T03:01:10.501Z", - "threatintel.indicator.provider": "CyberCrime", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "l0c23205.justinstalledpanel.com", - "threatintel.indicator.url.full": "http://l0c23205.justinstalledpanel.com/login", - "threatintel.indicator.url.original": "http://l0c23205.justinstalledpanel.com/login", - "threatintel.indicator.url.path": "/login", - "threatintel.indicator.url.scheme": "http" - }, - { + "anomali.limo.pattern": "[url:value = 'http://l535e9e5.justinstalledpanel.com/login']", + "anomali.limo.type": "indicator", + "anomali.limo.valid_from": "2020-01-24T03:01:10.518Z", "event.category": "threat", "event.dataset": "threatintel.anomali", "event.kind": "enrichment", @@ -3247,31 +3420,33 @@ "threatstream-confidence-83", "threatstream-severity-medium" ], - "threatintel.anomali.description": "TS ID: 55250078021; iType: mal_url; State: active; Org: MoreneHost; Source: CyberCrime", - "threatintel.anomali.id": "indicator--7471a595-e8b0-4c41-be4c-0a3e55675630", - "threatintel.anomali.labels": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali Limo", + "threat.indicator.first_seen": "2020-01-24T03:01:10.518Z", + "threat.indicator.provider": "CyberCrime", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "l535e9e5.justinstalledpanel.com", + "threat.indicator.url.full": "http://l535e9e5.justinstalledpanel.com/login", + "threat.indicator.url.original": "http://l535e9e5.justinstalledpanel.com/login", + "threat.indicator.url.path": "/login", + "threat.indicator.url.scheme": "http" + }, + { + "anomali.limo.description": "TS ID: 55250078007; iType: mal_ip; State: active; Source: CyberCrime", + "anomali.limo.id": "indicator--ead1e7e5-fdb3-47c2-9476-aa82741c038e", + "anomali.limo.labels": [ "malicious-activity", - "threatstream-confidence-83", + "threatstream-confidence-76", "threatstream-severity-medium" ], - "threatintel.anomali.modified": "2020-01-24T03:01:10.518Z", - "threatintel.anomali.name": "mal_url: http://l535e9e5.justinstalledpanel.com/login", - "threatintel.anomali.object_marking_refs": [ + "anomali.limo.modified": "2020-01-24T03:01:14.843Z", + "anomali.limo.name": "mal_ip: 217.8.117.47", + "anomali.limo.object_marking_refs": [ "marking-definition--34098fce-860f-48ae-8e50-ebd3cc5e41da" ], - "threatintel.anomali.pattern": "[url:value = 'http://l535e9e5.justinstalledpanel.com/login']", - "threatintel.anomali.type": "indicator", - "threatintel.anomali.valid_from": "2020-01-24T03:01:10.518Z", - "threatintel.indicator.first_seen": "2020-01-24T03:01:10.518Z", - "threatintel.indicator.provider": "CyberCrime", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "l535e9e5.justinstalledpanel.com", - "threatintel.indicator.url.full": "http://l535e9e5.justinstalledpanel.com/login", - "threatintel.indicator.url.original": "http://l535e9e5.justinstalledpanel.com/login", - "threatintel.indicator.url.path": "/login", - "threatintel.indicator.url.scheme": "http" - }, - { + "anomali.limo.pattern": "[ipv4-addr:value = '217.8.117.47']", + "anomali.limo.type": "indicator", + "anomali.limo.valid_from": "2020-01-24T03:01:14.843Z", "event.category": "threat", "event.dataset": "threatintel.anomali", "event.kind": "enrichment", @@ -3288,27 +3463,29 @@ "threatstream-confidence-76", "threatstream-severity-medium" ], - "threatintel.anomali.description": "TS ID: 55250078007; iType: mal_ip; State: active; Source: CyberCrime", - "threatintel.anomali.id": "indicator--ead1e7e5-fdb3-47c2-9476-aa82741c038e", - "threatintel.anomali.labels": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali Limo", + "threat.indicator.first_seen": "2020-01-24T03:01:14.843Z", + "threat.indicator.ip": "217.8.117.47", + "threat.indicator.provider": "CyberCrime", + "threat.indicator.type": "ipv4-addr" + }, + { + "anomali.limo.description": "TS ID: 55253484365; iType: mal_url; State: active; Org: Petersburg Internet Network ltd.; Source: CyberCrime", + "anomali.limo.id": "indicator--b0aee6bf-32f4-4f65-8de6-f65e04e92b15", + "anomali.limo.labels": [ "malicious-activity", - "threatstream-confidence-76", + "threatstream-confidence-67", "threatstream-severity-medium" ], - "threatintel.anomali.modified": "2020-01-24T03:01:14.843Z", - "threatintel.anomali.name": "mal_ip: 217.8.117.47", - "threatintel.anomali.object_marking_refs": [ + "anomali.limo.modified": "2020-01-25T02:57:12.699Z", + "anomali.limo.name": "mal_url: http://46.161.27.57/northon/", + "anomali.limo.object_marking_refs": [ "marking-definition--34098fce-860f-48ae-8e50-ebd3cc5e41da" ], - "threatintel.anomali.pattern": "[ipv4-addr:value = '217.8.117.47']", - "threatintel.anomali.type": "indicator", - "threatintel.anomali.valid_from": "2020-01-24T03:01:14.843Z", - "threatintel.indicator.first_seen": "2020-01-24T03:01:14.843Z", - "threatintel.indicator.ip": "217.8.117.47", - "threatintel.indicator.provider": "CyberCrime", - "threatintel.indicator.type": "ipv4-addr" - }, - { + "anomali.limo.pattern": "[url:value = 'http://46.161.27.57/northon/']", + "anomali.limo.type": "indicator", + "anomali.limo.valid_from": "2020-01-25T02:57:12.699Z", "event.category": "threat", "event.dataset": "threatintel.anomali", "event.kind": "enrichment", @@ -3325,31 +3502,33 @@ "threatstream-confidence-67", "threatstream-severity-medium" ], - "threatintel.anomali.description": "TS ID: 55253484365; iType: mal_url; State: active; Org: Petersburg Internet Network ltd.; Source: CyberCrime", - "threatintel.anomali.id": "indicator--b0aee6bf-32f4-4f65-8de6-f65e04e92b15", - "threatintel.anomali.labels": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali Limo", + "threat.indicator.first_seen": "2020-01-25T02:57:12.699Z", + "threat.indicator.provider": "CyberCrime", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "46.161.27.57", + "threat.indicator.url.full": "http://46.161.27.57/northon/", + "threat.indicator.url.original": "http://46.161.27.57/northon/", + "threat.indicator.url.path": "/northon/", + "threat.indicator.url.scheme": "http" + }, + { + "anomali.limo.description": "TS ID: 55253484350; iType: mal_url; State: active; Org: ColoCrossing; Source: CyberCrime", + "anomali.limo.id": "indicator--54afbceb-72f3-484e-aee4-904f77beeff6", + "anomali.limo.labels": [ "malicious-activity", - "threatstream-confidence-67", + "threatstream-confidence-90", "threatstream-severity-medium" ], - "threatintel.anomali.modified": "2020-01-25T02:57:12.699Z", - "threatintel.anomali.name": "mal_url: http://46.161.27.57/northon/", - "threatintel.anomali.object_marking_refs": [ + "anomali.limo.modified": "2020-01-25T02:57:28.034Z", + "anomali.limo.name": "mal_url: http://104.168.99.170/login", + "anomali.limo.object_marking_refs": [ "marking-definition--34098fce-860f-48ae-8e50-ebd3cc5e41da" ], - "threatintel.anomali.pattern": "[url:value = 'http://46.161.27.57/northon/']", - "threatintel.anomali.type": "indicator", - "threatintel.anomali.valid_from": "2020-01-25T02:57:12.699Z", - "threatintel.indicator.first_seen": "2020-01-25T02:57:12.699Z", - "threatintel.indicator.provider": "CyberCrime", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "46.161.27.57", - "threatintel.indicator.url.full": "http://46.161.27.57/northon/", - "threatintel.indicator.url.original": "http://46.161.27.57/northon/", - "threatintel.indicator.url.path": "/northon/", - "threatintel.indicator.url.scheme": "http" - }, - { + "anomali.limo.pattern": "[url:value = 'http://104.168.99.170/login']", + "anomali.limo.type": "indicator", + "anomali.limo.valid_from": "2020-01-25T02:57:28.034Z", "event.category": "threat", "event.dataset": "threatintel.anomali", "event.kind": "enrichment", @@ -3366,31 +3545,33 @@ "threatstream-confidence-90", "threatstream-severity-medium" ], - "threatintel.anomali.description": "TS ID: 55253484350; iType: mal_url; State: active; Org: ColoCrossing; Source: CyberCrime", - "threatintel.anomali.id": "indicator--54afbceb-72f3-484e-aee4-904f77beeff6", - "threatintel.anomali.labels": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali Limo", + "threat.indicator.first_seen": "2020-01-25T02:57:28.034Z", + "threat.indicator.provider": "CyberCrime", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "104.168.99.170", + "threat.indicator.url.full": "http://104.168.99.170/login", + "threat.indicator.url.original": "http://104.168.99.170/login", + "threat.indicator.url.path": "/login", + "threat.indicator.url.scheme": "http" + }, + { + "anomali.limo.description": "TS ID: 55253484356; iType: mal_url; State: active; Org: Namecheap; Source: CyberCrime", + "anomali.limo.id": "indicator--da030e10-af9f-462d-bda8-33abb223e950", + "anomali.limo.labels": [ "malicious-activity", - "threatstream-confidence-90", + "threatstream-confidence-89", "threatstream-severity-medium" ], - "threatintel.anomali.modified": "2020-01-25T02:57:28.034Z", - "threatintel.anomali.name": "mal_url: http://104.168.99.170/login", - "threatintel.anomali.object_marking_refs": [ + "anomali.limo.modified": "2020-01-25T02:57:38.187Z", + "anomali.limo.name": "mal_url: http://officelog.org/inc/js/jstree/scan/panel/admin.php", + "anomali.limo.object_marking_refs": [ "marking-definition--34098fce-860f-48ae-8e50-ebd3cc5e41da" ], - "threatintel.anomali.pattern": "[url:value = 'http://104.168.99.170/login']", - "threatintel.anomali.type": "indicator", - "threatintel.anomali.valid_from": "2020-01-25T02:57:28.034Z", - "threatintel.indicator.first_seen": "2020-01-25T02:57:28.034Z", - "threatintel.indicator.provider": "CyberCrime", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "104.168.99.170", - "threatintel.indicator.url.full": "http://104.168.99.170/login", - "threatintel.indicator.url.original": "http://104.168.99.170/login", - "threatintel.indicator.url.path": "/login", - "threatintel.indicator.url.scheme": "http" - }, - { + "anomali.limo.pattern": "[url:value = 'http://officelog.org/inc/js/jstree/scan/panel/admin.php']", + "anomali.limo.type": "indicator", + "anomali.limo.valid_from": "2020-01-25T02:57:38.187Z", "event.category": "threat", "event.dataset": "threatintel.anomali", "event.kind": "enrichment", @@ -3407,32 +3588,34 @@ "threatstream-confidence-89", "threatstream-severity-medium" ], - "threatintel.anomali.description": "TS ID: 55253484356; iType: mal_url; State: active; Org: Namecheap; Source: CyberCrime", - "threatintel.anomali.id": "indicator--da030e10-af9f-462d-bda8-33abb223e950", - "threatintel.anomali.labels": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali Limo", + "threat.indicator.first_seen": "2020-01-25T02:57:38.187Z", + "threat.indicator.provider": "CyberCrime", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "officelog.org", + "threat.indicator.url.extension": "php", + "threat.indicator.url.full": "http://officelog.org/inc/js/jstree/scan/panel/admin.php", + "threat.indicator.url.original": "http://officelog.org/inc/js/jstree/scan/panel/admin.php", + "threat.indicator.url.path": "/inc/js/jstree/scan/panel/admin.php", + "threat.indicator.url.scheme": "http" + }, + { + "anomali.limo.description": "TS ID: 55253484343; iType: mal_url; State: active; Org: SPRINTHOST.RU - shared/premium hosting, VDS, dedic; Source: CyberCrime", + "anomali.limo.id": "indicator--d38e051a-bc5b-4723-884a-65e017d98299", + "anomali.limo.labels": [ "malicious-activity", - "threatstream-confidence-89", + "threatstream-confidence-65", "threatstream-severity-medium" ], - "threatintel.anomali.modified": "2020-01-25T02:57:38.187Z", - "threatintel.anomali.name": "mal_url: http://officelog.org/inc/js/jstree/scan/panel/admin.php", - "threatintel.anomali.object_marking_refs": [ + "anomali.limo.modified": "2020-01-25T02:57:38.214Z", + "anomali.limo.name": "mal_url: http://f0391587.xsph.ru/login", + "anomali.limo.object_marking_refs": [ "marking-definition--34098fce-860f-48ae-8e50-ebd3cc5e41da" ], - "threatintel.anomali.pattern": "[url:value = 'http://officelog.org/inc/js/jstree/scan/panel/admin.php']", - "threatintel.anomali.type": "indicator", - "threatintel.anomali.valid_from": "2020-01-25T02:57:38.187Z", - "threatintel.indicator.first_seen": "2020-01-25T02:57:38.187Z", - "threatintel.indicator.provider": "CyberCrime", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "officelog.org", - "threatintel.indicator.url.extension": "php", - "threatintel.indicator.url.full": "http://officelog.org/inc/js/jstree/scan/panel/admin.php", - "threatintel.indicator.url.original": "http://officelog.org/inc/js/jstree/scan/panel/admin.php", - "threatintel.indicator.url.path": "/inc/js/jstree/scan/panel/admin.php", - "threatintel.indicator.url.scheme": "http" - }, - { + "anomali.limo.pattern": "[url:value = 'http://f0391587.xsph.ru/login']", + "anomali.limo.type": "indicator", + "anomali.limo.valid_from": "2020-01-25T02:57:38.214Z", "event.category": "threat", "event.dataset": "threatintel.anomali", "event.kind": "enrichment", @@ -3449,31 +3632,33 @@ "threatstream-confidence-65", "threatstream-severity-medium" ], - "threatintel.anomali.description": "TS ID: 55253484343; iType: mal_url; State: active; Org: SPRINTHOST.RU - shared/premium hosting, VDS, dedic; Source: CyberCrime", - "threatintel.anomali.id": "indicator--d38e051a-bc5b-4723-884a-65e017d98299", - "threatintel.anomali.labels": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali Limo", + "threat.indicator.first_seen": "2020-01-25T02:57:38.214Z", + "threat.indicator.provider": "CyberCrime", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "f0391587.xsph.ru", + "threat.indicator.url.full": "http://f0391587.xsph.ru/login", + "threat.indicator.url.original": "http://f0391587.xsph.ru/login", + "threat.indicator.url.path": "/login", + "threat.indicator.url.scheme": "http" + }, + { + "anomali.limo.description": "TS ID: 55253484367; iType: mal_url; State: active; Org: Petersburg Internet Network ltd.; Source: CyberCrime", + "anomali.limo.id": "indicator--46491826-6ba1-4217-a35e-1eb0081a9e6a", + "anomali.limo.labels": [ "malicious-activity", - "threatstream-confidence-65", + "threatstream-confidence-67", "threatstream-severity-medium" ], - "threatintel.anomali.modified": "2020-01-25T02:57:38.214Z", - "threatintel.anomali.name": "mal_url: http://f0391587.xsph.ru/login", - "threatintel.anomali.object_marking_refs": [ + "anomali.limo.modified": "2020-01-25T02:57:47.281Z", + "anomali.limo.name": "mal_url: http://46.161.27.57:8080/northon/", + "anomali.limo.object_marking_refs": [ "marking-definition--34098fce-860f-48ae-8e50-ebd3cc5e41da" ], - "threatintel.anomali.pattern": "[url:value = 'http://f0391587.xsph.ru/login']", - "threatintel.anomali.type": "indicator", - "threatintel.anomali.valid_from": "2020-01-25T02:57:38.214Z", - "threatintel.indicator.first_seen": "2020-01-25T02:57:38.214Z", - "threatintel.indicator.provider": "CyberCrime", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "f0391587.xsph.ru", - "threatintel.indicator.url.full": "http://f0391587.xsph.ru/login", - "threatintel.indicator.url.original": "http://f0391587.xsph.ru/login", - "threatintel.indicator.url.path": "/login", - "threatintel.indicator.url.scheme": "http" - }, - { + "anomali.limo.pattern": "[url:value = 'http://46.161.27.57:8080/northon/']", + "anomali.limo.type": "indicator", + "anomali.limo.valid_from": "2020-01-25T02:57:47.281Z", "event.category": "threat", "event.dataset": "threatintel.anomali", "event.kind": "enrichment", @@ -3490,32 +3675,34 @@ "threatstream-confidence-67", "threatstream-severity-medium" ], - "threatintel.anomali.description": "TS ID: 55253484367; iType: mal_url; State: active; Org: Petersburg Internet Network ltd.; Source: CyberCrime", - "threatintel.anomali.id": "indicator--46491826-6ba1-4217-a35e-1eb0081a9e6a", - "threatintel.anomali.labels": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali Limo", + "threat.indicator.first_seen": "2020-01-25T02:57:47.281Z", + "threat.indicator.provider": "CyberCrime", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "46.161.27.57", + "threat.indicator.url.full": "http://46.161.27.57:8080/northon/", + "threat.indicator.url.original": "http://46.161.27.57:8080/northon/", + "threat.indicator.url.path": "/northon/", + "threat.indicator.url.port": 8080, + "threat.indicator.url.scheme": "http" + }, + { + "anomali.limo.description": "TS ID: 55253484342; iType: mal_url; State: active; Org: SPRINTHOST.RU - shared/premium hosting, VDS, dedic; Source: CyberCrime", + "anomali.limo.id": "indicator--b9715fd5-b89a-4859-b19f-55e052709227", + "anomali.limo.labels": [ "malicious-activity", - "threatstream-confidence-67", + "threatstream-confidence-79", "threatstream-severity-medium" ], - "threatintel.anomali.modified": "2020-01-25T02:57:47.281Z", - "threatintel.anomali.name": "mal_url: http://46.161.27.57:8080/northon/", - "threatintel.anomali.object_marking_refs": [ + "anomali.limo.modified": "2020-01-25T02:57:51.296Z", + "anomali.limo.name": "mal_url: http://f0393086.xsph.ru/login", + "anomali.limo.object_marking_refs": [ "marking-definition--34098fce-860f-48ae-8e50-ebd3cc5e41da" ], - "threatintel.anomali.pattern": "[url:value = 'http://46.161.27.57:8080/northon/']", - "threatintel.anomali.type": "indicator", - "threatintel.anomali.valid_from": "2020-01-25T02:57:47.281Z", - "threatintel.indicator.first_seen": "2020-01-25T02:57:47.281Z", - "threatintel.indicator.provider": "CyberCrime", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "46.161.27.57", - "threatintel.indicator.url.full": "http://46.161.27.57:8080/northon/", - "threatintel.indicator.url.original": "http://46.161.27.57:8080/northon/", - "threatintel.indicator.url.path": "/northon/", - "threatintel.indicator.url.port": 8080, - "threatintel.indicator.url.scheme": "http" - }, - { + "anomali.limo.pattern": "[url:value = 'http://f0393086.xsph.ru/login']", + "anomali.limo.type": "indicator", + "anomali.limo.valid_from": "2020-01-25T02:57:51.296Z", "event.category": "threat", "event.dataset": "threatintel.anomali", "event.kind": "enrichment", @@ -3532,31 +3719,33 @@ "threatstream-confidence-79", "threatstream-severity-medium" ], - "threatintel.anomali.description": "TS ID: 55253484342; iType: mal_url; State: active; Org: SPRINTHOST.RU - shared/premium hosting, VDS, dedic; Source: CyberCrime", - "threatintel.anomali.id": "indicator--b9715fd5-b89a-4859-b19f-55e052709227", - "threatintel.anomali.labels": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali Limo", + "threat.indicator.first_seen": "2020-01-25T02:57:51.296Z", + "threat.indicator.provider": "CyberCrime", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "f0393086.xsph.ru", + "threat.indicator.url.full": "http://f0393086.xsph.ru/login", + "threat.indicator.url.original": "http://f0393086.xsph.ru/login", + "threat.indicator.url.path": "/login", + "threat.indicator.url.scheme": "http" + }, + { + "anomali.limo.description": "TS ID: 55253484363; iType: mal_url; State: active; Org: ServerMania; Source: CyberCrime", + "anomali.limo.id": "indicator--e3177515-f481-46c8-bad8-582ba0858ef3", + "anomali.limo.labels": [ "malicious-activity", - "threatstream-confidence-79", + "threatstream-confidence-87", "threatstream-severity-medium" ], - "threatintel.anomali.modified": "2020-01-25T02:57:51.296Z", - "threatintel.anomali.name": "mal_url: http://f0393086.xsph.ru/login", - "threatintel.anomali.object_marking_refs": [ + "anomali.limo.modified": "2020-01-25T02:57:56.007Z", + "anomali.limo.name": "mal_url: http://insuncos.com/files1/panel/admin.php", + "anomali.limo.object_marking_refs": [ "marking-definition--34098fce-860f-48ae-8e50-ebd3cc5e41da" ], - "threatintel.anomali.pattern": "[url:value = 'http://f0393086.xsph.ru/login']", - "threatintel.anomali.type": "indicator", - "threatintel.anomali.valid_from": "2020-01-25T02:57:51.296Z", - "threatintel.indicator.first_seen": "2020-01-25T02:57:51.296Z", - "threatintel.indicator.provider": "CyberCrime", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "f0393086.xsph.ru", - "threatintel.indicator.url.full": "http://f0393086.xsph.ru/login", - "threatintel.indicator.url.original": "http://f0393086.xsph.ru/login", - "threatintel.indicator.url.path": "/login", - "threatintel.indicator.url.scheme": "http" - }, - { + "anomali.limo.pattern": "[url:value = 'http://insuncos.com/files1/panel/admin.php']", + "anomali.limo.type": "indicator", + "anomali.limo.valid_from": "2020-01-25T02:57:56.007Z", "event.category": "threat", "event.dataset": "threatintel.anomali", "event.kind": "enrichment", @@ -3573,32 +3762,34 @@ "threatstream-confidence-87", "threatstream-severity-medium" ], - "threatintel.anomali.description": "TS ID: 55253484363; iType: mal_url; State: active; Org: ServerMania; Source: CyberCrime", - "threatintel.anomali.id": "indicator--e3177515-f481-46c8-bad8-582ba0858ef3", - "threatintel.anomali.labels": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali Limo", + "threat.indicator.first_seen": "2020-01-25T02:57:56.007Z", + "threat.indicator.provider": "CyberCrime", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "insuncos.com", + "threat.indicator.url.extension": "php", + "threat.indicator.url.full": "http://insuncos.com/files1/panel/admin.php", + "threat.indicator.url.original": "http://insuncos.com/files1/panel/admin.php", + "threat.indicator.url.path": "/files1/panel/admin.php", + "threat.indicator.url.scheme": "http" + }, + { + "anomali.limo.description": "TS ID: 55253484339; iType: mal_url; State: active; Org: DDoS-GUARD GmbH; Source: CyberCrime", + "anomali.limo.id": "indicator--33cdeaeb-5201-4fbb-b9ae-9c23377e7533", + "anomali.limo.labels": [ "malicious-activity", - "threatstream-confidence-87", + "threatstream-confidence-89", "threatstream-severity-medium" ], - "threatintel.anomali.modified": "2020-01-25T02:57:56.007Z", - "threatintel.anomali.name": "mal_url: http://insuncos.com/files1/panel/admin.php", - "threatintel.anomali.object_marking_refs": [ + "anomali.limo.modified": "2020-01-25T02:57:56.044Z", + "anomali.limo.name": "mal_url: http://tg-h.ru/login", + "anomali.limo.object_marking_refs": [ "marking-definition--34098fce-860f-48ae-8e50-ebd3cc5e41da" ], - "threatintel.anomali.pattern": "[url:value = 'http://insuncos.com/files1/panel/admin.php']", - "threatintel.anomali.type": "indicator", - "threatintel.anomali.valid_from": "2020-01-25T02:57:56.007Z", - "threatintel.indicator.first_seen": "2020-01-25T02:57:56.007Z", - "threatintel.indicator.provider": "CyberCrime", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "insuncos.com", - "threatintel.indicator.url.extension": "php", - "threatintel.indicator.url.full": "http://insuncos.com/files1/panel/admin.php", - "threatintel.indicator.url.original": "http://insuncos.com/files1/panel/admin.php", - "threatintel.indicator.url.path": "/files1/panel/admin.php", - "threatintel.indicator.url.scheme": "http" - }, - { + "anomali.limo.pattern": "[url:value = 'http://tg-h.ru/login']", + "anomali.limo.type": "indicator", + "anomali.limo.valid_from": "2020-01-25T02:57:56.044Z", "event.category": "threat", "event.dataset": "threatintel.anomali", "event.kind": "enrichment", @@ -3615,31 +3806,33 @@ "threatstream-confidence-89", "threatstream-severity-medium" ], - "threatintel.anomali.description": "TS ID: 55253484339; iType: mal_url; State: active; Org: DDoS-GUARD GmbH; Source: CyberCrime", - "threatintel.anomali.id": "indicator--33cdeaeb-5201-4fbb-b9ae-9c23377e7533", - "threatintel.anomali.labels": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali Limo", + "threat.indicator.first_seen": "2020-01-25T02:57:56.044Z", + "threat.indicator.provider": "CyberCrime", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "tg-h.ru", + "threat.indicator.url.full": "http://tg-h.ru/login", + "threat.indicator.url.original": "http://tg-h.ru/login", + "threat.indicator.url.path": "/login", + "threat.indicator.url.scheme": "http" + }, + { + "anomali.limo.description": "TS ID: 55253484351; iType: mal_url; State: active; Org: ServerMania; Source: CyberCrime", + "anomali.limo.id": "indicator--2baaa5f0-c2f6-4bd1-b59d-3a75931da735", + "anomali.limo.labels": [ "malicious-activity", - "threatstream-confidence-89", + "threatstream-confidence-86", "threatstream-severity-medium" ], - "threatintel.anomali.modified": "2020-01-25T02:57:56.044Z", - "threatintel.anomali.name": "mal_url: http://tg-h.ru/login", - "threatintel.anomali.object_marking_refs": [ + "anomali.limo.modified": "2020-01-25T02:58:11.038Z", + "anomali.limo.name": "mal_url: http://wusetwo.xyz/public_html/file/five/inc/class/pCharts/info/Panel/five/PvqDq929BSx_A_D_M1n_a.php", + "anomali.limo.object_marking_refs": [ "marking-definition--34098fce-860f-48ae-8e50-ebd3cc5e41da" ], - "threatintel.anomali.pattern": "[url:value = 'http://tg-h.ru/login']", - "threatintel.anomali.type": "indicator", - "threatintel.anomali.valid_from": "2020-01-25T02:57:56.044Z", - "threatintel.indicator.first_seen": "2020-01-25T02:57:56.044Z", - "threatintel.indicator.provider": "CyberCrime", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "tg-h.ru", - "threatintel.indicator.url.full": "http://tg-h.ru/login", - "threatintel.indicator.url.original": "http://tg-h.ru/login", - "threatintel.indicator.url.path": "/login", - "threatintel.indicator.url.scheme": "http" - }, - { + "anomali.limo.pattern": "[url:value = 'http://wusetwo.xyz/public_html/file/five/inc/class/pCharts/info/Panel/five/PvqDq929BSx_A_D_M1n_a.php']", + "anomali.limo.type": "indicator", + "anomali.limo.valid_from": "2020-01-25T02:58:11.038Z", "event.category": "threat", "event.dataset": "threatintel.anomali", "event.kind": "enrichment", @@ -3656,32 +3849,34 @@ "threatstream-confidence-86", "threatstream-severity-medium" ], - "threatintel.anomali.description": "TS ID: 55253484351; iType: mal_url; State: active; Org: ServerMania; Source: CyberCrime", - "threatintel.anomali.id": "indicator--2baaa5f0-c2f6-4bd1-b59d-3a75931da735", - "threatintel.anomali.labels": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali Limo", + "threat.indicator.first_seen": "2020-01-25T02:58:11.038Z", + "threat.indicator.provider": "CyberCrime", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "wusetwo.xyz", + "threat.indicator.url.extension": "php", + "threat.indicator.url.full": "http://wusetwo.xyz/public_html/file/five/inc/class/pCharts/info/Panel/five/PvqDq929BSx_A_D_M1n_a.php", + "threat.indicator.url.original": "http://wusetwo.xyz/public_html/file/five/inc/class/pCharts/info/Panel/five/PvqDq929BSx_A_D_M1n_a.php", + "threat.indicator.url.path": "/public_html/file/five/inc/class/pCharts/info/Panel/five/PvqDq929BSx_A_D_M1n_a.php", + "threat.indicator.url.scheme": "http" + }, + { + "anomali.limo.description": "TS ID: 55253484366; iType: mal_url; State: active; Org: World Hosting Farm Limited; Source: CyberCrime", + "anomali.limo.id": "indicator--f1bdef49-666f-46b5-a323-efa1f1446b62", + "anomali.limo.labels": [ "malicious-activity", - "threatstream-confidence-86", + "threatstream-confidence-64", "threatstream-severity-medium" ], - "threatintel.anomali.modified": "2020-01-25T02:58:11.038Z", - "threatintel.anomali.name": "mal_url: http://wusetwo.xyz/public_html/file/five/inc/class/pCharts/info/Panel/five/PvqDq929BSx_A_D_M1n_a.php", - "threatintel.anomali.object_marking_refs": [ + "anomali.limo.modified": "2020-01-25T02:58:20.420Z", + "anomali.limo.name": "mal_url: http://185.234.217.36/northon/", + "anomali.limo.object_marking_refs": [ "marking-definition--34098fce-860f-48ae-8e50-ebd3cc5e41da" ], - "threatintel.anomali.pattern": "[url:value = 'http://wusetwo.xyz/public_html/file/five/inc/class/pCharts/info/Panel/five/PvqDq929BSx_A_D_M1n_a.php']", - "threatintel.anomali.type": "indicator", - "threatintel.anomali.valid_from": "2020-01-25T02:58:11.038Z", - "threatintel.indicator.first_seen": "2020-01-25T02:58:11.038Z", - "threatintel.indicator.provider": "CyberCrime", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "wusetwo.xyz", - "threatintel.indicator.url.extension": "php", - "threatintel.indicator.url.full": "http://wusetwo.xyz/public_html/file/five/inc/class/pCharts/info/Panel/five/PvqDq929BSx_A_D_M1n_a.php", - "threatintel.indicator.url.original": "http://wusetwo.xyz/public_html/file/five/inc/class/pCharts/info/Panel/five/PvqDq929BSx_A_D_M1n_a.php", - "threatintel.indicator.url.path": "/public_html/file/five/inc/class/pCharts/info/Panel/five/PvqDq929BSx_A_D_M1n_a.php", - "threatintel.indicator.url.scheme": "http" - }, - { + "anomali.limo.pattern": "[url:value = 'http://185.234.217.36/northon/']", + "anomali.limo.type": "indicator", + "anomali.limo.valid_from": "2020-01-25T02:58:20.42Z", "event.category": "threat", "event.dataset": "threatintel.anomali", "event.kind": "enrichment", @@ -3698,31 +3893,33 @@ "threatstream-confidence-64", "threatstream-severity-medium" ], - "threatintel.anomali.description": "TS ID: 55253484366; iType: mal_url; State: active; Org: World Hosting Farm Limited; Source: CyberCrime", - "threatintel.anomali.id": "indicator--f1bdef49-666f-46b5-a323-efa1f1446b62", - "threatintel.anomali.labels": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali Limo", + "threat.indicator.first_seen": "2020-01-25T02:58:20.420Z", + "threat.indicator.provider": "CyberCrime", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "185.234.217.36", + "threat.indicator.url.full": "http://185.234.217.36/northon/", + "threat.indicator.url.original": "http://185.234.217.36/northon/", + "threat.indicator.url.path": "/northon/", + "threat.indicator.url.scheme": "http" + }, + { + "anomali.limo.description": "TS ID: 55253484354; iType: mal_url; State: active; Org: McHost.Ru; Source: CyberCrime", + "anomali.limo.id": "indicator--a173f4b1-67ce-44f8-a6d0-bd8a24e8c593", + "anomali.limo.labels": [ "malicious-activity", - "threatstream-confidence-64", + "threatstream-confidence-84", "threatstream-severity-medium" ], - "threatintel.anomali.modified": "2020-01-25T02:58:20.420Z", - "threatintel.anomali.name": "mal_url: http://185.234.217.36/northon/", - "threatintel.anomali.object_marking_refs": [ + "anomali.limo.modified": "2020-01-25T02:58:20.448Z", + "anomali.limo.name": "mal_url: http://topik07.mcdir.ru/papka/admin.php", + "anomali.limo.object_marking_refs": [ "marking-definition--34098fce-860f-48ae-8e50-ebd3cc5e41da" ], - "threatintel.anomali.pattern": "[url:value = 'http://185.234.217.36/northon/']", - "threatintel.anomali.type": "indicator", - "threatintel.anomali.valid_from": "2020-01-25T02:58:20.42Z", - "threatintel.indicator.first_seen": "2020-01-25T02:58:20.420Z", - "threatintel.indicator.provider": "CyberCrime", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "185.234.217.36", - "threatintel.indicator.url.full": "http://185.234.217.36/northon/", - "threatintel.indicator.url.original": "http://185.234.217.36/northon/", - "threatintel.indicator.url.path": "/northon/", - "threatintel.indicator.url.scheme": "http" - }, - { + "anomali.limo.pattern": "[url:value = 'http://topik07.mcdir.ru/papka/admin.php']", + "anomali.limo.type": "indicator", + "anomali.limo.valid_from": "2020-01-25T02:58:20.448Z", "event.category": "threat", "event.dataset": "threatintel.anomali", "event.kind": "enrichment", @@ -3739,32 +3936,34 @@ "threatstream-confidence-84", "threatstream-severity-medium" ], - "threatintel.anomali.description": "TS ID: 55253484354; iType: mal_url; State: active; Org: McHost.Ru; Source: CyberCrime", - "threatintel.anomali.id": "indicator--a173f4b1-67ce-44f8-a6d0-bd8a24e8c593", - "threatintel.anomali.labels": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali Limo", + "threat.indicator.first_seen": "2020-01-25T02:58:20.448Z", + "threat.indicator.provider": "CyberCrime", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "topik07.mcdir.ru", + "threat.indicator.url.extension": "php", + "threat.indicator.url.full": "http://topik07.mcdir.ru/papka/admin.php", + "threat.indicator.url.original": "http://topik07.mcdir.ru/papka/admin.php", + "threat.indicator.url.path": "/papka/admin.php", + "threat.indicator.url.scheme": "http" + }, + { + "anomali.limo.description": "TS ID: 55253484362; iType: mal_url; State: active; Org: ServerMania; Source: CyberCrime", + "anomali.limo.id": "indicator--b53dded1-d293-4cd1-9e63-b6e0cbd850f0", + "anomali.limo.labels": [ "malicious-activity", - "threatstream-confidence-84", + "threatstream-confidence-87", "threatstream-severity-medium" ], - "threatintel.anomali.modified": "2020-01-25T02:58:20.448Z", - "threatintel.anomali.name": "mal_url: http://topik07.mcdir.ru/papka/admin.php", - "threatintel.anomali.object_marking_refs": [ + "anomali.limo.modified": "2020-01-25T02:58:33.189Z", + "anomali.limo.name": "mal_url: http://insuncos.com/files2/panel/admin.php", + "anomali.limo.object_marking_refs": [ "marking-definition--34098fce-860f-48ae-8e50-ebd3cc5e41da" ], - "threatintel.anomali.pattern": "[url:value = 'http://topik07.mcdir.ru/papka/admin.php']", - "threatintel.anomali.type": "indicator", - "threatintel.anomali.valid_from": "2020-01-25T02:58:20.448Z", - "threatintel.indicator.first_seen": "2020-01-25T02:58:20.448Z", - "threatintel.indicator.provider": "CyberCrime", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "topik07.mcdir.ru", - "threatintel.indicator.url.extension": "php", - "threatintel.indicator.url.full": "http://topik07.mcdir.ru/papka/admin.php", - "threatintel.indicator.url.original": "http://topik07.mcdir.ru/papka/admin.php", - "threatintel.indicator.url.path": "/papka/admin.php", - "threatintel.indicator.url.scheme": "http" - }, - { + "anomali.limo.pattern": "[url:value = 'http://insuncos.com/files2/panel/admin.php']", + "anomali.limo.type": "indicator", + "anomali.limo.valid_from": "2020-01-25T02:58:33.189Z", "event.category": "threat", "event.dataset": "threatintel.anomali", "event.kind": "enrichment", @@ -3781,32 +3980,34 @@ "threatstream-confidence-87", "threatstream-severity-medium" ], - "threatintel.anomali.description": "TS ID: 55253484362; iType: mal_url; State: active; Org: ServerMania; Source: CyberCrime", - "threatintel.anomali.id": "indicator--b53dded1-d293-4cd1-9e63-b6e0cbd850f0", - "threatintel.anomali.labels": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali Limo", + "threat.indicator.first_seen": "2020-01-25T02:58:33.189Z", + "threat.indicator.provider": "CyberCrime", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "insuncos.com", + "threat.indicator.url.extension": "php", + "threat.indicator.url.full": "http://insuncos.com/files2/panel/admin.php", + "threat.indicator.url.original": "http://insuncos.com/files2/panel/admin.php", + "threat.indicator.url.path": "/files2/panel/admin.php", + "threat.indicator.url.scheme": "http" + }, + { + "anomali.limo.description": "TS ID: 55253484364; iType: mal_url; State: active; Org: World Hosting Farm Limited; Source: CyberCrime", + "anomali.limo.id": "indicator--2b30f8fe-13e8-4a7d-8eba-3e59c288bef7", + "anomali.limo.labels": [ "malicious-activity", - "threatstream-confidence-87", + "threatstream-confidence-47", "threatstream-severity-medium" ], - "threatintel.anomali.modified": "2020-01-25T02:58:33.189Z", - "threatintel.anomali.name": "mal_url: http://insuncos.com/files2/panel/admin.php", - "threatintel.anomali.object_marking_refs": [ + "anomali.limo.modified": "2020-01-25T02:58:49.056Z", + "anomali.limo.name": "mal_url: http://185.234.218.68/kaspersky/", + "anomali.limo.object_marking_refs": [ "marking-definition--34098fce-860f-48ae-8e50-ebd3cc5e41da" ], - "threatintel.anomali.pattern": "[url:value = 'http://insuncos.com/files2/panel/admin.php']", - "threatintel.anomali.type": "indicator", - "threatintel.anomali.valid_from": "2020-01-25T02:58:33.189Z", - "threatintel.indicator.first_seen": "2020-01-25T02:58:33.189Z", - "threatintel.indicator.provider": "CyberCrime", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "insuncos.com", - "threatintel.indicator.url.extension": "php", - "threatintel.indicator.url.full": "http://insuncos.com/files2/panel/admin.php", - "threatintel.indicator.url.original": "http://insuncos.com/files2/panel/admin.php", - "threatintel.indicator.url.path": "/files2/panel/admin.php", - "threatintel.indicator.url.scheme": "http" - }, - { + "anomali.limo.pattern": "[url:value = 'http://185.234.218.68/kaspersky/']", + "anomali.limo.type": "indicator", + "anomali.limo.valid_from": "2020-01-25T02:58:49.056Z", "event.category": "threat", "event.dataset": "threatintel.anomali", "event.kind": "enrichment", @@ -3823,31 +4024,33 @@ "threatstream-confidence-47", "threatstream-severity-medium" ], - "threatintel.anomali.description": "TS ID: 55253484364; iType: mal_url; State: active; Org: World Hosting Farm Limited; Source: CyberCrime", - "threatintel.anomali.id": "indicator--2b30f8fe-13e8-4a7d-8eba-3e59c288bef7", - "threatintel.anomali.labels": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali Limo", + "threat.indicator.first_seen": "2020-01-25T02:58:49.056Z", + "threat.indicator.provider": "CyberCrime", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "185.234.218.68", + "threat.indicator.url.full": "http://185.234.218.68/kaspersky/", + "threat.indicator.url.original": "http://185.234.218.68/kaspersky/", + "threat.indicator.url.path": "/kaspersky/", + "threat.indicator.url.scheme": "http" + }, + { + "anomali.limo.description": "TS ID: 55253484357; iType: mal_url; State: active; Org: Namecheap; Source: CyberCrime", + "anomali.limo.id": "indicator--f502199a-17a4-404b-a114-fb5eda28c32c", + "anomali.limo.labels": [ "malicious-activity", - "threatstream-confidence-47", + "threatstream-confidence-89", "threatstream-severity-medium" ], - "threatintel.anomali.modified": "2020-01-25T02:58:49.056Z", - "threatintel.anomali.name": "mal_url: http://185.234.218.68/kaspersky/", - "threatintel.anomali.object_marking_refs": [ + "anomali.limo.modified": "2020-01-25T02:58:59.472Z", + "anomali.limo.name": "mal_url: http://officelog.org/inc/js/jstree/mh/panel/admin.php", + "anomali.limo.object_marking_refs": [ "marking-definition--34098fce-860f-48ae-8e50-ebd3cc5e41da" ], - "threatintel.anomali.pattern": "[url:value = 'http://185.234.218.68/kaspersky/']", - "threatintel.anomali.type": "indicator", - "threatintel.anomali.valid_from": "2020-01-25T02:58:49.056Z", - "threatintel.indicator.first_seen": "2020-01-25T02:58:49.056Z", - "threatintel.indicator.provider": "CyberCrime", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "185.234.218.68", - "threatintel.indicator.url.full": "http://185.234.218.68/kaspersky/", - "threatintel.indicator.url.original": "http://185.234.218.68/kaspersky/", - "threatintel.indicator.url.path": "/kaspersky/", - "threatintel.indicator.url.scheme": "http" - }, - { + "anomali.limo.pattern": "[url:value = 'http://officelog.org/inc/js/jstree/mh/panel/admin.php']", + "anomali.limo.type": "indicator", + "anomali.limo.valid_from": "2020-01-25T02:58:59.472Z", "event.category": "threat", "event.dataset": "threatintel.anomali", "event.kind": "enrichment", @@ -3864,32 +4067,34 @@ "threatstream-confidence-89", "threatstream-severity-medium" ], - "threatintel.anomali.description": "TS ID: 55253484357; iType: mal_url; State: active; Org: Namecheap; Source: CyberCrime", - "threatintel.anomali.id": "indicator--f502199a-17a4-404b-a114-fb5eda28c32c", - "threatintel.anomali.labels": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali Limo", + "threat.indicator.first_seen": "2020-01-25T02:58:59.472Z", + "threat.indicator.provider": "CyberCrime", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "officelog.org", + "threat.indicator.url.extension": "php", + "threat.indicator.url.full": "http://officelog.org/inc/js/jstree/mh/panel/admin.php", + "threat.indicator.url.original": "http://officelog.org/inc/js/jstree/mh/panel/admin.php", + "threat.indicator.url.path": "/inc/js/jstree/mh/panel/admin.php", + "threat.indicator.url.scheme": "http" + }, + { + "anomali.limo.description": "TS ID: 55253484359; iType: mal_url; State: active; Org: Namecheap; Source: CyberCrime", + "anomali.limo.id": "indicator--af7422eb-5d8e-4878-bdd1-395313434dae", + "anomali.limo.labels": [ "malicious-activity", "threatstream-confidence-89", "threatstream-severity-medium" ], - "threatintel.anomali.modified": "2020-01-25T02:58:59.472Z", - "threatintel.anomali.name": "mal_url: http://officelog.org/inc/js/jstree/mh/panel/admin.php", - "threatintel.anomali.object_marking_refs": [ + "anomali.limo.modified": "2020-01-25T02:59:27.070Z", + "anomali.limo.name": "mal_url: http://officelog.org/inc/js/jstree/ch/panel/admin.php", + "anomali.limo.object_marking_refs": [ "marking-definition--34098fce-860f-48ae-8e50-ebd3cc5e41da" ], - "threatintel.anomali.pattern": "[url:value = 'http://officelog.org/inc/js/jstree/mh/panel/admin.php']", - "threatintel.anomali.type": "indicator", - "threatintel.anomali.valid_from": "2020-01-25T02:58:59.472Z", - "threatintel.indicator.first_seen": "2020-01-25T02:58:59.472Z", - "threatintel.indicator.provider": "CyberCrime", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "officelog.org", - "threatintel.indicator.url.extension": "php", - "threatintel.indicator.url.full": "http://officelog.org/inc/js/jstree/mh/panel/admin.php", - "threatintel.indicator.url.original": "http://officelog.org/inc/js/jstree/mh/panel/admin.php", - "threatintel.indicator.url.path": "/inc/js/jstree/mh/panel/admin.php", - "threatintel.indicator.url.scheme": "http" - }, - { + "anomali.limo.pattern": "[url:value = 'http://officelog.org/inc/js/jstree/ch/panel/admin.php']", + "anomali.limo.type": "indicator", + "anomali.limo.valid_from": "2020-01-25T02:59:27.07Z", "event.category": "threat", "event.dataset": "threatintel.anomali", "event.kind": "enrichment", @@ -3906,32 +4111,34 @@ "threatstream-confidence-89", "threatstream-severity-medium" ], - "threatintel.anomali.description": "TS ID: 55253484359; iType: mal_url; State: active; Org: Namecheap; Source: CyberCrime", - "threatintel.anomali.id": "indicator--af7422eb-5d8e-4878-bdd1-395313434dae", - "threatintel.anomali.labels": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali Limo", + "threat.indicator.first_seen": "2020-01-25T02:59:27.070Z", + "threat.indicator.provider": "CyberCrime", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "officelog.org", + "threat.indicator.url.extension": "php", + "threat.indicator.url.full": "http://officelog.org/inc/js/jstree/ch/panel/admin.php", + "threat.indicator.url.original": "http://officelog.org/inc/js/jstree/ch/panel/admin.php", + "threat.indicator.url.path": "/inc/js/jstree/ch/panel/admin.php", + "threat.indicator.url.scheme": "http" + }, + { + "anomali.limo.description": "TS ID: 55253484358; iType: mal_url; State: active; Org: Namecheap; Source: CyberCrime", + "anomali.limo.id": "indicator--71b36c05-86dd-4685-81c0-5a99e2e14c23", + "anomali.limo.labels": [ "malicious-activity", "threatstream-confidence-89", "threatstream-severity-medium" ], - "threatintel.anomali.modified": "2020-01-25T02:59:27.070Z", - "threatintel.anomali.name": "mal_url: http://officelog.org/inc/js/jstree/ch/panel/admin.php", - "threatintel.anomali.object_marking_refs": [ + "anomali.limo.modified": "2020-01-25T02:59:28.967Z", + "anomali.limo.name": "mal_url: http://officelog.org/inc/js/jstree/dar/panel/admin.php", + "anomali.limo.object_marking_refs": [ "marking-definition--34098fce-860f-48ae-8e50-ebd3cc5e41da" ], - "threatintel.anomali.pattern": "[url:value = 'http://officelog.org/inc/js/jstree/ch/panel/admin.php']", - "threatintel.anomali.type": "indicator", - "threatintel.anomali.valid_from": "2020-01-25T02:59:27.07Z", - "threatintel.indicator.first_seen": "2020-01-25T02:59:27.070Z", - "threatintel.indicator.provider": "CyberCrime", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "officelog.org", - "threatintel.indicator.url.extension": "php", - "threatintel.indicator.url.full": "http://officelog.org/inc/js/jstree/ch/panel/admin.php", - "threatintel.indicator.url.original": "http://officelog.org/inc/js/jstree/ch/panel/admin.php", - "threatintel.indicator.url.path": "/inc/js/jstree/ch/panel/admin.php", - "threatintel.indicator.url.scheme": "http" - }, - { + "anomali.limo.pattern": "[url:value = 'http://officelog.org/inc/js/jstree/dar/panel/admin.php']", + "anomali.limo.type": "indicator", + "anomali.limo.valid_from": "2020-01-25T02:59:28.967Z", "event.category": "threat", "event.dataset": "threatintel.anomali", "event.kind": "enrichment", @@ -3948,32 +4155,34 @@ "threatstream-confidence-89", "threatstream-severity-medium" ], - "threatintel.anomali.description": "TS ID: 55253484358; iType: mal_url; State: active; Org: Namecheap; Source: CyberCrime", - "threatintel.anomali.id": "indicator--71b36c05-86dd-4685-81c0-5a99e2e14c23", - "threatintel.anomali.labels": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali Limo", + "threat.indicator.first_seen": "2020-01-25T02:59:28.967Z", + "threat.indicator.provider": "CyberCrime", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "officelog.org", + "threat.indicator.url.extension": "php", + "threat.indicator.url.full": "http://officelog.org/inc/js/jstree/dar/panel/admin.php", + "threat.indicator.url.original": "http://officelog.org/inc/js/jstree/dar/panel/admin.php", + "threat.indicator.url.path": "/inc/js/jstree/dar/panel/admin.php", + "threat.indicator.url.scheme": "http" + }, + { + "anomali.limo.description": "TS ID: 55253484352; iType: mal_url; State: active; Org: Best-Hoster Group Co. Ltd.; Source: CyberCrime", + "anomali.limo.id": "indicator--9d948509-dfb4-45b6-b8bc-780df88a213f", + "anomali.limo.labels": [ "malicious-activity", - "threatstream-confidence-89", + "threatstream-confidence-81", "threatstream-severity-medium" ], - "threatintel.anomali.modified": "2020-01-25T02:59:28.967Z", - "threatintel.anomali.name": "mal_url: http://officelog.org/inc/js/jstree/dar/panel/admin.php", - "threatintel.anomali.object_marking_refs": [ + "anomali.limo.modified": "2020-01-25T02:59:37.661Z", + "anomali.limo.name": "mal_url: http://oaa-my.com/cage/five/PvqDq929BSx_A_D_M1n_a.php", + "anomali.limo.object_marking_refs": [ "marking-definition--34098fce-860f-48ae-8e50-ebd3cc5e41da" ], - "threatintel.anomali.pattern": "[url:value = 'http://officelog.org/inc/js/jstree/dar/panel/admin.php']", - "threatintel.anomali.type": "indicator", - "threatintel.anomali.valid_from": "2020-01-25T02:59:28.967Z", - "threatintel.indicator.first_seen": "2020-01-25T02:59:28.967Z", - "threatintel.indicator.provider": "CyberCrime", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "officelog.org", - "threatintel.indicator.url.extension": "php", - "threatintel.indicator.url.full": "http://officelog.org/inc/js/jstree/dar/panel/admin.php", - "threatintel.indicator.url.original": "http://officelog.org/inc/js/jstree/dar/panel/admin.php", - "threatintel.indicator.url.path": "/inc/js/jstree/dar/panel/admin.php", - "threatintel.indicator.url.scheme": "http" - }, - { + "anomali.limo.pattern": "[url:value = 'http://oaa-my.com/cage/five/PvqDq929BSx_A_D_M1n_a.php']", + "anomali.limo.type": "indicator", + "anomali.limo.valid_from": "2020-01-25T02:59:37.661Z", "event.category": "threat", "event.dataset": "threatintel.anomali", "event.kind": "enrichment", @@ -3990,32 +4199,34 @@ "threatstream-confidence-81", "threatstream-severity-medium" ], - "threatintel.anomali.description": "TS ID: 55253484352; iType: mal_url; State: active; Org: Best-Hoster Group Co. Ltd.; Source: CyberCrime", - "threatintel.anomali.id": "indicator--9d948509-dfb4-45b6-b8bc-780df88a213f", - "threatintel.anomali.labels": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali Limo", + "threat.indicator.first_seen": "2020-01-25T02:59:37.661Z", + "threat.indicator.provider": "CyberCrime", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "oaa-my.com", + "threat.indicator.url.extension": "php", + "threat.indicator.url.full": "http://oaa-my.com/cage/five/PvqDq929BSx_A_D_M1n_a.php", + "threat.indicator.url.original": "http://oaa-my.com/cage/five/PvqDq929BSx_A_D_M1n_a.php", + "threat.indicator.url.path": "/cage/five/PvqDq929BSx_A_D_M1n_a.php", + "threat.indicator.url.scheme": "http" + }, + { + "anomali.limo.description": "TS ID: 55253484224; iType: mal_ip; State: active; Org: Namecheap; Source: CyberCrime", + "anomali.limo.id": "indicator--9f613f8e-2040-4eee-8044-044023a8093e", + "anomali.limo.labels": [ "malicious-activity", - "threatstream-confidence-81", + "threatstream-confidence-53", "threatstream-severity-medium" ], - "threatintel.anomali.modified": "2020-01-25T02:59:37.661Z", - "threatintel.anomali.name": "mal_url: http://oaa-my.com/cage/five/PvqDq929BSx_A_D_M1n_a.php", - "threatintel.anomali.object_marking_refs": [ + "anomali.limo.modified": "2020-01-25T02:59:37.692Z", + "anomali.limo.name": "mal_ip: 192.64.118.56", + "anomali.limo.object_marking_refs": [ "marking-definition--34098fce-860f-48ae-8e50-ebd3cc5e41da" ], - "threatintel.anomali.pattern": "[url:value = 'http://oaa-my.com/cage/five/PvqDq929BSx_A_D_M1n_a.php']", - "threatintel.anomali.type": "indicator", - "threatintel.anomali.valid_from": "2020-01-25T02:59:37.661Z", - "threatintel.indicator.first_seen": "2020-01-25T02:59:37.661Z", - "threatintel.indicator.provider": "CyberCrime", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "oaa-my.com", - "threatintel.indicator.url.extension": "php", - "threatintel.indicator.url.full": "http://oaa-my.com/cage/five/PvqDq929BSx_A_D_M1n_a.php", - "threatintel.indicator.url.original": "http://oaa-my.com/cage/five/PvqDq929BSx_A_D_M1n_a.php", - "threatintel.indicator.url.path": "/cage/five/PvqDq929BSx_A_D_M1n_a.php", - "threatintel.indicator.url.scheme": "http" - }, - { + "anomali.limo.pattern": "[ipv4-addr:value = '192.64.118.56']", + "anomali.limo.type": "indicator", + "anomali.limo.valid_from": "2020-01-25T02:59:37.692Z", "event.category": "threat", "event.dataset": "threatintel.anomali", "event.kind": "enrichment", @@ -4032,27 +4243,29 @@ "threatstream-confidence-53", "threatstream-severity-medium" ], - "threatintel.anomali.description": "TS ID: 55253484224; iType: mal_ip; State: active; Org: Namecheap; Source: CyberCrime", - "threatintel.anomali.id": "indicator--9f613f8e-2040-4eee-8044-044023a8093e", - "threatintel.anomali.labels": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali Limo", + "threat.indicator.first_seen": "2020-01-25T02:59:37.692Z", + "threat.indicator.ip": "192.64.118.56", + "threat.indicator.provider": "CyberCrime", + "threat.indicator.type": "ipv4-addr" + }, + { + "anomali.limo.description": "TS ID: 55253484361; iType: mal_url; State: active; Org: ServerMania; Source: CyberCrime", + "anomali.limo.id": "indicator--518c3959-6c26-413f-9a5f-c8f76d86185a", + "anomali.limo.labels": [ "malicious-activity", - "threatstream-confidence-53", + "threatstream-confidence-87", "threatstream-severity-medium" ], - "threatintel.anomali.modified": "2020-01-25T02:59:37.692Z", - "threatintel.anomali.name": "mal_ip: 192.64.118.56", - "threatintel.anomali.object_marking_refs": [ + "anomali.limo.modified": "2020-01-25T02:59:54.296Z", + "anomali.limo.name": "mal_url: http://insuncos.com/files3/panel/admin.php", + "anomali.limo.object_marking_refs": [ "marking-definition--34098fce-860f-48ae-8e50-ebd3cc5e41da" ], - "threatintel.anomali.pattern": "[ipv4-addr:value = '192.64.118.56']", - "threatintel.anomali.type": "indicator", - "threatintel.anomali.valid_from": "2020-01-25T02:59:37.692Z", - "threatintel.indicator.first_seen": "2020-01-25T02:59:37.692Z", - "threatintel.indicator.ip": "192.64.118.56", - "threatintel.indicator.provider": "CyberCrime", - "threatintel.indicator.type": "ipv4-addr" - }, - { + "anomali.limo.pattern": "[url:value = 'http://insuncos.com/files3/panel/admin.php']", + "anomali.limo.type": "indicator", + "anomali.limo.valid_from": "2020-01-25T02:59:54.296Z", "event.category": "threat", "event.dataset": "threatintel.anomali", "event.kind": "enrichment", @@ -4069,29 +4282,16 @@ "threatstream-confidence-87", "threatstream-severity-medium" ], - "threatintel.anomali.description": "TS ID: 55253484361; iType: mal_url; State: active; Org: ServerMania; Source: CyberCrime", - "threatintel.anomali.id": "indicator--518c3959-6c26-413f-9a5f-c8f76d86185a", - "threatintel.anomali.labels": [ - "malicious-activity", - "threatstream-confidence-87", - "threatstream-severity-medium" - ], - "threatintel.anomali.modified": "2020-01-25T02:59:54.296Z", - "threatintel.anomali.name": "mal_url: http://insuncos.com/files3/panel/admin.php", - "threatintel.anomali.object_marking_refs": [ - "marking-definition--34098fce-860f-48ae-8e50-ebd3cc5e41da" - ], - "threatintel.anomali.pattern": "[url:value = 'http://insuncos.com/files3/panel/admin.php']", - "threatintel.anomali.type": "indicator", - "threatintel.anomali.valid_from": "2020-01-25T02:59:54.296Z", - "threatintel.indicator.first_seen": "2020-01-25T02:59:54.296Z", - "threatintel.indicator.provider": "CyberCrime", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "insuncos.com", - "threatintel.indicator.url.extension": "php", - "threatintel.indicator.url.full": "http://insuncos.com/files3/panel/admin.php", - "threatintel.indicator.url.original": "http://insuncos.com/files3/panel/admin.php", - "threatintel.indicator.url.path": "/files3/panel/admin.php", - "threatintel.indicator.url.scheme": "http" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali Limo", + "threat.indicator.first_seen": "2020-01-25T02:59:54.296Z", + "threat.indicator.provider": "CyberCrime", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "insuncos.com", + "threat.indicator.url.extension": "php", + "threat.indicator.url.full": "http://insuncos.com/files3/panel/admin.php", + "threat.indicator.url.original": "http://insuncos.com/files3/panel/admin.php", + "threat.indicator.url.path": "/files3/panel/admin.php", + "threat.indicator.url.scheme": "http" } ] \ No newline at end of file diff --git a/x-pack/filebeat/module/threatintel/anomalithreatstream/_meta/fields.yml b/x-pack/filebeat/module/threatintel/anomalithreatstream/_meta/fields.yml index de0ededab33..41fae21921c 100644 --- a/x-pack/filebeat/module/threatintel/anomalithreatstream/_meta/fields.yml +++ b/x-pack/filebeat/module/threatintel/anomalithreatstream/_meta/fields.yml @@ -1,4 +1,4 @@ -- name: anomalithreatstream +- name: anomali.threatstream type: group description: > Fields for Anomali ThreatStream diff --git a/x-pack/filebeat/module/threatintel/anomalithreatstream/config/config.yml b/x-pack/filebeat/module/threatintel/anomalithreatstream/config/config.yml index f6cfe024305..4d814c03fe5 100644 --- a/x-pack/filebeat/module/threatintel/anomalithreatstream/config/config.yml +++ b/x-pack/filebeat/module/threatintel/anomalithreatstream/config/config.yml @@ -1,7 +1,6 @@ {{ if eq .input "http_endpoint" }} type: http_endpoint -enabled: true listen_address: {{ .listen_address }} listen_port: {{ .listen_port }} @@ -16,12 +15,12 @@ hmac: prefix: sha256= {{ end }} -{{ if .ssl_certificate }} -ssl: - enabled: true - certificate: {{ .ssl_certificate }} - key: {{ .ssl_key }} - verification_mode: none +{{ if .ssl }} +ssl: {{ .ssl | tojson }} +{{ end }} + +{{ if .preserve_original_event }} +preserve_original_event: true {{ end }} {{ else if eq .input "file" }} @@ -35,24 +34,12 @@ exclude_files: [".gz$"] json.add_error_key: true {{ end }} -tags: {{.tags | tojson}} - -processors: - - add_fields: - target: '' - fields: - ecs.version: 1.12.0 - - fingerprint: - fields: - - event.dataset - - json.id - target_field: '@metadata._id' - encoding: base64 - - script: - lang: javascript - id: my_filter - source: > - function process(event) { - event.Put("@metadata.op_type", "index"); - } +tags: +{{if .preserve_original_event}} + - preserve_original_event +{{end}} +{{range $val := .tags}} + - {{$val}} +{{end}} +publisher_pipeline.disable_host: {{ inList .tags "forwarded" }} diff --git a/x-pack/filebeat/module/threatintel/anomalithreatstream/ingest/pipeline.yml b/x-pack/filebeat/module/threatintel/anomalithreatstream/ingest/pipeline.yml index 22644d79518..50b5c6c7bb2 100644 --- a/x-pack/filebeat/module/threatintel/anomalithreatstream/ingest/pipeline.yml +++ b/x-pack/filebeat/module/threatintel/anomalithreatstream/ingest/pipeline.yml @@ -1,19 +1,21 @@ +--- description: Pipeline for parsing Anomali ThreatStream processors: - # - # Safeguard against feeding the pipeline with documents other - # that the ones generated by Filebeat's http_endpoint input. - # - - fail: - if: "ctx.json == null || !(ctx.json instanceof Map)" - message: "missing json object in input document" - # # Set basic ECS fields. # - set: field: event.ingested value: "{{{ _ingest.timestamp }}}" + - set: + field: ecs.version + value: "1.12" + - fingerprint: + fields: + - event.dataset + - json.id + target_field: "_id" + ignore_missing: true - set: field: event.kind value: enrichment @@ -24,14 +26,21 @@ processors: field: event.type value: indicator + - set: + field: threat.feed.name + value: "[Filebeat] Anomali ThreatStream" + - set: + field: threat.feed.dashboard_id + value: "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f" + # - # Map itype field to STIX 2.0 Cyber Observable values (threatintel.indicator.type). + # Map itype field to STIX 2.0 Cyber Observable values (threat.indicator.type). # - script: lang: painless if: "ctx.json.itype != null" description: > - Map itype field to STIX 2.0 Cyber Observable values (threatintel.indicator.type). + Map itype field to STIX 2.0 Cyber Observable values (threat.indicator.type). params: actor_ip: ipv4-addr adware_domain: domain-name @@ -125,26 +134,26 @@ processors: - rename: field: threatintel_indicator_type - target_field: threatintel.indicator.type + target_field: threat.indicator.type ignore_missing: true # # Detect ipv6 for ipv4-addr types. # - set: - field: threatintel.indicator.type + field: threat.indicator.type value: ipv6-addr - if: 'ctx.threatintel?.indicator?.type == "ipv4-addr" && ctx.json.srcip != null && ctx.json.srcip.contains(":")' + if: 'ctx.threat?.indicator?.type == "ipv4-addr" && ctx.json?.srcip != null && ctx.json.srcip.contains(":")' # # Map first and last seen dates. # - date: field: json.date_first - target_field: threatintel.indicator.first_seen + target_field: threat.indicator.first_seen formats: - ISO8601 - if: "ctx.json.date_first != null" + if: "ctx.json?.date_first != null" on_failure: - append: field: error.message @@ -152,10 +161,10 @@ processors: - date: field: json.date_last - target_field: threatintel.indicator.last_seen + target_field: threat.indicator.last_seen formats: - ISO8601 - if: "ctx.json.date_last != null" + if: "ctx.json?.date_last != null" on_failure: - append: field: error.message @@ -166,18 +175,18 @@ processors: # - convert: field: json.lat - target_field: threatintel.indicator.geo.location.lat + target_field: threat.indicator.geo.location.lat type: double - if: "ctx.json.lat != null && ctx.json.lon != null" + if: "ctx.json?.lat != null && ctx.json?.lon != null" on_failure: - append: field: error.message value: 'Cannot convert lat field "{{{ json.lat }}}" to double: {{{ _ingest.on_failure_message }}}' - convert: field: json.lon - target_field: threatintel.indicator.geo.location.lon + target_field: threat.indicator.geo.location.lon type: double - if: "ctx.json.lat != null && ctx.json.lon != null" + if: "ctx.json?.lat != null && ctx.json?.lon != null" on_failure: - append: field: error.message @@ -190,25 +199,40 @@ processors: # private => Amber ("Limited disclosure, restricted to participants’ organizations."). # - append: - field: threatintel.indicator.marking.tlp + field: threat.indicator.marking.tlp value: Amber - if: 'ctx.json.classification == "private"' + if: 'ctx.json?.classification == "private"' - append: - field: threatintel.indicator.marking.tlp + field: threat.indicator.marking.tlp value: White - if: 'ctx.json.classification == "public"' + if: 'ctx.json?.classification == "public"' # # Convert confidence field (-1..100) to ECS confidence (0..10). # - script: lang: painless + if: ctx.json?.confidence != null description: > Normalize confidence level. source: > def value = ctx.json.confidence; - if (value == null || value < 0.0 || value > 100.0) return; - ctx["threatintel_indicator_confidence"] = (long)Math.round((double)value / 10.0); + if (value <= 0.0 || value > 100.0) { + ctx["threatintel_indicator_confidence"] = "None"; + return; + } + if (value >= 1.0 && value <= 29.0) { + ctx["threatintel_indicator_confidence"] = "Low"; + return; + } + if (value >= 30.0 && value <= 69.0) { + ctx["threatintel_indicator_confidence"] = "Med"; + return; + } + if (value >= 70 && value <= 100) { + ctx["threatintel_indicator_confidence"] = "High"; + return; + } on_failure: - append: field: error.message @@ -216,7 +240,7 @@ processors: - rename: field: threatintel_indicator_confidence - target_field: threatintel.indicator.confidence + target_field: threat.indicator.confidence ignore_missing: true # @@ -224,7 +248,7 @@ processors: # - convert: field: json.asn - target_field: threatintel.indicator.as.number + target_field: threat.indicator.as.number type: long ignore_missing: true on_failure: @@ -234,41 +258,41 @@ processors: - rename: field: json.org - target_field: threatintel.indicator.as.organization.name + target_field: threat.indicator.as.organization.name ignore_missing: true - rename: field: json.email - target_field: threatintel.indicator.email.address + target_field: threat.indicator.email.address ignore_missing: true - rename: field: json.srcip - target_field: threatintel.indicator.ip + target_field: threat.indicator.ip ignore_missing: true - uri_parts: field: json.url - target_field: threatintel.indicator.url + target_field: threat.indicator.url keep_original: true remove_if_successful: true - if: "ctx.json.url != null" + if: "ctx.json?.url != null" on_failure: - append: field: error.message value: "Cannot parse url field `{{{ json.url }}}`: {{{ _ingest.on_failure_message }}}" - set: - field: threatintel.indicator.url.full - value: "{{{threatintel.indicator.url.original}}}" + field: threat.indicator.url.full + value: "{{{threat.indicator.url.original}}}" ignore_empty_value: true - rename: field: json.domain - target_field: threatintel.indicator.url.domain + target_field: threat.indicator.url.domain ignore_missing: true - if: ctx.threatintel?.indicator?.url?.domain == null + if: ctx.threat?.indicator?.url?.domain == null - rename: field: json.country - target_field: threatintel.indicator.geo.country_iso_code + target_field: threat.indicator.geo.country_iso_code ignore_missing: true # @@ -277,27 +301,27 @@ processors: # - rename: field: json.md5 - target_field: threatintel.indicator.file.hash.md5 - if: "ctx.json.md5 != null && ctx.json.md5.length() == 32" + target_field: threat.indicator.file.hash.md5 + if: "ctx.json?.md5 != null && ctx.json.md5.length() == 32" - rename: field: json.md5 - target_field: threatintel.indicator.file.hash.sha1 - if: "ctx.json.md5 != null && ctx.json.md5.length() == 40" + target_field: threat.indicator.file.hash.sha1 + if: "ctx.json?.md5 != null && ctx.json.md5.length() == 40" - rename: field: json.md5 - target_field: threatintel.indicator.file.hash.sha256 - if: "ctx.json.md5 != null && ctx.json.md5.length() == 64" + target_field: threat.indicator.file.hash.sha256 + if: "ctx.json?.md5 != null && ctx.json.md5.length() == 64" - rename: field: json.md5 - target_field: threatintel.indicator.file.hash.sha512 - if: "ctx.json.md5 != null && ctx.json.md5.length() == 128" + target_field: threat.indicator.file.hash.sha512 + if: "ctx.json?.md5 != null && ctx.json.md5.length() == 128" - rename: field: json.source - target_field: threatintel.indicator.provider + target_field: threat.indicator.provider ignore_missing: true # @@ -310,22 +334,22 @@ processors: - set: field: event.severity value: 3 - if: 'ctx.json.severity == "low"' + if: 'ctx.json?.severity == "low"' - set: field: event.severity value: 5 - if: 'ctx.json.severity == "medium"' + if: 'ctx.json?.severity == "medium"' - set: field: event.severity value: 7 - if: 'ctx.json.severity == "high"' + if: 'ctx.json?.severity == "high"' - set: field: event.severity value: 9 - if: 'ctx.json.severity == "very-high"' + if: 'ctx.json?.severity == "very-high"' # # Field trusted_circles_ids is a comma-separated string @@ -335,24 +359,16 @@ processors: # - script: lang: painless - if: "ctx.json.trusted_circle_ids != null && ctx.json.trusted_circle_ids instanceof String" + if: "ctx.json?.trusted_circle_ids != null && ctx.json?.trusted_circle_ids instanceof String" description: > Convert trusted_circles_ids from CSV to an array. source: > - def lst = - Stream.of(ctx.json.trusted_circle_ids.splitOnToken(",")) - .filter(s -> !s.isEmpty()) - .toArray(String[]::new); - if (lst.length > 0) { + def lst = Stream.of(ctx.json.trusted_circle_ids.splitOnToken(',')).filter(s -> !s.isEmpty()).collect(Collectors.toList()); + if (lst.size() > 0) { ctx.json.trusted_circle_ids = lst; } else { ctx.json.remove('trusted_circle_ids'); } - on_failure: - - append: - field: error.message - value: 'unable to split trusted_circle_ids "{{{ json.trusted_circle_ids }}}": {{{ _ingest.on_failure_message }}}' - # # Split detail field and append each component to ECS tags field. # @@ -372,10 +388,33 @@ processors: append: field: tags value: "{{{ _ingest._value }}}" - + # + # Convert certain fields to the correct value + # + - convert: + field: json.id + type: string + if: "ctx.json?.id != null" + - convert: + field: json.source_feed_id + type: string + if: "ctx.json?.source_feed_id != null" + - convert: + field: json.update_id + type: string + if: "ctx.json?.update_id != null" + - convert: + field: json.import_session_id + type: string + if: "ctx.json?.import_session_id != null" # # Remove fields converted to an ECS field. # + - remove: + field: event.original + if: "ctx?.tags == null || !(ctx.tags.contains('preserve_original_event'))" + ignore_failure: true + ignore_missing: true - remove: field: - json.asn @@ -391,7 +430,7 @@ processors: # - rename: field: json - target_field: threatintel.anomalithreatstream + target_field: anomali.threatstream on_failure: - append: diff --git a/x-pack/filebeat/module/threatintel/anomalithreatstream/manifest.yml b/x-pack/filebeat/module/threatintel/anomalithreatstream/manifest.yml index de6faeea227..011e2bb553e 100644 --- a/x-pack/filebeat/module/threatintel/anomalithreatstream/manifest.yml +++ b/x-pack/filebeat/module/threatintel/anomalithreatstream/manifest.yml @@ -8,13 +8,15 @@ var: - name: listen_port default: 8080 - name: secret - - name: ssl_certificate - - name: ssl_key + - name: ssl - name: paths default: /path/to/testing.log - name: tags default: - threatintel-anomalithreatstream + - forwarded + - name: preserve_original_event + default: false ingest_pipeline: - ingest/pipeline.yml input: config/config.yml diff --git a/x-pack/filebeat/module/threatintel/anomalithreatstream/test/generated.log-expected.json b/x-pack/filebeat/module/threatintel/anomalithreatstream/test/generated.log-expected.json index 21c627dde57..b101076a9e1 100644 --- a/x-pack/filebeat/module/threatintel/anomalithreatstream/test/generated.log-expected.json +++ b/x-pack/filebeat/module/threatintel/anomalithreatstream/test/generated.log-expected.json @@ -1,5 +1,20 @@ [ { + "anomali.threatstream.classification": "public", + "anomali.threatstream.confidence": 20, + "anomali.threatstream.detail2": "imported by user 184", + "anomali.threatstream.id": "3135167627", + "anomali.threatstream.import_session_id": "1400", + "anomali.threatstream.itype": "mal_domain", + "anomali.threatstream.resource_uri": "/api/v1/intelligence/P46279656657/", + "anomali.threatstream.severity": "high", + "anomali.threatstream.source_feed_id": "3143", + "anomali.threatstream.state": "active", + "anomali.threatstream.trusted_circle_ids": [ + "122" + ], + "anomali.threatstream.update_id": "3786618776", + "anomali.threatstream.value_type": "domain", "event.category": "threat", "event.dataset": "threatintel.anomalithreatstream", "event.kind": "enrichment", @@ -11,39 +26,44 @@ "log.offset": 0, "service.type": "threatintel", "tags": [ + "forwarded", "threatintel-anomalithreatstream" ], - "threatintel.anomalithreatstream.classification": "public", - "threatintel.anomalithreatstream.confidence": 20, - "threatintel.anomalithreatstream.detail2": "imported by user 184", - "threatintel.anomalithreatstream.id": 3135167627, - "threatintel.anomalithreatstream.import_session_id": 1400, - "threatintel.anomalithreatstream.itype": "mal_domain", - "threatintel.anomalithreatstream.resource_uri": "/api/v1/intelligence/P46279656657/", - "threatintel.anomalithreatstream.severity": "high", - "threatintel.anomalithreatstream.source_feed_id": 3143, - "threatintel.anomalithreatstream.state": "active", - "threatintel.anomalithreatstream.trusted_circle_ids": [ - "122" - ], - "threatintel.anomalithreatstream.update_id": 3786618776, - "threatintel.anomalithreatstream.value_type": "domain", - "threatintel.indicator.as.organization.name": "OVH Hosting", - "threatintel.indicator.confidence": 2, - "threatintel.indicator.first_seen": "2020-10-08T12:21:50.000Z", - "threatintel.indicator.geo.country_iso_code": "FR", - "threatintel.indicator.geo.location.lat": -49.1, - "threatintel.indicator.geo.location.lon": 94.4, - "threatintel.indicator.ip": "203.0.113.35", - "threatintel.indicator.last_seen": "2020-10-08T12:24:42.000Z", - "threatintel.indicator.marking.tlp": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali ThreatStream", + "threat.indicator.as.organization.name": "OVH Hosting", + "threat.indicator.confidence": "Low", + "threat.indicator.first_seen": "2020-10-08T12:21:50.000Z", + "threat.indicator.geo.country_iso_code": "FR", + "threat.indicator.geo.location.lat": -49.1, + "threat.indicator.geo.location.lon": 94.4, + "threat.indicator.ip": "203.0.113.35", + "threat.indicator.last_seen": "2020-10-08T12:24:42.000Z", + "threat.indicator.marking.tlp": [ "White" ], - "threatintel.indicator.provider": "Default Organization", - "threatintel.indicator.type": "domain-name", - "threatintel.indicator.url.domain": "d4xgfj.example.net" + "threat.indicator.provider": "Default Organization", + "threat.indicator.type": "domain-name", + "threat.indicator.url.domain": "d4xgfj.example.net" }, { + "anomali.threatstream.classification": "private", + "anomali.threatstream.confidence": 51, + "anomali.threatstream.detail2": "imported by user 979", + "anomali.threatstream.id": "2465691587", + "anomali.threatstream.import_session_id": "1934", + "anomali.threatstream.itype": "mal_ip", + "anomali.threatstream.resource_uri": "/api/v1/intelligence/P26893014825/", + "anomali.threatstream.severity": "low", + "anomali.threatstream.source_feed_id": "639", + "anomali.threatstream.state": "active", + "anomali.threatstream.trusted_circle_ids": [ + "355", + "386", + "461" + ], + "anomali.threatstream.update_id": "3311633654", + "anomali.threatstream.value_type": "ip", "event.category": "threat", "event.dataset": "threatintel.anomalithreatstream", "event.kind": "enrichment", @@ -55,40 +75,42 @@ "log.offset": 575, "service.type": "threatintel", "tags": [ + "forwarded", "threatintel-anomalithreatstream" ], - "threatintel.anomalithreatstream.classification": "private", - "threatintel.anomalithreatstream.confidence": 51, - "threatintel.anomalithreatstream.detail2": "imported by user 979", - "threatintel.anomalithreatstream.id": 2465691587, - "threatintel.anomalithreatstream.import_session_id": 1934, - "threatintel.anomalithreatstream.itype": "mal_ip", - "threatintel.anomalithreatstream.resource_uri": "/api/v1/intelligence/P26893014825/", - "threatintel.anomalithreatstream.severity": "low", - "threatintel.anomalithreatstream.source_feed_id": 639, - "threatintel.anomalithreatstream.state": "active", - "threatintel.anomalithreatstream.trusted_circle_ids": [ - "355", - "386", - "461" - ], - "threatintel.anomalithreatstream.update_id": 3311633654, - "threatintel.anomalithreatstream.value_type": "ip", - "threatintel.indicator.as.organization.name": "IP Khnykin Vitaliy Yakovlevich", - "threatintel.indicator.confidence": 5, - "threatintel.indicator.first_seen": "2020-10-08T12:21:59.000Z", - "threatintel.indicator.geo.country_iso_code": "RU", - "threatintel.indicator.geo.location.lat": -51.2, - "threatintel.indicator.geo.location.lon": -64.7, - "threatintel.indicator.ip": "2001:db8:fc77:2510:5ab8:7bc8:65a3:4894", - "threatintel.indicator.last_seen": "2020-10-08T12:24:42.000Z", - "threatintel.indicator.marking.tlp": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali ThreatStream", + "threat.indicator.as.organization.name": "IP Khnykin Vitaliy Yakovlevich", + "threat.indicator.confidence": "Med", + "threat.indicator.first_seen": "2020-10-08T12:21:59.000Z", + "threat.indicator.geo.country_iso_code": "RU", + "threat.indicator.geo.location.lat": -51.2, + "threat.indicator.geo.location.lon": -64.7, + "threat.indicator.ip": "2001:db8:fc77:2510:5ab8:7bc8:65a3:4894", + "threat.indicator.last_seen": "2020-10-08T12:24:42.000Z", + "threat.indicator.marking.tlp": [ "Amber" ], - "threatintel.indicator.provider": "Default Organization", - "threatintel.indicator.type": "ipv6-addr" + "threat.indicator.provider": "Default Organization", + "threat.indicator.type": "ipv6-addr" }, { + "anomali.threatstream.classification": "public", + "anomali.threatstream.confidence": 24, + "anomali.threatstream.detail2": "imported by user 830", + "anomali.threatstream.id": "1886961414", + "anomali.threatstream.import_session_id": "3569", + "anomali.threatstream.itype": "mal_ip", + "anomali.threatstream.resource_uri": "/api/v1/intelligence/P16938191113/", + "anomali.threatstream.severity": "high", + "anomali.threatstream.source_feed_id": "2564", + "anomali.threatstream.state": "active", + "anomali.threatstream.trusted_circle_ids": [ + "740", + "954" + ], + "anomali.threatstream.update_id": "1860329541", + "anomali.threatstream.value_type": "ip", "event.category": "threat", "event.dataset": "threatintel.anomalithreatstream", "event.kind": "enrichment", @@ -100,40 +122,45 @@ "log.offset": 1163, "service.type": "threatintel", "tags": [ + "forwarded", "threatintel-anomalithreatstream" ], - "threatintel.anomalithreatstream.classification": "public", - "threatintel.anomalithreatstream.confidence": 24, - "threatintel.anomalithreatstream.detail2": "imported by user 830", - "threatintel.anomalithreatstream.id": 1886961414, - "threatintel.anomalithreatstream.import_session_id": 3569, - "threatintel.anomalithreatstream.itype": "mal_ip", - "threatintel.anomalithreatstream.resource_uri": "/api/v1/intelligence/P16938191113/", - "threatintel.anomalithreatstream.severity": "high", - "threatintel.anomalithreatstream.source_feed_id": 2564, - "threatintel.anomalithreatstream.state": "active", - "threatintel.anomalithreatstream.trusted_circle_ids": [ - "740", - "954" - ], - "threatintel.anomalithreatstream.update_id": 1860329541, - "threatintel.anomalithreatstream.value_type": "ip", - "threatintel.indicator.as.number": 22773, - "threatintel.indicator.as.organization.name": "Cox Communications", - "threatintel.indicator.confidence": 2, - "threatintel.indicator.first_seen": "2020-10-08T12:22:11.000Z", - "threatintel.indicator.geo.country_iso_code": "US", - "threatintel.indicator.geo.location.lat": 38.4, - "threatintel.indicator.geo.location.lon": 0.0, - "threatintel.indicator.ip": "192.0.2.8", - "threatintel.indicator.last_seen": "2020-10-08T12:24:42.000Z", - "threatintel.indicator.marking.tlp": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali ThreatStream", + "threat.indicator.as.number": 22773, + "threat.indicator.as.organization.name": "Cox Communications", + "threat.indicator.confidence": "Low", + "threat.indicator.first_seen": "2020-10-08T12:22:11.000Z", + "threat.indicator.geo.country_iso_code": "US", + "threat.indicator.geo.location.lat": 38.4, + "threat.indicator.geo.location.lon": 0.0, + "threat.indicator.ip": "192.0.2.8", + "threat.indicator.last_seen": "2020-10-08T12:24:42.000Z", + "threat.indicator.marking.tlp": [ "White" ], - "threatintel.indicator.provider": "Default Organization", - "threatintel.indicator.type": "ipv4-addr" + "threat.indicator.provider": "Default Organization", + "threat.indicator.type": "ipv4-addr" }, { + "anomali.threatstream.classification": "public", + "anomali.threatstream.confidence": 56, + "anomali.threatstream.detail2": "imported by user 723", + "anomali.threatstream.id": "1785659799", + "anomali.threatstream.import_session_id": "244", + "anomali.threatstream.itype": "mal_md5", + "anomali.threatstream.md5": "6466e2", + "anomali.threatstream.resource_uri": "/api/v1/intelligence/P44706407813/", + "anomali.threatstream.severity": "very-high", + "anomali.threatstream.source_feed_id": "3759", + "anomali.threatstream.state": "active", + "anomali.threatstream.trusted_circle_ids": [ + "439", + "801", + "942" + ], + "anomali.threatstream.update_id": "3898969521", + "anomali.threatstream.value_type": "md5", "event.category": "threat", "event.dataset": "threatintel.anomalithreatstream", "event.kind": "enrichment", @@ -145,36 +172,38 @@ "log.offset": 1720, "service.type": "threatintel", "tags": [ + "forwarded", "threatintel-anomalithreatstream" ], - "threatintel.anomalithreatstream.classification": "public", - "threatintel.anomalithreatstream.confidence": 56, - "threatintel.anomalithreatstream.detail2": "imported by user 723", - "threatintel.anomalithreatstream.id": 1785659799, - "threatintel.anomalithreatstream.import_session_id": 244, - "threatintel.anomalithreatstream.itype": "mal_md5", - "threatintel.anomalithreatstream.md5": "6466e2", - "threatintel.anomalithreatstream.resource_uri": "/api/v1/intelligence/P44706407813/", - "threatintel.anomalithreatstream.severity": "very-high", - "threatintel.anomalithreatstream.source_feed_id": 3759, - "threatintel.anomalithreatstream.state": "active", - "threatintel.anomalithreatstream.trusted_circle_ids": [ - "439", - "801", - "942" - ], - "threatintel.anomalithreatstream.update_id": 3898969521, - "threatintel.anomalithreatstream.value_type": "md5", - "threatintel.indicator.confidence": 6, - "threatintel.indicator.first_seen": "2020-10-08T12:22:16.000Z", - "threatintel.indicator.last_seen": "2020-10-08T12:24:42.000Z", - "threatintel.indicator.marking.tlp": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali ThreatStream", + "threat.indicator.confidence": "Med", + "threat.indicator.first_seen": "2020-10-08T12:22:16.000Z", + "threat.indicator.last_seen": "2020-10-08T12:24:42.000Z", + "threat.indicator.marking.tlp": [ "White" ], - "threatintel.indicator.provider": "Default Organization", - "threatintel.indicator.type": "file" + "threat.indicator.provider": "Default Organization", + "threat.indicator.type": "file" }, { + "anomali.threatstream.classification": "private", + "anomali.threatstream.confidence": 61, + "anomali.threatstream.detail2": "imported by user 16", + "anomali.threatstream.id": "2788278724", + "anomali.threatstream.import_session_id": "3146", + "anomali.threatstream.itype": "mal_ip", + "anomali.threatstream.resource_uri": "/api/v1/intelligence/P39996084337/", + "anomali.threatstream.severity": "very-high", + "anomali.threatstream.source_feed_id": "1834", + "anomali.threatstream.state": "active", + "anomali.threatstream.trusted_circle_ids": [ + "310", + "553", + "709" + ], + "anomali.threatstream.update_id": "1925356831", + "anomali.threatstream.value_type": "ip", "event.category": "threat", "event.dataset": "threatintel.anomalithreatstream", "event.kind": "enrichment", @@ -186,41 +215,43 @@ "log.offset": 2195, "service.type": "threatintel", "tags": [ + "forwarded", "threatintel-anomalithreatstream" ], - "threatintel.anomalithreatstream.classification": "private", - "threatintel.anomalithreatstream.confidence": 61, - "threatintel.anomalithreatstream.detail2": "imported by user 16", - "threatintel.anomalithreatstream.id": 2788278724, - "threatintel.anomalithreatstream.import_session_id": 3146, - "threatintel.anomalithreatstream.itype": "mal_ip", - "threatintel.anomalithreatstream.resource_uri": "/api/v1/intelligence/P39996084337/", - "threatintel.anomalithreatstream.severity": "very-high", - "threatintel.anomalithreatstream.source_feed_id": 1834, - "threatintel.anomalithreatstream.state": "active", - "threatintel.anomalithreatstream.trusted_circle_ids": [ - "310", - "553", - "709" - ], - "threatintel.anomalithreatstream.update_id": 1925356831, - "threatintel.anomalithreatstream.value_type": "ip", - "threatintel.indicator.as.number": 20001, - "threatintel.indicator.as.organization.name": "Spectrum", - "threatintel.indicator.confidence": 6, - "threatintel.indicator.first_seen": "2020-10-08T12:28:50.000Z", - "threatintel.indicator.geo.country_iso_code": "US", - "threatintel.indicator.geo.location.lat": -64.8, - "threatintel.indicator.geo.location.lon": -129.3, - "threatintel.indicator.ip": "192.0.2.235", - "threatintel.indicator.last_seen": "2020-10-09T18:49:37.000Z", - "threatintel.indicator.marking.tlp": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali ThreatStream", + "threat.indicator.as.number": 20001, + "threat.indicator.as.organization.name": "Spectrum", + "threat.indicator.confidence": "Med", + "threat.indicator.first_seen": "2020-10-08T12:28:50.000Z", + "threat.indicator.geo.country_iso_code": "US", + "threat.indicator.geo.location.lat": -64.8, + "threat.indicator.geo.location.lon": -129.3, + "threat.indicator.ip": "192.0.2.235", + "threat.indicator.last_seen": "2020-10-09T18:49:37.000Z", + "threat.indicator.marking.tlp": [ "Amber" ], - "threatintel.indicator.provider": "Default Organization", - "threatintel.indicator.type": "ipv4-addr" + "threat.indicator.provider": "Default Organization", + "threat.indicator.type": "ipv4-addr" }, { + "anomali.threatstream.classification": "public", + "anomali.threatstream.confidence": 31, + "anomali.threatstream.detail2": "imported by user 659", + "anomali.threatstream.id": "2979716207", + "anomali.threatstream.import_session_id": "2369", + "anomali.threatstream.itype": "mal_ip", + "anomali.threatstream.resource_uri": "/api/v1/intelligence/P24601068254/", + "anomali.threatstream.severity": "low", + "anomali.threatstream.source_feed_id": "2122", + "anomali.threatstream.state": "active", + "anomali.threatstream.trusted_circle_ids": [ + "297", + "811" + ], + "anomali.threatstream.update_id": "1327494837", + "anomali.threatstream.value_type": "ip", "event.category": "threat", "event.dataset": "threatintel.anomalithreatstream", "event.kind": "enrichment", @@ -232,40 +263,44 @@ "log.offset": 2757, "service.type": "threatintel", "tags": [ + "forwarded", "threatintel-anomalithreatstream" ], - "threatintel.anomalithreatstream.classification": "public", - "threatintel.anomalithreatstream.confidence": 31, - "threatintel.anomalithreatstream.detail2": "imported by user 659", - "threatintel.anomalithreatstream.id": 2979716207, - "threatintel.anomalithreatstream.import_session_id": 2369, - "threatintel.anomalithreatstream.itype": "mal_ip", - "threatintel.anomalithreatstream.resource_uri": "/api/v1/intelligence/P24601068254/", - "threatintel.anomalithreatstream.severity": "low", - "threatintel.anomalithreatstream.source_feed_id": 2122, - "threatintel.anomalithreatstream.state": "active", - "threatintel.anomalithreatstream.trusted_circle_ids": [ - "297", - "811" - ], - "threatintel.anomalithreatstream.update_id": 1327494837, - "threatintel.anomalithreatstream.value_type": "ip", - "threatintel.indicator.as.number": 11351, - "threatintel.indicator.as.organization.name": "Spectrum", - "threatintel.indicator.confidence": 3, - "threatintel.indicator.first_seen": "2020-10-08T12:29:01.000Z", - "threatintel.indicator.geo.country_iso_code": "US", - "threatintel.indicator.geo.location.lat": 72.1, - "threatintel.indicator.geo.location.lon": -52.2, - "threatintel.indicator.ip": "2001:db8:df14:f43b:a986:5e2a:8ce9:4523", - "threatintel.indicator.last_seen": "2020-10-09T18:49:37.000Z", - "threatintel.indicator.marking.tlp": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali ThreatStream", + "threat.indicator.as.number": 11351, + "threat.indicator.as.organization.name": "Spectrum", + "threat.indicator.confidence": "Med", + "threat.indicator.first_seen": "2020-10-08T12:29:01.000Z", + "threat.indicator.geo.country_iso_code": "US", + "threat.indicator.geo.location.lat": 72.1, + "threat.indicator.geo.location.lon": -52.2, + "threat.indicator.ip": "2001:db8:df14:f43b:a986:5e2a:8ce9:4523", + "threat.indicator.last_seen": "2020-10-09T18:49:37.000Z", + "threat.indicator.marking.tlp": [ "White" ], - "threatintel.indicator.provider": "Default Organization", - "threatintel.indicator.type": "ipv6-addr" + "threat.indicator.provider": "Default Organization", + "threat.indicator.type": "ipv6-addr" }, { + "anomali.threatstream.classification": "private", + "anomali.threatstream.confidence": 72, + "anomali.threatstream.detail2": "imported by user 50", + "anomali.threatstream.id": "3763825895", + "anomali.threatstream.itype": "c2_domain", + "anomali.threatstream.maltype": "malware:r47agu9", + "anomali.threatstream.resource_uri": "/api/v1/intelligence/P49850231022/", + "anomali.threatstream.severity": "very-high", + "anomali.threatstream.source_feed_id": "967", + "anomali.threatstream.state": "active", + "anomali.threatstream.trusted_circle_ids": [ + "238", + "259", + "537" + ], + "anomali.threatstream.update_id": "1356750652", + "anomali.threatstream.value_type": "domain", "event.category": "threat", "event.dataset": "threatintel.anomalithreatstream", "event.kind": "enrichment", @@ -281,6 +316,7 @@ "Botnet-1QZ2U", "Botnet-VXPC5QK8T", "first_seen=2020-07-24T07:36:41", + "forwarded", "mask=2001:db8:867f:42a1:d692:b396:4f14:548c", "popularity=high", "popularity=high", @@ -288,35 +324,37 @@ "threatintel-anomalithreatstream", "type=2" ], - "threatintel.anomalithreatstream.classification": "private", - "threatintel.anomalithreatstream.confidence": 72, - "threatintel.anomalithreatstream.detail2": "imported by user 50", - "threatintel.anomalithreatstream.id": 3763825895, - "threatintel.anomalithreatstream.itype": "c2_domain", - "threatintel.anomalithreatstream.maltype": "malware:r47agu9", - "threatintel.anomalithreatstream.resource_uri": "/api/v1/intelligence/P49850231022/", - "threatintel.anomalithreatstream.severity": "very-high", - "threatintel.anomalithreatstream.source_feed_id": 967, - "threatintel.anomalithreatstream.state": "active", - "threatintel.anomalithreatstream.trusted_circle_ids": [ - "238", - "259", - "537" - ], - "threatintel.anomalithreatstream.update_id": 1356750652, - "threatintel.anomalithreatstream.value_type": "domain", - "threatintel.indicator.confidence": 7, - "threatintel.indicator.first_seen": "2020-10-09T18:14:43.000Z", - "threatintel.indicator.ip": "203.0.113.130", - "threatintel.indicator.last_seen": "2020-10-09T18:14:43.000Z", - "threatintel.indicator.marking.tlp": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali ThreatStream", + "threat.indicator.confidence": "High", + "threat.indicator.first_seen": "2020-10-09T18:14:43.000Z", + "threat.indicator.ip": "203.0.113.130", + "threat.indicator.last_seen": "2020-10-09T18:14:43.000Z", + "threat.indicator.marking.tlp": [ "Amber" ], - "threatintel.indicator.provider": "Default Organization", - "threatintel.indicator.type": "domain-name", - "threatintel.indicator.url.domain": "ei1im6skd.example.com" + "threat.indicator.provider": "Default Organization", + "threat.indicator.type": "domain-name", + "threat.indicator.url.domain": "ei1im6skd.example.com" }, { + "anomali.threatstream.classification": "private", + "anomali.threatstream.confidence": 60, + "anomali.threatstream.detail2": "imported by user 167", + "anomali.threatstream.id": "3178646499", + "anomali.threatstream.itype": "mal_md5", + "anomali.threatstream.md5": "0f321db9", + "anomali.threatstream.resource_uri": "/api/v1/intelligence/P35792781031/", + "anomali.threatstream.severity": "low", + "anomali.threatstream.source_feed_id": "1743", + "anomali.threatstream.state": "active", + "anomali.threatstream.trusted_circle_ids": [ + "112", + "455", + "761" + ], + "anomali.threatstream.update_id": "1585930018", + "anomali.threatstream.value_type": "md5", "event.category": "threat", "event.dataset": "threatintel.anomalithreatstream", "event.kind": "enrichment", @@ -328,35 +366,37 @@ "log.offset": 4049, "service.type": "threatintel", "tags": [ + "forwarded", "threatintel-anomalithreatstream" ], - "threatintel.anomalithreatstream.classification": "private", - "threatintel.anomalithreatstream.confidence": 60, - "threatintel.anomalithreatstream.detail2": "imported by user 167", - "threatintel.anomalithreatstream.id": 3178646499, - "threatintel.anomalithreatstream.itype": "mal_md5", - "threatintel.anomalithreatstream.md5": "0f321db9", - "threatintel.anomalithreatstream.resource_uri": "/api/v1/intelligence/P35792781031/", - "threatintel.anomalithreatstream.severity": "low", - "threatintel.anomalithreatstream.source_feed_id": 1743, - "threatintel.anomalithreatstream.state": "active", - "threatintel.anomalithreatstream.trusted_circle_ids": [ - "112", - "455", - "761" - ], - "threatintel.anomalithreatstream.update_id": 1585930018, - "threatintel.anomalithreatstream.value_type": "md5", - "threatintel.indicator.confidence": 6, - "threatintel.indicator.first_seen": "2020-10-09T18:30:10.000Z", - "threatintel.indicator.last_seen": "2020-10-09T18:30:10.000Z", - "threatintel.indicator.marking.tlp": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali ThreatStream", + "threat.indicator.confidence": "Med", + "threat.indicator.first_seen": "2020-10-09T18:30:10.000Z", + "threat.indicator.last_seen": "2020-10-09T18:30:10.000Z", + "threat.indicator.marking.tlp": [ "Amber" ], - "threatintel.indicator.provider": "Default Organization", - "threatintel.indicator.type": "file" + "threat.indicator.provider": "Default Organization", + "threat.indicator.type": "file" }, { + "anomali.threatstream.classification": "public", + "anomali.threatstream.confidence": 70, + "anomali.threatstream.detail2": "imported by user 654", + "anomali.threatstream.id": "2435568409", + "anomali.threatstream.itype": "phish_url", + "anomali.threatstream.maltype": "malware:9rb9", + "anomali.threatstream.resource_uri": "/api/v1/intelligence/P41264495308/", + "anomali.threatstream.severity": "low", + "anomali.threatstream.source_feed_id": "3940", + "anomali.threatstream.state": "active", + "anomali.threatstream.trusted_circle_ids": [ + "633", + "641" + ], + "anomali.threatstream.update_id": "2070423140", + "anomali.threatstream.value_type": "url", "event.category": "threat", "event.dataset": "threatintel.anomalithreatstream", "event.kind": "enrichment", @@ -368,43 +408,46 @@ "log.offset": 4495, "service.type": "threatintel", "tags": [ + "forwarded", "jn5jpvg", "threatintel-anomalithreatstream" ], - "threatintel.anomalithreatstream.classification": "public", - "threatintel.anomalithreatstream.confidence": 70, - "threatintel.anomalithreatstream.detail2": "imported by user 654", - "threatintel.anomalithreatstream.id": 2435568409, - "threatintel.anomalithreatstream.itype": "phish_url", - "threatintel.anomalithreatstream.maltype": "malware:9rb9", - "threatintel.anomalithreatstream.resource_uri": "/api/v1/intelligence/P41264495308/", - "threatintel.anomalithreatstream.severity": "low", - "threatintel.anomalithreatstream.source_feed_id": 3940, - "threatintel.anomalithreatstream.state": "active", - "threatintel.anomalithreatstream.trusted_circle_ids": [ - "633", - "641" - ], - "threatintel.anomalithreatstream.update_id": 2070423140, - "threatintel.anomalithreatstream.value_type": "url", - "threatintel.indicator.confidence": 7, - "threatintel.indicator.first_seen": "2020-10-09T18:30:13.000Z", - "threatintel.indicator.geo.country_iso_code": "US", - "threatintel.indicator.ip": "203.0.113.236", - "threatintel.indicator.last_seen": "2020-10-09T18:30:13.000Z", - "threatintel.indicator.marking.tlp": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali ThreatStream", + "threat.indicator.confidence": "High", + "threat.indicator.first_seen": "2020-10-09T18:30:13.000Z", + "threat.indicator.geo.country_iso_code": "US", + "threat.indicator.ip": "203.0.113.236", + "threat.indicator.last_seen": "2020-10-09T18:30:13.000Z", + "threat.indicator.marking.tlp": [ "White" ], - "threatintel.indicator.provider": "Default Organization", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "ax1a6o38z.example.org", - "threatintel.indicator.url.full": "https://ax1a6o38z.example.org/enec3i/f1n8fv?4shpqq9=fbo9osx8p", - "threatintel.indicator.url.original": "https://ax1a6o38z.example.org/enec3i/f1n8fv?4shpqq9=fbo9osx8p", - "threatintel.indicator.url.path": "/enec3i/f1n8fv", - "threatintel.indicator.url.query": "4shpqq9=fbo9osx8p", - "threatintel.indicator.url.scheme": "https" + "threat.indicator.provider": "Default Organization", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "ax1a6o38z.example.org", + "threat.indicator.url.full": "https://ax1a6o38z.example.org/enec3i/f1n8fv?4shpqq9=fbo9osx8p", + "threat.indicator.url.original": "https://ax1a6o38z.example.org/enec3i/f1n8fv?4shpqq9=fbo9osx8p", + "threat.indicator.url.path": "/enec3i/f1n8fv", + "threat.indicator.url.query": "4shpqq9=fbo9osx8p", + "threat.indicator.url.scheme": "https" }, { + "anomali.threatstream.classification": "public", + "anomali.threatstream.confidence": 35, + "anomali.threatstream.detail2": "imported by user 81", + "anomali.threatstream.id": "1404936664", + "anomali.threatstream.itype": "mal_url", + "anomali.threatstream.maltype": "malware:4p1lc0bf", + "anomali.threatstream.resource_uri": "/api/v1/intelligence/P22799247040/", + "anomali.threatstream.severity": "low", + "anomali.threatstream.source_feed_id": "2236", + "anomali.threatstream.state": "active", + "anomali.threatstream.trusted_circle_ids": [ + "424", + "718" + ], + "anomali.threatstream.update_id": "2151391711", + "anomali.threatstream.value_type": "url", "event.category": "threat", "event.dataset": "threatintel.anomalithreatstream", "event.kind": "enrichment", @@ -417,43 +460,46 @@ "service.type": "threatintel", "tags": [ "7zhsn5t7", + "forwarded", "threatintel-anomalithreatstream", "xl4" ], - "threatintel.anomalithreatstream.classification": "public", - "threatintel.anomalithreatstream.confidence": 35, - "threatintel.anomalithreatstream.detail2": "imported by user 81", - "threatintel.anomalithreatstream.id": 1404936664, - "threatintel.anomalithreatstream.itype": "mal_url", - "threatintel.anomalithreatstream.maltype": "malware:4p1lc0bf", - "threatintel.anomalithreatstream.resource_uri": "/api/v1/intelligence/P22799247040/", - "threatintel.anomalithreatstream.severity": "low", - "threatintel.anomalithreatstream.source_feed_id": 2236, - "threatintel.anomalithreatstream.state": "active", - "threatintel.anomalithreatstream.trusted_circle_ids": [ - "424", - "718" - ], - "threatintel.anomalithreatstream.update_id": 2151391711, - "threatintel.anomalithreatstream.value_type": "url", - "threatintel.indicator.confidence": 4, - "threatintel.indicator.first_seen": "2020-10-09T18:30:13.000Z", - "threatintel.indicator.geo.country_iso_code": "CN", - "threatintel.indicator.ip": "2001:db8:62cc:2fd2:f406:9c03:e2e8:617d", - "threatintel.indicator.last_seen": "2020-10-09T18:30:13.000Z", - "threatintel.indicator.marking.tlp": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali ThreatStream", + "threat.indicator.confidence": "Med", + "threat.indicator.first_seen": "2020-10-09T18:30:13.000Z", + "threat.indicator.geo.country_iso_code": "CN", + "threat.indicator.ip": "2001:db8:62cc:2fd2:f406:9c03:e2e8:617d", + "threat.indicator.last_seen": "2020-10-09T18:30:13.000Z", + "threat.indicator.marking.tlp": [ "White" ], - "threatintel.indicator.provider": "Default Organization", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "beko3.example.com", - "threatintel.indicator.url.full": "https://beko3.example.com/vkelnz/jdz6zf-ga?g39fu=88309ge", - "threatintel.indicator.url.original": "https://beko3.example.com/vkelnz/jdz6zf-ga?g39fu=88309ge", - "threatintel.indicator.url.path": "/vkelnz/jdz6zf-ga", - "threatintel.indicator.url.query": "g39fu=88309ge", - "threatintel.indicator.url.scheme": "https" + "threat.indicator.provider": "Default Organization", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "beko3.example.com", + "threat.indicator.url.full": "https://beko3.example.com/vkelnz/jdz6zf-ga?g39fu=88309ge", + "threat.indicator.url.original": "https://beko3.example.com/vkelnz/jdz6zf-ga?g39fu=88309ge", + "threat.indicator.url.path": "/vkelnz/jdz6zf-ga", + "threat.indicator.url.query": "g39fu=88309ge", + "threat.indicator.url.scheme": "https" }, { + "anomali.threatstream.classification": "public", + "anomali.threatstream.confidence": 7, + "anomali.threatstream.detail2": "imported by user 993", + "anomali.threatstream.id": "1300368058", + "anomali.threatstream.itype": "mal_md5", + "anomali.threatstream.maltype": "malware:s7-t", + "anomali.threatstream.md5": "b91c", + "anomali.threatstream.resource_uri": "/api/v1/intelligence/P43593676062/", + "anomali.threatstream.severity": "very-high", + "anomali.threatstream.source_feed_id": "1581", + "anomali.threatstream.state": "active", + "anomali.threatstream.trusted_circle_ids": [ + "812" + ], + "anomali.threatstream.update_id": "1852221746", + "anomali.threatstream.value_type": "md5", "event.category": "threat", "event.dataset": "threatintel.anomalithreatstream", "event.kind": "enrichment", @@ -467,34 +513,39 @@ "tags": [ "aampq5", "d6-", + "forwarded", "threatintel-anomalithreatstream" ], - "threatintel.anomalithreatstream.classification": "public", - "threatintel.anomalithreatstream.confidence": 7, - "threatintel.anomalithreatstream.detail2": "imported by user 993", - "threatintel.anomalithreatstream.id": 1300368058, - "threatintel.anomalithreatstream.itype": "mal_md5", - "threatintel.anomalithreatstream.maltype": "malware:s7-t", - "threatintel.anomalithreatstream.md5": "b91c", - "threatintel.anomalithreatstream.resource_uri": "/api/v1/intelligence/P43593676062/", - "threatintel.anomalithreatstream.severity": "very-high", - "threatintel.anomalithreatstream.source_feed_id": 1581, - "threatintel.anomalithreatstream.state": "active", - "threatintel.anomalithreatstream.trusted_circle_ids": [ - "812" - ], - "threatintel.anomalithreatstream.update_id": 1852221746, - "threatintel.anomalithreatstream.value_type": "md5", - "threatintel.indicator.confidence": 1, - "threatintel.indicator.first_seen": "2020-10-09T18:30:22.000Z", - "threatintel.indicator.last_seen": "2020-10-09T18:30:22.000Z", - "threatintel.indicator.marking.tlp": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali ThreatStream", + "threat.indicator.confidence": "Low", + "threat.indicator.first_seen": "2020-10-09T18:30:22.000Z", + "threat.indicator.last_seen": "2020-10-09T18:30:22.000Z", + "threat.indicator.marking.tlp": [ "White" ], - "threatintel.indicator.provider": "Default Organization", - "threatintel.indicator.type": "file" + "threat.indicator.provider": "Default Organization", + "threat.indicator.type": "file" }, { + "anomali.threatstream.classification": "private", + "anomali.threatstream.confidence": 63, + "anomali.threatstream.detail2": "imported by user 963", + "anomali.threatstream.id": "1511736215", + "anomali.threatstream.itype": "mal_md5", + "anomali.threatstream.maltype": "malware:0vnvp84", + "anomali.threatstream.md5": "3c49c", + "anomali.threatstream.resource_uri": "/api/v1/intelligence/P47666251160/", + "anomali.threatstream.severity": "very-high", + "anomali.threatstream.source_feed_id": "1695", + "anomali.threatstream.state": "active", + "anomali.threatstream.trusted_circle_ids": [ + "29", + "537", + "879" + ], + "anomali.threatstream.update_id": "3048270616", + "anomali.threatstream.value_type": "md5", "event.category": "threat", "event.dataset": "threatintel.anomalithreatstream", "event.kind": "enrichment", @@ -507,36 +558,37 @@ "service.type": "threatintel", "tags": [ "", + "forwarded", "threatintel-anomalithreatstream" ], - "threatintel.anomalithreatstream.classification": "private", - "threatintel.anomalithreatstream.confidence": 63, - "threatintel.anomalithreatstream.detail2": "imported by user 963", - "threatintel.anomalithreatstream.id": 1511736215, - "threatintel.anomalithreatstream.itype": "mal_md5", - "threatintel.anomalithreatstream.maltype": "malware:0vnvp84", - "threatintel.anomalithreatstream.md5": "3c49c", - "threatintel.anomalithreatstream.resource_uri": "/api/v1/intelligence/P47666251160/", - "threatintel.anomalithreatstream.severity": "very-high", - "threatintel.anomalithreatstream.source_feed_id": 1695, - "threatintel.anomalithreatstream.state": "active", - "threatintel.anomalithreatstream.trusted_circle_ids": [ - "29", - "537", - "879" - ], - "threatintel.anomalithreatstream.update_id": 3048270616, - "threatintel.anomalithreatstream.value_type": "md5", - "threatintel.indicator.confidence": 6, - "threatintel.indicator.first_seen": "2020-10-09T18:30:23.000Z", - "threatintel.indicator.last_seen": "2020-10-09T18:30:23.000Z", - "threatintel.indicator.marking.tlp": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali ThreatStream", + "threat.indicator.confidence": "Med", + "threat.indicator.first_seen": "2020-10-09T18:30:23.000Z", + "threat.indicator.last_seen": "2020-10-09T18:30:23.000Z", + "threat.indicator.marking.tlp": [ "Amber" ], - "threatintel.indicator.provider": "Default Organization", - "threatintel.indicator.type": "file" + "threat.indicator.provider": "Default Organization", + "threat.indicator.type": "file" }, { + "anomali.threatstream.classification": "private", + "anomali.threatstream.confidence": 95, + "anomali.threatstream.detail2": "imported by user 302", + "anomali.threatstream.id": "2213035853", + "anomali.threatstream.itype": "phish_url", + "anomali.threatstream.maltype": "malware:25iv", + "anomali.threatstream.resource_uri": "/api/v1/intelligence/P11608678465/", + "anomali.threatstream.severity": "very-high", + "anomali.threatstream.source_feed_id": "787", + "anomali.threatstream.state": "active", + "anomali.threatstream.trusted_circle_ids": [ + "154", + "766" + ], + "anomali.threatstream.update_id": "2851232102", + "anomali.threatstream.value_type": "url", "event.category": "threat", "event.dataset": "threatintel.anomalithreatstream", "event.kind": "enrichment", @@ -549,42 +601,46 @@ "service.type": "threatintel", "tags": [ "22nciqjs", + "forwarded", "threatintel-anomalithreatstream" ], - "threatintel.anomalithreatstream.classification": "private", - "threatintel.anomalithreatstream.confidence": 95, - "threatintel.anomalithreatstream.detail2": "imported by user 302", - "threatintel.anomalithreatstream.id": 2213035853, - "threatintel.anomalithreatstream.itype": "phish_url", - "threatintel.anomalithreatstream.maltype": "malware:25iv", - "threatintel.anomalithreatstream.resource_uri": "/api/v1/intelligence/P11608678465/", - "threatintel.anomalithreatstream.severity": "very-high", - "threatintel.anomalithreatstream.source_feed_id": 787, - "threatintel.anomalithreatstream.state": "active", - "threatintel.anomalithreatstream.trusted_circle_ids": [ - "154", - "766" - ], - "threatintel.anomalithreatstream.update_id": 2851232102, - "threatintel.anomalithreatstream.value_type": "url", - "threatintel.indicator.confidence": 10, - "threatintel.indicator.first_seen": "2020-10-09T18:30:30.000Z", - "threatintel.indicator.geo.country_iso_code": "US", - "threatintel.indicator.ip": "192.0.2.162", - "threatintel.indicator.last_seen": "2020-10-09T18:30:30.000Z", - "threatintel.indicator.marking.tlp": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali ThreatStream", + "threat.indicator.confidence": "High", + "threat.indicator.first_seen": "2020-10-09T18:30:30.000Z", + "threat.indicator.geo.country_iso_code": "US", + "threat.indicator.ip": "192.0.2.162", + "threat.indicator.last_seen": "2020-10-09T18:30:30.000Z", + "threat.indicator.marking.tlp": [ "Amber" ], - "threatintel.indicator.provider": "Default Organization", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "sevs82.example.com", - "threatintel.indicator.url.full": "http://sevs82.example.com/c5-d/hdajog?4rs78hl=wvwi", - "threatintel.indicator.url.original": "http://sevs82.example.com/c5-d/hdajog?4rs78hl=wvwi", - "threatintel.indicator.url.path": "/c5-d/hdajog", - "threatintel.indicator.url.query": "4rs78hl=wvwi", - "threatintel.indicator.url.scheme": "http" + "threat.indicator.provider": "Default Organization", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "sevs82.example.com", + "threat.indicator.url.full": "http://sevs82.example.com/c5-d/hdajog?4rs78hl=wvwi", + "threat.indicator.url.original": "http://sevs82.example.com/c5-d/hdajog?4rs78hl=wvwi", + "threat.indicator.url.path": "/c5-d/hdajog", + "threat.indicator.url.query": "4rs78hl=wvwi", + "threat.indicator.url.scheme": "http" }, { + "anomali.threatstream.classification": "private", + "anomali.threatstream.confidence": 18, + "anomali.threatstream.detail2": "imported by user 548", + "anomali.threatstream.id": "2594216423", + "anomali.threatstream.itype": "mal_md5", + "anomali.threatstream.maltype": "malware:i6z9qr", + "anomali.threatstream.md5": "e29608b", + "anomali.threatstream.resource_uri": "/api/v1/intelligence/P32471582403/", + "anomali.threatstream.severity": "low", + "anomali.threatstream.source_feed_id": "1475", + "anomali.threatstream.state": "active", + "anomali.threatstream.trusted_circle_ids": [ + "539", + "6" + ], + "anomali.threatstream.update_id": "2328838402", + "anomali.threatstream.value_type": "md5", "event.category": "threat", "event.dataset": "threatintel.anomalithreatstream", "event.kind": "enrichment", @@ -597,36 +653,38 @@ "service.type": "threatintel", "tags": [ "26sg-3-", + "forwarded", "threatintel-anomalithreatstream", "vnx4nu7c" ], - "threatintel.anomalithreatstream.classification": "private", - "threatintel.anomalithreatstream.confidence": 18, - "threatintel.anomalithreatstream.detail2": "imported by user 548", - "threatintel.anomalithreatstream.id": 2594216423, - "threatintel.anomalithreatstream.itype": "mal_md5", - "threatintel.anomalithreatstream.maltype": "malware:i6z9qr", - "threatintel.anomalithreatstream.md5": "e29608b", - "threatintel.anomalithreatstream.resource_uri": "/api/v1/intelligence/P32471582403/", - "threatintel.anomalithreatstream.severity": "low", - "threatintel.anomalithreatstream.source_feed_id": 1475, - "threatintel.anomalithreatstream.state": "active", - "threatintel.anomalithreatstream.trusted_circle_ids": [ - "539", - "6" - ], - "threatintel.anomalithreatstream.update_id": 2328838402, - "threatintel.anomalithreatstream.value_type": "md5", - "threatintel.indicator.confidence": 2, - "threatintel.indicator.first_seen": "2020-10-09T18:30:37.000Z", - "threatintel.indicator.last_seen": "2020-10-09T18:30:37.000Z", - "threatintel.indicator.marking.tlp": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali ThreatStream", + "threat.indicator.confidence": "Low", + "threat.indicator.first_seen": "2020-10-09T18:30:37.000Z", + "threat.indicator.last_seen": "2020-10-09T18:30:37.000Z", + "threat.indicator.marking.tlp": [ "Amber" ], - "threatintel.indicator.provider": "Default Organization", - "threatintel.indicator.type": "file" + "threat.indicator.provider": "Default Organization", + "threat.indicator.type": "file" }, { + "anomali.threatstream.classification": "private", + "anomali.threatstream.confidence": 54, + "anomali.threatstream.detail2": "imported by user 438", + "anomali.threatstream.id": "1133111133", + "anomali.threatstream.itype": "mal_md5", + "anomali.threatstream.maltype": "malware:4rs9qpc1", + "anomali.threatstream.md5": "c38d2e6d", + "anomali.threatstream.resource_uri": "/api/v1/intelligence/P20539380512/", + "anomali.threatstream.severity": "medium", + "anomali.threatstream.source_feed_id": "3600", + "anomali.threatstream.state": "active", + "anomali.threatstream.trusted_circle_ids": [ + "762" + ], + "anomali.threatstream.update_id": "1784507596", + "anomali.threatstream.value_type": "md5", "event.category": "threat", "event.dataset": "threatintel.anomalithreatstream", "event.kind": "enrichment", @@ -639,34 +697,37 @@ "service.type": "threatintel", "tags": [ "", + "forwarded", "threatintel-anomalithreatstream" ], - "threatintel.anomalithreatstream.classification": "private", - "threatintel.anomalithreatstream.confidence": 54, - "threatintel.anomalithreatstream.detail2": "imported by user 438", - "threatintel.anomalithreatstream.id": 1133111133, - "threatintel.anomalithreatstream.itype": "mal_md5", - "threatintel.anomalithreatstream.maltype": "malware:4rs9qpc1", - "threatintel.anomalithreatstream.md5": "c38d2e6d", - "threatintel.anomalithreatstream.resource_uri": "/api/v1/intelligence/P20539380512/", - "threatintel.anomalithreatstream.severity": "medium", - "threatintel.anomalithreatstream.source_feed_id": 3600, - "threatintel.anomalithreatstream.state": "active", - "threatintel.anomalithreatstream.trusted_circle_ids": [ - "762" - ], - "threatintel.anomalithreatstream.update_id": 1784507596, - "threatintel.anomalithreatstream.value_type": "md5", - "threatintel.indicator.confidence": 5, - "threatintel.indicator.first_seen": "2020-10-09T18:30:40.000Z", - "threatintel.indicator.last_seen": "2020-10-09T18:30:40.000Z", - "threatintel.indicator.marking.tlp": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali ThreatStream", + "threat.indicator.confidence": "Med", + "threat.indicator.first_seen": "2020-10-09T18:30:40.000Z", + "threat.indicator.last_seen": "2020-10-09T18:30:40.000Z", + "threat.indicator.marking.tlp": [ "Amber" ], - "threatintel.indicator.provider": "Default Organization", - "threatintel.indicator.type": "file" + "threat.indicator.provider": "Default Organization", + "threat.indicator.type": "file" }, { + "anomali.threatstream.classification": "public", + "anomali.threatstream.confidence": 78, + "anomali.threatstream.detail2": "imported by user 690", + "anomali.threatstream.id": "2543010039", + "anomali.threatstream.itype": "mal_md5", + "anomali.threatstream.maltype": "malware:ghdl7nwwq", + "anomali.threatstream.md5": "67808c", + "anomali.threatstream.resource_uri": "/api/v1/intelligence/P16167095005/", + "anomali.threatstream.severity": "medium", + "anomali.threatstream.source_feed_id": "926", + "anomali.threatstream.state": "active", + "anomali.threatstream.trusted_circle_ids": [ + "751" + ], + "anomali.threatstream.update_id": "2343991526", + "anomali.threatstream.value_type": "md5", "event.category": "threat", "event.dataset": "threatintel.anomalithreatstream", "event.kind": "enrichment", @@ -679,35 +740,40 @@ "service.type": "threatintel", "tags": [ "8ahl", + "forwarded", "ica", "threatintel-anomalithreatstream" ], - "threatintel.anomalithreatstream.classification": "public", - "threatintel.anomalithreatstream.confidence": 78, - "threatintel.anomalithreatstream.detail2": "imported by user 690", - "threatintel.anomalithreatstream.id": 2543010039, - "threatintel.anomalithreatstream.itype": "mal_md5", - "threatintel.anomalithreatstream.maltype": "malware:ghdl7nwwq", - "threatintel.anomalithreatstream.md5": "67808c", - "threatintel.anomalithreatstream.resource_uri": "/api/v1/intelligence/P16167095005/", - "threatintel.anomalithreatstream.severity": "medium", - "threatintel.anomalithreatstream.source_feed_id": 926, - "threatintel.anomalithreatstream.state": "active", - "threatintel.anomalithreatstream.trusted_circle_ids": [ - "751" - ], - "threatintel.anomalithreatstream.update_id": 2343991526, - "threatintel.anomalithreatstream.value_type": "md5", - "threatintel.indicator.confidence": 8, - "threatintel.indicator.first_seen": "2020-10-09T18:30:45.000Z", - "threatintel.indicator.last_seen": "2020-10-09T18:30:45.000Z", - "threatintel.indicator.marking.tlp": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali ThreatStream", + "threat.indicator.confidence": "High", + "threat.indicator.first_seen": "2020-10-09T18:30:45.000Z", + "threat.indicator.last_seen": "2020-10-09T18:30:45.000Z", + "threat.indicator.marking.tlp": [ "White" ], - "threatintel.indicator.provider": "Default Organization", - "threatintel.indicator.type": "file" + "threat.indicator.provider": "Default Organization", + "threat.indicator.type": "file" }, { + "anomali.threatstream.classification": "private", + "anomali.threatstream.confidence": 0, + "anomali.threatstream.detail2": "imported by user 517", + "anomali.threatstream.id": "3233930917", + "anomali.threatstream.itype": "mal_md5", + "anomali.threatstream.maltype": "malware:m5pk44o", + "anomali.threatstream.md5": "efa99", + "anomali.threatstream.resource_uri": "/api/v1/intelligence/P15758111412/", + "anomali.threatstream.severity": "high", + "anomali.threatstream.source_feed_id": "2010", + "anomali.threatstream.state": "active", + "anomali.threatstream.trusted_circle_ids": [ + "390", + "519", + "909" + ], + "anomali.threatstream.update_id": "3008175946", + "anomali.threatstream.value_type": "md5", "event.category": "threat", "event.dataset": "threatintel.anomalithreatstream", "event.kind": "enrichment", @@ -719,38 +785,41 @@ "log.offset": 8774, "service.type": "threatintel", "tags": [ + "forwarded", "gyu-", "iop", "threatintel-anomalithreatstream" ], - "threatintel.anomalithreatstream.classification": "private", - "threatintel.anomalithreatstream.confidence": 0, - "threatintel.anomalithreatstream.detail2": "imported by user 517", - "threatintel.anomalithreatstream.id": 3233930917, - "threatintel.anomalithreatstream.itype": "mal_md5", - "threatintel.anomalithreatstream.maltype": "malware:m5pk44o", - "threatintel.anomalithreatstream.md5": "efa99", - "threatintel.anomalithreatstream.resource_uri": "/api/v1/intelligence/P15758111412/", - "threatintel.anomalithreatstream.severity": "high", - "threatintel.anomalithreatstream.source_feed_id": 2010, - "threatintel.anomalithreatstream.state": "active", - "threatintel.anomalithreatstream.trusted_circle_ids": [ - "390", - "519", - "909" - ], - "threatintel.anomalithreatstream.update_id": 3008175946, - "threatintel.anomalithreatstream.value_type": "md5", - "threatintel.indicator.confidence": 0, - "threatintel.indicator.first_seen": "2020-10-09T18:30:54.000Z", - "threatintel.indicator.last_seen": "2020-10-09T18:30:54.000Z", - "threatintel.indicator.marking.tlp": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali ThreatStream", + "threat.indicator.confidence": "None", + "threat.indicator.first_seen": "2020-10-09T18:30:54.000Z", + "threat.indicator.last_seen": "2020-10-09T18:30:54.000Z", + "threat.indicator.marking.tlp": [ "Amber" ], - "threatintel.indicator.provider": "Default Organization", - "threatintel.indicator.type": "file" + "threat.indicator.provider": "Default Organization", + "threat.indicator.type": "file" }, { + "anomali.threatstream.classification": "private", + "anomali.threatstream.confidence": 34, + "anomali.threatstream.detail2": "imported by user 303", + "anomali.threatstream.id": "1777540600", + "anomali.threatstream.itype": "mal_md5", + "anomali.threatstream.maltype": "malware:-fesxy", + "anomali.threatstream.md5": "e8c1", + "anomali.threatstream.resource_uri": "/api/v1/intelligence/P13990676648/", + "anomali.threatstream.severity": "high", + "anomali.threatstream.source_feed_id": "3201", + "anomali.threatstream.state": "active", + "anomali.threatstream.trusted_circle_ids": [ + "109", + "621", + "718" + ], + "anomali.threatstream.update_id": "2404949482", + "anomali.threatstream.value_type": "md5", "event.category": "threat", "event.dataset": "threatintel.anomalithreatstream", "event.kind": "enrichment", @@ -763,36 +832,37 @@ "service.type": "threatintel", "tags": [ "", + "forwarded", "threatintel-anomalithreatstream" ], - "threatintel.anomalithreatstream.classification": "private", - "threatintel.anomalithreatstream.confidence": 34, - "threatintel.anomalithreatstream.detail2": "imported by user 303", - "threatintel.anomalithreatstream.id": 1777540600, - "threatintel.anomalithreatstream.itype": "mal_md5", - "threatintel.anomalithreatstream.maltype": "malware:-fesxy", - "threatintel.anomalithreatstream.md5": "e8c1", - "threatintel.anomalithreatstream.resource_uri": "/api/v1/intelligence/P13990676648/", - "threatintel.anomalithreatstream.severity": "high", - "threatintel.anomalithreatstream.source_feed_id": 3201, - "threatintel.anomalithreatstream.state": "active", - "threatintel.anomalithreatstream.trusted_circle_ids": [ - "109", - "621", - "718" - ], - "threatintel.anomalithreatstream.update_id": 2404949482, - "threatintel.anomalithreatstream.value_type": "md5", - "threatintel.indicator.confidence": 3, - "threatintel.indicator.first_seen": "2020-10-09T18:30:59.000Z", - "threatintel.indicator.last_seen": "2020-10-09T18:30:59.000Z", - "threatintel.indicator.marking.tlp": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali ThreatStream", + "threat.indicator.confidence": "Med", + "threat.indicator.first_seen": "2020-10-09T18:30:59.000Z", + "threat.indicator.last_seen": "2020-10-09T18:30:59.000Z", + "threat.indicator.marking.tlp": [ "Amber" ], - "threatintel.indicator.provider": "Default Organization", - "threatintel.indicator.type": "file" + "threat.indicator.provider": "Default Organization", + "threat.indicator.type": "file" }, { + "anomali.threatstream.classification": "private", + "anomali.threatstream.confidence": 15, + "anomali.threatstream.detail2": "imported by user 219", + "anomali.threatstream.id": "2796250594", + "anomali.threatstream.itype": "mal_md5", + "anomali.threatstream.maltype": "malware:c1b7kt7", + "anomali.threatstream.md5": "be24", + "anomali.threatstream.resource_uri": "/api/v1/intelligence/P13506696048/", + "anomali.threatstream.severity": "low", + "anomali.threatstream.source_feed_id": "3205", + "anomali.threatstream.state": "active", + "anomali.threatstream.trusted_circle_ids": [ + "559" + ], + "anomali.threatstream.update_id": "3529199846", + "anomali.threatstream.value_type": "md5", "event.category": "threat", "event.dataset": "threatintel.anomalithreatstream", "event.kind": "enrichment", @@ -805,34 +875,39 @@ "service.type": "threatintel", "tags": [ "", + "forwarded", "threatintel-anomalithreatstream" ], - "threatintel.anomalithreatstream.classification": "private", - "threatintel.anomalithreatstream.confidence": 15, - "threatintel.anomalithreatstream.detail2": "imported by user 219", - "threatintel.anomalithreatstream.id": 2796250594, - "threatintel.anomalithreatstream.itype": "mal_md5", - "threatintel.anomalithreatstream.maltype": "malware:c1b7kt7", - "threatintel.anomalithreatstream.md5": "be24", - "threatintel.anomalithreatstream.resource_uri": "/api/v1/intelligence/P13506696048/", - "threatintel.anomalithreatstream.severity": "low", - "threatintel.anomalithreatstream.source_feed_id": 3205, - "threatintel.anomalithreatstream.state": "active", - "threatintel.anomalithreatstream.trusted_circle_ids": [ - "559" - ], - "threatintel.anomalithreatstream.update_id": 3529199846, - "threatintel.anomalithreatstream.value_type": "md5", - "threatintel.indicator.confidence": 2, - "threatintel.indicator.first_seen": "2020-10-09T18:31:10.000Z", - "threatintel.indicator.last_seen": "2020-10-09T18:31:10.000Z", - "threatintel.indicator.marking.tlp": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali ThreatStream", + "threat.indicator.confidence": "Low", + "threat.indicator.first_seen": "2020-10-09T18:31:10.000Z", + "threat.indicator.last_seen": "2020-10-09T18:31:10.000Z", + "threat.indicator.marking.tlp": [ "Amber" ], - "threatintel.indicator.provider": "Default Organization", - "threatintel.indicator.type": "file" + "threat.indicator.provider": "Default Organization", + "threat.indicator.type": "file" }, { + "anomali.threatstream.classification": "public", + "anomali.threatstream.confidence": 56, + "anomali.threatstream.detail2": "imported by user 762", + "anomali.threatstream.id": "2310429917", + "anomali.threatstream.itype": "mal_md5", + "anomali.threatstream.maltype": "malware:slwl", + "anomali.threatstream.md5": "a2678fc", + "anomali.threatstream.resource_uri": "/api/v1/intelligence/P35629727989/", + "anomali.threatstream.severity": "low", + "anomali.threatstream.source_feed_id": "885", + "anomali.threatstream.state": "active", + "anomali.threatstream.trusted_circle_ids": [ + "190", + "495", + "959" + ], + "anomali.threatstream.update_id": "3510871820", + "anomali.threatstream.value_type": "md5", "event.category": "threat", "event.dataset": "threatintel.anomalithreatstream", "event.kind": "enrichment", @@ -845,36 +920,38 @@ "service.type": "threatintel", "tags": [ "", + "forwarded", "threatintel-anomalithreatstream" ], - "threatintel.anomalithreatstream.classification": "public", - "threatintel.anomalithreatstream.confidence": 56, - "threatintel.anomalithreatstream.detail2": "imported by user 762", - "threatintel.anomalithreatstream.id": 2310429917, - "threatintel.anomalithreatstream.itype": "mal_md5", - "threatintel.anomalithreatstream.maltype": "malware:slwl", - "threatintel.anomalithreatstream.md5": "a2678fc", - "threatintel.anomalithreatstream.resource_uri": "/api/v1/intelligence/P35629727989/", - "threatintel.anomalithreatstream.severity": "low", - "threatintel.anomalithreatstream.source_feed_id": 885, - "threatintel.anomalithreatstream.state": "active", - "threatintel.anomalithreatstream.trusted_circle_ids": [ - "190", - "495", - "959" - ], - "threatintel.anomalithreatstream.update_id": 3510871820, - "threatintel.anomalithreatstream.value_type": "md5", - "threatintel.indicator.confidence": 6, - "threatintel.indicator.first_seen": "2020-10-09T18:31:16.000Z", - "threatintel.indicator.last_seen": "2020-10-09T18:31:16.000Z", - "threatintel.indicator.marking.tlp": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali ThreatStream", + "threat.indicator.confidence": "Med", + "threat.indicator.first_seen": "2020-10-09T18:31:16.000Z", + "threat.indicator.last_seen": "2020-10-09T18:31:16.000Z", + "threat.indicator.marking.tlp": [ "White" ], - "threatintel.indicator.provider": "Default Organization", - "threatintel.indicator.type": "file" + "threat.indicator.provider": "Default Organization", + "threat.indicator.type": "file" }, { + "anomali.threatstream.classification": "public", + "anomali.threatstream.confidence": 11, + "anomali.threatstream.detail2": "imported by user 616", + "anomali.threatstream.id": "2853859039", + "anomali.threatstream.itype": "mal_md5", + "anomali.threatstream.maltype": "malware:voc", + "anomali.threatstream.md5": "2ee715a9b", + "anomali.threatstream.resource_uri": "/api/v1/intelligence/P39948074871/", + "anomali.threatstream.severity": "medium", + "anomali.threatstream.source_feed_id": "586", + "anomali.threatstream.state": "active", + "anomali.threatstream.trusted_circle_ids": [ + "454", + "562" + ], + "anomali.threatstream.update_id": "3756244435", + "anomali.threatstream.value_type": "md5", "event.category": "threat", "event.dataset": "threatintel.anomalithreatstream", "event.kind": "enrichment", @@ -887,35 +964,38 @@ "service.type": "threatintel", "tags": [ "", + "forwarded", "threatintel-anomalithreatstream" ], - "threatintel.anomalithreatstream.classification": "public", - "threatintel.anomalithreatstream.confidence": 11, - "threatintel.anomalithreatstream.detail2": "imported by user 616", - "threatintel.anomalithreatstream.id": 2853859039, - "threatintel.anomalithreatstream.itype": "mal_md5", - "threatintel.anomalithreatstream.maltype": "malware:voc", - "threatintel.anomalithreatstream.md5": "2ee715a9b", - "threatintel.anomalithreatstream.resource_uri": "/api/v1/intelligence/P39948074871/", - "threatintel.anomalithreatstream.severity": "medium", - "threatintel.anomalithreatstream.source_feed_id": 586, - "threatintel.anomalithreatstream.state": "active", - "threatintel.anomalithreatstream.trusted_circle_ids": [ - "454", - "562" - ], - "threatintel.anomalithreatstream.update_id": 3756244435, - "threatintel.anomalithreatstream.value_type": "md5", - "threatintel.indicator.confidence": 1, - "threatintel.indicator.first_seen": "2020-10-09T18:31:22.000Z", - "threatintel.indicator.last_seen": "2020-10-09T18:31:22.000Z", - "threatintel.indicator.marking.tlp": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali ThreatStream", + "threat.indicator.confidence": "Low", + "threat.indicator.first_seen": "2020-10-09T18:31:22.000Z", + "threat.indicator.last_seen": "2020-10-09T18:31:22.000Z", + "threat.indicator.marking.tlp": [ "White" ], - "threatintel.indicator.provider": "Default Organization", - "threatintel.indicator.type": "file" + "threat.indicator.provider": "Default Organization", + "threat.indicator.type": "file" }, { + "anomali.threatstream.classification": "private", + "anomali.threatstream.confidence": 51, + "anomali.threatstream.detail2": "imported by user 510", + "anomali.threatstream.id": "2328858169", + "anomali.threatstream.itype": "mal_md5", + "anomali.threatstream.maltype": "malware:yuq33pg5", + "anomali.threatstream.md5": "e1df8d", + "anomali.threatstream.resource_uri": "/api/v1/intelligence/P30902643017/", + "anomali.threatstream.severity": "very-high", + "anomali.threatstream.source_feed_id": "826", + "anomali.threatstream.state": "active", + "anomali.threatstream.trusted_circle_ids": [ + "362", + "846" + ], + "anomali.threatstream.update_id": "1410682100", + "anomali.threatstream.value_type": "md5", "event.category": "threat", "event.dataset": "threatintel.anomalithreatstream", "event.kind": "enrichment", @@ -928,39 +1008,41 @@ "service.type": "threatintel", "tags": [ "etukwxhs", + "forwarded", "g0vc9", "gcgm1we6l", "mask=203.0.113.182", "threat=bm-uj8c12", "threatintel-anomalithreatstream" ], - "threatintel.anomalithreatstream.classification": "private", - "threatintel.anomalithreatstream.confidence": 51, - "threatintel.anomalithreatstream.detail2": "imported by user 510", - "threatintel.anomalithreatstream.id": 2328858169, - "threatintel.anomalithreatstream.itype": "mal_md5", - "threatintel.anomalithreatstream.maltype": "malware:yuq33pg5", - "threatintel.anomalithreatstream.md5": "e1df8d", - "threatintel.anomalithreatstream.resource_uri": "/api/v1/intelligence/P30902643017/", - "threatintel.anomalithreatstream.severity": "very-high", - "threatintel.anomalithreatstream.source_feed_id": 826, - "threatintel.anomalithreatstream.state": "active", - "threatintel.anomalithreatstream.trusted_circle_ids": [ - "362", - "846" - ], - "threatintel.anomalithreatstream.update_id": 1410682100, - "threatintel.anomalithreatstream.value_type": "md5", - "threatintel.indicator.confidence": 5, - "threatintel.indicator.first_seen": "2020-10-09T18:31:27.000Z", - "threatintel.indicator.last_seen": "2020-10-09T18:31:27.000Z", - "threatintel.indicator.marking.tlp": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali ThreatStream", + "threat.indicator.confidence": "Med", + "threat.indicator.first_seen": "2020-10-09T18:31:27.000Z", + "threat.indicator.last_seen": "2020-10-09T18:31:27.000Z", + "threat.indicator.marking.tlp": [ "Amber" ], - "threatintel.indicator.provider": "Default Organization", - "threatintel.indicator.type": "file" + "threat.indicator.provider": "Default Organization", + "threat.indicator.type": "file" }, { + "anomali.threatstream.classification": "public", + "anomali.threatstream.confidence": -1, + "anomali.threatstream.detail2": "imported by user 14", + "anomali.threatstream.id": "1145199430", + "anomali.threatstream.itype": "mal_md5", + "anomali.threatstream.maltype": "malware:qc6c9qt", + "anomali.threatstream.md5": "9006d07f", + "anomali.threatstream.resource_uri": "/api/v1/intelligence/P14842247088/", + "anomali.threatstream.severity": "very-high", + "anomali.threatstream.source_feed_id": "1793", + "anomali.threatstream.state": "active", + "anomali.threatstream.trusted_circle_ids": [ + "305" + ], + "anomali.threatstream.update_id": "1592676961", + "anomali.threatstream.value_type": "md5", "event.category": "threat", "event.dataset": "threatintel.anomalithreatstream", "event.kind": "enrichment", @@ -973,33 +1055,36 @@ "service.type": "threatintel", "tags": [ "", + "forwarded", "threatintel-anomalithreatstream" ], - "threatintel.anomalithreatstream.classification": "public", - "threatintel.anomalithreatstream.confidence": -1, - "threatintel.anomalithreatstream.detail2": "imported by user 14", - "threatintel.anomalithreatstream.id": 1145199430, - "threatintel.anomalithreatstream.itype": "mal_md5", - "threatintel.anomalithreatstream.maltype": "malware:qc6c9qt", - "threatintel.anomalithreatstream.md5": "9006d07f", - "threatintel.anomalithreatstream.resource_uri": "/api/v1/intelligence/P14842247088/", - "threatintel.anomalithreatstream.severity": "very-high", - "threatintel.anomalithreatstream.source_feed_id": 1793, - "threatintel.anomalithreatstream.state": "active", - "threatintel.anomalithreatstream.trusted_circle_ids": [ - "305" - ], - "threatintel.anomalithreatstream.update_id": 1592676961, - "threatintel.anomalithreatstream.value_type": "md5", - "threatintel.indicator.first_seen": "2020-10-09T18:31:29.000Z", - "threatintel.indicator.last_seen": "2020-10-09T18:31:29.000Z", - "threatintel.indicator.marking.tlp": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali ThreatStream", + "threat.indicator.confidence": "None", + "threat.indicator.first_seen": "2020-10-09T18:31:29.000Z", + "threat.indicator.last_seen": "2020-10-09T18:31:29.000Z", + "threat.indicator.marking.tlp": [ "White" ], - "threatintel.indicator.provider": "Default Organization", - "threatintel.indicator.type": "file" + "threat.indicator.provider": "Default Organization", + "threat.indicator.type": "file" }, { + "anomali.threatstream.classification": "public", + "anomali.threatstream.confidence": 2, + "anomali.threatstream.detail2": "imported by user 600", + "anomali.threatstream.id": "1726466938", + "anomali.threatstream.itype": "phish_url", + "anomali.threatstream.maltype": "malware:t52oo3", + "anomali.threatstream.resource_uri": "/api/v1/intelligence/P39735553093/", + "anomali.threatstream.severity": "high", + "anomali.threatstream.source_feed_id": "1965", + "anomali.threatstream.state": "active", + "anomali.threatstream.trusted_circle_ids": [ + "553" + ], + "anomali.threatstream.update_id": "2718905308", + "anomali.threatstream.value_type": "url", "event.category": "threat", "event.dataset": "threatintel.anomalithreatstream", "event.kind": "enrichment", @@ -1011,42 +1096,46 @@ "log.offset": 12237, "service.type": "threatintel", "tags": [ + "forwarded", "g1wn0g", "threatintel-anomalithreatstream" ], - "threatintel.anomalithreatstream.classification": "public", - "threatintel.anomalithreatstream.confidence": 2, - "threatintel.anomalithreatstream.detail2": "imported by user 600", - "threatintel.anomalithreatstream.id": 1726466938, - "threatintel.anomalithreatstream.itype": "phish_url", - "threatintel.anomalithreatstream.maltype": "malware:t52oo3", - "threatintel.anomalithreatstream.resource_uri": "/api/v1/intelligence/P39735553093/", - "threatintel.anomalithreatstream.severity": "high", - "threatintel.anomalithreatstream.source_feed_id": 1965, - "threatintel.anomalithreatstream.state": "active", - "threatintel.anomalithreatstream.trusted_circle_ids": [ - "553" - ], - "threatintel.anomalithreatstream.update_id": 2718905308, - "threatintel.anomalithreatstream.value_type": "url", - "threatintel.indicator.confidence": 0, - "threatintel.indicator.first_seen": "2020-10-09T18:31:34.000Z", - "threatintel.indicator.geo.country_iso_code": "US", - "threatintel.indicator.ip": "203.0.113.229", - "threatintel.indicator.last_seen": "2020-10-09T18:31:34.000Z", - "threatintel.indicator.marking.tlp": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali ThreatStream", + "threat.indicator.confidence": "Low", + "threat.indicator.first_seen": "2020-10-09T18:31:34.000Z", + "threat.indicator.geo.country_iso_code": "US", + "threat.indicator.ip": "203.0.113.229", + "threat.indicator.last_seen": "2020-10-09T18:31:34.000Z", + "threat.indicator.marking.tlp": [ "White" ], - "threatintel.indicator.provider": "Default Organization", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "faahk3drf.example.net", - "threatintel.indicator.url.full": "http://faahk3drf.example.net/julf98x5/0g1t8f?cbffxs2qv=vwgz", - "threatintel.indicator.url.original": "http://faahk3drf.example.net/julf98x5/0g1t8f?cbffxs2qv=vwgz", - "threatintel.indicator.url.path": "/julf98x5/0g1t8f", - "threatintel.indicator.url.query": "cbffxs2qv=vwgz", - "threatintel.indicator.url.scheme": "http" + "threat.indicator.provider": "Default Organization", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "faahk3drf.example.net", + "threat.indicator.url.full": "http://faahk3drf.example.net/julf98x5/0g1t8f?cbffxs2qv=vwgz", + "threat.indicator.url.original": "http://faahk3drf.example.net/julf98x5/0g1t8f?cbffxs2qv=vwgz", + "threat.indicator.url.path": "/julf98x5/0g1t8f", + "threat.indicator.url.query": "cbffxs2qv=vwgz", + "threat.indicator.url.scheme": "http" }, { + "anomali.threatstream.classification": "public", + "anomali.threatstream.confidence": 71, + "anomali.threatstream.detail2": "imported by user 976", + "anomali.threatstream.id": "1457264389", + "anomali.threatstream.itype": "mal_md5", + "anomali.threatstream.maltype": "malware:nx1qwwprl", + "anomali.threatstream.md5": "f5d", + "anomali.threatstream.resource_uri": "/api/v1/intelligence/P20794801988/", + "anomali.threatstream.severity": "medium", + "anomali.threatstream.source_feed_id": "1437", + "anomali.threatstream.state": "active", + "anomali.threatstream.trusted_circle_ids": [ + "866" + ], + "anomali.threatstream.update_id": "2310970191", + "anomali.threatstream.value_type": "md5", "event.category": "threat", "event.dataset": "threatintel.anomalithreatstream", "event.kind": "enrichment", @@ -1059,35 +1148,40 @@ "service.type": "threatintel", "tags": [ "6rblg", + "forwarded", "pzs4xlqy", "threatintel-anomalithreatstream" ], - "threatintel.anomalithreatstream.classification": "public", - "threatintel.anomalithreatstream.confidence": 71, - "threatintel.anomalithreatstream.detail2": "imported by user 976", - "threatintel.anomalithreatstream.id": 1457264389, - "threatintel.anomalithreatstream.itype": "mal_md5", - "threatintel.anomalithreatstream.maltype": "malware:nx1qwwprl", - "threatintel.anomalithreatstream.md5": "f5d", - "threatintel.anomalithreatstream.resource_uri": "/api/v1/intelligence/P20794801988/", - "threatintel.anomalithreatstream.severity": "medium", - "threatintel.anomalithreatstream.source_feed_id": 1437, - "threatintel.anomalithreatstream.state": "active", - "threatintel.anomalithreatstream.trusted_circle_ids": [ - "866" - ], - "threatintel.anomalithreatstream.update_id": 2310970191, - "threatintel.anomalithreatstream.value_type": "md5", - "threatintel.indicator.confidence": 7, - "threatintel.indicator.first_seen": "2020-10-09T18:31:36.000Z", - "threatintel.indicator.last_seen": "2020-10-09T18:31:36.000Z", - "threatintel.indicator.marking.tlp": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali ThreatStream", + "threat.indicator.confidence": "High", + "threat.indicator.first_seen": "2020-10-09T18:31:36.000Z", + "threat.indicator.last_seen": "2020-10-09T18:31:36.000Z", + "threat.indicator.marking.tlp": [ "White" ], - "threatintel.indicator.provider": "Default Organization", - "threatintel.indicator.type": "file" + "threat.indicator.provider": "Default Organization", + "threat.indicator.type": "file" }, { + "anomali.threatstream.classification": "public", + "anomali.threatstream.confidence": 70, + "anomali.threatstream.detail2": "imported by user 761", + "anomali.threatstream.id": "3532094043", + "anomali.threatstream.itype": "mal_md5", + "anomali.threatstream.maltype": "malware:k1y", + "anomali.threatstream.md5": "cfd9", + "anomali.threatstream.resource_uri": "/api/v1/intelligence/P48760414603/", + "anomali.threatstream.severity": "medium", + "anomali.threatstream.source_feed_id": "2198", + "anomali.threatstream.state": "active", + "anomali.threatstream.trusted_circle_ids": [ + "68", + "70", + "789" + ], + "anomali.threatstream.update_id": "1487534287", + "anomali.threatstream.value_type": "md5", "event.category": "threat", "event.dataset": "threatintel.anomalithreatstream", "event.kind": "enrichment", @@ -1100,36 +1194,37 @@ "service.type": "threatintel", "tags": [ "", + "forwarded", "threatintel-anomalithreatstream" ], - "threatintel.anomalithreatstream.classification": "public", - "threatintel.anomalithreatstream.confidence": 70, - "threatintel.anomalithreatstream.detail2": "imported by user 761", - "threatintel.anomalithreatstream.id": 3532094043, - "threatintel.anomalithreatstream.itype": "mal_md5", - "threatintel.anomalithreatstream.maltype": "malware:k1y", - "threatintel.anomalithreatstream.md5": "cfd9", - "threatintel.anomalithreatstream.resource_uri": "/api/v1/intelligence/P48760414603/", - "threatintel.anomalithreatstream.severity": "medium", - "threatintel.anomalithreatstream.source_feed_id": 2198, - "threatintel.anomalithreatstream.state": "active", - "threatintel.anomalithreatstream.trusted_circle_ids": [ - "68", - "70", - "789" - ], - "threatintel.anomalithreatstream.update_id": 1487534287, - "threatintel.anomalithreatstream.value_type": "md5", - "threatintel.indicator.confidence": 7, - "threatintel.indicator.first_seen": "2020-10-09T18:31:39.000Z", - "threatintel.indicator.last_seen": "2020-10-09T18:31:39.000Z", - "threatintel.indicator.marking.tlp": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali ThreatStream", + "threat.indicator.confidence": "High", + "threat.indicator.first_seen": "2020-10-09T18:31:39.000Z", + "threat.indicator.last_seen": "2020-10-09T18:31:39.000Z", + "threat.indicator.marking.tlp": [ "White" ], - "threatintel.indicator.provider": "Default Organization", - "threatintel.indicator.type": "file" + "threat.indicator.provider": "Default Organization", + "threat.indicator.type": "file" }, { + "anomali.threatstream.classification": "private", + "anomali.threatstream.confidence": 23, + "anomali.threatstream.detail2": "imported by user 680", + "anomali.threatstream.id": "1753194968", + "anomali.threatstream.itype": "mal_md5", + "anomali.threatstream.maltype": "malware:ixlyb", + "anomali.threatstream.md5": "93daa", + "anomali.threatstream.resource_uri": "/api/v1/intelligence/P36997562731/", + "anomali.threatstream.severity": "low", + "anomali.threatstream.source_feed_id": "2101", + "anomali.threatstream.state": "active", + "anomali.threatstream.trusted_circle_ids": [ + "15" + ], + "anomali.threatstream.update_id": "1772862647", + "anomali.threatstream.value_type": "md5", "event.category": "threat", "event.dataset": "threatintel.anomalithreatstream", "event.kind": "enrichment", @@ -1142,35 +1237,38 @@ "service.type": "threatintel", "tags": [ "6rw", + "forwarded", "g80r1d4sj", "threatintel-anomalithreatstream" ], - "threatintel.anomalithreatstream.classification": "private", - "threatintel.anomalithreatstream.confidence": 23, - "threatintel.anomalithreatstream.detail2": "imported by user 680", - "threatintel.anomalithreatstream.id": 1753194968, - "threatintel.anomalithreatstream.itype": "mal_md5", - "threatintel.anomalithreatstream.maltype": "malware:ixlyb", - "threatintel.anomalithreatstream.md5": "93daa", - "threatintel.anomalithreatstream.resource_uri": "/api/v1/intelligence/P36997562731/", - "threatintel.anomalithreatstream.severity": "low", - "threatintel.anomalithreatstream.source_feed_id": 2101, - "threatintel.anomalithreatstream.state": "active", - "threatintel.anomalithreatstream.trusted_circle_ids": [ - "15" - ], - "threatintel.anomalithreatstream.update_id": 1772862647, - "threatintel.anomalithreatstream.value_type": "md5", - "threatintel.indicator.confidence": 2, - "threatintel.indicator.first_seen": "2020-10-09T18:31:43.000Z", - "threatintel.indicator.last_seen": "2020-10-09T18:31:43.000Z", - "threatintel.indicator.marking.tlp": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali ThreatStream", + "threat.indicator.confidence": "Low", + "threat.indicator.first_seen": "2020-10-09T18:31:43.000Z", + "threat.indicator.last_seen": "2020-10-09T18:31:43.000Z", + "threat.indicator.marking.tlp": [ "Amber" ], - "threatintel.indicator.provider": "Default Organization", - "threatintel.indicator.type": "file" + "threat.indicator.provider": "Default Organization", + "threat.indicator.type": "file" }, { + "anomali.threatstream.classification": "public", + "anomali.threatstream.confidence": 0, + "anomali.threatstream.detail2": "imported by user 820", + "anomali.threatstream.id": "3285278133", + "anomali.threatstream.itype": "scan_ip", + "anomali.threatstream.maltype": "malware:1u76t", + "anomali.threatstream.resource_uri": "/api/v1/intelligence/P45121980169/", + "anomali.threatstream.severity": "high", + "anomali.threatstream.source_feed_id": "1152", + "anomali.threatstream.state": "active", + "anomali.threatstream.trusted_circle_ids": [ + "390", + "7" + ], + "anomali.threatstream.update_id": "2657969647", + "anomali.threatstream.value_type": "ip", "event.category": "threat", "event.dataset": "threatintel.anomalithreatstream", "event.kind": "enrichment", @@ -1183,36 +1281,38 @@ "service.type": "threatintel", "tags": [ "", + "forwarded", "threatintel-anomalithreatstream" ], - "threatintel.anomalithreatstream.classification": "public", - "threatintel.anomalithreatstream.confidence": 0, - "threatintel.anomalithreatstream.detail2": "imported by user 820", - "threatintel.anomalithreatstream.id": 3285278133, - "threatintel.anomalithreatstream.itype": "scan_ip", - "threatintel.anomalithreatstream.maltype": "malware:1u76t", - "threatintel.anomalithreatstream.resource_uri": "/api/v1/intelligence/P45121980169/", - "threatintel.anomalithreatstream.severity": "high", - "threatintel.anomalithreatstream.source_feed_id": 1152, - "threatintel.anomalithreatstream.state": "active", - "threatintel.anomalithreatstream.trusted_circle_ids": [ - "390", - "7" - ], - "threatintel.anomalithreatstream.update_id": 2657969647, - "threatintel.anomalithreatstream.value_type": "ip", - "threatintel.indicator.confidence": 0, - "threatintel.indicator.first_seen": "2020-10-09T18:31:49.000Z", - "threatintel.indicator.geo.country_iso_code": "DE", - "threatintel.indicator.ip": "192.0.2.219", - "threatintel.indicator.last_seen": "2020-10-09T18:31:49.000Z", - "threatintel.indicator.marking.tlp": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali ThreatStream", + "threat.indicator.confidence": "None", + "threat.indicator.first_seen": "2020-10-09T18:31:49.000Z", + "threat.indicator.geo.country_iso_code": "DE", + "threat.indicator.ip": "192.0.2.219", + "threat.indicator.last_seen": "2020-10-09T18:31:49.000Z", + "threat.indicator.marking.tlp": [ "White" ], - "threatintel.indicator.provider": "Default Organization", - "threatintel.indicator.type": "ipv4-addr" + "threat.indicator.provider": "Default Organization", + "threat.indicator.type": "ipv4-addr" }, { + "anomali.threatstream.classification": "public", + "anomali.threatstream.confidence": 45, + "anomali.threatstream.detail2": "imported by user 894", + "anomali.threatstream.id": "2098390184", + "anomali.threatstream.itype": "phish_url", + "anomali.threatstream.maltype": "malware:hc-wh", + "anomali.threatstream.resource_uri": "/api/v1/intelligence/P33231447204/", + "anomali.threatstream.severity": "low", + "anomali.threatstream.source_feed_id": "3354", + "anomali.threatstream.state": "active", + "anomali.threatstream.trusted_circle_ids": [ + "846" + ], + "anomali.threatstream.update_id": "2110937414", + "anomali.threatstream.value_type": "url", "event.category": "threat", "event.dataset": "threatintel.anomalithreatstream", "event.kind": "enrichment", @@ -1224,42 +1324,46 @@ "log.offset": 14812, "service.type": "threatintel", "tags": [ + "forwarded", "om0z7", "threatintel-anomalithreatstream" ], - "threatintel.anomalithreatstream.classification": "public", - "threatintel.anomalithreatstream.confidence": 45, - "threatintel.anomalithreatstream.detail2": "imported by user 894", - "threatintel.anomalithreatstream.id": 2098390184, - "threatintel.anomalithreatstream.itype": "phish_url", - "threatintel.anomalithreatstream.maltype": "malware:hc-wh", - "threatintel.anomalithreatstream.resource_uri": "/api/v1/intelligence/P33231447204/", - "threatintel.anomalithreatstream.severity": "low", - "threatintel.anomalithreatstream.source_feed_id": 3354, - "threatintel.anomalithreatstream.state": "active", - "threatintel.anomalithreatstream.trusted_circle_ids": [ - "846" - ], - "threatintel.anomalithreatstream.update_id": 2110937414, - "threatintel.anomalithreatstream.value_type": "url", - "threatintel.indicator.confidence": 5, - "threatintel.indicator.first_seen": "2020-10-09T18:31:49.000Z", - "threatintel.indicator.geo.country_iso_code": "US", - "threatintel.indicator.ip": "192.0.2.208", - "threatintel.indicator.last_seen": "2020-10-09T18:31:49.000Z", - "threatintel.indicator.marking.tlp": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali ThreatStream", + "threat.indicator.confidence": "Med", + "threat.indicator.first_seen": "2020-10-09T18:31:49.000Z", + "threat.indicator.geo.country_iso_code": "US", + "threat.indicator.ip": "192.0.2.208", + "threat.indicator.last_seen": "2020-10-09T18:31:49.000Z", + "threat.indicator.marking.tlp": [ "White" ], - "threatintel.indicator.provider": "Default Organization", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "p9okf0.example.org", - "threatintel.indicator.url.full": "http://p9okf0.example.org/jyb3n8f/f55vfyt48?s2n=0t2d", - "threatintel.indicator.url.original": "http://p9okf0.example.org/jyb3n8f/f55vfyt48?s2n=0t2d", - "threatintel.indicator.url.path": "/jyb3n8f/f55vfyt48", - "threatintel.indicator.url.query": "s2n=0t2d", - "threatintel.indicator.url.scheme": "http" + "threat.indicator.provider": "Default Organization", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "p9okf0.example.org", + "threat.indicator.url.full": "http://p9okf0.example.org/jyb3n8f/f55vfyt48?s2n=0t2d", + "threat.indicator.url.original": "http://p9okf0.example.org/jyb3n8f/f55vfyt48?s2n=0t2d", + "threat.indicator.url.path": "/jyb3n8f/f55vfyt48", + "threat.indicator.url.query": "s2n=0t2d", + "threat.indicator.url.scheme": "http" }, { + "anomali.threatstream.classification": "private", + "anomali.threatstream.confidence": 34, + "anomali.threatstream.detail2": "imported by user 747", + "anomali.threatstream.id": "3367490507", + "anomali.threatstream.itype": "phish_url", + "anomali.threatstream.maltype": "malware:0ua9", + "anomali.threatstream.resource_uri": "/api/v1/intelligence/P34959401147/", + "anomali.threatstream.severity": "low", + "anomali.threatstream.source_feed_id": "959", + "anomali.threatstream.state": "active", + "anomali.threatstream.trusted_circle_ids": [ + "404", + "574" + ], + "anomali.threatstream.update_id": "2335801340", + "anomali.threatstream.value_type": "url", "event.category": "threat", "event.dataset": "threatintel.anomalithreatstream", "event.kind": "enrichment", @@ -1272,42 +1376,47 @@ "service.type": "threatintel", "tags": [ "adeba89", + "forwarded", "threatintel-anomalithreatstream" ], - "threatintel.anomalithreatstream.classification": "private", - "threatintel.anomalithreatstream.confidence": 34, - "threatintel.anomalithreatstream.detail2": "imported by user 747", - "threatintel.anomalithreatstream.id": 3367490507, - "threatintel.anomalithreatstream.itype": "phish_url", - "threatintel.anomalithreatstream.maltype": "malware:0ua9", - "threatintel.anomalithreatstream.resource_uri": "/api/v1/intelligence/P34959401147/", - "threatintel.anomalithreatstream.severity": "low", - "threatintel.anomalithreatstream.source_feed_id": 959, - "threatintel.anomalithreatstream.state": "active", - "threatintel.anomalithreatstream.trusted_circle_ids": [ - "404", - "574" - ], - "threatintel.anomalithreatstream.update_id": 2335801340, - "threatintel.anomalithreatstream.value_type": "url", - "threatintel.indicator.confidence": 3, - "threatintel.indicator.first_seen": "2020-10-09T18:31:58.000Z", - "threatintel.indicator.geo.country_iso_code": "US", - "threatintel.indicator.ip": "203.0.113.105", - "threatintel.indicator.last_seen": "2020-10-09T18:31:58.000Z", - "threatintel.indicator.marking.tlp": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali ThreatStream", + "threat.indicator.confidence": "Med", + "threat.indicator.first_seen": "2020-10-09T18:31:58.000Z", + "threat.indicator.geo.country_iso_code": "US", + "threat.indicator.ip": "203.0.113.105", + "threat.indicator.last_seen": "2020-10-09T18:31:58.000Z", + "threat.indicator.marking.tlp": [ "Amber" ], - "threatintel.indicator.provider": "Default Organization", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "fxkeo24m.example.com", - "threatintel.indicator.url.full": "https://fxkeo24m.example.com/y75tg7sw/jnnu9xmc?apus=ob1hnba4", - "threatintel.indicator.url.original": "https://fxkeo24m.example.com/y75tg7sw/jnnu9xmc?apus=ob1hnba4", - "threatintel.indicator.url.path": "/y75tg7sw/jnnu9xmc", - "threatintel.indicator.url.query": "apus=ob1hnba4", - "threatintel.indicator.url.scheme": "https" + "threat.indicator.provider": "Default Organization", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "fxkeo24m.example.com", + "threat.indicator.url.full": "https://fxkeo24m.example.com/y75tg7sw/jnnu9xmc?apus=ob1hnba4", + "threat.indicator.url.original": "https://fxkeo24m.example.com/y75tg7sw/jnnu9xmc?apus=ob1hnba4", + "threat.indicator.url.path": "/y75tg7sw/jnnu9xmc", + "threat.indicator.url.query": "apus=ob1hnba4", + "threat.indicator.url.scheme": "https" }, { + "anomali.threatstream.classification": "public", + "anomali.threatstream.confidence": 14, + "anomali.threatstream.detail2": "imported by user 604", + "anomali.threatstream.id": "1998649659", + "anomali.threatstream.itype": "mal_md5", + "anomali.threatstream.maltype": "malware:s0anj", + "anomali.threatstream.md5": "b4dd5cf7", + "anomali.threatstream.resource_uri": "/api/v1/intelligence/P21831217400/", + "anomali.threatstream.severity": "medium", + "anomali.threatstream.source_feed_id": "1405", + "anomali.threatstream.state": "active", + "anomali.threatstream.trusted_circle_ids": [ + "422", + "749", + "852" + ], + "anomali.threatstream.update_id": "1339527388", + "anomali.threatstream.value_type": "md5", "event.category": "threat", "event.dataset": "threatintel.anomalithreatstream", "event.kind": "enrichment", @@ -1320,36 +1429,37 @@ "service.type": "threatintel", "tags": [ "", + "forwarded", "threatintel-anomalithreatstream" ], - "threatintel.anomalithreatstream.classification": "public", - "threatintel.anomalithreatstream.confidence": 14, - "threatintel.anomalithreatstream.detail2": "imported by user 604", - "threatintel.anomalithreatstream.id": 1998649659, - "threatintel.anomalithreatstream.itype": "mal_md5", - "threatintel.anomalithreatstream.maltype": "malware:s0anj", - "threatintel.anomalithreatstream.md5": "b4dd5cf7", - "threatintel.anomalithreatstream.resource_uri": "/api/v1/intelligence/P21831217400/", - "threatintel.anomalithreatstream.severity": "medium", - "threatintel.anomalithreatstream.source_feed_id": 1405, - "threatintel.anomalithreatstream.state": "active", - "threatintel.anomalithreatstream.trusted_circle_ids": [ - "422", - "749", - "852" - ], - "threatintel.anomalithreatstream.update_id": 1339527388, - "threatintel.anomalithreatstream.value_type": "md5", - "threatintel.indicator.confidence": 1, - "threatintel.indicator.first_seen": "2020-10-09T18:32:02.000Z", - "threatintel.indicator.last_seen": "2020-10-09T18:32:02.000Z", - "threatintel.indicator.marking.tlp": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali ThreatStream", + "threat.indicator.confidence": "Low", + "threat.indicator.first_seen": "2020-10-09T18:32:02.000Z", + "threat.indicator.last_seen": "2020-10-09T18:32:02.000Z", + "threat.indicator.marking.tlp": [ "White" ], - "threatintel.indicator.provider": "Default Organization", - "threatintel.indicator.type": "file" + "threat.indicator.provider": "Default Organization", + "threat.indicator.type": "file" }, { + "anomali.threatstream.classification": "public", + "anomali.threatstream.confidence": 85, + "anomali.threatstream.detail2": "imported by user 386", + "anomali.threatstream.id": "3005939184", + "anomali.threatstream.itype": "mal_md5", + "anomali.threatstream.maltype": "malware:hn5uajghq", + "anomali.threatstream.md5": "b890cdad", + "anomali.threatstream.resource_uri": "/api/v1/intelligence/P23229581043/", + "anomali.threatstream.severity": "very-high", + "anomali.threatstream.source_feed_id": "652", + "anomali.threatstream.state": "active", + "anomali.threatstream.trusted_circle_ids": [ + "120" + ], + "anomali.threatstream.update_id": "1316735853", + "anomali.threatstream.value_type": "md5", "event.category": "threat", "event.dataset": "threatintel.anomalithreatstream", "event.kind": "enrichment", @@ -1362,35 +1472,40 @@ "service.type": "threatintel", "tags": [ "a-e8lz", + "forwarded", "nj3f", "threatintel-anomalithreatstream" ], - "threatintel.anomalithreatstream.classification": "public", - "threatintel.anomalithreatstream.confidence": 85, - "threatintel.anomalithreatstream.detail2": "imported by user 386", - "threatintel.anomalithreatstream.id": 3005939184, - "threatintel.anomalithreatstream.itype": "mal_md5", - "threatintel.anomalithreatstream.maltype": "malware:hn5uajghq", - "threatintel.anomalithreatstream.md5": "b890cdad", - "threatintel.anomalithreatstream.resource_uri": "/api/v1/intelligence/P23229581043/", - "threatintel.anomalithreatstream.severity": "very-high", - "threatintel.anomalithreatstream.source_feed_id": 652, - "threatintel.anomalithreatstream.state": "active", - "threatintel.anomalithreatstream.trusted_circle_ids": [ - "120" - ], - "threatintel.anomalithreatstream.update_id": 1316735853, - "threatintel.anomalithreatstream.value_type": "md5", - "threatintel.indicator.confidence": 9, - "threatintel.indicator.first_seen": "2020-10-09T18:32:03.000Z", - "threatintel.indicator.last_seen": "2020-10-09T18:32:03.000Z", - "threatintel.indicator.marking.tlp": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali ThreatStream", + "threat.indicator.confidence": "High", + "threat.indicator.first_seen": "2020-10-09T18:32:03.000Z", + "threat.indicator.last_seen": "2020-10-09T18:32:03.000Z", + "threat.indicator.marking.tlp": [ "White" ], - "threatintel.indicator.provider": "Default Organization", - "threatintel.indicator.type": "file" + "threat.indicator.provider": "Default Organization", + "threat.indicator.type": "file" }, { + "anomali.threatstream.classification": "private", + "anomali.threatstream.confidence": 31, + "anomali.threatstream.detail2": "imported by user 706", + "anomali.threatstream.id": "1900495748", + "anomali.threatstream.itype": "mal_md5", + "anomali.threatstream.maltype": "malware:3taf", + "anomali.threatstream.md5": "817", + "anomali.threatstream.resource_uri": "/api/v1/intelligence/P35660572297/", + "anomali.threatstream.severity": "low", + "anomali.threatstream.source_feed_id": "506", + "anomali.threatstream.state": "active", + "anomali.threatstream.trusted_circle_ids": [ + "718", + "828", + "98" + ], + "anomali.threatstream.update_id": "3243777736", + "anomali.threatstream.value_type": "md5", "event.category": "threat", "event.dataset": "threatintel.anomalithreatstream", "event.kind": "enrichment", @@ -1403,36 +1518,38 @@ "service.type": "threatintel", "tags": [ "", + "forwarded", "threatintel-anomalithreatstream" ], - "threatintel.anomalithreatstream.classification": "private", - "threatintel.anomalithreatstream.confidence": 31, - "threatintel.anomalithreatstream.detail2": "imported by user 706", - "threatintel.anomalithreatstream.id": 1900495748, - "threatintel.anomalithreatstream.itype": "mal_md5", - "threatintel.anomalithreatstream.maltype": "malware:3taf", - "threatintel.anomalithreatstream.md5": "817", - "threatintel.anomalithreatstream.resource_uri": "/api/v1/intelligence/P35660572297/", - "threatintel.anomalithreatstream.severity": "low", - "threatintel.anomalithreatstream.source_feed_id": 506, - "threatintel.anomalithreatstream.state": "active", - "threatintel.anomalithreatstream.trusted_circle_ids": [ - "718", - "828", - "98" - ], - "threatintel.anomalithreatstream.update_id": 3243777736, - "threatintel.anomalithreatstream.value_type": "md5", - "threatintel.indicator.confidence": 3, - "threatintel.indicator.first_seen": "2020-10-09T18:32:04.000Z", - "threatintel.indicator.last_seen": "2020-10-09T18:32:04.000Z", - "threatintel.indicator.marking.tlp": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali ThreatStream", + "threat.indicator.confidence": "Med", + "threat.indicator.first_seen": "2020-10-09T18:32:04.000Z", + "threat.indicator.last_seen": "2020-10-09T18:32:04.000Z", + "threat.indicator.marking.tlp": [ "Amber" ], - "threatintel.indicator.provider": "Default Organization", - "threatintel.indicator.type": "file" + "threat.indicator.provider": "Default Organization", + "threat.indicator.type": "file" }, { + "anomali.threatstream.classification": "public", + "anomali.threatstream.confidence": 50, + "anomali.threatstream.detail2": "imported by user 222", + "anomali.threatstream.id": "1040883425", + "anomali.threatstream.itype": "mal_md5", + "anomali.threatstream.maltype": "malware:wsge", + "anomali.threatstream.md5": "a06b", + "anomali.threatstream.resource_uri": "/api/v1/intelligence/P33297645928/", + "anomali.threatstream.severity": "very-high", + "anomali.threatstream.source_feed_id": "146", + "anomali.threatstream.state": "active", + "anomali.threatstream.trusted_circle_ids": [ + "539", + "959" + ], + "anomali.threatstream.update_id": "1284922297", + "anomali.threatstream.value_type": "md5", "event.category": "threat", "event.dataset": "threatintel.anomalithreatstream", "event.kind": "enrichment", @@ -1445,35 +1562,39 @@ "service.type": "threatintel", "tags": [ "", + "forwarded", "threatintel-anomalithreatstream" ], - "threatintel.anomalithreatstream.classification": "public", - "threatintel.anomalithreatstream.confidence": 50, - "threatintel.anomalithreatstream.detail2": "imported by user 222", - "threatintel.anomalithreatstream.id": 1040883425, - "threatintel.anomalithreatstream.itype": "mal_md5", - "threatintel.anomalithreatstream.maltype": "malware:wsge", - "threatintel.anomalithreatstream.md5": "a06b", - "threatintel.anomalithreatstream.resource_uri": "/api/v1/intelligence/P33297645928/", - "threatintel.anomalithreatstream.severity": "very-high", - "threatintel.anomalithreatstream.source_feed_id": 146, - "threatintel.anomalithreatstream.state": "active", - "threatintel.anomalithreatstream.trusted_circle_ids": [ - "539", - "959" - ], - "threatintel.anomalithreatstream.update_id": 1284922297, - "threatintel.anomalithreatstream.value_type": "md5", - "threatintel.indicator.confidence": 5, - "threatintel.indicator.first_seen": "2020-10-09T18:32:08.000Z", - "threatintel.indicator.last_seen": "2020-10-09T18:32:08.000Z", - "threatintel.indicator.marking.tlp": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali ThreatStream", + "threat.indicator.confidence": "Med", + "threat.indicator.first_seen": "2020-10-09T18:32:08.000Z", + "threat.indicator.last_seen": "2020-10-09T18:32:08.000Z", + "threat.indicator.marking.tlp": [ "White" ], - "threatintel.indicator.provider": "Default Organization", - "threatintel.indicator.type": "file" + "threat.indicator.provider": "Default Organization", + "threat.indicator.type": "file" }, { + "anomali.threatstream.classification": "public", + "anomali.threatstream.confidence": 50, + "anomali.threatstream.detail2": "imported by user 414", + "anomali.threatstream.id": "1703603090", + "anomali.threatstream.itype": "mal_md5", + "anomali.threatstream.maltype": "malware:yid8n1", + "anomali.threatstream.md5": "ebd6108", + "anomali.threatstream.resource_uri": "/api/v1/intelligence/P25381157923/", + "anomali.threatstream.severity": "low", + "anomali.threatstream.source_feed_id": "294", + "anomali.threatstream.state": "active", + "anomali.threatstream.trusted_circle_ids": [ + "124", + "394", + "820" + ], + "anomali.threatstream.update_id": "1405107391", + "anomali.threatstream.value_type": "md5", "event.category": "threat", "event.dataset": "threatintel.anomalithreatstream", "event.kind": "enrichment", @@ -1486,36 +1607,38 @@ "service.type": "threatintel", "tags": [ "", + "forwarded", "threatintel-anomalithreatstream" ], - "threatintel.anomalithreatstream.classification": "public", - "threatintel.anomalithreatstream.confidence": 50, - "threatintel.anomalithreatstream.detail2": "imported by user 414", - "threatintel.anomalithreatstream.id": 1703603090, - "threatintel.anomalithreatstream.itype": "mal_md5", - "threatintel.anomalithreatstream.maltype": "malware:yid8n1", - "threatintel.anomalithreatstream.md5": "ebd6108", - "threatintel.anomalithreatstream.resource_uri": "/api/v1/intelligence/P25381157923/", - "threatintel.anomalithreatstream.severity": "low", - "threatintel.anomalithreatstream.source_feed_id": 294, - "threatintel.anomalithreatstream.state": "active", - "threatintel.anomalithreatstream.trusted_circle_ids": [ - "124", - "394", - "820" - ], - "threatintel.anomalithreatstream.update_id": 1405107391, - "threatintel.anomalithreatstream.value_type": "md5", - "threatintel.indicator.confidence": 5, - "threatintel.indicator.first_seen": "2020-10-09T18:32:11.000Z", - "threatintel.indicator.last_seen": "2020-10-09T18:32:11.000Z", - "threatintel.indicator.marking.tlp": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali ThreatStream", + "threat.indicator.confidence": "Med", + "threat.indicator.first_seen": "2020-10-09T18:32:11.000Z", + "threat.indicator.last_seen": "2020-10-09T18:32:11.000Z", + "threat.indicator.marking.tlp": [ "White" ], - "threatintel.indicator.provider": "Default Organization", - "threatintel.indicator.type": "file" + "threat.indicator.provider": "Default Organization", + "threat.indicator.type": "file" }, { + "anomali.threatstream.classification": "private", + "anomali.threatstream.confidence": 6, + "anomali.threatstream.detail2": "imported by user 872", + "anomali.threatstream.id": "1393798645", + "anomali.threatstream.itype": "mal_md5", + "anomali.threatstream.maltype": "malware:aeu2f0", + "anomali.threatstream.md5": "5afe0a", + "anomali.threatstream.resource_uri": "/api/v1/intelligence/P34100122259/", + "anomali.threatstream.severity": "high", + "anomali.threatstream.source_feed_id": "1256", + "anomali.threatstream.state": "active", + "anomali.threatstream.trusted_circle_ids": [ + "386", + "980" + ], + "anomali.threatstream.update_id": "2194495180", + "anomali.threatstream.value_type": "md5", "event.category": "threat", "event.dataset": "threatintel.anomalithreatstream", "event.kind": "enrichment", @@ -1528,35 +1651,36 @@ "service.type": "threatintel", "tags": [ "", + "forwarded", "threatintel-anomalithreatstream" ], - "threatintel.anomalithreatstream.classification": "private", - "threatintel.anomalithreatstream.confidence": 6, - "threatintel.anomalithreatstream.detail2": "imported by user 872", - "threatintel.anomalithreatstream.id": 1393798645, - "threatintel.anomalithreatstream.itype": "mal_md5", - "threatintel.anomalithreatstream.maltype": "malware:aeu2f0", - "threatintel.anomalithreatstream.md5": "5afe0a", - "threatintel.anomalithreatstream.resource_uri": "/api/v1/intelligence/P34100122259/", - "threatintel.anomalithreatstream.severity": "high", - "threatintel.anomalithreatstream.source_feed_id": 1256, - "threatintel.anomalithreatstream.state": "active", - "threatintel.anomalithreatstream.trusted_circle_ids": [ - "386", - "980" - ], - "threatintel.anomalithreatstream.update_id": 2194495180, - "threatintel.anomalithreatstream.value_type": "md5", - "threatintel.indicator.confidence": 1, - "threatintel.indicator.first_seen": "2020-10-09T18:32:19.000Z", - "threatintel.indicator.last_seen": "2020-10-09T18:32:19.000Z", - "threatintel.indicator.marking.tlp": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali ThreatStream", + "threat.indicator.confidence": "Low", + "threat.indicator.first_seen": "2020-10-09T18:32:19.000Z", + "threat.indicator.last_seen": "2020-10-09T18:32:19.000Z", + "threat.indicator.marking.tlp": [ "Amber" ], - "threatintel.indicator.provider": "Default Organization", - "threatintel.indicator.type": "file" + "threat.indicator.provider": "Default Organization", + "threat.indicator.type": "file" }, { + "anomali.threatstream.classification": "public", + "anomali.threatstream.confidence": 46, + "anomali.threatstream.detail2": "imported by user 237", + "anomali.threatstream.id": "3384379889", + "anomali.threatstream.itype": "scan_ip", + "anomali.threatstream.maltype": "malware:w3rx", + "anomali.threatstream.resource_uri": "/api/v1/intelligence/P38445847685/", + "anomali.threatstream.severity": "very-high", + "anomali.threatstream.source_feed_id": "773", + "anomali.threatstream.state": "active", + "anomali.threatstream.trusted_circle_ids": [ + "830" + ], + "anomali.threatstream.update_id": "2280522298", + "anomali.threatstream.value_type": "ip", "event.category": "threat", "event.dataset": "threatintel.anomalithreatstream", "event.kind": "enrichment", @@ -1569,35 +1693,40 @@ "service.type": "threatintel", "tags": [ "", + "forwarded", "threatintel-anomalithreatstream" ], - "threatintel.anomalithreatstream.classification": "public", - "threatintel.anomalithreatstream.confidence": 46, - "threatintel.anomalithreatstream.detail2": "imported by user 237", - "threatintel.anomalithreatstream.id": 3384379889, - "threatintel.anomalithreatstream.itype": "scan_ip", - "threatintel.anomalithreatstream.maltype": "malware:w3rx", - "threatintel.anomalithreatstream.resource_uri": "/api/v1/intelligence/P38445847685/", - "threatintel.anomalithreatstream.severity": "very-high", - "threatintel.anomalithreatstream.source_feed_id": 773, - "threatintel.anomalithreatstream.state": "active", - "threatintel.anomalithreatstream.trusted_circle_ids": [ - "830" - ], - "threatintel.anomalithreatstream.update_id": 2280522298, - "threatintel.anomalithreatstream.value_type": "ip", - "threatintel.indicator.confidence": 5, - "threatintel.indicator.first_seen": "2020-10-09T18:32:30.000Z", - "threatintel.indicator.geo.country_iso_code": "CN", - "threatintel.indicator.ip": "2001:db8:b94f:43d3:f1ef:8964:c8e3:48d4", - "threatintel.indicator.last_seen": "2020-10-09T18:32:30.000Z", - "threatintel.indicator.marking.tlp": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali ThreatStream", + "threat.indicator.confidence": "Med", + "threat.indicator.first_seen": "2020-10-09T18:32:30.000Z", + "threat.indicator.geo.country_iso_code": "CN", + "threat.indicator.ip": "2001:db8:b94f:43d3:f1ef:8964:c8e3:48d4", + "threat.indicator.last_seen": "2020-10-09T18:32:30.000Z", + "threat.indicator.marking.tlp": [ "White" ], - "threatintel.indicator.provider": "Default Organization", - "threatintel.indicator.type": "ipv6-addr" + "threat.indicator.provider": "Default Organization", + "threat.indicator.type": "ipv6-addr" }, { + "anomali.threatstream.classification": "private", + "anomali.threatstream.confidence": 60, + "anomali.threatstream.detail2": "imported by user 317", + "anomali.threatstream.id": "1291701932", + "anomali.threatstream.itype": "mal_md5", + "anomali.threatstream.maltype": "malware:upf65oc8", + "anomali.threatstream.md5": "758a81", + "anomali.threatstream.resource_uri": "/api/v1/intelligence/P40886917073/", + "anomali.threatstream.severity": "medium", + "anomali.threatstream.source_feed_id": "2980", + "anomali.threatstream.state": "active", + "anomali.threatstream.trusted_circle_ids": [ + "407", + "437" + ], + "anomali.threatstream.update_id": "1128332354", + "anomali.threatstream.value_type": "md5", "event.category": "threat", "event.dataset": "threatintel.anomalithreatstream", "event.kind": "enrichment", @@ -1610,35 +1739,38 @@ "service.type": "threatintel", "tags": [ "", + "forwarded", "threatintel-anomalithreatstream" ], - "threatintel.anomalithreatstream.classification": "private", - "threatintel.anomalithreatstream.confidence": 60, - "threatintel.anomalithreatstream.detail2": "imported by user 317", - "threatintel.anomalithreatstream.id": 1291701932, - "threatintel.anomalithreatstream.itype": "mal_md5", - "threatintel.anomalithreatstream.maltype": "malware:upf65oc8", - "threatintel.anomalithreatstream.md5": "758a81", - "threatintel.anomalithreatstream.resource_uri": "/api/v1/intelligence/P40886917073/", - "threatintel.anomalithreatstream.severity": "medium", - "threatintel.anomalithreatstream.source_feed_id": 2980, - "threatintel.anomalithreatstream.state": "active", - "threatintel.anomalithreatstream.trusted_circle_ids": [ - "407", - "437" - ], - "threatintel.anomalithreatstream.update_id": 1128332354, - "threatintel.anomalithreatstream.value_type": "md5", - "threatintel.indicator.confidence": 6, - "threatintel.indicator.first_seen": "2020-10-09T18:32:35.000Z", - "threatintel.indicator.last_seen": "2020-10-09T18:32:35.000Z", - "threatintel.indicator.marking.tlp": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali ThreatStream", + "threat.indicator.confidence": "Med", + "threat.indicator.first_seen": "2020-10-09T18:32:35.000Z", + "threat.indicator.last_seen": "2020-10-09T18:32:35.000Z", + "threat.indicator.marking.tlp": [ "Amber" ], - "threatintel.indicator.provider": "Default Organization", - "threatintel.indicator.type": "file" + "threat.indicator.provider": "Default Organization", + "threat.indicator.type": "file" }, { + "anomali.threatstream.classification": "private", + "anomali.threatstream.confidence": -1, + "anomali.threatstream.detail2": "imported by user 352", + "anomali.threatstream.id": "3279148213", + "anomali.threatstream.itype": "phish_url", + "anomali.threatstream.maltype": "malware:u0e", + "anomali.threatstream.resource_uri": "/api/v1/intelligence/P37449871811/", + "anomali.threatstream.severity": "very-high", + "anomali.threatstream.source_feed_id": "2315", + "anomali.threatstream.state": "active", + "anomali.threatstream.trusted_circle_ids": [ + "29", + "817", + "831" + ], + "anomali.threatstream.update_id": "2267992225", + "anomali.threatstream.value_type": "url", "event.category": "threat", "event.dataset": "threatintel.anomalithreatstream", "event.kind": "enrichment", @@ -1650,43 +1782,47 @@ "log.offset": 19948, "service.type": "threatintel", "tags": [ + "forwarded", "threatintel-anomalithreatstream", "ziqdk" ], - "threatintel.anomalithreatstream.classification": "private", - "threatintel.anomalithreatstream.confidence": -1, - "threatintel.anomalithreatstream.detail2": "imported by user 352", - "threatintel.anomalithreatstream.id": 3279148213, - "threatintel.anomalithreatstream.itype": "phish_url", - "threatintel.anomalithreatstream.maltype": "malware:u0e", - "threatintel.anomalithreatstream.resource_uri": "/api/v1/intelligence/P37449871811/", - "threatintel.anomalithreatstream.severity": "very-high", - "threatintel.anomalithreatstream.source_feed_id": 2315, - "threatintel.anomalithreatstream.state": "active", - "threatintel.anomalithreatstream.trusted_circle_ids": [ - "29", - "817", - "831" - ], - "threatintel.anomalithreatstream.update_id": 2267992225, - "threatintel.anomalithreatstream.value_type": "url", - "threatintel.indicator.first_seen": "2020-10-09T18:33:10.000Z", - "threatintel.indicator.geo.country_iso_code": "US", - "threatintel.indicator.ip": "203.0.113.16", - "threatintel.indicator.last_seen": "2020-10-09T18:33:10.000Z", - "threatintel.indicator.marking.tlp": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali ThreatStream", + "threat.indicator.confidence": "None", + "threat.indicator.first_seen": "2020-10-09T18:33:10.000Z", + "threat.indicator.geo.country_iso_code": "US", + "threat.indicator.ip": "203.0.113.16", + "threat.indicator.last_seen": "2020-10-09T18:33:10.000Z", + "threat.indicator.marking.tlp": [ "Amber" ], - "threatintel.indicator.provider": "Default Organization", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "ke4ffyj5.example.com", - "threatintel.indicator.url.full": "http://ke4ffyj5.example.com/t-9ikyrtt/ai91?s6u=3y1", - "threatintel.indicator.url.original": "http://ke4ffyj5.example.com/t-9ikyrtt/ai91?s6u=3y1", - "threatintel.indicator.url.path": "/t-9ikyrtt/ai91", - "threatintel.indicator.url.query": "s6u=3y1", - "threatintel.indicator.url.scheme": "http" + "threat.indicator.provider": "Default Organization", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "ke4ffyj5.example.com", + "threat.indicator.url.full": "http://ke4ffyj5.example.com/t-9ikyrtt/ai91?s6u=3y1", + "threat.indicator.url.original": "http://ke4ffyj5.example.com/t-9ikyrtt/ai91?s6u=3y1", + "threat.indicator.url.path": "/t-9ikyrtt/ai91", + "threat.indicator.url.query": "s6u=3y1", + "threat.indicator.url.scheme": "http" }, { + "anomali.threatstream.classification": "public", + "anomali.threatstream.confidence": 42, + "anomali.threatstream.detail2": "imported by user 768", + "anomali.threatstream.id": "2138145846", + "anomali.threatstream.itype": "mal_md5", + "anomali.threatstream.maltype": "malware:-shiotjs", + "anomali.threatstream.md5": "c9b4", + "anomali.threatstream.resource_uri": "/api/v1/intelligence/P24530928152/", + "anomali.threatstream.severity": "very-high", + "anomali.threatstream.source_feed_id": "837", + "anomali.threatstream.state": "active", + "anomali.threatstream.trusted_circle_ids": [ + "322", + "410" + ], + "anomali.threatstream.update_id": "3812327380", + "anomali.threatstream.value_type": "md5", "event.category": "threat", "event.dataset": "threatintel.anomalithreatstream", "event.kind": "enrichment", @@ -1699,35 +1835,38 @@ "service.type": "threatintel", "tags": [ "", + "forwarded", "threatintel-anomalithreatstream" ], - "threatintel.anomalithreatstream.classification": "public", - "threatintel.anomalithreatstream.confidence": 42, - "threatintel.anomalithreatstream.detail2": "imported by user 768", - "threatintel.anomalithreatstream.id": 2138145846, - "threatintel.anomalithreatstream.itype": "mal_md5", - "threatintel.anomalithreatstream.maltype": "malware:-shiotjs", - "threatintel.anomalithreatstream.md5": "c9b4", - "threatintel.anomalithreatstream.resource_uri": "/api/v1/intelligence/P24530928152/", - "threatintel.anomalithreatstream.severity": "very-high", - "threatintel.anomalithreatstream.source_feed_id": 837, - "threatintel.anomalithreatstream.state": "active", - "threatintel.anomalithreatstream.trusted_circle_ids": [ - "322", - "410" - ], - "threatintel.anomalithreatstream.update_id": 3812327380, - "threatintel.anomalithreatstream.value_type": "md5", - "threatintel.indicator.confidence": 4, - "threatintel.indicator.first_seen": "2020-10-09T18:33:13.000Z", - "threatintel.indicator.last_seen": "2020-10-09T18:33:13.000Z", - "threatintel.indicator.marking.tlp": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali ThreatStream", + "threat.indicator.confidence": "Med", + "threat.indicator.first_seen": "2020-10-09T18:33:13.000Z", + "threat.indicator.last_seen": "2020-10-09T18:33:13.000Z", + "threat.indicator.marking.tlp": [ "White" ], - "threatintel.indicator.provider": "Default Organization", - "threatintel.indicator.type": "file" + "threat.indicator.provider": "Default Organization", + "threat.indicator.type": "file" }, { + "anomali.threatstream.classification": "public", + "anomali.threatstream.confidence": 25, + "anomali.threatstream.detail2": "imported by user 148", + "anomali.threatstream.id": "1502954738", + "anomali.threatstream.itype": "mal_md5", + "anomali.threatstream.maltype": "malware:c8f0r5d4", + "anomali.threatstream.md5": "ad0", + "anomali.threatstream.resource_uri": "/api/v1/intelligence/P43216360516/", + "anomali.threatstream.severity": "medium", + "anomali.threatstream.source_feed_id": "3786", + "anomali.threatstream.state": "active", + "anomali.threatstream.trusted_circle_ids": [ + "520", + "695" + ], + "anomali.threatstream.update_id": "2085432040", + "anomali.threatstream.value_type": "md5", "event.category": "threat", "event.dataset": "threatintel.anomalithreatstream", "event.kind": "enrichment", @@ -1740,35 +1879,37 @@ "service.type": "threatintel", "tags": [ "", + "forwarded", "threatintel-anomalithreatstream" ], - "threatintel.anomalithreatstream.classification": "public", - "threatintel.anomalithreatstream.confidence": 25, - "threatintel.anomalithreatstream.detail2": "imported by user 148", - "threatintel.anomalithreatstream.id": 1502954738, - "threatintel.anomalithreatstream.itype": "mal_md5", - "threatintel.anomalithreatstream.maltype": "malware:c8f0r5d4", - "threatintel.anomalithreatstream.md5": "ad0", - "threatintel.anomalithreatstream.resource_uri": "/api/v1/intelligence/P43216360516/", - "threatintel.anomalithreatstream.severity": "medium", - "threatintel.anomalithreatstream.source_feed_id": 3786, - "threatintel.anomalithreatstream.state": "active", - "threatintel.anomalithreatstream.trusted_circle_ids": [ - "520", - "695" - ], - "threatintel.anomalithreatstream.update_id": 2085432040, - "threatintel.anomalithreatstream.value_type": "md5", - "threatintel.indicator.confidence": 3, - "threatintel.indicator.first_seen": "2020-10-09T18:33:14.000Z", - "threatintel.indicator.last_seen": "2020-10-09T18:33:14.000Z", - "threatintel.indicator.marking.tlp": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali ThreatStream", + "threat.indicator.confidence": "Low", + "threat.indicator.first_seen": "2020-10-09T18:33:14.000Z", + "threat.indicator.last_seen": "2020-10-09T18:33:14.000Z", + "threat.indicator.marking.tlp": [ "White" ], - "threatintel.indicator.provider": "Default Organization", - "threatintel.indicator.type": "file" + "threat.indicator.provider": "Default Organization", + "threat.indicator.type": "file" }, { + "anomali.threatstream.classification": "private", + "anomali.threatstream.confidence": 56, + "anomali.threatstream.detail2": "imported by user 649", + "anomali.threatstream.id": "2730182815", + "anomali.threatstream.itype": "mal_md5", + "anomali.threatstream.maltype": "malware:2vsd1miq", + "anomali.threatstream.md5": "571957", + "anomali.threatstream.resource_uri": "/api/v1/intelligence/P23842171060/", + "anomali.threatstream.severity": "medium", + "anomali.threatstream.source_feed_id": "2923", + "anomali.threatstream.state": "active", + "anomali.threatstream.trusted_circle_ids": [ + "127" + ], + "anomali.threatstream.update_id": "3768246717", + "anomali.threatstream.value_type": "md5", "event.category": "threat", "event.dataset": "threatintel.anomalithreatstream", "event.kind": "enrichment", @@ -1781,34 +1922,38 @@ "service.type": "threatintel", "tags": [ "", + "forwarded", "threatintel-anomalithreatstream" ], - "threatintel.anomalithreatstream.classification": "private", - "threatintel.anomalithreatstream.confidence": 56, - "threatintel.anomalithreatstream.detail2": "imported by user 649", - "threatintel.anomalithreatstream.id": 2730182815, - "threatintel.anomalithreatstream.itype": "mal_md5", - "threatintel.anomalithreatstream.maltype": "malware:2vsd1miq", - "threatintel.anomalithreatstream.md5": "571957", - "threatintel.anomalithreatstream.resource_uri": "/api/v1/intelligence/P23842171060/", - "threatintel.anomalithreatstream.severity": "medium", - "threatintel.anomalithreatstream.source_feed_id": 2923, - "threatintel.anomalithreatstream.state": "active", - "threatintel.anomalithreatstream.trusted_circle_ids": [ - "127" - ], - "threatintel.anomalithreatstream.update_id": 3768246717, - "threatintel.anomalithreatstream.value_type": "md5", - "threatintel.indicator.confidence": 6, - "threatintel.indicator.first_seen": "2020-10-09T18:33:14.000Z", - "threatintel.indicator.last_seen": "2020-10-09T18:33:14.000Z", - "threatintel.indicator.marking.tlp": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali ThreatStream", + "threat.indicator.confidence": "Med", + "threat.indicator.first_seen": "2020-10-09T18:33:14.000Z", + "threat.indicator.last_seen": "2020-10-09T18:33:14.000Z", + "threat.indicator.marking.tlp": [ "Amber" ], - "threatintel.indicator.provider": "Default Organization", - "threatintel.indicator.type": "file" + "threat.indicator.provider": "Default Organization", + "threat.indicator.type": "file" }, { + "anomali.threatstream.classification": "public", + "anomali.threatstream.confidence": -1, + "anomali.threatstream.detail2": "imported by user 132", + "anomali.threatstream.id": "1649793681", + "anomali.threatstream.itype": "phish_url", + "anomali.threatstream.maltype": "malware:d1q-sdovn", + "anomali.threatstream.resource_uri": "/api/v1/intelligence/P13727067406/", + "anomali.threatstream.severity": "high", + "anomali.threatstream.source_feed_id": "1993", + "anomali.threatstream.state": "active", + "anomali.threatstream.trusted_circle_ids": [ + "176", + "715", + "824" + ], + "anomali.threatstream.update_id": "3498000116", + "anomali.threatstream.value_type": "url", "event.category": "threat", "event.dataset": "threatintel.anomalithreatstream", "event.kind": "enrichment", @@ -1821,42 +1966,45 @@ "service.type": "threatintel", "tags": [ "73d", + "forwarded", "threatintel-anomalithreatstream" ], - "threatintel.anomalithreatstream.classification": "public", - "threatintel.anomalithreatstream.confidence": -1, - "threatintel.anomalithreatstream.detail2": "imported by user 132", - "threatintel.anomalithreatstream.id": 1649793681, - "threatintel.anomalithreatstream.itype": "phish_url", - "threatintel.anomalithreatstream.maltype": "malware:d1q-sdovn", - "threatintel.anomalithreatstream.resource_uri": "/api/v1/intelligence/P13727067406/", - "threatintel.anomalithreatstream.severity": "high", - "threatintel.anomalithreatstream.source_feed_id": 1993, - "threatintel.anomalithreatstream.state": "active", - "threatintel.anomalithreatstream.trusted_circle_ids": [ - "176", - "715", - "824" - ], - "threatintel.anomalithreatstream.update_id": 3498000116, - "threatintel.anomalithreatstream.value_type": "url", - "threatintel.indicator.first_seen": "2020-10-09T18:33:22.000Z", - "threatintel.indicator.geo.country_iso_code": "US", - "threatintel.indicator.ip": "192.0.2.154", - "threatintel.indicator.last_seen": "2020-10-09T18:33:22.000Z", - "threatintel.indicator.marking.tlp": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali ThreatStream", + "threat.indicator.confidence": "None", + "threat.indicator.first_seen": "2020-10-09T18:33:22.000Z", + "threat.indicator.geo.country_iso_code": "US", + "threat.indicator.ip": "192.0.2.154", + "threat.indicator.last_seen": "2020-10-09T18:33:22.000Z", + "threat.indicator.marking.tlp": [ "White" ], - "threatintel.indicator.provider": "Default Organization", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "rl27d.example.net", - "threatintel.indicator.url.full": "https://rl27d.example.net/ko6/4rtt?b12=o4mgzz2kk", - "threatintel.indicator.url.original": "https://rl27d.example.net/ko6/4rtt?b12=o4mgzz2kk", - "threatintel.indicator.url.path": "/ko6/4rtt", - "threatintel.indicator.url.query": "b12=o4mgzz2kk", - "threatintel.indicator.url.scheme": "https" + "threat.indicator.provider": "Default Organization", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "rl27d.example.net", + "threat.indicator.url.full": "https://rl27d.example.net/ko6/4rtt?b12=o4mgzz2kk", + "threat.indicator.url.original": "https://rl27d.example.net/ko6/4rtt?b12=o4mgzz2kk", + "threat.indicator.url.path": "/ko6/4rtt", + "threat.indicator.url.query": "b12=o4mgzz2kk", + "threat.indicator.url.scheme": "https" }, { + "anomali.threatstream.classification": "public", + "anomali.threatstream.confidence": 48, + "anomali.threatstream.detail2": "imported by user 137", + "anomali.threatstream.id": "2195098028", + "anomali.threatstream.itype": "mal_md5", + "anomali.threatstream.maltype": "malware:886x", + "anomali.threatstream.md5": "7f4", + "anomali.threatstream.resource_uri": "/api/v1/intelligence/P39956518309/", + "anomali.threatstream.severity": "low", + "anomali.threatstream.source_feed_id": "1936", + "anomali.threatstream.state": "active", + "anomali.threatstream.trusted_circle_ids": [ + "469" + ], + "anomali.threatstream.update_id": "1238197737", + "anomali.threatstream.value_type": "md5", "event.category": "threat", "event.dataset": "threatintel.anomalithreatstream", "event.kind": "enrichment", @@ -1869,35 +2017,38 @@ "service.type": "threatintel", "tags": [ "e3mm2h", + "forwarded", "knjq-wt", "threatintel-anomalithreatstream" ], - "threatintel.anomalithreatstream.classification": "public", - "threatintel.anomalithreatstream.confidence": 48, - "threatintel.anomalithreatstream.detail2": "imported by user 137", - "threatintel.anomalithreatstream.id": 2195098028, - "threatintel.anomalithreatstream.itype": "mal_md5", - "threatintel.anomalithreatstream.maltype": "malware:886x", - "threatintel.anomalithreatstream.md5": "7f4", - "threatintel.anomalithreatstream.resource_uri": "/api/v1/intelligence/P39956518309/", - "threatintel.anomalithreatstream.severity": "low", - "threatintel.anomalithreatstream.source_feed_id": 1936, - "threatintel.anomalithreatstream.state": "active", - "threatintel.anomalithreatstream.trusted_circle_ids": [ - "469" - ], - "threatintel.anomalithreatstream.update_id": 1238197737, - "threatintel.anomalithreatstream.value_type": "md5", - "threatintel.indicator.confidence": 5, - "threatintel.indicator.first_seen": "2020-10-09T18:33:24.000Z", - "threatintel.indicator.last_seen": "2020-10-09T18:33:24.000Z", - "threatintel.indicator.marking.tlp": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali ThreatStream", + "threat.indicator.confidence": "Med", + "threat.indicator.first_seen": "2020-10-09T18:33:24.000Z", + "threat.indicator.last_seen": "2020-10-09T18:33:24.000Z", + "threat.indicator.marking.tlp": [ "White" ], - "threatintel.indicator.provider": "Default Organization", - "threatintel.indicator.type": "file" + "threat.indicator.provider": "Default Organization", + "threat.indicator.type": "file" }, { + "anomali.threatstream.classification": "private", + "anomali.threatstream.confidence": 62, + "anomali.threatstream.detail2": "imported by user 76", + "anomali.threatstream.id": "2273277634", + "anomali.threatstream.itype": "phish_url", + "anomali.threatstream.maltype": "malware:eem8vy0", + "anomali.threatstream.resource_uri": "/api/v1/intelligence/P28216636081/", + "anomali.threatstream.severity": "high", + "anomali.threatstream.source_feed_id": "2583", + "anomali.threatstream.state": "active", + "anomali.threatstream.trusted_circle_ids": [ + "143", + "22" + ], + "anomali.threatstream.update_id": "3547953290", + "anomali.threatstream.value_type": "url", "event.category": "threat", "event.dataset": "threatintel.anomalithreatstream", "event.kind": "enrichment", @@ -1909,43 +2060,45 @@ "log.offset": 23077, "service.type": "threatintel", "tags": [ + "forwarded", "rb2my5u7", "threatintel-anomalithreatstream" ], - "threatintel.anomalithreatstream.classification": "private", - "threatintel.anomalithreatstream.confidence": 62, - "threatintel.anomalithreatstream.detail2": "imported by user 76", - "threatintel.anomalithreatstream.id": 2273277634, - "threatintel.anomalithreatstream.itype": "phish_url", - "threatintel.anomalithreatstream.maltype": "malware:eem8vy0", - "threatintel.anomalithreatstream.resource_uri": "/api/v1/intelligence/P28216636081/", - "threatintel.anomalithreatstream.severity": "high", - "threatintel.anomalithreatstream.source_feed_id": 2583, - "threatintel.anomalithreatstream.state": "active", - "threatintel.anomalithreatstream.trusted_circle_ids": [ - "143", - "22" - ], - "threatintel.anomalithreatstream.update_id": 3547953290, - "threatintel.anomalithreatstream.value_type": "url", - "threatintel.indicator.confidence": 6, - "threatintel.indicator.first_seen": "2020-10-09T18:33:26.000Z", - "threatintel.indicator.geo.country_iso_code": "US", - "threatintel.indicator.ip": "203.0.113.228", - "threatintel.indicator.last_seen": "2020-10-09T18:33:26.000Z", - "threatintel.indicator.marking.tlp": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali ThreatStream", + "threat.indicator.confidence": "Med", + "threat.indicator.first_seen": "2020-10-09T18:33:26.000Z", + "threat.indicator.geo.country_iso_code": "US", + "threat.indicator.ip": "203.0.113.228", + "threat.indicator.last_seen": "2020-10-09T18:33:26.000Z", + "threat.indicator.marking.tlp": [ "Amber" ], - "threatintel.indicator.provider": "Default Organization", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "6ygk0y.example.com", - "threatintel.indicator.url.full": "http://6ygk0y.example.com/t520/4twe?ql4bhkpop=yfpkef", - "threatintel.indicator.url.original": "http://6ygk0y.example.com/t520/4twe?ql4bhkpop=yfpkef", - "threatintel.indicator.url.path": "/t520/4twe", - "threatintel.indicator.url.query": "ql4bhkpop=yfpkef", - "threatintel.indicator.url.scheme": "http" + "threat.indicator.provider": "Default Organization", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "6ygk0y.example.com", + "threat.indicator.url.full": "http://6ygk0y.example.com/t520/4twe?ql4bhkpop=yfpkef", + "threat.indicator.url.original": "http://6ygk0y.example.com/t520/4twe?ql4bhkpop=yfpkef", + "threat.indicator.url.path": "/t520/4twe", + "threat.indicator.url.query": "ql4bhkpop=yfpkef", + "threat.indicator.url.scheme": "http" }, { + "anomali.threatstream.classification": "private", + "anomali.threatstream.confidence": 47, + "anomali.threatstream.detail2": "imported by user 304", + "anomali.threatstream.id": "1593951372", + "anomali.threatstream.itype": "phish_url", + "anomali.threatstream.maltype": "malware:lrfqa", + "anomali.threatstream.resource_uri": "/api/v1/intelligence/P18416887501/", + "anomali.threatstream.severity": "very-high", + "anomali.threatstream.source_feed_id": "1922", + "anomali.threatstream.state": "active", + "anomali.threatstream.trusted_circle_ids": [ + "281" + ], + "anomali.threatstream.update_id": "3726618139", + "anomali.threatstream.value_type": "url", "event.category": "threat", "event.dataset": "threatintel.anomalithreatstream", "event.kind": "enrichment", @@ -1958,41 +2111,47 @@ "service.type": "threatintel", "tags": [ "3jujb6j", + "forwarded", "threatintel-anomalithreatstream" ], - "threatintel.anomalithreatstream.classification": "private", - "threatintel.anomalithreatstream.confidence": 47, - "threatintel.anomalithreatstream.detail2": "imported by user 304", - "threatintel.anomalithreatstream.id": 1593951372, - "threatintel.anomalithreatstream.itype": "phish_url", - "threatintel.anomalithreatstream.maltype": "malware:lrfqa", - "threatintel.anomalithreatstream.resource_uri": "/api/v1/intelligence/P18416887501/", - "threatintel.anomalithreatstream.severity": "very-high", - "threatintel.anomalithreatstream.source_feed_id": 1922, - "threatintel.anomalithreatstream.state": "active", - "threatintel.anomalithreatstream.trusted_circle_ids": [ - "281" - ], - "threatintel.anomalithreatstream.update_id": 3726618139, - "threatintel.anomalithreatstream.value_type": "url", - "threatintel.indicator.confidence": 5, - "threatintel.indicator.first_seen": "2020-10-09T18:33:27.000Z", - "threatintel.indicator.geo.country_iso_code": "US", - "threatintel.indicator.ip": "203.0.113.38", - "threatintel.indicator.last_seen": "2020-10-09T18:33:27.000Z", - "threatintel.indicator.marking.tlp": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali ThreatStream", + "threat.indicator.confidence": "Med", + "threat.indicator.first_seen": "2020-10-09T18:33:27.000Z", + "threat.indicator.geo.country_iso_code": "US", + "threat.indicator.ip": "203.0.113.38", + "threat.indicator.last_seen": "2020-10-09T18:33:27.000Z", + "threat.indicator.marking.tlp": [ "Amber" ], - "threatintel.indicator.provider": "Default Organization", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "rcsr9o.example.net", - "threatintel.indicator.url.full": "http://rcsr9o.example.net/e6f/08b?8d2y=d-42fr-", - "threatintel.indicator.url.original": "http://rcsr9o.example.net/e6f/08b?8d2y=d-42fr-", - "threatintel.indicator.url.path": "/e6f/08b", - "threatintel.indicator.url.query": "8d2y=d-42fr-", - "threatintel.indicator.url.scheme": "http" + "threat.indicator.provider": "Default Organization", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "rcsr9o.example.net", + "threat.indicator.url.full": "http://rcsr9o.example.net/e6f/08b?8d2y=d-42fr-", + "threat.indicator.url.original": "http://rcsr9o.example.net/e6f/08b?8d2y=d-42fr-", + "threat.indicator.url.path": "/e6f/08b", + "threat.indicator.url.query": "8d2y=d-42fr-", + "threat.indicator.url.scheme": "http" }, { + "anomali.threatstream.classification": "private", + "anomali.threatstream.confidence": -1, + "anomali.threatstream.detail2": "imported by user 578", + "anomali.threatstream.id": "2881597176", + "anomali.threatstream.itype": "mal_md5", + "anomali.threatstream.maltype": "malware:wpo", + "anomali.threatstream.md5": "89a0a684", + "anomali.threatstream.resource_uri": "/api/v1/intelligence/P37162617510/", + "anomali.threatstream.severity": "medium", + "anomali.threatstream.source_feed_id": "1312", + "anomali.threatstream.state": "active", + "anomali.threatstream.trusted_circle_ids": [ + "450", + "588", + "873" + ], + "anomali.threatstream.update_id": "2444963851", + "anomali.threatstream.value_type": "md5", "event.category": "threat", "event.dataset": "threatintel.anomalithreatstream", "event.kind": "enrichment", @@ -2006,35 +2165,39 @@ "tags": [ "2uu9b", "f7ciq9", + "forwarded", "threatintel-anomalithreatstream" ], - "threatintel.anomalithreatstream.classification": "private", - "threatintel.anomalithreatstream.confidence": -1, - "threatintel.anomalithreatstream.detail2": "imported by user 578", - "threatintel.anomalithreatstream.id": 2881597176, - "threatintel.anomalithreatstream.itype": "mal_md5", - "threatintel.anomalithreatstream.maltype": "malware:wpo", - "threatintel.anomalithreatstream.md5": "89a0a684", - "threatintel.anomalithreatstream.resource_uri": "/api/v1/intelligence/P37162617510/", - "threatintel.anomalithreatstream.severity": "medium", - "threatintel.anomalithreatstream.source_feed_id": 1312, - "threatintel.anomalithreatstream.state": "active", - "threatintel.anomalithreatstream.trusted_circle_ids": [ - "450", - "588", - "873" - ], - "threatintel.anomalithreatstream.update_id": 2444963851, - "threatintel.anomalithreatstream.value_type": "md5", - "threatintel.indicator.first_seen": "2020-10-09T18:33:29.000Z", - "threatintel.indicator.last_seen": "2020-10-09T18:33:29.000Z", - "threatintel.indicator.marking.tlp": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali ThreatStream", + "threat.indicator.confidence": "None", + "threat.indicator.first_seen": "2020-10-09T18:33:29.000Z", + "threat.indicator.last_seen": "2020-10-09T18:33:29.000Z", + "threat.indicator.marking.tlp": [ "Amber" ], - "threatintel.indicator.provider": "Default Organization", - "threatintel.indicator.type": "file" + "threat.indicator.provider": "Default Organization", + "threat.indicator.type": "file" }, { + "anomali.threatstream.classification": "private", + "anomali.threatstream.confidence": 51, + "anomali.threatstream.detail2": "imported by user 347", + "anomali.threatstream.id": "1789877636", + "anomali.threatstream.itype": "mal_md5", + "anomali.threatstream.maltype": "malware:f7l", + "anomali.threatstream.md5": "a41f", + "anomali.threatstream.resource_uri": "/api/v1/intelligence/P15884312830/", + "anomali.threatstream.severity": "low", + "anomali.threatstream.source_feed_id": "1250", + "anomali.threatstream.state": "active", + "anomali.threatstream.trusted_circle_ids": [ + "299", + "501", + "551" + ], + "anomali.threatstream.update_id": "3210446946", + "anomali.threatstream.value_type": "md5", "event.category": "threat", "event.dataset": "threatintel.anomalithreatstream", "event.kind": "enrichment", @@ -2047,36 +2210,39 @@ "service.type": "threatintel", "tags": [ "", + "forwarded", "threatintel-anomalithreatstream" ], - "threatintel.anomalithreatstream.classification": "private", - "threatintel.anomalithreatstream.confidence": 51, - "threatintel.anomalithreatstream.detail2": "imported by user 347", - "threatintel.anomalithreatstream.id": 1789877636, - "threatintel.anomalithreatstream.itype": "mal_md5", - "threatintel.anomalithreatstream.maltype": "malware:f7l", - "threatintel.anomalithreatstream.md5": "a41f", - "threatintel.anomalithreatstream.resource_uri": "/api/v1/intelligence/P15884312830/", - "threatintel.anomalithreatstream.severity": "low", - "threatintel.anomalithreatstream.source_feed_id": 1250, - "threatintel.anomalithreatstream.state": "active", - "threatintel.anomalithreatstream.trusted_circle_ids": [ - "299", - "501", - "551" - ], - "threatintel.anomalithreatstream.update_id": 3210446946, - "threatintel.anomalithreatstream.value_type": "md5", - "threatintel.indicator.confidence": 5, - "threatintel.indicator.first_seen": "2020-10-09T18:33:43.000Z", - "threatintel.indicator.last_seen": "2020-10-09T18:33:43.000Z", - "threatintel.indicator.marking.tlp": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali ThreatStream", + "threat.indicator.confidence": "Med", + "threat.indicator.first_seen": "2020-10-09T18:33:43.000Z", + "threat.indicator.last_seen": "2020-10-09T18:33:43.000Z", + "threat.indicator.marking.tlp": [ "Amber" ], - "threatintel.indicator.provider": "Default Organization", - "threatintel.indicator.type": "file" + "threat.indicator.provider": "Default Organization", + "threat.indicator.type": "file" }, { + "anomali.threatstream.classification": "public", + "anomali.threatstream.confidence": 56, + "anomali.threatstream.detail2": "imported by user 182", + "anomali.threatstream.id": "1300434967", + "anomali.threatstream.itype": "mal_md5", + "anomali.threatstream.maltype": "malware:5kjd", + "anomali.threatstream.md5": "d0f5f32", + "anomali.threatstream.resource_uri": "/api/v1/intelligence/P44427200974/", + "anomali.threatstream.severity": "low", + "anomali.threatstream.source_feed_id": "1603", + "anomali.threatstream.state": "active", + "anomali.threatstream.trusted_circle_ids": [ + "122", + "460", + "615" + ], + "anomali.threatstream.update_id": "2994196701", + "anomali.threatstream.value_type": "md5", "event.category": "threat", "event.dataset": "threatintel.anomalithreatstream", "event.kind": "enrichment", @@ -2089,37 +2255,38 @@ "service.type": "threatintel", "tags": [ "f5c6pl", + "forwarded", "kpjt", "threatintel-anomalithreatstream" ], - "threatintel.anomalithreatstream.classification": "public", - "threatintel.anomalithreatstream.confidence": 56, - "threatintel.anomalithreatstream.detail2": "imported by user 182", - "threatintel.anomalithreatstream.id": 1300434967, - "threatintel.anomalithreatstream.itype": "mal_md5", - "threatintel.anomalithreatstream.maltype": "malware:5kjd", - "threatintel.anomalithreatstream.md5": "d0f5f32", - "threatintel.anomalithreatstream.resource_uri": "/api/v1/intelligence/P44427200974/", - "threatintel.anomalithreatstream.severity": "low", - "threatintel.anomalithreatstream.source_feed_id": 1603, - "threatintel.anomalithreatstream.state": "active", - "threatintel.anomalithreatstream.trusted_circle_ids": [ - "122", - "460", - "615" - ], - "threatintel.anomalithreatstream.update_id": 2994196701, - "threatintel.anomalithreatstream.value_type": "md5", - "threatintel.indicator.confidence": 6, - "threatintel.indicator.first_seen": "2020-10-09T18:33:45.000Z", - "threatintel.indicator.last_seen": "2020-10-09T18:33:45.000Z", - "threatintel.indicator.marking.tlp": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali ThreatStream", + "threat.indicator.confidence": "Med", + "threat.indicator.first_seen": "2020-10-09T18:33:45.000Z", + "threat.indicator.last_seen": "2020-10-09T18:33:45.000Z", + "threat.indicator.marking.tlp": [ "White" ], - "threatintel.indicator.provider": "Default Organization", - "threatintel.indicator.type": "file" + "threat.indicator.provider": "Default Organization", + "threat.indicator.type": "file" }, { + "anomali.threatstream.classification": "private", + "anomali.threatstream.confidence": 79, + "anomali.threatstream.detail2": "imported by user 976", + "anomali.threatstream.id": "2448066635", + "anomali.threatstream.itype": "mal_md5", + "anomali.threatstream.maltype": "malware:7x9cgytj", + "anomali.threatstream.md5": "4f984375b", + "anomali.threatstream.resource_uri": "/api/v1/intelligence/P15169037907/", + "anomali.threatstream.severity": "low", + "anomali.threatstream.source_feed_id": "814", + "anomali.threatstream.state": "active", + "anomali.threatstream.trusted_circle_ids": [ + "804" + ], + "anomali.threatstream.update_id": "2396481494", + "anomali.threatstream.value_type": "md5", "event.category": "threat", "event.dataset": "threatintel.anomalithreatstream", "event.kind": "enrichment", @@ -2132,34 +2299,37 @@ "service.type": "threatintel", "tags": [ "", + "forwarded", "threatintel-anomalithreatstream" ], - "threatintel.anomalithreatstream.classification": "private", - "threatintel.anomalithreatstream.confidence": 79, - "threatintel.anomalithreatstream.detail2": "imported by user 976", - "threatintel.anomalithreatstream.id": 2448066635, - "threatintel.anomalithreatstream.itype": "mal_md5", - "threatintel.anomalithreatstream.maltype": "malware:7x9cgytj", - "threatintel.anomalithreatstream.md5": "4f984375b", - "threatintel.anomalithreatstream.resource_uri": "/api/v1/intelligence/P15169037907/", - "threatintel.anomalithreatstream.severity": "low", - "threatintel.anomalithreatstream.source_feed_id": 814, - "threatintel.anomalithreatstream.state": "active", - "threatintel.anomalithreatstream.trusted_circle_ids": [ - "804" - ], - "threatintel.anomalithreatstream.update_id": 2396481494, - "threatintel.anomalithreatstream.value_type": "md5", - "threatintel.indicator.confidence": 8, - "threatintel.indicator.first_seen": "2020-10-09T18:33:45.000Z", - "threatintel.indicator.last_seen": "2020-10-09T18:33:45.000Z", - "threatintel.indicator.marking.tlp": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali ThreatStream", + "threat.indicator.confidence": "High", + "threat.indicator.first_seen": "2020-10-09T18:33:45.000Z", + "threat.indicator.last_seen": "2020-10-09T18:33:45.000Z", + "threat.indicator.marking.tlp": [ "Amber" ], - "threatintel.indicator.provider": "Default Organization", - "threatintel.indicator.type": "file" + "threat.indicator.provider": "Default Organization", + "threat.indicator.type": "file" }, { + "anomali.threatstream.classification": "public", + "anomali.threatstream.confidence": 15, + "anomali.threatstream.detail2": "imported by user 408", + "anomali.threatstream.id": "1693329110", + "anomali.threatstream.itype": "phish_url", + "anomali.threatstream.maltype": "malware:1l5tib0", + "anomali.threatstream.resource_uri": "/api/v1/intelligence/P46598563676/", + "anomali.threatstream.severity": "medium", + "anomali.threatstream.source_feed_id": "3431", + "anomali.threatstream.state": "active", + "anomali.threatstream.trusted_circle_ids": [ + "301", + "374" + ], + "anomali.threatstream.update_id": "1425004305", + "anomali.threatstream.value_type": "url", "event.category": "threat", "event.dataset": "threatintel.anomalithreatstream", "event.kind": "enrichment", @@ -2172,42 +2342,47 @@ "service.type": "threatintel", "tags": [ "5w8i", + "forwarded", "threatintel-anomalithreatstream" ], - "threatintel.anomalithreatstream.classification": "public", - "threatintel.anomalithreatstream.confidence": 15, - "threatintel.anomalithreatstream.detail2": "imported by user 408", - "threatintel.anomalithreatstream.id": 1693329110, - "threatintel.anomalithreatstream.itype": "phish_url", - "threatintel.anomalithreatstream.maltype": "malware:1l5tib0", - "threatintel.anomalithreatstream.resource_uri": "/api/v1/intelligence/P46598563676/", - "threatintel.anomalithreatstream.severity": "medium", - "threatintel.anomalithreatstream.source_feed_id": 3431, - "threatintel.anomalithreatstream.state": "active", - "threatintel.anomalithreatstream.trusted_circle_ids": [ - "301", - "374" - ], - "threatintel.anomalithreatstream.update_id": 1425004305, - "threatintel.anomalithreatstream.value_type": "url", - "threatintel.indicator.confidence": 2, - "threatintel.indicator.first_seen": "2020-10-09T18:33:48.000Z", - "threatintel.indicator.geo.country_iso_code": "US", - "threatintel.indicator.ip": "192.0.2.115", - "threatintel.indicator.last_seen": "2020-10-09T18:33:48.000Z", - "threatintel.indicator.marking.tlp": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali ThreatStream", + "threat.indicator.confidence": "Low", + "threat.indicator.first_seen": "2020-10-09T18:33:48.000Z", + "threat.indicator.geo.country_iso_code": "US", + "threat.indicator.ip": "192.0.2.115", + "threat.indicator.last_seen": "2020-10-09T18:33:48.000Z", + "threat.indicator.marking.tlp": [ "White" ], - "threatintel.indicator.provider": "Default Organization", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "cc7d.example.com", - "threatintel.indicator.url.full": "https://cc7d.example.com/kxxwobg/hd6omn?tr8=essb", - "threatintel.indicator.url.original": "https://cc7d.example.com/kxxwobg/hd6omn?tr8=essb", - "threatintel.indicator.url.path": "/kxxwobg/hd6omn", - "threatintel.indicator.url.query": "tr8=essb", - "threatintel.indicator.url.scheme": "https" + "threat.indicator.provider": "Default Organization", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "cc7d.example.com", + "threat.indicator.url.full": "https://cc7d.example.com/kxxwobg/hd6omn?tr8=essb", + "threat.indicator.url.original": "https://cc7d.example.com/kxxwobg/hd6omn?tr8=essb", + "threat.indicator.url.path": "/kxxwobg/hd6omn", + "threat.indicator.url.query": "tr8=essb", + "threat.indicator.url.scheme": "https" }, { + "anomali.threatstream.classification": "private", + "anomali.threatstream.confidence": 35, + "anomali.threatstream.detail2": "imported by user 843", + "anomali.threatstream.id": "1522150430", + "anomali.threatstream.itype": "mal_md5", + "anomali.threatstream.maltype": "malware:8-8a", + "anomali.threatstream.md5": "9c67037e6", + "anomali.threatstream.resource_uri": "/api/v1/intelligence/P28645937174/", + "anomali.threatstream.severity": "medium", + "anomali.threatstream.source_feed_id": "2342", + "anomali.threatstream.state": "active", + "anomali.threatstream.trusted_circle_ids": [ + "27", + "396", + "989" + ], + "anomali.threatstream.update_id": "3573181354", + "anomali.threatstream.value_type": "md5", "event.category": "threat", "event.dataset": "threatintel.anomalithreatstream", "event.kind": "enrichment", @@ -2220,36 +2395,37 @@ "service.type": "threatintel", "tags": [ "", + "forwarded", "threatintel-anomalithreatstream" ], - "threatintel.anomalithreatstream.classification": "private", - "threatintel.anomalithreatstream.confidence": 35, - "threatintel.anomalithreatstream.detail2": "imported by user 843", - "threatintel.anomalithreatstream.id": 1522150430, - "threatintel.anomalithreatstream.itype": "mal_md5", - "threatintel.anomalithreatstream.maltype": "malware:8-8a", - "threatintel.anomalithreatstream.md5": "9c67037e6", - "threatintel.anomalithreatstream.resource_uri": "/api/v1/intelligence/P28645937174/", - "threatintel.anomalithreatstream.severity": "medium", - "threatintel.anomalithreatstream.source_feed_id": 2342, - "threatintel.anomalithreatstream.state": "active", - "threatintel.anomalithreatstream.trusted_circle_ids": [ - "27", - "396", - "989" - ], - "threatintel.anomalithreatstream.update_id": 3573181354, - "threatintel.anomalithreatstream.value_type": "md5", - "threatintel.indicator.confidence": 4, - "threatintel.indicator.first_seen": "2020-10-09T18:33:51.000Z", - "threatintel.indicator.last_seen": "2020-10-09T18:33:51.000Z", - "threatintel.indicator.marking.tlp": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali ThreatStream", + "threat.indicator.confidence": "Med", + "threat.indicator.first_seen": "2020-10-09T18:33:51.000Z", + "threat.indicator.last_seen": "2020-10-09T18:33:51.000Z", + "threat.indicator.marking.tlp": [ "Amber" ], - "threatintel.indicator.provider": "Default Organization", - "threatintel.indicator.type": "file" + "threat.indicator.provider": "Default Organization", + "threat.indicator.type": "file" }, { + "anomali.threatstream.classification": "private", + "anomali.threatstream.confidence": 71, + "anomali.threatstream.detail2": "imported by user 831", + "anomali.threatstream.id": "1760436567", + "anomali.threatstream.itype": "scan_ip", + "anomali.threatstream.maltype": "malware:vy02k4", + "anomali.threatstream.resource_uri": "/api/v1/intelligence/P14276852864/", + "anomali.threatstream.severity": "very-high", + "anomali.threatstream.source_feed_id": "271", + "anomali.threatstream.state": "active", + "anomali.threatstream.trusted_circle_ids": [ + "342", + "504" + ], + "anomali.threatstream.update_id": "1253389383", + "anomali.threatstream.value_type": "ip", "event.category": "threat", "event.dataset": "threatintel.anomalithreatstream", "event.kind": "enrichment", @@ -2262,36 +2438,38 @@ "service.type": "threatintel", "tags": [ "f3ctz7j", + "forwarded", "threatintel-anomalithreatstream" ], - "threatintel.anomalithreatstream.classification": "private", - "threatintel.anomalithreatstream.confidence": 71, - "threatintel.anomalithreatstream.detail2": "imported by user 831", - "threatintel.anomalithreatstream.id": 1760436567, - "threatintel.anomalithreatstream.itype": "scan_ip", - "threatintel.anomalithreatstream.maltype": "malware:vy02k4", - "threatintel.anomalithreatstream.resource_uri": "/api/v1/intelligence/P14276852864/", - "threatintel.anomalithreatstream.severity": "very-high", - "threatintel.anomalithreatstream.source_feed_id": 271, - "threatintel.anomalithreatstream.state": "active", - "threatintel.anomalithreatstream.trusted_circle_ids": [ - "342", - "504" - ], - "threatintel.anomalithreatstream.update_id": 1253389383, - "threatintel.anomalithreatstream.value_type": "ip", - "threatintel.indicator.confidence": 7, - "threatintel.indicator.first_seen": "2020-10-09T18:33:57.000Z", - "threatintel.indicator.geo.country_iso_code": "VN", - "threatintel.indicator.ip": "192.0.2.61", - "threatintel.indicator.last_seen": "2020-10-09T18:33:57.000Z", - "threatintel.indicator.marking.tlp": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali ThreatStream", + "threat.indicator.confidence": "High", + "threat.indicator.first_seen": "2020-10-09T18:33:57.000Z", + "threat.indicator.geo.country_iso_code": "VN", + "threat.indicator.ip": "192.0.2.61", + "threat.indicator.last_seen": "2020-10-09T18:33:57.000Z", + "threat.indicator.marking.tlp": [ "Amber" ], - "threatintel.indicator.provider": "Default Organization", - "threatintel.indicator.type": "ipv4-addr" + "threat.indicator.provider": "Default Organization", + "threat.indicator.type": "ipv4-addr" }, { + "anomali.threatstream.classification": "public", + "anomali.threatstream.confidence": 85, + "anomali.threatstream.detail2": "imported by user 650", + "anomali.threatstream.id": "1925240476", + "anomali.threatstream.itype": "scan_ip", + "anomali.threatstream.maltype": "malware:2bnikxoma", + "anomali.threatstream.resource_uri": "/api/v1/intelligence/P15033658538/", + "anomali.threatstream.severity": "very-high", + "anomali.threatstream.source_feed_id": "1067", + "anomali.threatstream.state": "active", + "anomali.threatstream.trusted_circle_ids": [ + "51" + ], + "anomali.threatstream.update_id": "1098288836", + "anomali.threatstream.value_type": "ip", "event.category": "threat", "event.dataset": "threatintel.anomalithreatstream", "event.kind": "enrichment", @@ -2304,35 +2482,38 @@ "service.type": "threatintel", "tags": [ "", + "forwarded", "threatintel-anomalithreatstream" ], - "threatintel.anomalithreatstream.classification": "public", - "threatintel.anomalithreatstream.confidence": 85, - "threatintel.anomalithreatstream.detail2": "imported by user 650", - "threatintel.anomalithreatstream.id": 1925240476, - "threatintel.anomalithreatstream.itype": "scan_ip", - "threatintel.anomalithreatstream.maltype": "malware:2bnikxoma", - "threatintel.anomalithreatstream.resource_uri": "/api/v1/intelligence/P15033658538/", - "threatintel.anomalithreatstream.severity": "very-high", - "threatintel.anomalithreatstream.source_feed_id": 1067, - "threatintel.anomalithreatstream.state": "active", - "threatintel.anomalithreatstream.trusted_circle_ids": [ - "51" - ], - "threatintel.anomalithreatstream.update_id": 1098288836, - "threatintel.anomalithreatstream.value_type": "ip", - "threatintel.indicator.confidence": 9, - "threatintel.indicator.first_seen": "2020-10-09T18:34:00.000Z", - "threatintel.indicator.geo.country_iso_code": "DE", - "threatintel.indicator.ip": "192.0.2.233", - "threatintel.indicator.last_seen": "2020-10-09T18:34:00.000Z", - "threatintel.indicator.marking.tlp": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali ThreatStream", + "threat.indicator.confidence": "High", + "threat.indicator.first_seen": "2020-10-09T18:34:00.000Z", + "threat.indicator.geo.country_iso_code": "DE", + "threat.indicator.ip": "192.0.2.233", + "threat.indicator.last_seen": "2020-10-09T18:34:00.000Z", + "threat.indicator.marking.tlp": [ "White" ], - "threatintel.indicator.provider": "Default Organization", - "threatintel.indicator.type": "ipv4-addr" + "threat.indicator.provider": "Default Organization", + "threat.indicator.type": "ipv4-addr" }, { + "anomali.threatstream.classification": "private", + "anomali.threatstream.confidence": 91, + "anomali.threatstream.detail2": "imported by user 489", + "anomali.threatstream.id": "3001806953", + "anomali.threatstream.itype": "phish_url", + "anomali.threatstream.maltype": "malware:ak63t", + "anomali.threatstream.resource_uri": "/api/v1/intelligence/P34696300225/", + "anomali.threatstream.severity": "very-high", + "anomali.threatstream.source_feed_id": "782", + "anomali.threatstream.state": "active", + "anomali.threatstream.trusted_circle_ids": [ + "484" + ], + "anomali.threatstream.update_id": "2722308334", + "anomali.threatstream.value_type": "url", "event.category": "threat", "event.dataset": "threatintel.anomalithreatstream", "event.kind": "enrichment", @@ -2344,42 +2525,45 @@ "log.offset": 28355, "service.type": "threatintel", "tags": [ + "forwarded", "threatintel-anomalithreatstream", "v9ycq" ], - "threatintel.anomalithreatstream.classification": "private", - "threatintel.anomalithreatstream.confidence": 91, - "threatintel.anomalithreatstream.detail2": "imported by user 489", - "threatintel.anomalithreatstream.id": 3001806953, - "threatintel.anomalithreatstream.itype": "phish_url", - "threatintel.anomalithreatstream.maltype": "malware:ak63t", - "threatintel.anomalithreatstream.resource_uri": "/api/v1/intelligence/P34696300225/", - "threatintel.anomalithreatstream.severity": "very-high", - "threatintel.anomalithreatstream.source_feed_id": 782, - "threatintel.anomalithreatstream.state": "active", - "threatintel.anomalithreatstream.trusted_circle_ids": [ - "484" - ], - "threatintel.anomalithreatstream.update_id": 2722308334, - "threatintel.anomalithreatstream.value_type": "url", - "threatintel.indicator.confidence": 9, - "threatintel.indicator.first_seen": "2020-10-09T18:34:00.000Z", - "threatintel.indicator.geo.country_iso_code": "US", - "threatintel.indicator.ip": "2001:db8:9850:9607:e204:423b:cade:837e", - "threatintel.indicator.last_seen": "2020-10-09T18:34:00.000Z", - "threatintel.indicator.marking.tlp": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali ThreatStream", + "threat.indicator.confidence": "High", + "threat.indicator.first_seen": "2020-10-09T18:34:00.000Z", + "threat.indicator.geo.country_iso_code": "US", + "threat.indicator.ip": "2001:db8:9850:9607:e204:423b:cade:837e", + "threat.indicator.last_seen": "2020-10-09T18:34:00.000Z", + "threat.indicator.marking.tlp": [ "Amber" ], - "threatintel.indicator.provider": "Default Organization", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "v9aqrp81q.example.net", - "threatintel.indicator.url.full": "http://v9aqrp81q.example.net/psuj4bs/rvp?qufy=ymryh", - "threatintel.indicator.url.original": "http://v9aqrp81q.example.net/psuj4bs/rvp?qufy=ymryh", - "threatintel.indicator.url.path": "/psuj4bs/rvp", - "threatintel.indicator.url.query": "qufy=ymryh", - "threatintel.indicator.url.scheme": "http" + "threat.indicator.provider": "Default Organization", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "v9aqrp81q.example.net", + "threat.indicator.url.full": "http://v9aqrp81q.example.net/psuj4bs/rvp?qufy=ymryh", + "threat.indicator.url.original": "http://v9aqrp81q.example.net/psuj4bs/rvp?qufy=ymryh", + "threat.indicator.url.path": "/psuj4bs/rvp", + "threat.indicator.url.query": "qufy=ymryh", + "threat.indicator.url.scheme": "http" }, { + "anomali.threatstream.classification": "public", + "anomali.threatstream.confidence": -1, + "anomali.threatstream.detail2": "imported by user 453", + "anomali.threatstream.id": "3933431319", + "anomali.threatstream.itype": "scan_ip", + "anomali.threatstream.maltype": "malware:ejrypgr", + "anomali.threatstream.resource_uri": "/api/v1/intelligence/P46019487828/", + "anomali.threatstream.severity": "very-high", + "anomali.threatstream.source_feed_id": "1904", + "anomali.threatstream.state": "active", + "anomali.threatstream.trusted_circle_ids": [ + "444" + ], + "anomali.threatstream.update_id": "3520784497", + "anomali.threatstream.value_type": "ip", "event.category": "threat", "event.dataset": "threatintel.anomalithreatstream", "event.kind": "enrichment", @@ -2392,34 +2576,40 @@ "service.type": "threatintel", "tags": [ "", + "forwarded", "threatintel-anomalithreatstream" ], - "threatintel.anomalithreatstream.classification": "public", - "threatintel.anomalithreatstream.confidence": -1, - "threatintel.anomalithreatstream.detail2": "imported by user 453", - "threatintel.anomalithreatstream.id": 3933431319, - "threatintel.anomalithreatstream.itype": "scan_ip", - "threatintel.anomalithreatstream.maltype": "malware:ejrypgr", - "threatintel.anomalithreatstream.resource_uri": "/api/v1/intelligence/P46019487828/", - "threatintel.anomalithreatstream.severity": "very-high", - "threatintel.anomalithreatstream.source_feed_id": 1904, - "threatintel.anomalithreatstream.state": "active", - "threatintel.anomalithreatstream.trusted_circle_ids": [ - "444" - ], - "threatintel.anomalithreatstream.update_id": 3520784497, - "threatintel.anomalithreatstream.value_type": "ip", - "threatintel.indicator.first_seen": "2020-10-09T18:34:00.000Z", - "threatintel.indicator.geo.country_iso_code": "IN", - "threatintel.indicator.ip": "192.0.2.234", - "threatintel.indicator.last_seen": "2020-10-09T18:34:00.000Z", - "threatintel.indicator.marking.tlp": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali ThreatStream", + "threat.indicator.confidence": "None", + "threat.indicator.first_seen": "2020-10-09T18:34:00.000Z", + "threat.indicator.geo.country_iso_code": "IN", + "threat.indicator.ip": "192.0.2.234", + "threat.indicator.last_seen": "2020-10-09T18:34:00.000Z", + "threat.indicator.marking.tlp": [ "White" ], - "threatintel.indicator.provider": "Default Organization", - "threatintel.indicator.type": "ipv4-addr" + "threat.indicator.provider": "Default Organization", + "threat.indicator.type": "ipv4-addr" }, { + "anomali.threatstream.classification": "private", + "anomali.threatstream.confidence": 95, + "anomali.threatstream.detail2": "imported by user 722", + "anomali.threatstream.id": "1356788940", + "anomali.threatstream.itype": "mal_md5", + "anomali.threatstream.maltype": "malware:q4a", + "anomali.threatstream.md5": "a4fa", + "anomali.threatstream.resource_uri": "/api/v1/intelligence/P30118085912/", + "anomali.threatstream.severity": "high", + "anomali.threatstream.source_feed_id": "3698", + "anomali.threatstream.state": "active", + "anomali.threatstream.trusted_circle_ids": [ + "743", + "936" + ], + "anomali.threatstream.update_id": "3707298072", + "anomali.threatstream.value_type": "md5", "event.category": "threat", "event.dataset": "threatintel.anomalithreatstream", "event.kind": "enrichment", @@ -2431,37 +2621,41 @@ "log.offset": 29493, "service.type": "threatintel", "tags": [ + "forwarded", "qxwn7lw", "threatintel-anomalithreatstream", "xva1ki" ], - "threatintel.anomalithreatstream.classification": "private", - "threatintel.anomalithreatstream.confidence": 95, - "threatintel.anomalithreatstream.detail2": "imported by user 722", - "threatintel.anomalithreatstream.id": 1356788940, - "threatintel.anomalithreatstream.itype": "mal_md5", - "threatintel.anomalithreatstream.maltype": "malware:q4a", - "threatintel.anomalithreatstream.md5": "a4fa", - "threatintel.anomalithreatstream.resource_uri": "/api/v1/intelligence/P30118085912/", - "threatintel.anomalithreatstream.severity": "high", - "threatintel.anomalithreatstream.source_feed_id": 3698, - "threatintel.anomalithreatstream.state": "active", - "threatintel.anomalithreatstream.trusted_circle_ids": [ - "743", - "936" - ], - "threatintel.anomalithreatstream.update_id": 3707298072, - "threatintel.anomalithreatstream.value_type": "md5", - "threatintel.indicator.confidence": 10, - "threatintel.indicator.first_seen": "2020-10-09T18:34:02.000Z", - "threatintel.indicator.last_seen": "2020-10-09T18:34:02.000Z", - "threatintel.indicator.marking.tlp": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali ThreatStream", + "threat.indicator.confidence": "High", + "threat.indicator.first_seen": "2020-10-09T18:34:02.000Z", + "threat.indicator.last_seen": "2020-10-09T18:34:02.000Z", + "threat.indicator.marking.tlp": [ "Amber" ], - "threatintel.indicator.provider": "Default Organization", - "threatintel.indicator.type": "file" + "threat.indicator.provider": "Default Organization", + "threat.indicator.type": "file" }, { + "anomali.threatstream.classification": "private", + "anomali.threatstream.confidence": 6, + "anomali.threatstream.detail2": "imported by user 236", + "anomali.threatstream.id": "3804309005", + "anomali.threatstream.itype": "mal_md5", + "anomali.threatstream.maltype": "malware:2sclqws1s", + "anomali.threatstream.md5": "5e11299", + "anomali.threatstream.resource_uri": "/api/v1/intelligence/P14689465586/", + "anomali.threatstream.severity": "very-high", + "anomali.threatstream.source_feed_id": "342", + "anomali.threatstream.state": "active", + "anomali.threatstream.trusted_circle_ids": [ + "50", + "642", + "948" + ], + "anomali.threatstream.update_id": "3749914856", + "anomali.threatstream.value_type": "md5", "event.category": "threat", "event.dataset": "threatintel.anomalithreatstream", "event.kind": "enrichment", @@ -2473,38 +2667,39 @@ "log.offset": 29986, "service.type": "threatintel", "tags": [ + "forwarded", "r81f4", "threatintel-anomalithreatstream", "wwsw" ], - "threatintel.anomalithreatstream.classification": "private", - "threatintel.anomalithreatstream.confidence": 6, - "threatintel.anomalithreatstream.detail2": "imported by user 236", - "threatintel.anomalithreatstream.id": 3804309005, - "threatintel.anomalithreatstream.itype": "mal_md5", - "threatintel.anomalithreatstream.maltype": "malware:2sclqws1s", - "threatintel.anomalithreatstream.md5": "5e11299", - "threatintel.anomalithreatstream.resource_uri": "/api/v1/intelligence/P14689465586/", - "threatintel.anomalithreatstream.severity": "very-high", - "threatintel.anomalithreatstream.source_feed_id": 342, - "threatintel.anomalithreatstream.state": "active", - "threatintel.anomalithreatstream.trusted_circle_ids": [ - "50", - "642", - "948" - ], - "threatintel.anomalithreatstream.update_id": 3749914856, - "threatintel.anomalithreatstream.value_type": "md5", - "threatintel.indicator.confidence": 1, - "threatintel.indicator.first_seen": "2020-10-09T18:34:05.000Z", - "threatintel.indicator.last_seen": "2020-10-09T18:34:05.000Z", - "threatintel.indicator.marking.tlp": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali ThreatStream", + "threat.indicator.confidence": "Low", + "threat.indicator.first_seen": "2020-10-09T18:34:05.000Z", + "threat.indicator.last_seen": "2020-10-09T18:34:05.000Z", + "threat.indicator.marking.tlp": [ "Amber" ], - "threatintel.indicator.provider": "Default Organization", - "threatintel.indicator.type": "file" + "threat.indicator.provider": "Default Organization", + "threat.indicator.type": "file" }, { + "anomali.threatstream.classification": "private", + "anomali.threatstream.confidence": 15, + "anomali.threatstream.detail2": "imported by user 488", + "anomali.threatstream.id": "1022859708", + "anomali.threatstream.itype": "mal_md5", + "anomali.threatstream.maltype": "malware:9cfecc", + "anomali.threatstream.md5": "22315f8", + "anomali.threatstream.resource_uri": "/api/v1/intelligence/P33092174596/", + "anomali.threatstream.severity": "medium", + "anomali.threatstream.source_feed_id": "2811", + "anomali.threatstream.state": "active", + "anomali.threatstream.trusted_circle_ids": [ + "1" + ], + "anomali.threatstream.update_id": "1637146862", + "anomali.threatstream.value_type": "md5", "event.category": "threat", "event.dataset": "threatintel.anomalithreatstream", "event.kind": "enrichment", @@ -2517,34 +2712,38 @@ "service.type": "threatintel", "tags": [ "", + "forwarded", "threatintel-anomalithreatstream" ], - "threatintel.anomalithreatstream.classification": "private", - "threatintel.anomalithreatstream.confidence": 15, - "threatintel.anomalithreatstream.detail2": "imported by user 488", - "threatintel.anomalithreatstream.id": 1022859708, - "threatintel.anomalithreatstream.itype": "mal_md5", - "threatintel.anomalithreatstream.maltype": "malware:9cfecc", - "threatintel.anomalithreatstream.md5": "22315f8", - "threatintel.anomalithreatstream.resource_uri": "/api/v1/intelligence/P33092174596/", - "threatintel.anomalithreatstream.severity": "medium", - "threatintel.anomalithreatstream.source_feed_id": 2811, - "threatintel.anomalithreatstream.state": "active", - "threatintel.anomalithreatstream.trusted_circle_ids": [ - "1" - ], - "threatintel.anomalithreatstream.update_id": 1637146862, - "threatintel.anomalithreatstream.value_type": "md5", - "threatintel.indicator.confidence": 2, - "threatintel.indicator.first_seen": "2020-10-09T18:34:11.000Z", - "threatintel.indicator.last_seen": "2020-10-09T18:34:11.000Z", - "threatintel.indicator.marking.tlp": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali ThreatStream", + "threat.indicator.confidence": "Low", + "threat.indicator.first_seen": "2020-10-09T18:34:11.000Z", + "threat.indicator.last_seen": "2020-10-09T18:34:11.000Z", + "threat.indicator.marking.tlp": [ "Amber" ], - "threatintel.indicator.provider": "Default Organization", - "threatintel.indicator.type": "file" + "threat.indicator.provider": "Default Organization", + "threat.indicator.type": "file" }, { + "anomali.threatstream.classification": "public", + "anomali.threatstream.confidence": 54, + "anomali.threatstream.detail2": "imported by user 310", + "anomali.threatstream.id": "1581368214", + "anomali.threatstream.itype": "mal_md5", + "anomali.threatstream.maltype": "malware:r7vbej", + "anomali.threatstream.md5": "d4a", + "anomali.threatstream.resource_uri": "/api/v1/intelligence/P28408487114/", + "anomali.threatstream.severity": "high", + "anomali.threatstream.source_feed_id": "1371", + "anomali.threatstream.state": "active", + "anomali.threatstream.trusted_circle_ids": [ + "810", + "910" + ], + "anomali.threatstream.update_id": "1671617316", + "anomali.threatstream.value_type": "md5", "event.category": "threat", "event.dataset": "threatintel.anomalithreatstream", "event.kind": "enrichment", @@ -2557,35 +2756,36 @@ "service.type": "threatintel", "tags": [ "", + "forwarded", "threatintel-anomalithreatstream" ], - "threatintel.anomalithreatstream.classification": "public", - "threatintel.anomalithreatstream.confidence": 54, - "threatintel.anomalithreatstream.detail2": "imported by user 310", - "threatintel.anomalithreatstream.id": 1581368214, - "threatintel.anomalithreatstream.itype": "mal_md5", - "threatintel.anomalithreatstream.maltype": "malware:r7vbej", - "threatintel.anomalithreatstream.md5": "d4a", - "threatintel.anomalithreatstream.resource_uri": "/api/v1/intelligence/P28408487114/", - "threatintel.anomalithreatstream.severity": "high", - "threatintel.anomalithreatstream.source_feed_id": 1371, - "threatintel.anomalithreatstream.state": "active", - "threatintel.anomalithreatstream.trusted_circle_ids": [ - "810", - "910" - ], - "threatintel.anomalithreatstream.update_id": 1671617316, - "threatintel.anomalithreatstream.value_type": "md5", - "threatintel.indicator.confidence": 5, - "threatintel.indicator.first_seen": "2020-10-09T18:34:12.000Z", - "threatintel.indicator.last_seen": "2020-10-09T18:34:12.000Z", - "threatintel.indicator.marking.tlp": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali ThreatStream", + "threat.indicator.confidence": "Med", + "threat.indicator.first_seen": "2020-10-09T18:34:12.000Z", + "threat.indicator.last_seen": "2020-10-09T18:34:12.000Z", + "threat.indicator.marking.tlp": [ "White" ], - "threatintel.indicator.provider": "Default Organization", - "threatintel.indicator.type": "file" + "threat.indicator.provider": "Default Organization", + "threat.indicator.type": "file" }, { + "anomali.threatstream.classification": "public", + "anomali.threatstream.confidence": -1, + "anomali.threatstream.detail2": "imported by user 376", + "anomali.threatstream.id": "3576055846", + "anomali.threatstream.itype": "phish_url", + "anomali.threatstream.maltype": "malware:0qqrz", + "anomali.threatstream.resource_uri": "/api/v1/intelligence/P27429039546/", + "anomali.threatstream.severity": "low", + "anomali.threatstream.source_feed_id": "1808", + "anomali.threatstream.state": "active", + "anomali.threatstream.trusted_circle_ids": [ + "660" + ], + "anomali.threatstream.update_id": "2477226249", + "anomali.threatstream.value_type": "url", "event.category": "threat", "event.dataset": "threatintel.anomalithreatstream", "event.kind": "enrichment", @@ -2597,41 +2797,48 @@ "log.offset": 31451, "service.type": "threatintel", "tags": [ + "forwarded", "gry2doqf", "threatintel-anomalithreatstream" ], - "threatintel.anomalithreatstream.classification": "public", - "threatintel.anomalithreatstream.confidence": -1, - "threatintel.anomalithreatstream.detail2": "imported by user 376", - "threatintel.anomalithreatstream.id": 3576055846, - "threatintel.anomalithreatstream.itype": "phish_url", - "threatintel.anomalithreatstream.maltype": "malware:0qqrz", - "threatintel.anomalithreatstream.resource_uri": "/api/v1/intelligence/P27429039546/", - "threatintel.anomalithreatstream.severity": "low", - "threatintel.anomalithreatstream.source_feed_id": 1808, - "threatintel.anomalithreatstream.state": "active", - "threatintel.anomalithreatstream.trusted_circle_ids": [ - "660" - ], - "threatintel.anomalithreatstream.update_id": 2477226249, - "threatintel.anomalithreatstream.value_type": "url", - "threatintel.indicator.first_seen": "2020-10-09T18:34:17.000Z", - "threatintel.indicator.geo.country_iso_code": "US", - "threatintel.indicator.ip": "203.0.113.83", - "threatintel.indicator.last_seen": "2020-10-09T18:34:17.000Z", - "threatintel.indicator.marking.tlp": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali ThreatStream", + "threat.indicator.confidence": "None", + "threat.indicator.first_seen": "2020-10-09T18:34:17.000Z", + "threat.indicator.geo.country_iso_code": "US", + "threat.indicator.ip": "203.0.113.83", + "threat.indicator.last_seen": "2020-10-09T18:34:17.000Z", + "threat.indicator.marking.tlp": [ "White" ], - "threatintel.indicator.provider": "Default Organization", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "o4kqv8b8.example.net", - "threatintel.indicator.url.full": "https://o4kqv8b8.example.net/gm4d-9gt/v2iqt?x65ry67ao=skta9rp", - "threatintel.indicator.url.original": "https://o4kqv8b8.example.net/gm4d-9gt/v2iqt?x65ry67ao=skta9rp", - "threatintel.indicator.url.path": "/gm4d-9gt/v2iqt", - "threatintel.indicator.url.query": "x65ry67ao=skta9rp", - "threatintel.indicator.url.scheme": "https" + "threat.indicator.provider": "Default Organization", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "o4kqv8b8.example.net", + "threat.indicator.url.full": "https://o4kqv8b8.example.net/gm4d-9gt/v2iqt?x65ry67ao=skta9rp", + "threat.indicator.url.original": "https://o4kqv8b8.example.net/gm4d-9gt/v2iqt?x65ry67ao=skta9rp", + "threat.indicator.url.path": "/gm4d-9gt/v2iqt", + "threat.indicator.url.query": "x65ry67ao=skta9rp", + "threat.indicator.url.scheme": "https" }, { + "anomali.threatstream.classification": "private", + "anomali.threatstream.confidence": 89, + "anomali.threatstream.detail2": "imported by user 748", + "anomali.threatstream.id": "1315247197", + "anomali.threatstream.itype": "mal_md5", + "anomali.threatstream.maltype": "malware:r38g5hbgx", + "anomali.threatstream.md5": "3eac", + "anomali.threatstream.resource_uri": "/api/v1/intelligence/P15092591036/", + "anomali.threatstream.severity": "medium", + "anomali.threatstream.source_feed_id": "206", + "anomali.threatstream.state": "active", + "anomali.threatstream.trusted_circle_ids": [ + "19", + "6", + "954" + ], + "anomali.threatstream.update_id": "1760504719", + "anomali.threatstream.value_type": "md5", "event.category": "threat", "event.dataset": "threatintel.anomalithreatstream", "event.kind": "enrichment", @@ -2644,37 +2851,39 @@ "service.type": "threatintel", "tags": [ "1l9tule2", + "forwarded", "k6p", "threatintel-anomalithreatstream" ], - "threatintel.anomalithreatstream.classification": "private", - "threatintel.anomalithreatstream.confidence": 89, - "threatintel.anomalithreatstream.detail2": "imported by user 748", - "threatintel.anomalithreatstream.id": 1315247197, - "threatintel.anomalithreatstream.itype": "mal_md5", - "threatintel.anomalithreatstream.maltype": "malware:r38g5hbgx", - "threatintel.anomalithreatstream.md5": "3eac", - "threatintel.anomalithreatstream.resource_uri": "/api/v1/intelligence/P15092591036/", - "threatintel.anomalithreatstream.severity": "medium", - "threatintel.anomalithreatstream.source_feed_id": 206, - "threatintel.anomalithreatstream.state": "active", - "threatintel.anomalithreatstream.trusted_circle_ids": [ - "19", - "6", - "954" - ], - "threatintel.anomalithreatstream.update_id": 1760504719, - "threatintel.anomalithreatstream.value_type": "md5", - "threatintel.indicator.confidence": 9, - "threatintel.indicator.first_seen": "2020-10-09T18:34:20.000Z", - "threatintel.indicator.last_seen": "2020-10-09T18:34:20.000Z", - "threatintel.indicator.marking.tlp": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali ThreatStream", + "threat.indicator.confidence": "High", + "threat.indicator.first_seen": "2020-10-09T18:34:20.000Z", + "threat.indicator.last_seen": "2020-10-09T18:34:20.000Z", + "threat.indicator.marking.tlp": [ "Amber" ], - "threatintel.indicator.provider": "Default Organization", - "threatintel.indicator.type": "file" + "threat.indicator.provider": "Default Organization", + "threat.indicator.type": "file" }, { + "anomali.threatstream.classification": "public", + "anomali.threatstream.confidence": 25, + "anomali.threatstream.detail2": "imported by user 380", + "anomali.threatstream.id": "1562423716", + "anomali.threatstream.itype": "mal_md5", + "anomali.threatstream.maltype": "malware:882dlx", + "anomali.threatstream.md5": "59893613", + "anomali.threatstream.resource_uri": "/api/v1/intelligence/P35184012550/", + "anomali.threatstream.severity": "high", + "anomali.threatstream.source_feed_id": "3446", + "anomali.threatstream.state": "active", + "anomali.threatstream.trusted_circle_ids": [ + "392", + "581" + ], + "anomali.threatstream.update_id": "2530088908", + "anomali.threatstream.value_type": "md5", "event.category": "threat", "event.dataset": "threatintel.anomalithreatstream", "event.kind": "enrichment", @@ -2687,36 +2896,40 @@ "service.type": "threatintel", "tags": [ "d9qquxe", + "forwarded", "threatintel-anomalithreatstream", "ulx" ], - "threatintel.anomalithreatstream.classification": "public", - "threatintel.anomalithreatstream.confidence": 25, - "threatintel.anomalithreatstream.detail2": "imported by user 380", - "threatintel.anomalithreatstream.id": 1562423716, - "threatintel.anomalithreatstream.itype": "mal_md5", - "threatintel.anomalithreatstream.maltype": "malware:882dlx", - "threatintel.anomalithreatstream.md5": "59893613", - "threatintel.anomalithreatstream.resource_uri": "/api/v1/intelligence/P35184012550/", - "threatintel.anomalithreatstream.severity": "high", - "threatintel.anomalithreatstream.source_feed_id": 3446, - "threatintel.anomalithreatstream.state": "active", - "threatintel.anomalithreatstream.trusted_circle_ids": [ - "392", - "581" - ], - "threatintel.anomalithreatstream.update_id": 2530088908, - "threatintel.anomalithreatstream.value_type": "md5", - "threatintel.indicator.confidence": 3, - "threatintel.indicator.first_seen": "2020-10-09T18:34:20.000Z", - "threatintel.indicator.last_seen": "2020-10-09T18:34:20.000Z", - "threatintel.indicator.marking.tlp": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali ThreatStream", + "threat.indicator.confidence": "Low", + "threat.indicator.first_seen": "2020-10-09T18:34:20.000Z", + "threat.indicator.last_seen": "2020-10-09T18:34:20.000Z", + "threat.indicator.marking.tlp": [ "White" ], - "threatintel.indicator.provider": "Default Organization", - "threatintel.indicator.type": "file" + "threat.indicator.provider": "Default Organization", + "threat.indicator.type": "file" }, { + "anomali.threatstream.classification": "public", + "anomali.threatstream.confidence": 4, + "anomali.threatstream.detail2": "imported by user 423", + "anomali.threatstream.id": "1470897088", + "anomali.threatstream.itype": "mal_md5", + "anomali.threatstream.maltype": "malware:rwo6s", + "anomali.threatstream.md5": "5facf1f", + "anomali.threatstream.resource_uri": "/api/v1/intelligence/P10368659748/", + "anomali.threatstream.severity": "low", + "anomali.threatstream.source_feed_id": "599", + "anomali.threatstream.state": "active", + "anomali.threatstream.trusted_circle_ids": [ + "591", + "663", + "848" + ], + "anomali.threatstream.update_id": "1937893007", + "anomali.threatstream.value_type": "md5", "event.category": "threat", "event.dataset": "threatintel.anomalithreatstream", "event.kind": "enrichment", @@ -2728,38 +2941,39 @@ "log.offset": 33043, "service.type": "threatintel", "tags": [ + "forwarded", "threatintel-anomalithreatstream", "wsu7l1", "zrb" ], - "threatintel.anomalithreatstream.classification": "public", - "threatintel.anomalithreatstream.confidence": 4, - "threatintel.anomalithreatstream.detail2": "imported by user 423", - "threatintel.anomalithreatstream.id": 1470897088, - "threatintel.anomalithreatstream.itype": "mal_md5", - "threatintel.anomalithreatstream.maltype": "malware:rwo6s", - "threatintel.anomalithreatstream.md5": "5facf1f", - "threatintel.anomalithreatstream.resource_uri": "/api/v1/intelligence/P10368659748/", - "threatintel.anomalithreatstream.severity": "low", - "threatintel.anomalithreatstream.source_feed_id": 599, - "threatintel.anomalithreatstream.state": "active", - "threatintel.anomalithreatstream.trusted_circle_ids": [ - "591", - "663", - "848" - ], - "threatintel.anomalithreatstream.update_id": 1937893007, - "threatintel.anomalithreatstream.value_type": "md5", - "threatintel.indicator.confidence": 0, - "threatintel.indicator.first_seen": "2020-10-09T18:34:32.000Z", - "threatintel.indicator.last_seen": "2020-10-09T18:34:32.000Z", - "threatintel.indicator.marking.tlp": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali ThreatStream", + "threat.indicator.confidence": "Low", + "threat.indicator.first_seen": "2020-10-09T18:34:32.000Z", + "threat.indicator.last_seen": "2020-10-09T18:34:32.000Z", + "threat.indicator.marking.tlp": [ "White" ], - "threatintel.indicator.provider": "Default Organization", - "threatintel.indicator.type": "file" + "threat.indicator.provider": "Default Organization", + "threat.indicator.type": "file" }, { + "anomali.threatstream.classification": "private", + "anomali.threatstream.confidence": 9, + "anomali.threatstream.detail2": "imported by user 983", + "anomali.threatstream.id": "1205553827", + "anomali.threatstream.itype": "mal_md5", + "anomali.threatstream.maltype": "malware:-pbnrmv", + "anomali.threatstream.md5": "708b2c", + "anomali.threatstream.resource_uri": "/api/v1/intelligence/P41514908414/", + "anomali.threatstream.severity": "high", + "anomali.threatstream.source_feed_id": "3751", + "anomali.threatstream.state": "active", + "anomali.threatstream.trusted_circle_ids": [ + "299" + ], + "anomali.threatstream.update_id": "3858315866", + "anomali.threatstream.value_type": "md5", "event.category": "threat", "event.dataset": "threatintel.anomalithreatstream", "event.kind": "enrichment", @@ -2772,34 +2986,37 @@ "service.type": "threatintel", "tags": [ "", + "forwarded", "threatintel-anomalithreatstream" ], - "threatintel.anomalithreatstream.classification": "private", - "threatintel.anomalithreatstream.confidence": 9, - "threatintel.anomalithreatstream.detail2": "imported by user 983", - "threatintel.anomalithreatstream.id": 1205553827, - "threatintel.anomalithreatstream.itype": "mal_md5", - "threatintel.anomalithreatstream.maltype": "malware:-pbnrmv", - "threatintel.anomalithreatstream.md5": "708b2c", - "threatintel.anomalithreatstream.resource_uri": "/api/v1/intelligence/P41514908414/", - "threatintel.anomalithreatstream.severity": "high", - "threatintel.anomalithreatstream.source_feed_id": 3751, - "threatintel.anomalithreatstream.state": "active", - "threatintel.anomalithreatstream.trusted_circle_ids": [ - "299" - ], - "threatintel.anomalithreatstream.update_id": 3858315866, - "threatintel.anomalithreatstream.value_type": "md5", - "threatintel.indicator.confidence": 1, - "threatintel.indicator.first_seen": "2020-10-09T18:34:32.000Z", - "threatintel.indicator.last_seen": "2020-10-09T18:34:32.000Z", - "threatintel.indicator.marking.tlp": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali ThreatStream", + "threat.indicator.confidence": "Low", + "threat.indicator.first_seen": "2020-10-09T18:34:32.000Z", + "threat.indicator.last_seen": "2020-10-09T18:34:32.000Z", + "threat.indicator.marking.tlp": [ "Amber" ], - "threatintel.indicator.provider": "Default Organization", - "threatintel.indicator.type": "file" + "threat.indicator.provider": "Default Organization", + "threat.indicator.type": "file" }, { + "anomali.threatstream.classification": "public", + "anomali.threatstream.confidence": -1, + "anomali.threatstream.detail2": "imported by user 314", + "anomali.threatstream.id": "1744295971", + "anomali.threatstream.itype": "mal_md5", + "anomali.threatstream.maltype": "malware:uqw", + "anomali.threatstream.md5": "0df", + "anomali.threatstream.resource_uri": "/api/v1/intelligence/P36955243007/", + "anomali.threatstream.severity": "low", + "anomali.threatstream.source_feed_id": "2305", + "anomali.threatstream.state": "active", + "anomali.threatstream.trusted_circle_ids": [ + "556" + ], + "anomali.threatstream.update_id": "2655715062", + "anomali.threatstream.value_type": "md5", "event.category": "threat", "event.dataset": "threatintel.anomalithreatstream", "event.kind": "enrichment", @@ -2812,33 +3029,37 @@ "service.type": "threatintel", "tags": [ "", + "forwarded", "threatintel-anomalithreatstream" ], - "threatintel.anomalithreatstream.classification": "public", - "threatintel.anomalithreatstream.confidence": -1, - "threatintel.anomalithreatstream.detail2": "imported by user 314", - "threatintel.anomalithreatstream.id": 1744295971, - "threatintel.anomalithreatstream.itype": "mal_md5", - "threatintel.anomalithreatstream.maltype": "malware:uqw", - "threatintel.anomalithreatstream.md5": "0df", - "threatintel.anomalithreatstream.resource_uri": "/api/v1/intelligence/P36955243007/", - "threatintel.anomalithreatstream.severity": "low", - "threatintel.anomalithreatstream.source_feed_id": 2305, - "threatintel.anomalithreatstream.state": "active", - "threatintel.anomalithreatstream.trusted_circle_ids": [ - "556" - ], - "threatintel.anomalithreatstream.update_id": 2655715062, - "threatintel.anomalithreatstream.value_type": "md5", - "threatintel.indicator.first_seen": "2020-10-09T18:34:39.000Z", - "threatintel.indicator.last_seen": "2020-10-09T18:34:39.000Z", - "threatintel.indicator.marking.tlp": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali ThreatStream", + "threat.indicator.confidence": "None", + "threat.indicator.first_seen": "2020-10-09T18:34:39.000Z", + "threat.indicator.last_seen": "2020-10-09T18:34:39.000Z", + "threat.indicator.marking.tlp": [ "White" ], - "threatintel.indicator.provider": "Default Organization", - "threatintel.indicator.type": "file" + "threat.indicator.provider": "Default Organization", + "threat.indicator.type": "file" }, { + "anomali.threatstream.classification": "private", + "anomali.threatstream.confidence": 45, + "anomali.threatstream.detail2": "imported by user 986", + "anomali.threatstream.id": "1782793990", + "anomali.threatstream.itype": "mal_md5", + "anomali.threatstream.maltype": "malware:mkctzuaaf", + "anomali.threatstream.md5": "770", + "anomali.threatstream.resource_uri": "/api/v1/intelligence/P41751433270/", + "anomali.threatstream.severity": "high", + "anomali.threatstream.source_feed_id": "3513", + "anomali.threatstream.state": "active", + "anomali.threatstream.trusted_circle_ids": [ + "445" + ], + "anomali.threatstream.update_id": "2172945223", + "anomali.threatstream.value_type": "md5", "event.category": "threat", "event.dataset": "threatintel.anomalithreatstream", "event.kind": "enrichment", @@ -2850,36 +3071,38 @@ "log.offset": 34489, "service.type": "threatintel", "tags": [ + "forwarded", "ps2", "qr2wno4", "threatintel-anomalithreatstream" ], - "threatintel.anomalithreatstream.classification": "private", - "threatintel.anomalithreatstream.confidence": 45, - "threatintel.anomalithreatstream.detail2": "imported by user 986", - "threatintel.anomalithreatstream.id": 1782793990, - "threatintel.anomalithreatstream.itype": "mal_md5", - "threatintel.anomalithreatstream.maltype": "malware:mkctzuaaf", - "threatintel.anomalithreatstream.md5": "770", - "threatintel.anomalithreatstream.resource_uri": "/api/v1/intelligence/P41751433270/", - "threatintel.anomalithreatstream.severity": "high", - "threatintel.anomalithreatstream.source_feed_id": 3513, - "threatintel.anomalithreatstream.state": "active", - "threatintel.anomalithreatstream.trusted_circle_ids": [ - "445" - ], - "threatintel.anomalithreatstream.update_id": 2172945223, - "threatintel.anomalithreatstream.value_type": "md5", - "threatintel.indicator.confidence": 5, - "threatintel.indicator.first_seen": "2020-10-09T18:34:40.000Z", - "threatintel.indicator.last_seen": "2020-10-09T18:34:40.000Z", - "threatintel.indicator.marking.tlp": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali ThreatStream", + "threat.indicator.confidence": "Med", + "threat.indicator.first_seen": "2020-10-09T18:34:40.000Z", + "threat.indicator.last_seen": "2020-10-09T18:34:40.000Z", + "threat.indicator.marking.tlp": [ "Amber" ], - "threatintel.indicator.provider": "Default Organization", - "threatintel.indicator.type": "file" + "threat.indicator.provider": "Default Organization", + "threat.indicator.type": "file" }, { + "anomali.threatstream.classification": "public", + "anomali.threatstream.confidence": 98, + "anomali.threatstream.detail2": "imported by user 615", + "anomali.threatstream.id": "1130190904", + "anomali.threatstream.itype": "scan_ip", + "anomali.threatstream.maltype": "malware:3zu2d2", + "anomali.threatstream.resource_uri": "/api/v1/intelligence/P13755730530/", + "anomali.threatstream.severity": "medium", + "anomali.threatstream.source_feed_id": "1192", + "anomali.threatstream.state": "active", + "anomali.threatstream.trusted_circle_ids": [ + "88" + ], + "anomali.threatstream.update_id": "1575621349", + "anomali.threatstream.value_type": "ip", "event.category": "threat", "event.dataset": "threatintel.anomalithreatstream", "event.kind": "enrichment", @@ -2892,35 +3115,39 @@ "service.type": "threatintel", "tags": [ "", + "forwarded", "threatintel-anomalithreatstream" ], - "threatintel.anomalithreatstream.classification": "public", - "threatintel.anomalithreatstream.confidence": 98, - "threatintel.anomalithreatstream.detail2": "imported by user 615", - "threatintel.anomalithreatstream.id": 1130190904, - "threatintel.anomalithreatstream.itype": "scan_ip", - "threatintel.anomalithreatstream.maltype": "malware:3zu2d2", - "threatintel.anomalithreatstream.resource_uri": "/api/v1/intelligence/P13755730530/", - "threatintel.anomalithreatstream.severity": "medium", - "threatintel.anomalithreatstream.source_feed_id": 1192, - "threatintel.anomalithreatstream.state": "active", - "threatintel.anomalithreatstream.trusted_circle_ids": [ - "88" - ], - "threatintel.anomalithreatstream.update_id": 1575621349, - "threatintel.anomalithreatstream.value_type": "ip", - "threatintel.indicator.confidence": 10, - "threatintel.indicator.first_seen": "2020-10-09T18:34:41.000Z", - "threatintel.indicator.geo.country_iso_code": "VN", - "threatintel.indicator.ip": "192.0.2.88", - "threatintel.indicator.last_seen": "2020-10-09T18:34:41.000Z", - "threatintel.indicator.marking.tlp": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali ThreatStream", + "threat.indicator.confidence": "High", + "threat.indicator.first_seen": "2020-10-09T18:34:41.000Z", + "threat.indicator.geo.country_iso_code": "VN", + "threat.indicator.ip": "192.0.2.88", + "threat.indicator.last_seen": "2020-10-09T18:34:41.000Z", + "threat.indicator.marking.tlp": [ "White" ], - "threatintel.indicator.provider": "Default Organization", - "threatintel.indicator.type": "ipv4-addr" + "threat.indicator.provider": "Default Organization", + "threat.indicator.type": "ipv4-addr" }, { + "anomali.threatstream.classification": "public", + "anomali.threatstream.confidence": 17, + "anomali.threatstream.detail2": "imported by user 202", + "anomali.threatstream.id": "2499059829", + "anomali.threatstream.itype": "phish_url", + "anomali.threatstream.maltype": "malware:86-jrf6o", + "anomali.threatstream.resource_uri": "/api/v1/intelligence/P43937262060/", + "anomali.threatstream.severity": "medium", + "anomali.threatstream.source_feed_id": "852", + "anomali.threatstream.state": "active", + "anomali.threatstream.trusted_circle_ids": [ + "308", + "949" + ], + "anomali.threatstream.update_id": "2450069481", + "anomali.threatstream.value_type": "url", "event.category": "threat", "event.dataset": "threatintel.anomalithreatstream", "event.kind": "enrichment", @@ -2933,42 +3160,45 @@ "service.type": "threatintel", "tags": [ "ao6", + "forwarded", "threatintel-anomalithreatstream" ], - "threatintel.anomalithreatstream.classification": "public", - "threatintel.anomalithreatstream.confidence": 17, - "threatintel.anomalithreatstream.detail2": "imported by user 202", - "threatintel.anomalithreatstream.id": 2499059829, - "threatintel.anomalithreatstream.itype": "phish_url", - "threatintel.anomalithreatstream.maltype": "malware:86-jrf6o", - "threatintel.anomalithreatstream.resource_uri": "/api/v1/intelligence/P43937262060/", - "threatintel.anomalithreatstream.severity": "medium", - "threatintel.anomalithreatstream.source_feed_id": 852, - "threatintel.anomalithreatstream.state": "active", - "threatintel.anomalithreatstream.trusted_circle_ids": [ - "308", - "949" - ], - "threatintel.anomalithreatstream.update_id": 2450069481, - "threatintel.anomalithreatstream.value_type": "url", - "threatintel.indicator.confidence": 2, - "threatintel.indicator.first_seen": "2020-10-09T18:34:43.000Z", - "threatintel.indicator.geo.country_iso_code": "US", - "threatintel.indicator.ip": "203.0.113.111", - "threatintel.indicator.last_seen": "2020-10-09T18:34:43.000Z", - "threatintel.indicator.marking.tlp": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali ThreatStream", + "threat.indicator.confidence": "Low", + "threat.indicator.first_seen": "2020-10-09T18:34:43.000Z", + "threat.indicator.geo.country_iso_code": "US", + "threat.indicator.ip": "203.0.113.111", + "threat.indicator.last_seen": "2020-10-09T18:34:43.000Z", + "threat.indicator.marking.tlp": [ "White" ], - "threatintel.indicator.provider": "Default Organization", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "91p0p.example.com", - "threatintel.indicator.url.full": "https://91p0p.example.com/easx3j6iy/xvnchuoa?dvkljl=h21", - "threatintel.indicator.url.original": "https://91p0p.example.com/easx3j6iy/xvnchuoa?dvkljl=h21", - "threatintel.indicator.url.path": "/easx3j6iy/xvnchuoa", - "threatintel.indicator.url.query": "dvkljl=h21", - "threatintel.indicator.url.scheme": "https" + "threat.indicator.provider": "Default Organization", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "91p0p.example.com", + "threat.indicator.url.full": "https://91p0p.example.com/easx3j6iy/xvnchuoa?dvkljl=h21", + "threat.indicator.url.original": "https://91p0p.example.com/easx3j6iy/xvnchuoa?dvkljl=h21", + "threat.indicator.url.path": "/easx3j6iy/xvnchuoa", + "threat.indicator.url.query": "dvkljl=h21", + "threat.indicator.url.scheme": "https" }, { + "anomali.threatstream.classification": "public", + "anomali.threatstream.confidence": 67, + "anomali.threatstream.detail2": "imported by user 421", + "anomali.threatstream.id": "2799251412", + "anomali.threatstream.itype": "mal_md5", + "anomali.threatstream.maltype": "malware:91o2", + "anomali.threatstream.md5": "f9edba87a", + "anomali.threatstream.resource_uri": "/api/v1/intelligence/P31632809876/", + "anomali.threatstream.severity": "medium", + "anomali.threatstream.source_feed_id": "3756", + "anomali.threatstream.state": "active", + "anomali.threatstream.trusted_circle_ids": [ + "776" + ], + "anomali.threatstream.update_id": "3951093865", + "anomali.threatstream.value_type": "md5", "event.category": "threat", "event.dataset": "threatintel.anomalithreatstream", "event.kind": "enrichment", @@ -2981,34 +3211,37 @@ "service.type": "threatintel", "tags": [ "", + "forwarded", "threatintel-anomalithreatstream" ], - "threatintel.anomalithreatstream.classification": "public", - "threatintel.anomalithreatstream.confidence": 67, - "threatintel.anomalithreatstream.detail2": "imported by user 421", - "threatintel.anomalithreatstream.id": 2799251412, - "threatintel.anomalithreatstream.itype": "mal_md5", - "threatintel.anomalithreatstream.maltype": "malware:91o2", - "threatintel.anomalithreatstream.md5": "f9edba87a", - "threatintel.anomalithreatstream.resource_uri": "/api/v1/intelligence/P31632809876/", - "threatintel.anomalithreatstream.severity": "medium", - "threatintel.anomalithreatstream.source_feed_id": 3756, - "threatintel.anomalithreatstream.state": "active", - "threatintel.anomalithreatstream.trusted_circle_ids": [ - "776" - ], - "threatintel.anomalithreatstream.update_id": 3951093865, - "threatintel.anomalithreatstream.value_type": "md5", - "threatintel.indicator.confidence": 7, - "threatintel.indicator.first_seen": "2020-10-09T18:34:48.000Z", - "threatintel.indicator.last_seen": "2020-10-09T18:34:48.000Z", - "threatintel.indicator.marking.tlp": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali ThreatStream", + "threat.indicator.confidence": "Med", + "threat.indicator.first_seen": "2020-10-09T18:34:48.000Z", + "threat.indicator.last_seen": "2020-10-09T18:34:48.000Z", + "threat.indicator.marking.tlp": [ "White" ], - "threatintel.indicator.provider": "Default Organization", - "threatintel.indicator.type": "file" + "threat.indicator.provider": "Default Organization", + "threat.indicator.type": "file" }, { + "anomali.threatstream.classification": "public", + "anomali.threatstream.confidence": 22, + "anomali.threatstream.detail2": "imported by user 807", + "anomali.threatstream.id": "3711409360", + "anomali.threatstream.itype": "mal_md5", + "anomali.threatstream.maltype": "malware:yakt8pe9r", + "anomali.threatstream.md5": "c3b497", + "anomali.threatstream.resource_uri": "/api/v1/intelligence/P37263483140/", + "anomali.threatstream.severity": "medium", + "anomali.threatstream.source_feed_id": "3903", + "anomali.threatstream.state": "active", + "anomali.threatstream.trusted_circle_ids": [ + "35" + ], + "anomali.threatstream.update_id": "3046847198", + "anomali.threatstream.value_type": "md5", "event.category": "threat", "event.dataset": "threatintel.anomalithreatstream", "event.kind": "enrichment", @@ -3021,34 +3254,38 @@ "service.type": "threatintel", "tags": [ "", + "forwarded", "threatintel-anomalithreatstream" ], - "threatintel.anomalithreatstream.classification": "public", - "threatintel.anomalithreatstream.confidence": 22, - "threatintel.anomalithreatstream.detail2": "imported by user 807", - "threatintel.anomalithreatstream.id": 3711409360, - "threatintel.anomalithreatstream.itype": "mal_md5", - "threatintel.anomalithreatstream.maltype": "malware:yakt8pe9r", - "threatintel.anomalithreatstream.md5": "c3b497", - "threatintel.anomalithreatstream.resource_uri": "/api/v1/intelligence/P37263483140/", - "threatintel.anomalithreatstream.severity": "medium", - "threatintel.anomalithreatstream.source_feed_id": 3903, - "threatintel.anomalithreatstream.state": "active", - "threatintel.anomalithreatstream.trusted_circle_ids": [ - "35" - ], - "threatintel.anomalithreatstream.update_id": 3046847198, - "threatintel.anomalithreatstream.value_type": "md5", - "threatintel.indicator.confidence": 2, - "threatintel.indicator.first_seen": "2020-10-09T18:34:53.000Z", - "threatintel.indicator.last_seen": "2020-10-09T18:34:53.000Z", - "threatintel.indicator.marking.tlp": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali ThreatStream", + "threat.indicator.confidence": "Low", + "threat.indicator.first_seen": "2020-10-09T18:34:53.000Z", + "threat.indicator.last_seen": "2020-10-09T18:34:53.000Z", + "threat.indicator.marking.tlp": [ "White" ], - "threatintel.indicator.provider": "Default Organization", - "threatintel.indicator.type": "file" + "threat.indicator.provider": "Default Organization", + "threat.indicator.type": "file" }, { + "anomali.threatstream.classification": "private", + "anomali.threatstream.confidence": 20, + "anomali.threatstream.detail2": "imported by user 298", + "anomali.threatstream.id": "3346530445", + "anomali.threatstream.itype": "mal_md5", + "anomali.threatstream.maltype": "malware:jfje", + "anomali.threatstream.md5": "ec57713c", + "anomali.threatstream.resource_uri": "/api/v1/intelligence/P10248765051/", + "anomali.threatstream.severity": "medium", + "anomali.threatstream.source_feed_id": "1239", + "anomali.threatstream.state": "active", + "anomali.threatstream.trusted_circle_ids": [ + "196", + "775" + ], + "anomali.threatstream.update_id": "2946803375", + "anomali.threatstream.value_type": "md5", "event.category": "threat", "event.dataset": "threatintel.anomalithreatstream", "event.kind": "enrichment", @@ -3061,35 +3298,37 @@ "service.type": "threatintel", "tags": [ "", + "forwarded", "threatintel-anomalithreatstream" ], - "threatintel.anomalithreatstream.classification": "private", - "threatintel.anomalithreatstream.confidence": 20, - "threatintel.anomalithreatstream.detail2": "imported by user 298", - "threatintel.anomalithreatstream.id": 3346530445, - "threatintel.anomalithreatstream.itype": "mal_md5", - "threatintel.anomalithreatstream.maltype": "malware:jfje", - "threatintel.anomalithreatstream.md5": "ec57713c", - "threatintel.anomalithreatstream.resource_uri": "/api/v1/intelligence/P10248765051/", - "threatintel.anomalithreatstream.severity": "medium", - "threatintel.anomalithreatstream.source_feed_id": 1239, - "threatintel.anomalithreatstream.state": "active", - "threatintel.anomalithreatstream.trusted_circle_ids": [ - "196", - "775" - ], - "threatintel.anomalithreatstream.update_id": 2946803375, - "threatintel.anomalithreatstream.value_type": "md5", - "threatintel.indicator.confidence": 2, - "threatintel.indicator.first_seen": "2020-10-09T18:34:53.000Z", - "threatintel.indicator.last_seen": "2020-10-09T18:34:53.000Z", - "threatintel.indicator.marking.tlp": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali ThreatStream", + "threat.indicator.confidence": "Low", + "threat.indicator.first_seen": "2020-10-09T18:34:53.000Z", + "threat.indicator.last_seen": "2020-10-09T18:34:53.000Z", + "threat.indicator.marking.tlp": [ "Amber" ], - "threatintel.indicator.provider": "Default Organization", - "threatintel.indicator.type": "file" + "threat.indicator.provider": "Default Organization", + "threat.indicator.type": "file" }, { + "anomali.threatstream.classification": "public", + "anomali.threatstream.confidence": -1, + "anomali.threatstream.detail2": "imported by user 345", + "anomali.threatstream.id": "2804727563", + "anomali.threatstream.itype": "phish_url", + "anomali.threatstream.maltype": "malware:c7e", + "anomali.threatstream.resource_uri": "/api/v1/intelligence/P11093591971/", + "anomali.threatstream.severity": "high", + "anomali.threatstream.source_feed_id": "2617", + "anomali.threatstream.state": "active", + "anomali.threatstream.trusted_circle_ids": [ + "131", + "793" + ], + "anomali.threatstream.update_id": "1687817836", + "anomali.threatstream.value_type": "url", "event.category": "threat", "event.dataset": "threatintel.anomalithreatstream", "event.kind": "enrichment", @@ -3102,41 +3341,45 @@ "service.type": "threatintel", "tags": [ "-g6", + "forwarded", "threatintel-anomalithreatstream" ], - "threatintel.anomalithreatstream.classification": "public", - "threatintel.anomalithreatstream.confidence": -1, - "threatintel.anomalithreatstream.detail2": "imported by user 345", - "threatintel.anomalithreatstream.id": 2804727563, - "threatintel.anomalithreatstream.itype": "phish_url", - "threatintel.anomalithreatstream.maltype": "malware:c7e", - "threatintel.anomalithreatstream.resource_uri": "/api/v1/intelligence/P11093591971/", - "threatintel.anomalithreatstream.severity": "high", - "threatintel.anomalithreatstream.source_feed_id": 2617, - "threatintel.anomalithreatstream.state": "active", - "threatintel.anomalithreatstream.trusted_circle_ids": [ - "131", - "793" - ], - "threatintel.anomalithreatstream.update_id": 1687817836, - "threatintel.anomalithreatstream.value_type": "url", - "threatintel.indicator.first_seen": "2020-10-09T18:34:54.000Z", - "threatintel.indicator.geo.country_iso_code": "US", - "threatintel.indicator.ip": "203.0.113.133", - "threatintel.indicator.last_seen": "2020-10-09T18:34:54.000Z", - "threatintel.indicator.marking.tlp": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali ThreatStream", + "threat.indicator.confidence": "None", + "threat.indicator.first_seen": "2020-10-09T18:34:54.000Z", + "threat.indicator.geo.country_iso_code": "US", + "threat.indicator.ip": "203.0.113.133", + "threat.indicator.last_seen": "2020-10-09T18:34:54.000Z", + "threat.indicator.marking.tlp": [ "White" ], - "threatintel.indicator.provider": "Default Organization", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "lzr6.example.org", - "threatintel.indicator.url.full": "https://lzr6.example.org/a7og/4vpv?e7k5=wun", - "threatintel.indicator.url.original": "https://lzr6.example.org/a7og/4vpv?e7k5=wun", - "threatintel.indicator.url.path": "/a7og/4vpv", - "threatintel.indicator.url.query": "e7k5=wun", - "threatintel.indicator.url.scheme": "https" + "threat.indicator.provider": "Default Organization", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "lzr6.example.org", + "threat.indicator.url.full": "https://lzr6.example.org/a7og/4vpv?e7k5=wun", + "threat.indicator.url.original": "https://lzr6.example.org/a7og/4vpv?e7k5=wun", + "threat.indicator.url.path": "/a7og/4vpv", + "threat.indicator.url.query": "e7k5=wun", + "threat.indicator.url.scheme": "https" }, { + "anomali.threatstream.classification": "public", + "anomali.threatstream.confidence": 84, + "anomali.threatstream.detail2": "imported by user 747", + "anomali.threatstream.id": "2229747614", + "anomali.threatstream.itype": "mal_md5", + "anomali.threatstream.maltype": "malware:0d7cxf", + "anomali.threatstream.md5": "bde", + "anomali.threatstream.resource_uri": "/api/v1/intelligence/P12084157836/", + "anomali.threatstream.severity": "very-high", + "anomali.threatstream.source_feed_id": "1620", + "anomali.threatstream.state": "active", + "anomali.threatstream.trusted_circle_ids": [ + "30" + ], + "anomali.threatstream.update_id": "2339220849", + "anomali.threatstream.value_type": "md5", "event.category": "threat", "event.dataset": "threatintel.anomalithreatstream", "event.kind": "enrichment", @@ -3149,34 +3392,37 @@ "service.type": "threatintel", "tags": [ "", + "forwarded", "threatintel-anomalithreatstream" ], - "threatintel.anomalithreatstream.classification": "public", - "threatintel.anomalithreatstream.confidence": 84, - "threatintel.anomalithreatstream.detail2": "imported by user 747", - "threatintel.anomalithreatstream.id": 2229747614, - "threatintel.anomalithreatstream.itype": "mal_md5", - "threatintel.anomalithreatstream.maltype": "malware:0d7cxf", - "threatintel.anomalithreatstream.md5": "bde", - "threatintel.anomalithreatstream.resource_uri": "/api/v1/intelligence/P12084157836/", - "threatintel.anomalithreatstream.severity": "very-high", - "threatintel.anomalithreatstream.source_feed_id": 1620, - "threatintel.anomalithreatstream.state": "active", - "threatintel.anomalithreatstream.trusted_circle_ids": [ - "30" - ], - "threatintel.anomalithreatstream.update_id": 2339220849, - "threatintel.anomalithreatstream.value_type": "md5", - "threatintel.indicator.confidence": 8, - "threatintel.indicator.first_seen": "2020-10-09T18:34:55.000Z", - "threatintel.indicator.last_seen": "2020-10-09T18:34:55.000Z", - "threatintel.indicator.marking.tlp": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali ThreatStream", + "threat.indicator.confidence": "High", + "threat.indicator.first_seen": "2020-10-09T18:34:55.000Z", + "threat.indicator.last_seen": "2020-10-09T18:34:55.000Z", + "threat.indicator.marking.tlp": [ "White" ], - "threatintel.indicator.provider": "Default Organization", - "threatintel.indicator.type": "file" + "threat.indicator.provider": "Default Organization", + "threat.indicator.type": "file" }, { + "anomali.threatstream.classification": "private", + "anomali.threatstream.confidence": 54, + "anomali.threatstream.detail2": "imported by user 832", + "anomali.threatstream.id": "2821279948", + "anomali.threatstream.itype": "mal_md5", + "anomali.threatstream.maltype": "malware:-farvj0e", + "anomali.threatstream.md5": "aa674f5f", + "anomali.threatstream.resource_uri": "/api/v1/intelligence/P43981956471/", + "anomali.threatstream.severity": "high", + "anomali.threatstream.source_feed_id": "2038", + "anomali.threatstream.state": "active", + "anomali.threatstream.trusted_circle_ids": [ + "908" + ], + "anomali.threatstream.update_id": "2083515068", + "anomali.threatstream.value_type": "md5", "event.category": "threat", "event.dataset": "threatintel.anomalithreatstream", "event.kind": "enrichment", @@ -3189,34 +3435,39 @@ "service.type": "threatintel", "tags": [ "", + "forwarded", "threatintel-anomalithreatstream" ], - "threatintel.anomalithreatstream.classification": "private", - "threatintel.anomalithreatstream.confidence": 54, - "threatintel.anomalithreatstream.detail2": "imported by user 832", - "threatintel.anomalithreatstream.id": 2821279948, - "threatintel.anomalithreatstream.itype": "mal_md5", - "threatintel.anomalithreatstream.maltype": "malware:-farvj0e", - "threatintel.anomalithreatstream.md5": "aa674f5f", - "threatintel.anomalithreatstream.resource_uri": "/api/v1/intelligence/P43981956471/", - "threatintel.anomalithreatstream.severity": "high", - "threatintel.anomalithreatstream.source_feed_id": 2038, - "threatintel.anomalithreatstream.state": "active", - "threatintel.anomalithreatstream.trusted_circle_ids": [ - "908" - ], - "threatintel.anomalithreatstream.update_id": 2083515068, - "threatintel.anomalithreatstream.value_type": "md5", - "threatintel.indicator.confidence": 5, - "threatintel.indicator.first_seen": "2020-10-09T18:35:01.000Z", - "threatintel.indicator.last_seen": "2020-10-09T18:35:01.000Z", - "threatintel.indicator.marking.tlp": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali ThreatStream", + "threat.indicator.confidence": "Med", + "threat.indicator.first_seen": "2020-10-09T18:35:01.000Z", + "threat.indicator.last_seen": "2020-10-09T18:35:01.000Z", + "threat.indicator.marking.tlp": [ "Amber" ], - "threatintel.indicator.provider": "Default Organization", - "threatintel.indicator.type": "file" + "threat.indicator.provider": "Default Organization", + "threat.indicator.type": "file" }, { + "anomali.threatstream.classification": "public", + "anomali.threatstream.confidence": 63, + "anomali.threatstream.detail2": "imported by user 217", + "anomali.threatstream.id": "3118884222", + "anomali.threatstream.itype": "mal_md5", + "anomali.threatstream.maltype": "malware:23xfw4nyi", + "anomali.threatstream.md5": "48721c98", + "anomali.threatstream.resource_uri": "/api/v1/intelligence/P20451120036/", + "anomali.threatstream.severity": "high", + "anomali.threatstream.source_feed_id": "1492", + "anomali.threatstream.state": "active", + "anomali.threatstream.trusted_circle_ids": [ + "207", + "501", + "993" + ], + "anomali.threatstream.update_id": "3429396478", + "anomali.threatstream.value_type": "md5", "event.category": "threat", "event.dataset": "threatintel.anomalithreatstream", "event.kind": "enrichment", @@ -3229,36 +3480,36 @@ "service.type": "threatintel", "tags": [ "", + "forwarded", "threatintel-anomalithreatstream" ], - "threatintel.anomalithreatstream.classification": "public", - "threatintel.anomalithreatstream.confidence": 63, - "threatintel.anomalithreatstream.detail2": "imported by user 217", - "threatintel.anomalithreatstream.id": 3118884222, - "threatintel.anomalithreatstream.itype": "mal_md5", - "threatintel.anomalithreatstream.maltype": "malware:23xfw4nyi", - "threatintel.anomalithreatstream.md5": "48721c98", - "threatintel.anomalithreatstream.resource_uri": "/api/v1/intelligence/P20451120036/", - "threatintel.anomalithreatstream.severity": "high", - "threatintel.anomalithreatstream.source_feed_id": 1492, - "threatintel.anomalithreatstream.state": "active", - "threatintel.anomalithreatstream.trusted_circle_ids": [ - "207", - "501", - "993" - ], - "threatintel.anomalithreatstream.update_id": 3429396478, - "threatintel.anomalithreatstream.value_type": "md5", - "threatintel.indicator.confidence": 6, - "threatintel.indicator.first_seen": "2020-10-09T18:35:01.000Z", - "threatintel.indicator.last_seen": "2020-10-09T18:35:01.000Z", - "threatintel.indicator.marking.tlp": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali ThreatStream", + "threat.indicator.confidence": "Med", + "threat.indicator.first_seen": "2020-10-09T18:35:01.000Z", + "threat.indicator.last_seen": "2020-10-09T18:35:01.000Z", + "threat.indicator.marking.tlp": [ "White" ], - "threatintel.indicator.provider": "Default Organization", - "threatintel.indicator.type": "file" + "threat.indicator.provider": "Default Organization", + "threat.indicator.type": "file" }, { + "anomali.threatstream.classification": "public", + "anomali.threatstream.confidence": 72, + "anomali.threatstream.detail2": "imported by user 402", + "anomali.threatstream.id": "3912225830", + "anomali.threatstream.itype": "phish_url", + "anomali.threatstream.maltype": "malware:dto", + "anomali.threatstream.resource_uri": "/api/v1/intelligence/P16185398807/", + "anomali.threatstream.severity": "low", + "anomali.threatstream.source_feed_id": "1594", + "anomali.threatstream.state": "active", + "anomali.threatstream.trusted_circle_ids": [ + "439" + ], + "anomali.threatstream.update_id": "3320773285", + "anomali.threatstream.value_type": "url", "event.category": "threat", "event.dataset": "threatintel.anomalithreatstream", "event.kind": "enrichment", @@ -3270,42 +3521,46 @@ "log.offset": 39578, "service.type": "threatintel", "tags": [ + "forwarded", "threatintel-anomalithreatstream", "y7d71" ], - "threatintel.anomalithreatstream.classification": "public", - "threatintel.anomalithreatstream.confidence": 72, - "threatintel.anomalithreatstream.detail2": "imported by user 402", - "threatintel.anomalithreatstream.id": 3912225830, - "threatintel.anomalithreatstream.itype": "phish_url", - "threatintel.anomalithreatstream.maltype": "malware:dto", - "threatintel.anomalithreatstream.resource_uri": "/api/v1/intelligence/P16185398807/", - "threatintel.anomalithreatstream.severity": "low", - "threatintel.anomalithreatstream.source_feed_id": 1594, - "threatintel.anomalithreatstream.state": "active", - "threatintel.anomalithreatstream.trusted_circle_ids": [ - "439" - ], - "threatintel.anomalithreatstream.update_id": 3320773285, - "threatintel.anomalithreatstream.value_type": "url", - "threatintel.indicator.confidence": 7, - "threatintel.indicator.first_seen": "2020-10-09T18:35:04.000Z", - "threatintel.indicator.geo.country_iso_code": "US", - "threatintel.indicator.ip": "203.0.113.177", - "threatintel.indicator.last_seen": "2020-10-09T18:35:04.000Z", - "threatintel.indicator.marking.tlp": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali ThreatStream", + "threat.indicator.confidence": "High", + "threat.indicator.first_seen": "2020-10-09T18:35:04.000Z", + "threat.indicator.geo.country_iso_code": "US", + "threat.indicator.ip": "203.0.113.177", + "threat.indicator.last_seen": "2020-10-09T18:35:04.000Z", + "threat.indicator.marking.tlp": [ "White" ], - "threatintel.indicator.provider": "Default Organization", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "932.example.com", - "threatintel.indicator.url.full": "http://932.example.com/1xmdjyom/tf3inx1?s6zgr=ajgw", - "threatintel.indicator.url.original": "http://932.example.com/1xmdjyom/tf3inx1?s6zgr=ajgw", - "threatintel.indicator.url.path": "/1xmdjyom/tf3inx1", - "threatintel.indicator.url.query": "s6zgr=ajgw", - "threatintel.indicator.url.scheme": "http" + "threat.indicator.provider": "Default Organization", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "932.example.com", + "threat.indicator.url.full": "http://932.example.com/1xmdjyom/tf3inx1?s6zgr=ajgw", + "threat.indicator.url.original": "http://932.example.com/1xmdjyom/tf3inx1?s6zgr=ajgw", + "threat.indicator.url.path": "/1xmdjyom/tf3inx1", + "threat.indicator.url.query": "s6zgr=ajgw", + "threat.indicator.url.scheme": "http" }, { + "anomali.threatstream.classification": "public", + "anomali.threatstream.confidence": 34, + "anomali.threatstream.detail2": "imported by user 626", + "anomali.threatstream.id": "2591984894", + "anomali.threatstream.itype": "mal_md5", + "anomali.threatstream.maltype": "malware:7nq6far", + "anomali.threatstream.md5": "114bd63e0", + "anomali.threatstream.resource_uri": "/api/v1/intelligence/P19612019110/", + "anomali.threatstream.severity": "low", + "anomali.threatstream.source_feed_id": "1579", + "anomali.threatstream.state": "active", + "anomali.threatstream.trusted_circle_ids": [ + "669" + ], + "anomali.threatstream.update_id": "2275758319", + "anomali.threatstream.value_type": "md5", "event.category": "threat", "event.dataset": "threatintel.anomalithreatstream", "event.kind": "enrichment", @@ -3317,36 +3572,40 @@ "log.offset": 40161, "service.type": "threatintel", "tags": [ + "forwarded", "hlq", "nknea", "threatintel-anomalithreatstream" ], - "threatintel.anomalithreatstream.classification": "public", - "threatintel.anomalithreatstream.confidence": 34, - "threatintel.anomalithreatstream.detail2": "imported by user 626", - "threatintel.anomalithreatstream.id": 2591984894, - "threatintel.anomalithreatstream.itype": "mal_md5", - "threatintel.anomalithreatstream.maltype": "malware:7nq6far", - "threatintel.anomalithreatstream.md5": "114bd63e0", - "threatintel.anomalithreatstream.resource_uri": "/api/v1/intelligence/P19612019110/", - "threatintel.anomalithreatstream.severity": "low", - "threatintel.anomalithreatstream.source_feed_id": 1579, - "threatintel.anomalithreatstream.state": "active", - "threatintel.anomalithreatstream.trusted_circle_ids": [ - "669" - ], - "threatintel.anomalithreatstream.update_id": 2275758319, - "threatintel.anomalithreatstream.value_type": "md5", - "threatintel.indicator.confidence": 3, - "threatintel.indicator.first_seen": "2020-10-09T18:35:06.000Z", - "threatintel.indicator.last_seen": "2020-10-09T18:35:06.000Z", - "threatintel.indicator.marking.tlp": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali ThreatStream", + "threat.indicator.confidence": "Med", + "threat.indicator.first_seen": "2020-10-09T18:35:06.000Z", + "threat.indicator.last_seen": "2020-10-09T18:35:06.000Z", + "threat.indicator.marking.tlp": [ "White" ], - "threatintel.indicator.provider": "Default Organization", - "threatintel.indicator.type": "file" + "threat.indicator.provider": "Default Organization", + "threat.indicator.type": "file" }, { + "anomali.threatstream.classification": "public", + "anomali.threatstream.confidence": 53, + "anomali.threatstream.detail2": "imported by user 756", + "anomali.threatstream.id": "2589012476", + "anomali.threatstream.itype": "mal_md5", + "anomali.threatstream.maltype": "malware:c1z0qya", + "anomali.threatstream.md5": "636cd4267", + "anomali.threatstream.resource_uri": "/api/v1/intelligence/P47658489795/", + "anomali.threatstream.severity": "low", + "anomali.threatstream.source_feed_id": "3665", + "anomali.threatstream.state": "active", + "anomali.threatstream.trusted_circle_ids": [ + "835", + "850" + ], + "anomali.threatstream.update_id": "2399518196", + "anomali.threatstream.value_type": "md5", "event.category": "threat", "event.dataset": "threatintel.anomalithreatstream", "event.kind": "enrichment", @@ -3359,35 +3618,37 @@ "service.type": "threatintel", "tags": [ "", + "forwarded", "threatintel-anomalithreatstream" ], - "threatintel.anomalithreatstream.classification": "public", - "threatintel.anomalithreatstream.confidence": 53, - "threatintel.anomalithreatstream.detail2": "imported by user 756", - "threatintel.anomalithreatstream.id": 2589012476, - "threatintel.anomalithreatstream.itype": "mal_md5", - "threatintel.anomalithreatstream.maltype": "malware:c1z0qya", - "threatintel.anomalithreatstream.md5": "636cd4267", - "threatintel.anomalithreatstream.resource_uri": "/api/v1/intelligence/P47658489795/", - "threatintel.anomalithreatstream.severity": "low", - "threatintel.anomalithreatstream.source_feed_id": 3665, - "threatintel.anomalithreatstream.state": "active", - "threatintel.anomalithreatstream.trusted_circle_ids": [ - "835", - "850" - ], - "threatintel.anomalithreatstream.update_id": 2399518196, - "threatintel.anomalithreatstream.value_type": "md5", - "threatintel.indicator.confidence": 5, - "threatintel.indicator.first_seen": "2020-10-09T18:35:22.000Z", - "threatintel.indicator.last_seen": "2020-10-09T18:35:22.000Z", - "threatintel.indicator.marking.tlp": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali ThreatStream", + "threat.indicator.confidence": "Med", + "threat.indicator.first_seen": "2020-10-09T18:35:22.000Z", + "threat.indicator.last_seen": "2020-10-09T18:35:22.000Z", + "threat.indicator.marking.tlp": [ "White" ], - "threatintel.indicator.provider": "Default Organization", - "threatintel.indicator.type": "file" + "threat.indicator.provider": "Default Organization", + "threat.indicator.type": "file" }, { + "anomali.threatstream.classification": "private", + "anomali.threatstream.confidence": 57, + "anomali.threatstream.detail2": "imported by user 893", + "anomali.threatstream.id": "2677187012", + "anomali.threatstream.itype": "mal_url", + "anomali.threatstream.maltype": "malware:qtp", + "anomali.threatstream.resource_uri": "/api/v1/intelligence/P28161033466/", + "anomali.threatstream.severity": "low", + "anomali.threatstream.source_feed_id": "3395", + "anomali.threatstream.state": "active", + "anomali.threatstream.trusted_circle_ids": [ + "234", + "909" + ], + "anomali.threatstream.update_id": "3342338979", + "anomali.threatstream.value_type": "url", "event.category": "threat", "event.dataset": "threatintel.anomalithreatstream", "event.kind": "enrichment", @@ -3403,44 +3664,48 @@ "5z6", "IP=192.0.2.45", "first_seen=2020-11-24T05:32:17", + "forwarded", "mask=2001:db8:6d86:4a6:af9b:4385:14d6:b714", "popularity=high", "threatintel-anomalithreatstream" ], - "threatintel.anomalithreatstream.classification": "private", - "threatintel.anomalithreatstream.confidence": 57, - "threatintel.anomalithreatstream.detail2": "imported by user 893", - "threatintel.anomalithreatstream.id": 2677187012, - "threatintel.anomalithreatstream.itype": "mal_url", - "threatintel.anomalithreatstream.maltype": "malware:qtp", - "threatintel.anomalithreatstream.resource_uri": "/api/v1/intelligence/P28161033466/", - "threatintel.anomalithreatstream.severity": "low", - "threatintel.anomalithreatstream.source_feed_id": 3395, - "threatintel.anomalithreatstream.state": "active", - "threatintel.anomalithreatstream.trusted_circle_ids": [ - "234", - "909" - ], - "threatintel.anomalithreatstream.update_id": 3342338979, - "threatintel.anomalithreatstream.value_type": "url", - "threatintel.indicator.confidence": 6, - "threatintel.indicator.first_seen": "2020-10-09T18:44:01.000Z", - "threatintel.indicator.geo.country_iso_code": "US", - "threatintel.indicator.ip": "203.0.113.71", - "threatintel.indicator.last_seen": "2020-10-09T18:44:01.000Z", - "threatintel.indicator.marking.tlp": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali ThreatStream", + "threat.indicator.confidence": "Med", + "threat.indicator.first_seen": "2020-10-09T18:44:01.000Z", + "threat.indicator.geo.country_iso_code": "US", + "threat.indicator.ip": "203.0.113.71", + "threat.indicator.last_seen": "2020-10-09T18:44:01.000Z", + "threat.indicator.marking.tlp": [ "Amber" ], - "threatintel.indicator.provider": "Default Organization", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "0te9x75e.example.net", - "threatintel.indicator.url.full": "https://0te9x75e.example.net/y2cbl5ov5/u-s9?vhppw120=bt0ze0du3", - "threatintel.indicator.url.original": "https://0te9x75e.example.net/y2cbl5ov5/u-s9?vhppw120=bt0ze0du3", - "threatintel.indicator.url.path": "/y2cbl5ov5/u-s9", - "threatintel.indicator.url.query": "vhppw120=bt0ze0du3", - "threatintel.indicator.url.scheme": "https" + "threat.indicator.provider": "Default Organization", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "0te9x75e.example.net", + "threat.indicator.url.full": "https://0te9x75e.example.net/y2cbl5ov5/u-s9?vhppw120=bt0ze0du3", + "threat.indicator.url.original": "https://0te9x75e.example.net/y2cbl5ov5/u-s9?vhppw120=bt0ze0du3", + "threat.indicator.url.path": "/y2cbl5ov5/u-s9", + "threat.indicator.url.query": "vhppw120=bt0ze0du3", + "threat.indicator.url.scheme": "https" }, { + "anomali.threatstream.classification": "private", + "anomali.threatstream.confidence": 31, + "anomali.threatstream.detail2": "imported by user 450", + "anomali.threatstream.id": "3137219963", + "anomali.threatstream.itype": "phish_url", + "anomali.threatstream.maltype": "malware:nosy8", + "anomali.threatstream.resource_uri": "/api/v1/intelligence/P33588463803/", + "anomali.threatstream.severity": "medium", + "anomali.threatstream.source_feed_id": "2108", + "anomali.threatstream.state": "active", + "anomali.threatstream.trusted_circle_ids": [ + "755", + "843", + "943" + ], + "anomali.threatstream.update_id": "1484831936", + "anomali.threatstream.value_type": "url", "event.category": "threat", "event.dataset": "threatintel.anomalithreatstream", "event.kind": "enrichment", @@ -3453,43 +3718,45 @@ "service.type": "threatintel", "tags": [ "06epx", + "forwarded", "threatintel-anomalithreatstream" ], - "threatintel.anomalithreatstream.classification": "private", - "threatintel.anomalithreatstream.confidence": 31, - "threatintel.anomalithreatstream.detail2": "imported by user 450", - "threatintel.anomalithreatstream.id": 3137219963, - "threatintel.anomalithreatstream.itype": "phish_url", - "threatintel.anomalithreatstream.maltype": "malware:nosy8", - "threatintel.anomalithreatstream.resource_uri": "/api/v1/intelligence/P33588463803/", - "threatintel.anomalithreatstream.severity": "medium", - "threatintel.anomalithreatstream.source_feed_id": 2108, - "threatintel.anomalithreatstream.state": "active", - "threatintel.anomalithreatstream.trusted_circle_ids": [ - "755", - "843", - "943" - ], - "threatintel.anomalithreatstream.update_id": 1484831936, - "threatintel.anomalithreatstream.value_type": "url", - "threatintel.indicator.confidence": 3, - "threatintel.indicator.first_seen": "2020-10-09T18:44:04.000Z", - "threatintel.indicator.geo.country_iso_code": "US", - "threatintel.indicator.ip": "203.0.113.180", - "threatintel.indicator.last_seen": "2020-10-09T18:44:04.000Z", - "threatintel.indicator.marking.tlp": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali ThreatStream", + "threat.indicator.confidence": "Med", + "threat.indicator.first_seen": "2020-10-09T18:44:04.000Z", + "threat.indicator.geo.country_iso_code": "US", + "threat.indicator.ip": "203.0.113.180", + "threat.indicator.last_seen": "2020-10-09T18:44:04.000Z", + "threat.indicator.marking.tlp": [ "Amber" ], - "threatintel.indicator.provider": "Default Organization", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "b7qdtnl8f.example.org", - "threatintel.indicator.url.full": "http://b7qdtnl8f.example.org/z2a-tx3ip/7cv?9a67ct3mb=ijse", - "threatintel.indicator.url.original": "http://b7qdtnl8f.example.org/z2a-tx3ip/7cv?9a67ct3mb=ijse", - "threatintel.indicator.url.path": "/z2a-tx3ip/7cv", - "threatintel.indicator.url.query": "9a67ct3mb=ijse", - "threatintel.indicator.url.scheme": "http" + "threat.indicator.provider": "Default Organization", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "b7qdtnl8f.example.org", + "threat.indicator.url.full": "http://b7qdtnl8f.example.org/z2a-tx3ip/7cv?9a67ct3mb=ijse", + "threat.indicator.url.original": "http://b7qdtnl8f.example.org/z2a-tx3ip/7cv?9a67ct3mb=ijse", + "threat.indicator.url.path": "/z2a-tx3ip/7cv", + "threat.indicator.url.query": "9a67ct3mb=ijse", + "threat.indicator.url.scheme": "http" }, { + "anomali.threatstream.classification": "private", + "anomali.threatstream.confidence": 19, + "anomali.threatstream.detail2": "imported by user 479", + "anomali.threatstream.id": "2506436592", + "anomali.threatstream.itype": "mal_domain", + "anomali.threatstream.maltype": "malware:4okr", + "anomali.threatstream.resource_uri": "/api/v1/intelligence/P42606732542/", + "anomali.threatstream.severity": "very-high", + "anomali.threatstream.source_feed_id": "393", + "anomali.threatstream.state": "active", + "anomali.threatstream.trusted_circle_ids": [ + "324", + "63" + ], + "anomali.threatstream.update_id": "1826833096", + "anomali.threatstream.value_type": "domain", "event.category": "threat", "event.dataset": "threatintel.anomalithreatstream", "event.kind": "enrichment", @@ -3501,37 +3768,40 @@ "log.offset": 42447, "service.type": "threatintel", "tags": [ + "forwarded", "jjz8e", "n5okkr7mg", "threatintel-anomalithreatstream" ], - "threatintel.anomalithreatstream.classification": "private", - "threatintel.anomalithreatstream.confidence": 19, - "threatintel.anomalithreatstream.detail2": "imported by user 479", - "threatintel.anomalithreatstream.id": 2506436592, - "threatintel.anomalithreatstream.itype": "mal_domain", - "threatintel.anomalithreatstream.maltype": "malware:4okr", - "threatintel.anomalithreatstream.resource_uri": "/api/v1/intelligence/P42606732542/", - "threatintel.anomalithreatstream.severity": "very-high", - "threatintel.anomalithreatstream.source_feed_id": 393, - "threatintel.anomalithreatstream.state": "active", - "threatintel.anomalithreatstream.trusted_circle_ids": [ - "324", - "63" - ], - "threatintel.anomalithreatstream.update_id": 1826833096, - "threatintel.anomalithreatstream.value_type": "domain", - "threatintel.indicator.confidence": 2, - "threatintel.indicator.first_seen": "2020-10-09T18:44:19.000Z", - "threatintel.indicator.last_seen": "2020-10-09T18:44:19.000Z", - "threatintel.indicator.marking.tlp": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali ThreatStream", + "threat.indicator.confidence": "Low", + "threat.indicator.first_seen": "2020-10-09T18:44:19.000Z", + "threat.indicator.last_seen": "2020-10-09T18:44:19.000Z", + "threat.indicator.marking.tlp": [ "Amber" ], - "threatintel.indicator.provider": "Default Organization", - "threatintel.indicator.type": "domain-name", - "threatintel.indicator.url.domain": "4gtq1n.example.net" + "threat.indicator.provider": "Default Organization", + "threat.indicator.type": "domain-name", + "threat.indicator.url.domain": "4gtq1n.example.net" }, { + "anomali.threatstream.classification": "public", + "anomali.threatstream.confidence": 83, + "anomali.threatstream.detail2": "imported by user 969", + "anomali.threatstream.id": "1214135687", + "anomali.threatstream.itype": "mal_ip", + "anomali.threatstream.maltype": "malware:h68c70o", + "anomali.threatstream.resource_uri": "/api/v1/intelligence/P25206292349/", + "anomali.threatstream.severity": "very-high", + "anomali.threatstream.source_feed_id": "425", + "anomali.threatstream.state": "active", + "anomali.threatstream.trusted_circle_ids": [ + "324", + "474" + ], + "anomali.threatstream.update_id": "2101635974", + "anomali.threatstream.value_type": "ip", "event.category": "threat", "event.dataset": "threatintel.anomalithreatstream", "event.kind": "enrichment", @@ -3545,40 +3815,43 @@ "tags": [ "IP=203.0.113.163", "first_seen=2020-02-14T13:46:51", + "forwarded", "gnz6", "mask=203.0.113.12", "popularity=high", "threatintel-anomalithreatstream", "u96h" ], - "threatintel.anomalithreatstream.classification": "public", - "threatintel.anomalithreatstream.confidence": 83, - "threatintel.anomalithreatstream.detail2": "imported by user 969", - "threatintel.anomalithreatstream.id": 1214135687, - "threatintel.anomalithreatstream.itype": "mal_ip", - "threatintel.anomalithreatstream.maltype": "malware:h68c70o", - "threatintel.anomalithreatstream.resource_uri": "/api/v1/intelligence/P25206292349/", - "threatintel.anomalithreatstream.severity": "very-high", - "threatintel.anomalithreatstream.source_feed_id": 425, - "threatintel.anomalithreatstream.state": "active", - "threatintel.anomalithreatstream.trusted_circle_ids": [ - "324", - "474" - ], - "threatintel.anomalithreatstream.update_id": 2101635974, - "threatintel.anomalithreatstream.value_type": "ip", - "threatintel.indicator.confidence": 8, - "threatintel.indicator.first_seen": "2020-10-09T18:44:27.000Z", - "threatintel.indicator.geo.country_iso_code": "RU", - "threatintel.indicator.ip": "192.0.2.17", - "threatintel.indicator.last_seen": "2020-10-09T18:44:27.000Z", - "threatintel.indicator.marking.tlp": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali ThreatStream", + "threat.indicator.confidence": "High", + "threat.indicator.first_seen": "2020-10-09T18:44:27.000Z", + "threat.indicator.geo.country_iso_code": "RU", + "threat.indicator.ip": "192.0.2.17", + "threat.indicator.last_seen": "2020-10-09T18:44:27.000Z", + "threat.indicator.marking.tlp": [ "White" ], - "threatintel.indicator.provider": "Default Organization", - "threatintel.indicator.type": "ipv4-addr" + "threat.indicator.provider": "Default Organization", + "threat.indicator.type": "ipv4-addr" }, { + "anomali.threatstream.classification": "private", + "anomali.threatstream.confidence": 15, + "anomali.threatstream.detail2": "imported by user 501", + "anomali.threatstream.id": "1632578144", + "anomali.threatstream.itype": "phish_url", + "anomali.threatstream.maltype": "malware:y9xovpr2", + "anomali.threatstream.resource_uri": "/api/v1/intelligence/P21633460934/", + "anomali.threatstream.severity": "very-high", + "anomali.threatstream.source_feed_id": "1114", + "anomali.threatstream.state": "active", + "anomali.threatstream.trusted_circle_ids": [ + "615", + "818" + ], + "anomali.threatstream.update_id": "1949050295", + "anomali.threatstream.value_type": "url", "event.category": "threat", "event.dataset": "threatintel.anomalithreatstream", "event.kind": "enrichment", @@ -3590,43 +3863,47 @@ "log.offset": 43582, "service.type": "threatintel", "tags": [ + "forwarded", "t37z5d2", "threatintel-anomalithreatstream" ], - "threatintel.anomalithreatstream.classification": "private", - "threatintel.anomalithreatstream.confidence": 15, - "threatintel.anomalithreatstream.detail2": "imported by user 501", - "threatintel.anomalithreatstream.id": 1632578144, - "threatintel.anomalithreatstream.itype": "phish_url", - "threatintel.anomalithreatstream.maltype": "malware:y9xovpr2", - "threatintel.anomalithreatstream.resource_uri": "/api/v1/intelligence/P21633460934/", - "threatintel.anomalithreatstream.severity": "very-high", - "threatintel.anomalithreatstream.source_feed_id": 1114, - "threatintel.anomalithreatstream.state": "active", - "threatintel.anomalithreatstream.trusted_circle_ids": [ - "615", - "818" - ], - "threatintel.anomalithreatstream.update_id": 1949050295, - "threatintel.anomalithreatstream.value_type": "url", - "threatintel.indicator.confidence": 2, - "threatintel.indicator.first_seen": "2020-10-09T18:44:35.000Z", - "threatintel.indicator.geo.country_iso_code": "US", - "threatintel.indicator.ip": "192.0.2.183", - "threatintel.indicator.last_seen": "2020-10-09T18:44:35.000Z", - "threatintel.indicator.marking.tlp": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali ThreatStream", + "threat.indicator.confidence": "Low", + "threat.indicator.first_seen": "2020-10-09T18:44:35.000Z", + "threat.indicator.geo.country_iso_code": "US", + "threat.indicator.ip": "192.0.2.183", + "threat.indicator.last_seen": "2020-10-09T18:44:35.000Z", + "threat.indicator.marking.tlp": [ "Amber" ], - "threatintel.indicator.provider": "Default Organization", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "tfva.example.org", - "threatintel.indicator.url.full": "https://tfva.example.org/iih3qkj/b04g7?dwosh0qmt=wi9ao", - "threatintel.indicator.url.original": "https://tfva.example.org/iih3qkj/b04g7?dwosh0qmt=wi9ao", - "threatintel.indicator.url.path": "/iih3qkj/b04g7", - "threatintel.indicator.url.query": "dwosh0qmt=wi9ao", - "threatintel.indicator.url.scheme": "https" + "threat.indicator.provider": "Default Organization", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "tfva.example.org", + "threat.indicator.url.full": "https://tfva.example.org/iih3qkj/b04g7?dwosh0qmt=wi9ao", + "threat.indicator.url.original": "https://tfva.example.org/iih3qkj/b04g7?dwosh0qmt=wi9ao", + "threat.indicator.url.path": "/iih3qkj/b04g7", + "threat.indicator.url.query": "dwosh0qmt=wi9ao", + "threat.indicator.url.scheme": "https" }, { + "anomali.threatstream.classification": "public", + "anomali.threatstream.confidence": 85, + "anomali.threatstream.detail2": "imported by user 149", + "anomali.threatstream.id": "3098969355", + "anomali.threatstream.itype": "phish_url", + "anomali.threatstream.maltype": "malware:wxbuhcov9", + "anomali.threatstream.resource_uri": "/api/v1/intelligence/P30134520108/", + "anomali.threatstream.severity": "medium", + "anomali.threatstream.source_feed_id": "398", + "anomali.threatstream.state": "active", + "anomali.threatstream.trusted_circle_ids": [ + "597", + "913", + "946" + ], + "anomali.threatstream.update_id": "2645963867", + "anomali.threatstream.value_type": "url", "event.category": "threat", "event.dataset": "threatintel.anomalithreatstream", "event.kind": "enrichment", @@ -3638,44 +3915,47 @@ "log.offset": 44184, "service.type": "threatintel", "tags": [ + "forwarded", "rprsi-", "threatintel-anomalithreatstream" ], - "threatintel.anomalithreatstream.classification": "public", - "threatintel.anomalithreatstream.confidence": 85, - "threatintel.anomalithreatstream.detail2": "imported by user 149", - "threatintel.anomalithreatstream.id": 3098969355, - "threatintel.anomalithreatstream.itype": "phish_url", - "threatintel.anomalithreatstream.maltype": "malware:wxbuhcov9", - "threatintel.anomalithreatstream.resource_uri": "/api/v1/intelligence/P30134520108/", - "threatintel.anomalithreatstream.severity": "medium", - "threatintel.anomalithreatstream.source_feed_id": 398, - "threatintel.anomalithreatstream.state": "active", - "threatintel.anomalithreatstream.trusted_circle_ids": [ - "597", - "913", - "946" - ], - "threatintel.anomalithreatstream.update_id": 2645963867, - "threatintel.anomalithreatstream.value_type": "url", - "threatintel.indicator.confidence": 9, - "threatintel.indicator.first_seen": "2020-10-09T18:44:36.000Z", - "threatintel.indicator.geo.country_iso_code": "US", - "threatintel.indicator.ip": "203.0.113.149", - "threatintel.indicator.last_seen": "2020-10-09T18:44:36.000Z", - "threatintel.indicator.marking.tlp": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali ThreatStream", + "threat.indicator.confidence": "High", + "threat.indicator.first_seen": "2020-10-09T18:44:36.000Z", + "threat.indicator.geo.country_iso_code": "US", + "threat.indicator.ip": "203.0.113.149", + "threat.indicator.last_seen": "2020-10-09T18:44:36.000Z", + "threat.indicator.marking.tlp": [ "White" ], - "threatintel.indicator.provider": "Default Organization", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "erg2.example.com", - "threatintel.indicator.url.full": "https://erg2.example.com/4ys/vywa93c?7oru=evpi", - "threatintel.indicator.url.original": "https://erg2.example.com/4ys/vywa93c?7oru=evpi", - "threatintel.indicator.url.path": "/4ys/vywa93c", - "threatintel.indicator.url.query": "7oru=evpi", - "threatintel.indicator.url.scheme": "https" + "threat.indicator.provider": "Default Organization", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "erg2.example.com", + "threat.indicator.url.full": "https://erg2.example.com/4ys/vywa93c?7oru=evpi", + "threat.indicator.url.original": "https://erg2.example.com/4ys/vywa93c?7oru=evpi", + "threat.indicator.url.path": "/4ys/vywa93c", + "threat.indicator.url.query": "7oru=evpi", + "threat.indicator.url.scheme": "https" }, { + "anomali.threatstream.classification": "private", + "anomali.threatstream.confidence": 64, + "anomali.threatstream.detail2": "imported by user 59", + "anomali.threatstream.id": "2035701780", + "anomali.threatstream.itype": "mal_url", + "anomali.threatstream.maltype": "malware:xn2a", + "anomali.threatstream.resource_uri": "/api/v1/intelligence/P10508749376/", + "anomali.threatstream.severity": "low", + "anomali.threatstream.source_feed_id": "2760", + "anomali.threatstream.state": "active", + "anomali.threatstream.trusted_circle_ids": [ + "600", + "673", + "990" + ], + "anomali.threatstream.update_id": "2806149730", + "anomali.threatstream.value_type": "url", "event.category": "threat", "event.dataset": "threatintel.anomalithreatstream", "event.kind": "enrichment", @@ -3690,46 +3970,49 @@ "-jj", "IP=203.0.113.22", "first_seen=2020-12-24T20:20:31", + "forwarded", "gogpcno", "mask=2001:db8:bdc6:400b:c095:41c7:1d54:8ff6", "popularity=low", "threatintel-anomalithreatstream" ], - "threatintel.anomalithreatstream.classification": "private", - "threatintel.anomalithreatstream.confidence": 64, - "threatintel.anomalithreatstream.detail2": "imported by user 59", - "threatintel.anomalithreatstream.id": 2035701780, - "threatintel.anomalithreatstream.itype": "mal_url", - "threatintel.anomalithreatstream.maltype": "malware:xn2a", - "threatintel.anomalithreatstream.resource_uri": "/api/v1/intelligence/P10508749376/", - "threatintel.anomalithreatstream.severity": "low", - "threatintel.anomalithreatstream.source_feed_id": 2760, - "threatintel.anomalithreatstream.state": "active", - "threatintel.anomalithreatstream.trusted_circle_ids": [ - "600", - "673", - "990" - ], - "threatintel.anomalithreatstream.update_id": 2806149730, - "threatintel.anomalithreatstream.value_type": "url", - "threatintel.indicator.confidence": 6, - "threatintel.indicator.first_seen": "2020-10-09T18:44:37.000Z", - "threatintel.indicator.geo.country_iso_code": "IN", - "threatintel.indicator.ip": "203.0.113.27", - "threatintel.indicator.last_seen": "2020-10-09T18:44:37.000Z", - "threatintel.indicator.marking.tlp": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali ThreatStream", + "threat.indicator.confidence": "Med", + "threat.indicator.first_seen": "2020-10-09T18:44:37.000Z", + "threat.indicator.geo.country_iso_code": "IN", + "threat.indicator.ip": "203.0.113.27", + "threat.indicator.last_seen": "2020-10-09T18:44:37.000Z", + "threat.indicator.marking.tlp": [ "Amber" ], - "threatintel.indicator.provider": "Default Organization", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "0elz6c.example.com", - "threatintel.indicator.url.full": "https://0elz6c.example.com/3nhx/cadsn6?kfcj94=gnl", - "threatintel.indicator.url.original": "https://0elz6c.example.com/3nhx/cadsn6?kfcj94=gnl", - "threatintel.indicator.url.path": "/3nhx/cadsn6", - "threatintel.indicator.url.query": "kfcj94=gnl", - "threatintel.indicator.url.scheme": "https" + "threat.indicator.provider": "Default Organization", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "0elz6c.example.com", + "threat.indicator.url.full": "https://0elz6c.example.com/3nhx/cadsn6?kfcj94=gnl", + "threat.indicator.url.original": "https://0elz6c.example.com/3nhx/cadsn6?kfcj94=gnl", + "threat.indicator.url.path": "/3nhx/cadsn6", + "threat.indicator.url.query": "kfcj94=gnl", + "threat.indicator.url.scheme": "https" }, { + "anomali.threatstream.classification": "public", + "anomali.threatstream.confidence": 44, + "anomali.threatstream.detail2": "imported by user 134", + "anomali.threatstream.id": "2120958409", + "anomali.threatstream.itype": "phish_url", + "anomali.threatstream.maltype": "malware:cu6f11gp1", + "anomali.threatstream.resource_uri": "/api/v1/intelligence/P46535027346/", + "anomali.threatstream.severity": "medium", + "anomali.threatstream.source_feed_id": "1973", + "anomali.threatstream.state": "active", + "anomali.threatstream.trusted_circle_ids": [ + "125", + "279", + "552" + ], + "anomali.threatstream.update_id": "3490786662", + "anomali.threatstream.value_type": "url", "event.category": "threat", "event.dataset": "threatintel.anomalithreatstream", "event.kind": "enrichment", @@ -3741,44 +4024,46 @@ "log.offset": 45480, "service.type": "threatintel", "tags": [ + "forwarded", "qztcai", "threatintel-anomalithreatstream" ], - "threatintel.anomalithreatstream.classification": "public", - "threatintel.anomalithreatstream.confidence": 44, - "threatintel.anomalithreatstream.detail2": "imported by user 134", - "threatintel.anomalithreatstream.id": 2120958409, - "threatintel.anomalithreatstream.itype": "phish_url", - "threatintel.anomalithreatstream.maltype": "malware:cu6f11gp1", - "threatintel.anomalithreatstream.resource_uri": "/api/v1/intelligence/P46535027346/", - "threatintel.anomalithreatstream.severity": "medium", - "threatintel.anomalithreatstream.source_feed_id": 1973, - "threatintel.anomalithreatstream.state": "active", - "threatintel.anomalithreatstream.trusted_circle_ids": [ - "125", - "279", - "552" - ], - "threatintel.anomalithreatstream.update_id": 3490786662, - "threatintel.anomalithreatstream.value_type": "url", - "threatintel.indicator.confidence": 4, - "threatintel.indicator.first_seen": "2020-10-09T18:44:45.000Z", - "threatintel.indicator.geo.country_iso_code": "US", - "threatintel.indicator.ip": "2001:db8:129e:7520:8797:95ca:a4d1:3011", - "threatintel.indicator.last_seen": "2020-10-09T18:44:45.000Z", - "threatintel.indicator.marking.tlp": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali ThreatStream", + "threat.indicator.confidence": "Med", + "threat.indicator.first_seen": "2020-10-09T18:44:45.000Z", + "threat.indicator.geo.country_iso_code": "US", + "threat.indicator.ip": "2001:db8:129e:7520:8797:95ca:a4d1:3011", + "threat.indicator.last_seen": "2020-10-09T18:44:45.000Z", + "threat.indicator.marking.tlp": [ "White" ], - "threatintel.indicator.provider": "Default Organization", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "6i0-utr.example.com", - "threatintel.indicator.url.full": "https://6i0-utr.example.com/hsv/50qcugwt?xcl=ofr", - "threatintel.indicator.url.original": "https://6i0-utr.example.com/hsv/50qcugwt?xcl=ofr", - "threatintel.indicator.url.path": "/hsv/50qcugwt", - "threatintel.indicator.url.query": "xcl=ofr", - "threatintel.indicator.url.scheme": "https" + "threat.indicator.provider": "Default Organization", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "6i0-utr.example.com", + "threat.indicator.url.full": "https://6i0-utr.example.com/hsv/50qcugwt?xcl=ofr", + "threat.indicator.url.original": "https://6i0-utr.example.com/hsv/50qcugwt?xcl=ofr", + "threat.indicator.url.path": "/hsv/50qcugwt", + "threat.indicator.url.query": "xcl=ofr", + "threat.indicator.url.scheme": "https" }, { + "anomali.threatstream.classification": "private", + "anomali.threatstream.confidence": 94, + "anomali.threatstream.detail2": "imported by user 914", + "anomali.threatstream.id": "1139990065", + "anomali.threatstream.itype": "mal_ip", + "anomali.threatstream.maltype": "malware:9pyy91p7", + "anomali.threatstream.resource_uri": "/api/v1/intelligence/P20277063326/", + "anomali.threatstream.severity": "high", + "anomali.threatstream.source_feed_id": "2363", + "anomali.threatstream.state": "active", + "anomali.threatstream.trusted_circle_ids": [ + "346", + "610" + ], + "anomali.threatstream.update_id": "2750333841", + "anomali.threatstream.value_type": "ip", "event.category": "threat", "event.dataset": "threatintel.anomalithreatstream", "event.kind": "enrichment", @@ -3793,39 +4078,41 @@ "IP=203.0.113.155", "ail6s", "first_seen=2020-11-23T17:11:50", + "forwarded", "mask=203.0.113.23", "popularity=medium", "q0n", "threatintel-anomalithreatstream" ], - "threatintel.anomalithreatstream.classification": "private", - "threatintel.anomalithreatstream.confidence": 94, - "threatintel.anomalithreatstream.detail2": "imported by user 914", - "threatintel.anomalithreatstream.id": 1139990065, - "threatintel.anomalithreatstream.itype": "mal_ip", - "threatintel.anomalithreatstream.maltype": "malware:9pyy91p7", - "threatintel.anomalithreatstream.resource_uri": "/api/v1/intelligence/P20277063326/", - "threatintel.anomalithreatstream.severity": "high", - "threatintel.anomalithreatstream.source_feed_id": 2363, - "threatintel.anomalithreatstream.state": "active", - "threatintel.anomalithreatstream.trusted_circle_ids": [ - "346", - "610" - ], - "threatintel.anomalithreatstream.update_id": 2750333841, - "threatintel.anomalithreatstream.value_type": "ip", - "threatintel.indicator.confidence": 9, - "threatintel.indicator.first_seen": "2020-10-09T18:44:47.000Z", - "threatintel.indicator.geo.country_iso_code": "CN", - "threatintel.indicator.ip": "203.0.113.128", - "threatintel.indicator.last_seen": "2020-10-09T18:44:47.000Z", - "threatintel.indicator.marking.tlp": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali ThreatStream", + "threat.indicator.confidence": "High", + "threat.indicator.first_seen": "2020-10-09T18:44:47.000Z", + "threat.indicator.geo.country_iso_code": "CN", + "threat.indicator.ip": "203.0.113.128", + "threat.indicator.last_seen": "2020-10-09T18:44:47.000Z", + "threat.indicator.marking.tlp": [ "Amber" ], - "threatintel.indicator.provider": "Default Organization", - "threatintel.indicator.type": "ipv4-addr" + "threat.indicator.provider": "Default Organization", + "threat.indicator.type": "ipv4-addr" }, { + "anomali.threatstream.classification": "public", + "anomali.threatstream.confidence": 69, + "anomali.threatstream.detail2": "imported by user 886", + "anomali.threatstream.id": "2453026318", + "anomali.threatstream.itype": "mal_domain", + "anomali.threatstream.maltype": "malware:c0-a", + "anomali.threatstream.resource_uri": "/api/v1/intelligence/P26988858868/", + "anomali.threatstream.severity": "medium", + "anomali.threatstream.source_feed_id": "1281", + "anomali.threatstream.state": "active", + "anomali.threatstream.trusted_circle_ids": [ + "391" + ], + "anomali.threatstream.update_id": "3315952704", + "anomali.threatstream.value_type": "domain", "event.category": "threat", "event.dataset": "threatintel.anomalithreatstream", "event.kind": "enrichment", @@ -3839,39 +4126,44 @@ "tags": [ "0a3p", "first_seen=2020-03-11T09:04:13", + "forwarded", "mask=2001:db8:7aae:f1e6:e8b3:5702:40ea:29f0", "popularity=high", "smh", "threatintel-anomalithreatstream" ], - "threatintel.anomalithreatstream.classification": "public", - "threatintel.anomalithreatstream.confidence": 69, - "threatintel.anomalithreatstream.detail2": "imported by user 886", - "threatintel.anomalithreatstream.id": 2453026318, - "threatintel.anomalithreatstream.itype": "mal_domain", - "threatintel.anomalithreatstream.maltype": "malware:c0-a", - "threatintel.anomalithreatstream.resource_uri": "/api/v1/intelligence/P26988858868/", - "threatintel.anomalithreatstream.severity": "medium", - "threatintel.anomalithreatstream.source_feed_id": 1281, - "threatintel.anomalithreatstream.state": "active", - "threatintel.anomalithreatstream.trusted_circle_ids": [ - "391" - ], - "threatintel.anomalithreatstream.update_id": 3315952704, - "threatintel.anomalithreatstream.value_type": "domain", - "threatintel.indicator.confidence": 7, - "threatintel.indicator.first_seen": "2020-10-09T18:44:50.000Z", - "threatintel.indicator.geo.country_iso_code": "HK", - "threatintel.indicator.ip": "203.0.113.16", - "threatintel.indicator.last_seen": "2020-10-09T18:44:50.000Z", - "threatintel.indicator.marking.tlp": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali ThreatStream", + "threat.indicator.confidence": "Med", + "threat.indicator.first_seen": "2020-10-09T18:44:50.000Z", + "threat.indicator.geo.country_iso_code": "HK", + "threat.indicator.ip": "203.0.113.16", + "threat.indicator.last_seen": "2020-10-09T18:44:50.000Z", + "threat.indicator.marking.tlp": [ "White" ], - "threatintel.indicator.provider": "Default Organization", - "threatintel.indicator.type": "domain-name", - "threatintel.indicator.url.domain": "ztpyt.example.org" + "threat.indicator.provider": "Default Organization", + "threat.indicator.type": "domain-name", + "threat.indicator.url.domain": "ztpyt.example.org" }, { + "anomali.threatstream.classification": "private", + "anomali.threatstream.confidence": 88, + "anomali.threatstream.detail2": "imported by user 268", + "anomali.threatstream.id": "3554643386", + "anomali.threatstream.itype": "mal_url", + "anomali.threatstream.maltype": "malware:ai7s5vg01", + "anomali.threatstream.resource_uri": "/api/v1/intelligence/P48225335605/", + "anomali.threatstream.severity": "very-high", + "anomali.threatstream.source_feed_id": "744", + "anomali.threatstream.state": "active", + "anomali.threatstream.trusted_circle_ids": [ + "258", + "75", + "806" + ], + "anomali.threatstream.update_id": "3898530792", + "anomali.threatstream.value_type": "url", "event.category": "threat", "event.dataset": "threatintel.anomalithreatstream", "event.kind": "enrichment", @@ -3884,45 +4176,46 @@ "service.type": "threatintel", "tags": [ "first_seen=2020-07-17T00:42:30", + "forwarded", "mask=192.0.2.22", "mdedohd", "popularity=high", "sv5lmqoo", "threatintel-anomalithreatstream" ], - "threatintel.anomalithreatstream.classification": "private", - "threatintel.anomalithreatstream.confidence": 88, - "threatintel.anomalithreatstream.detail2": "imported by user 268", - "threatintel.anomalithreatstream.id": 3554643386, - "threatintel.anomalithreatstream.itype": "mal_url", - "threatintel.anomalithreatstream.maltype": "malware:ai7s5vg01", - "threatintel.anomalithreatstream.resource_uri": "/api/v1/intelligence/P48225335605/", - "threatintel.anomalithreatstream.severity": "very-high", - "threatintel.anomalithreatstream.source_feed_id": 744, - "threatintel.anomalithreatstream.state": "active", - "threatintel.anomalithreatstream.trusted_circle_ids": [ - "258", - "75", - "806" - ], - "threatintel.anomalithreatstream.update_id": 3898530792, - "threatintel.anomalithreatstream.value_type": "url", - "threatintel.indicator.confidence": 9, - "threatintel.indicator.first_seen": "2020-10-09T18:44:50.000Z", - "threatintel.indicator.last_seen": "2020-10-09T18:44:50.000Z", - "threatintel.indicator.marking.tlp": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali ThreatStream", + "threat.indicator.confidence": "High", + "threat.indicator.first_seen": "2020-10-09T18:44:50.000Z", + "threat.indicator.last_seen": "2020-10-09T18:44:50.000Z", + "threat.indicator.marking.tlp": [ "Amber" ], - "threatintel.indicator.provider": "Default Organization", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "e5el.example.net", - "threatintel.indicator.url.full": "http://e5el.example.net/rncer/fky?8tc53bbz=1pd-6w5", - "threatintel.indicator.url.original": "http://e5el.example.net/rncer/fky?8tc53bbz=1pd-6w5", - "threatintel.indicator.url.path": "/rncer/fky", - "threatintel.indicator.url.query": "8tc53bbz=1pd-6w5", - "threatintel.indicator.url.scheme": "http" + "threat.indicator.provider": "Default Organization", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "e5el.example.net", + "threat.indicator.url.full": "http://e5el.example.net/rncer/fky?8tc53bbz=1pd-6w5", + "threat.indicator.url.original": "http://e5el.example.net/rncer/fky?8tc53bbz=1pd-6w5", + "threat.indicator.url.path": "/rncer/fky", + "threat.indicator.url.query": "8tc53bbz=1pd-6w5", + "threat.indicator.url.scheme": "http" }, { + "anomali.threatstream.classification": "private", + "anomali.threatstream.confidence": 73, + "anomali.threatstream.detail2": "imported by user 737", + "anomali.threatstream.id": "2781657405", + "anomali.threatstream.itype": "phish_url", + "anomali.threatstream.maltype": "malware:6faja4zy-", + "anomali.threatstream.resource_uri": "/api/v1/intelligence/P13788530147/", + "anomali.threatstream.severity": "low", + "anomali.threatstream.source_feed_id": "518", + "anomali.threatstream.state": "active", + "anomali.threatstream.trusted_circle_ids": [ + "259" + ], + "anomali.threatstream.update_id": "1423149268", + "anomali.threatstream.value_type": "url", "event.category": "threat", "event.dataset": "threatintel.anomalithreatstream", "event.kind": "enrichment", @@ -3934,42 +4227,47 @@ "log.offset": 47992, "service.type": "threatintel", "tags": [ + "forwarded", "l019r8", "threatintel-anomalithreatstream" ], - "threatintel.anomalithreatstream.classification": "private", - "threatintel.anomalithreatstream.confidence": 73, - "threatintel.anomalithreatstream.detail2": "imported by user 737", - "threatintel.anomalithreatstream.id": 2781657405, - "threatintel.anomalithreatstream.itype": "phish_url", - "threatintel.anomalithreatstream.maltype": "malware:6faja4zy-", - "threatintel.anomalithreatstream.resource_uri": "/api/v1/intelligence/P13788530147/", - "threatintel.anomalithreatstream.severity": "low", - "threatintel.anomalithreatstream.source_feed_id": 518, - "threatintel.anomalithreatstream.state": "active", - "threatintel.anomalithreatstream.trusted_circle_ids": [ - "259" - ], - "threatintel.anomalithreatstream.update_id": 1423149268, - "threatintel.anomalithreatstream.value_type": "url", - "threatintel.indicator.confidence": 7, - "threatintel.indicator.first_seen": "2020-10-09T18:44:54.000Z", - "threatintel.indicator.geo.country_iso_code": "US", - "threatintel.indicator.ip": "192.0.2.226", - "threatintel.indicator.last_seen": "2020-10-09T18:44:54.000Z", - "threatintel.indicator.marking.tlp": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali ThreatStream", + "threat.indicator.confidence": "High", + "threat.indicator.first_seen": "2020-10-09T18:44:54.000Z", + "threat.indicator.geo.country_iso_code": "US", + "threat.indicator.ip": "192.0.2.226", + "threat.indicator.last_seen": "2020-10-09T18:44:54.000Z", + "threat.indicator.marking.tlp": [ "Amber" ], - "threatintel.indicator.provider": "Default Organization", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "eryz36i.example.net", - "threatintel.indicator.url.full": "http://eryz36i.example.net/9a86hdj/zti5r9fx?ahz=l7dsg01qo", - "threatintel.indicator.url.original": "http://eryz36i.example.net/9a86hdj/zti5r9fx?ahz=l7dsg01qo", - "threatintel.indicator.url.path": "/9a86hdj/zti5r9fx", - "threatintel.indicator.url.query": "ahz=l7dsg01qo", - "threatintel.indicator.url.scheme": "http" + "threat.indicator.provider": "Default Organization", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "eryz36i.example.net", + "threat.indicator.url.full": "http://eryz36i.example.net/9a86hdj/zti5r9fx?ahz=l7dsg01qo", + "threat.indicator.url.original": "http://eryz36i.example.net/9a86hdj/zti5r9fx?ahz=l7dsg01qo", + "threat.indicator.url.path": "/9a86hdj/zti5r9fx", + "threat.indicator.url.query": "ahz=l7dsg01qo", + "threat.indicator.url.scheme": "http" }, { + "anomali.threatstream.classification": "private", + "anomali.threatstream.confidence": 22, + "anomali.threatstream.detail2": "imported by user 703", + "anomali.threatstream.id": "1875325904", + "anomali.threatstream.itype": "phish_url", + "anomali.threatstream.maltype": "malware:rrcnb", + "anomali.threatstream.resource_uri": "/api/v1/intelligence/P12535858975/", + "anomali.threatstream.severity": "medium", + "anomali.threatstream.source_feed_id": "417", + "anomali.threatstream.state": "active", + "anomali.threatstream.trusted_circle_ids": [ + "114", + "792", + "802" + ], + "anomali.threatstream.update_id": "2621256767", + "anomali.threatstream.value_type": "url", "event.category": "threat", "event.dataset": "threatintel.anomalithreatstream", "event.kind": "enrichment", @@ -3982,43 +4280,45 @@ "service.type": "threatintel", "tags": [ "4yqbj3b", + "forwarded", "threatintel-anomalithreatstream" ], - "threatintel.anomalithreatstream.classification": "private", - "threatintel.anomalithreatstream.confidence": 22, - "threatintel.anomalithreatstream.detail2": "imported by user 703", - "threatintel.anomalithreatstream.id": 1875325904, - "threatintel.anomalithreatstream.itype": "phish_url", - "threatintel.anomalithreatstream.maltype": "malware:rrcnb", - "threatintel.anomalithreatstream.resource_uri": "/api/v1/intelligence/P12535858975/", - "threatintel.anomalithreatstream.severity": "medium", - "threatintel.anomalithreatstream.source_feed_id": 417, - "threatintel.anomalithreatstream.state": "active", - "threatintel.anomalithreatstream.trusted_circle_ids": [ - "114", - "792", - "802" - ], - "threatintel.anomalithreatstream.update_id": 2621256767, - "threatintel.anomalithreatstream.value_type": "url", - "threatintel.indicator.confidence": 2, - "threatintel.indicator.first_seen": "2020-10-09T18:44:58.000Z", - "threatintel.indicator.geo.country_iso_code": "US", - "threatintel.indicator.ip": "192.0.2.25", - "threatintel.indicator.last_seen": "2020-10-09T18:44:58.000Z", - "threatintel.indicator.marking.tlp": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali ThreatStream", + "threat.indicator.confidence": "Low", + "threat.indicator.first_seen": "2020-10-09T18:44:58.000Z", + "threat.indicator.geo.country_iso_code": "US", + "threat.indicator.ip": "192.0.2.25", + "threat.indicator.last_seen": "2020-10-09T18:44:58.000Z", + "threat.indicator.marking.tlp": [ "Amber" ], - "threatintel.indicator.provider": "Default Organization", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "i-pb.example.com", - "threatintel.indicator.url.full": "http://i-pb.example.com/pjmy3/w0tgzb?noe1pr9=eiwcfihd", - "threatintel.indicator.url.original": "http://i-pb.example.com/pjmy3/w0tgzb?noe1pr9=eiwcfihd", - "threatintel.indicator.url.path": "/pjmy3/w0tgzb", - "threatintel.indicator.url.query": "noe1pr9=eiwcfihd", - "threatintel.indicator.url.scheme": "http" + "threat.indicator.provider": "Default Organization", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "i-pb.example.com", + "threat.indicator.url.full": "http://i-pb.example.com/pjmy3/w0tgzb?noe1pr9=eiwcfihd", + "threat.indicator.url.original": "http://i-pb.example.com/pjmy3/w0tgzb?noe1pr9=eiwcfihd", + "threat.indicator.url.path": "/pjmy3/w0tgzb", + "threat.indicator.url.query": "noe1pr9=eiwcfihd", + "threat.indicator.url.scheme": "http" }, { + "anomali.threatstream.classification": "public", + "anomali.threatstream.confidence": 19, + "anomali.threatstream.detail2": "imported by user 846", + "anomali.threatstream.id": "2684776210", + "anomali.threatstream.itype": "mal_ip", + "anomali.threatstream.maltype": "malware:zfd", + "anomali.threatstream.resource_uri": "/api/v1/intelligence/P45743905551/", + "anomali.threatstream.severity": "very-high", + "anomali.threatstream.source_feed_id": "965", + "anomali.threatstream.state": "active", + "anomali.threatstream.trusted_circle_ids": [ + "641", + "697" + ], + "anomali.threatstream.update_id": "1171583779", + "anomali.threatstream.value_type": "ip", "event.category": "threat", "event.dataset": "threatintel.anomalithreatstream", "event.kind": "enrichment", @@ -4032,40 +4332,44 @@ "tags": [ "IP=2001:db8:61be:1efa:290:c941:bef8:3803", "first_seen=2020-12-01T02:16:04", + "forwarded", "j6vwgb6", "mask=2001:db8:fc83:375e:9c60:3d50:1dc1:9f89", "popularity=medium", "qqo5fg", "threatintel-anomalithreatstream" ], - "threatintel.anomalithreatstream.classification": "public", - "threatintel.anomalithreatstream.confidence": 19, - "threatintel.anomalithreatstream.detail2": "imported by user 846", - "threatintel.anomalithreatstream.id": 2684776210, - "threatintel.anomalithreatstream.itype": "mal_ip", - "threatintel.anomalithreatstream.maltype": "malware:zfd", - "threatintel.anomalithreatstream.resource_uri": "/api/v1/intelligence/P45743905551/", - "threatintel.anomalithreatstream.severity": "very-high", - "threatintel.anomalithreatstream.source_feed_id": 965, - "threatintel.anomalithreatstream.state": "active", - "threatintel.anomalithreatstream.trusted_circle_ids": [ - "641", - "697" - ], - "threatintel.anomalithreatstream.update_id": 1171583779, - "threatintel.anomalithreatstream.value_type": "ip", - "threatintel.indicator.confidence": 2, - "threatintel.indicator.first_seen": "2020-10-09T18:45:05.000Z", - "threatintel.indicator.geo.country_iso_code": "IN", - "threatintel.indicator.ip": "2001:db8:79d3:9083:95f2:a6fd:e475:4956", - "threatintel.indicator.last_seen": "2020-10-09T18:45:05.000Z", - "threatintel.indicator.marking.tlp": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali ThreatStream", + "threat.indicator.confidence": "Low", + "threat.indicator.first_seen": "2020-10-09T18:45:05.000Z", + "threat.indicator.geo.country_iso_code": "IN", + "threat.indicator.ip": "2001:db8:79d3:9083:95f2:a6fd:e475:4956", + "threat.indicator.last_seen": "2020-10-09T18:45:05.000Z", + "threat.indicator.marking.tlp": [ "White" ], - "threatintel.indicator.provider": "Default Organization", - "threatintel.indicator.type": "ipv6-addr" + "threat.indicator.provider": "Default Organization", + "threat.indicator.type": "ipv6-addr" }, { + "anomali.threatstream.classification": "public", + "anomali.threatstream.confidence": 14, + "anomali.threatstream.detail2": "imported by user 812", + "anomali.threatstream.id": "1705726884", + "anomali.threatstream.import_session_id": "2813", + "anomali.threatstream.itype": "mal_ip", + "anomali.threatstream.maltype": "malware:ib0ezg", + "anomali.threatstream.resource_uri": "/api/v1/intelligence/P12586136986/", + "anomali.threatstream.severity": "low", + "anomali.threatstream.source_feed_id": "632", + "anomali.threatstream.state": "active", + "anomali.threatstream.trusted_circle_ids": [ + "459", + "936" + ], + "anomali.threatstream.update_id": "3651210157", + "anomali.threatstream.value_type": "ip", "event.category": "threat", "event.dataset": "threatintel.anomalithreatstream", "event.kind": "enrichment", @@ -4077,41 +4381,42 @@ "log.offset": 49879, "service.type": "threatintel", "tags": [ + "forwarded", "threatintel-anomalithreatstream" ], - "threatintel.anomalithreatstream.classification": "public", - "threatintel.anomalithreatstream.confidence": 14, - "threatintel.anomalithreatstream.detail2": "imported by user 812", - "threatintel.anomalithreatstream.id": 1705726884, - "threatintel.anomalithreatstream.import_session_id": 2813, - "threatintel.anomalithreatstream.itype": "mal_ip", - "threatintel.anomalithreatstream.maltype": "malware:ib0ezg", - "threatintel.anomalithreatstream.resource_uri": "/api/v1/intelligence/P12586136986/", - "threatintel.anomalithreatstream.severity": "low", - "threatintel.anomalithreatstream.source_feed_id": 632, - "threatintel.anomalithreatstream.state": "active", - "threatintel.anomalithreatstream.trusted_circle_ids": [ - "459", - "936" - ], - "threatintel.anomalithreatstream.update_id": 3651210157, - "threatintel.anomalithreatstream.value_type": "ip", - "threatintel.indicator.as.number": 3356, - "threatintel.indicator.as.organization.name": "Level 3 Communications", - "threatintel.indicator.confidence": 1, - "threatintel.indicator.first_seen": "2021-04-07T13:10:07.000Z", - "threatintel.indicator.geo.country_iso_code": "US", - "threatintel.indicator.geo.location.lat": 5.6, - "threatintel.indicator.geo.location.lon": 112.8, - "threatintel.indicator.ip": "192.0.2.12", - "threatintel.indicator.last_seen": "2021-04-19T08:57:46.000Z", - "threatintel.indicator.marking.tlp": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali ThreatStream", + "threat.indicator.as.number": 3356, + "threat.indicator.as.organization.name": "Level 3 Communications", + "threat.indicator.confidence": "Low", + "threat.indicator.first_seen": "2021-04-07T13:10:07.000Z", + "threat.indicator.geo.country_iso_code": "US", + "threat.indicator.geo.location.lat": 5.6, + "threat.indicator.geo.location.lon": 112.8, + "threat.indicator.ip": "192.0.2.12", + "threat.indicator.last_seen": "2021-04-19T08:57:46.000Z", + "threat.indicator.marking.tlp": [ "White" ], - "threatintel.indicator.provider": "Default Organization", - "threatintel.indicator.type": "ipv4-addr" + "threat.indicator.provider": "Default Organization", + "threat.indicator.type": "ipv4-addr" }, { + "anomali.threatstream.classification": "private", + "anomali.threatstream.confidence": 81, + "anomali.threatstream.detail2": "imported by user 411", + "anomali.threatstream.id": "1502608684", + "anomali.threatstream.itype": "apt_ip", + "anomali.threatstream.resource_uri": "/api/v1/intelligence/P46655498126/", + "anomali.threatstream.severity": "very-high", + "anomali.threatstream.source_feed_id": "2891", + "anomali.threatstream.state": "active", + "anomali.threatstream.trusted_circle_ids": [ + "474", + "601" + ], + "anomali.threatstream.update_id": "1170853028", + "anomali.threatstream.value_type": "ip", "event.category": "threat", "event.dataset": "threatintel.anomalithreatstream", "event.kind": "enrichment", @@ -4123,34 +4428,36 @@ "log.offset": 50468, "service.type": "threatintel", "tags": [ + "forwarded", "threatintel-anomalithreatstream" ], - "threatintel.anomalithreatstream.classification": "private", - "threatintel.anomalithreatstream.confidence": 81, - "threatintel.anomalithreatstream.detail2": "imported by user 411", - "threatintel.anomalithreatstream.id": 1502608684, - "threatintel.anomalithreatstream.itype": "apt_ip", - "threatintel.anomalithreatstream.resource_uri": "/api/v1/intelligence/P46655498126/", - "threatintel.anomalithreatstream.severity": "very-high", - "threatintel.anomalithreatstream.source_feed_id": 2891, - "threatintel.anomalithreatstream.state": "active", - "threatintel.anomalithreatstream.trusted_circle_ids": [ - "474", - "601" - ], - "threatintel.anomalithreatstream.update_id": 1170853028, - "threatintel.anomalithreatstream.value_type": "ip", - "threatintel.indicator.confidence": 8, - "threatintel.indicator.first_seen": "2021-04-29T16:02:17.000Z", - "threatintel.indicator.ip": "203.0.113.5", - "threatintel.indicator.last_seen": "2021-04-29T16:02:17.000Z", - "threatintel.indicator.marking.tlp": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali ThreatStream", + "threat.indicator.confidence": "High", + "threat.indicator.first_seen": "2021-04-29T16:02:17.000Z", + "threat.indicator.ip": "203.0.113.5", + "threat.indicator.last_seen": "2021-04-29T16:02:17.000Z", + "threat.indicator.marking.tlp": [ "Amber" ], - "threatintel.indicator.provider": "Default Organization", - "threatintel.indicator.type": "ipv4-addr" + "threat.indicator.provider": "Default Organization", + "threat.indicator.type": "ipv4-addr" }, { + "anomali.threatstream.classification": "private", + "anomali.threatstream.confidence": 14, + "anomali.threatstream.detail2": "imported by user 601", + "anomali.threatstream.id": "1171635730", + "anomali.threatstream.itype": "ssh_ip", + "anomali.threatstream.resource_uri": "/api/v1/intelligence/P24647878518/", + "anomali.threatstream.severity": "medium", + "anomali.threatstream.source_feed_id": "822", + "anomali.threatstream.state": "active", + "anomali.threatstream.trusted_circle_ids": [ + "749" + ], + "anomali.threatstream.update_id": "1026394470", + "anomali.threatstream.value_type": "ip", "event.category": "threat", "event.dataset": "threatintel.anomalithreatstream", "event.kind": "enrichment", @@ -4162,33 +4469,37 @@ "log.offset": 50919, "service.type": "threatintel", "tags": [ + "forwarded", "threatintel-anomalithreatstream" ], - "threatintel.anomalithreatstream.classification": "private", - "threatintel.anomalithreatstream.confidence": 14, - "threatintel.anomalithreatstream.detail2": "imported by user 601", - "threatintel.anomalithreatstream.id": 1171635730, - "threatintel.anomalithreatstream.itype": "ssh_ip", - "threatintel.anomalithreatstream.resource_uri": "/api/v1/intelligence/P24647878518/", - "threatintel.anomalithreatstream.severity": "medium", - "threatintel.anomalithreatstream.source_feed_id": 822, - "threatintel.anomalithreatstream.state": "active", - "threatintel.anomalithreatstream.trusted_circle_ids": [ - "749" - ], - "threatintel.anomalithreatstream.update_id": 1026394470, - "threatintel.anomalithreatstream.value_type": "ip", - "threatintel.indicator.confidence": 1, - "threatintel.indicator.first_seen": "2021-04-29T16:02:23.000Z", - "threatintel.indicator.ip": "192.0.2.68", - "threatintel.indicator.last_seen": "2021-04-29T16:02:23.000Z", - "threatintel.indicator.marking.tlp": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali ThreatStream", + "threat.indicator.confidence": "Low", + "threat.indicator.first_seen": "2021-04-29T16:02:23.000Z", + "threat.indicator.ip": "192.0.2.68", + "threat.indicator.last_seen": "2021-04-29T16:02:23.000Z", + "threat.indicator.marking.tlp": [ "Amber" ], - "threatintel.indicator.provider": "Default Organization", - "threatintel.indicator.type": "ipv4-addr" + "threat.indicator.provider": "Default Organization", + "threat.indicator.type": "ipv4-addr" }, { + "anomali.threatstream.classification": "public", + "anomali.threatstream.confidence": 70, + "anomali.threatstream.detail2": "imported by user 964", + "anomali.threatstream.id": "2251817936", + "anomali.threatstream.itype": "i2p_ip", + "anomali.threatstream.resource_uri": "/api/v1/intelligence/P47421535249/", + "anomali.threatstream.severity": "medium", + "anomali.threatstream.source_feed_id": "3194", + "anomali.threatstream.state": "active", + "anomali.threatstream.trusted_circle_ids": [ + "235", + "630" + ], + "anomali.threatstream.update_id": "3118045359", + "anomali.threatstream.value_type": "ip", "event.category": "threat", "event.dataset": "threatintel.anomalithreatstream", "event.kind": "enrichment", @@ -4200,34 +4511,37 @@ "log.offset": 51361, "service.type": "threatintel", "tags": [ + "forwarded", "threatintel-anomalithreatstream" ], - "threatintel.anomalithreatstream.classification": "public", - "threatintel.anomalithreatstream.confidence": 70, - "threatintel.anomalithreatstream.detail2": "imported by user 964", - "threatintel.anomalithreatstream.id": 2251817936, - "threatintel.anomalithreatstream.itype": "i2p_ip", - "threatintel.anomalithreatstream.resource_uri": "/api/v1/intelligence/P47421535249/", - "threatintel.anomalithreatstream.severity": "medium", - "threatintel.anomalithreatstream.source_feed_id": 3194, - "threatintel.anomalithreatstream.state": "active", - "threatintel.anomalithreatstream.trusted_circle_ids": [ - "235", - "630" - ], - "threatintel.anomalithreatstream.update_id": 3118045359, - "threatintel.anomalithreatstream.value_type": "ip", - "threatintel.indicator.confidence": 7, - "threatintel.indicator.first_seen": "2021-04-29T16:02:24.000Z", - "threatintel.indicator.ip": "203.0.113.54", - "threatintel.indicator.last_seen": "2021-04-29T16:02:24.000Z", - "threatintel.indicator.marking.tlp": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali ThreatStream", + "threat.indicator.confidence": "High", + "threat.indicator.first_seen": "2021-04-29T16:02:24.000Z", + "threat.indicator.ip": "203.0.113.54", + "threat.indicator.last_seen": "2021-04-29T16:02:24.000Z", + "threat.indicator.marking.tlp": [ "White" ], - "threatintel.indicator.provider": "Default Organization", - "threatintel.indicator.type": "ipv4-addr" + "threat.indicator.provider": "Default Organization", + "threat.indicator.type": "ipv4-addr" }, { + "anomali.threatstream.classification": "public", + "anomali.threatstream.confidence": 77, + "anomali.threatstream.detail2": "imported by user 137", + "anomali.threatstream.id": "1966380326", + "anomali.threatstream.itype": "parked_ip", + "anomali.threatstream.resource_uri": "/api/v1/intelligence/P19479436344/", + "anomali.threatstream.severity": "low", + "anomali.threatstream.source_feed_id": "229", + "anomali.threatstream.state": "active", + "anomali.threatstream.trusted_circle_ids": [ + "303", + "461" + ], + "anomali.threatstream.update_id": "1757326916", + "anomali.threatstream.value_type": "ip", "event.category": "threat", "event.dataset": "threatintel.anomalithreatstream", "event.kind": "enrichment", @@ -4239,34 +4553,38 @@ "log.offset": 51809, "service.type": "threatintel", "tags": [ + "forwarded", "threatintel-anomalithreatstream" ], - "threatintel.anomalithreatstream.classification": "public", - "threatintel.anomalithreatstream.confidence": 77, - "threatintel.anomalithreatstream.detail2": "imported by user 137", - "threatintel.anomalithreatstream.id": 1966380326, - "threatintel.anomalithreatstream.itype": "parked_ip", - "threatintel.anomalithreatstream.resource_uri": "/api/v1/intelligence/P19479436344/", - "threatintel.anomalithreatstream.severity": "low", - "threatintel.anomalithreatstream.source_feed_id": 229, - "threatintel.anomalithreatstream.state": "active", - "threatintel.anomalithreatstream.trusted_circle_ids": [ - "303", - "461" - ], - "threatintel.anomalithreatstream.update_id": 1757326916, - "threatintel.anomalithreatstream.value_type": "ip", - "threatintel.indicator.confidence": 8, - "threatintel.indicator.first_seen": "2021-04-29T16:02:25.000Z", - "threatintel.indicator.ip": "203.0.113.195", - "threatintel.indicator.last_seen": "2021-04-29T16:02:25.000Z", - "threatintel.indicator.marking.tlp": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali ThreatStream", + "threat.indicator.confidence": "High", + "threat.indicator.first_seen": "2021-04-29T16:02:25.000Z", + "threat.indicator.ip": "203.0.113.195", + "threat.indicator.last_seen": "2021-04-29T16:02:25.000Z", + "threat.indicator.marking.tlp": [ "White" ], - "threatintel.indicator.provider": "Default Organization", - "threatintel.indicator.type": "ipv4-addr" + "threat.indicator.provider": "Default Organization", + "threat.indicator.type": "ipv4-addr" }, { + "anomali.threatstream.classification": "private", + "anomali.threatstream.confidence": 14, + "anomali.threatstream.detail2": "imported by user 997", + "anomali.threatstream.id": "3377960871", + "anomali.threatstream.itype": "tor_ip", + "anomali.threatstream.resource_uri": "/api/v1/intelligence/P25503355951/", + "anomali.threatstream.severity": "medium", + "anomali.threatstream.source_feed_id": "1710", + "anomali.threatstream.state": "active", + "anomali.threatstream.trusted_circle_ids": [ + "13", + "657", + "879" + ], + "anomali.threatstream.update_id": "1469037378", + "anomali.threatstream.value_type": "ip", "event.category": "threat", "event.dataset": "threatintel.anomalithreatstream", "event.kind": "enrichment", @@ -4278,35 +4596,38 @@ "log.offset": 52257, "service.type": "threatintel", "tags": [ + "forwarded", "threatintel-anomalithreatstream" ], - "threatintel.anomalithreatstream.classification": "private", - "threatintel.anomalithreatstream.confidence": 14, - "threatintel.anomalithreatstream.detail2": "imported by user 997", - "threatintel.anomalithreatstream.id": 3377960871, - "threatintel.anomalithreatstream.itype": "tor_ip", - "threatintel.anomalithreatstream.resource_uri": "/api/v1/intelligence/P25503355951/", - "threatintel.anomalithreatstream.severity": "medium", - "threatintel.anomalithreatstream.source_feed_id": 1710, - "threatintel.anomalithreatstream.state": "active", - "threatintel.anomalithreatstream.trusted_circle_ids": [ - "13", - "657", - "879" - ], - "threatintel.anomalithreatstream.update_id": 1469037378, - "threatintel.anomalithreatstream.value_type": "ip", - "threatintel.indicator.confidence": 1, - "threatintel.indicator.first_seen": "2021-04-29T16:02:25.000Z", - "threatintel.indicator.ip": "192.0.2.239", - "threatintel.indicator.last_seen": "2021-04-29T16:02:25.000Z", - "threatintel.indicator.marking.tlp": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali ThreatStream", + "threat.indicator.confidence": "Low", + "threat.indicator.first_seen": "2021-04-29T16:02:25.000Z", + "threat.indicator.ip": "192.0.2.239", + "threat.indicator.last_seen": "2021-04-29T16:02:25.000Z", + "threat.indicator.marking.tlp": [ "Amber" ], - "threatintel.indicator.provider": "Default Organization", - "threatintel.indicator.type": "ipv4-addr" + "threat.indicator.provider": "Default Organization", + "threat.indicator.type": "ipv4-addr" }, { + "anomali.threatstream.classification": "public", + "anomali.threatstream.confidence": 12, + "anomali.threatstream.detail2": "imported by user 445", + "anomali.threatstream.id": "1049633552", + "anomali.threatstream.itype": "c2_ip", + "anomali.threatstream.maltype": "malware:tos5xne", + "anomali.threatstream.resource_uri": "/api/v1/intelligence/P17175297976/", + "anomali.threatstream.severity": "high", + "anomali.threatstream.source_feed_id": "274", + "anomali.threatstream.state": "active", + "anomali.threatstream.trusted_circle_ids": [ + "683", + "719" + ], + "anomali.threatstream.update_id": "1541655552", + "anomali.threatstream.value_type": "ip", "event.category": "threat", "event.dataset": "threatintel.anomalithreatstream", "event.kind": "enrichment", @@ -4318,33 +4639,20 @@ "log.offset": 52708, "service.type": "threatintel", "tags": [ + "forwarded", "threatintel-anomalithreatstream", "vjb9lmpcf" ], - "threatintel.anomalithreatstream.classification": "public", - "threatintel.anomalithreatstream.confidence": 12, - "threatintel.anomalithreatstream.detail2": "imported by user 445", - "threatintel.anomalithreatstream.id": 1049633552, - "threatintel.anomalithreatstream.itype": "c2_ip", - "threatintel.anomalithreatstream.maltype": "malware:tos5xne", - "threatintel.anomalithreatstream.resource_uri": "/api/v1/intelligence/P17175297976/", - "threatintel.anomalithreatstream.severity": "high", - "threatintel.anomalithreatstream.source_feed_id": 274, - "threatintel.anomalithreatstream.state": "active", - "threatintel.anomalithreatstream.trusted_circle_ids": [ - "683", - "719" - ], - "threatintel.anomalithreatstream.update_id": 1541655552, - "threatintel.anomalithreatstream.value_type": "ip", - "threatintel.indicator.confidence": 1, - "threatintel.indicator.first_seen": "2021-04-29T16:02:26.000Z", - "threatintel.indicator.ip": "192.0.2.169", - "threatintel.indicator.last_seen": "2021-04-29T16:02:26.000Z", - "threatintel.indicator.marking.tlp": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Anomali ThreatStream", + "threat.indicator.confidence": "Low", + "threat.indicator.first_seen": "2021-04-29T16:02:26.000Z", + "threat.indicator.ip": "192.0.2.169", + "threat.indicator.last_seen": "2021-04-29T16:02:26.000Z", + "threat.indicator.marking.tlp": [ "White" ], - "threatintel.indicator.provider": "Default Organization", - "threatintel.indicator.type": "ipv4-addr" + "threat.indicator.provider": "Default Organization", + "threat.indicator.type": "ipv4-addr" } ] \ No newline at end of file diff --git a/x-pack/filebeat/module/threatintel/fields.go b/x-pack/filebeat/module/threatintel/fields.go index 4f915c83f55..d0fa140db90 100644 --- a/x-pack/filebeat/module/threatintel/fields.go +++ b/x-pack/filebeat/module/threatintel/fields.go @@ -19,5 +19,5 @@ func init() { // AssetThreatintel returns asset data. // This is the base64 encoded zlib format compressed contents of module/threatintel. func AssetThreatintel() string { - return "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" + return "eJzsXNtz2zaXf89fccYvSWYUNXGTztYPO+PmsvGM23R9yfZNAwFHIlYgwAKgFPWv/wYASVEUSEk25Ob7pn6yeDnnh4NzB8BXsMD1BdhMI7FcWhTPACy3ArsXNQokBi9gipY8A2BoqOaF5UpewH8/AwC48y+Af0PwOUqK8IkLnLqrvypWChw/A5hxFMxc+FdegSQ5XsDZmf8JYNcFXsBcq7KorrQfb78S4I25ZJwSq/R4xgWOM2KysRUma56vaS5wvVKata5HhlD/3WUIjt5zAzwvlLbgaI6Az4AsCRdk6sZyDCaTkR//620yVIEcONKHopohsrG70gti8E1GTDZVRLMJZ3uHURMg09IgzcY5ESuidzm3J3rP4D95PYCZ0nDpqL7/DL8GqrXiXVWqWv91NWcDywlx4hBsceibkUFY4FXcvwvzEo1BBtM13N9cZ6Q04+bZCArD55LYUidBUctiRnIu+HqQcamFAzdhaiWFIiwF/2tFibsDL+5vrl/CKkONsFYlUCKhZgQEqCrWoGZgM278PAwiXXJdGqssEWONphQ2BdTLr8DQIvVwtUd9KIgCNUUZQzETitgHYuASKsKH4hBcLpLMGpcLsApshvC1IQ8anc8b95pzqcX3Yso8ifY6z3r1IeglOvs4yH40zlC7MJdyKirPASit3mvGE2OJLU0qEdBSa5QWAtVaHPc312P4XRnDpwJhSUSJBojGC1BScIkjULOZ+weIZFDKhVSrYYsKcSUV6kANqNIaTaEk43IelJobqCKPH8QQpKkgdCG4sWZsSj0VKcDd3t/8cr2hXIm1R5buCWRehFLZSfh5KOKC5MGjJwJe0YMPMfxDoILnQJ1qbu9W3FrUkBHJBNYaWXMBmxHrkqD6CtuZdHihNBCp5DpXpXk5CF4Q3Zb5BvpUKYFEHg79KmSAaFwgtJlHiluwHOgpomwhD244U8Y6BS60WnKGGl5YXSIoDTMiDL4ctCsyT+ILLr02emmTuQFijKKcOJArbjMP888SNUfWHtNuuJAqJ4KPBc9VqngRSH4fcWKT50cYdjLtR7F0tA5iWhBnLTIV34rcoUNeEsHZZKZVHgHAiMXDuf9fhnKbIayISxi1sTBTpWTOIrgBqqRxZoIssI/hyhXjMx617CSoBDE2xmTjV6YokgXpQM0V5KTlNhpEMd2P3HsUBB+3dlRi5C0Uv5G8EOiKUnfXF0bcAFM54XIU/PNKlYLBFP0Tnlhs2low0ji11u2D9Nk3QpLIzBGqHpn67GQfa6qkjRcaRzP/+M1qAha/WWcyzaNLrJn0qlJUJomq5rstK3JERr5UbKvQFOGs1hvMCRcjX2x/JiZ7dfv58vzdT2cxiGr6/0jtJCd6weXcZenJbO/27uoPaNL+ilOkTqoCX8hMjdVI8pMEwNsu6W4AjKmWIMbwGQ/1egrJ7GY7RLYmlxsoNF8SG7IYrXIgUJRTwSnMsMp5mwZWdUesxx0unaz5oiY6qt7Yfr7SoeapQYkoOeOsp5AzmdJHFPZOS3IkptSNgySUlprQNbzwY3/t7OzN69cvXV7F5zI0jNrz+dwJDBmn3kqJJGJtOTVgkWZSCTVfOxKNgIczcoaWcHEeGZlzCYcP7IOnE/yIU8Sol2jJ/Sqv8trpGkqDGt6eD+J8ogQtxtkjnRg0his5SQOkBSI0kCvyoWShbrJ9tdL2gkpuqcEw6FSO+GrLCe81ujNS2Elwymej8Mu75voHL+r/Si3ORh1yZ1NVP0LPW2To+eaqfw/O+HlRXcuJaB7t0nP3Gv7ux+aVnL2r/61IFkQvkFWPFBk3Wf1ul2y42X6wImEokdV1V3S3hmCqF7qkTGkKTrny/db6Yau0e9h7PvdDo7QTqwldoPasBuc+J6Jn9ldcMEqOm/6Z0nlo3WqcE+27J6Sp63w/eT0CAu+/foSrDyMI9XRw89YSunBXQqQbRUvFw6wwZ+9SqLNLDrx/OpyzRqNKTXFSap4Cwo1Lp5znvr+52oVSOeQ9SwO4RM3tOgWc95pbTongdh2dnqp95iOxd06mLArBu95pr2cQajWCHBkv8xFkfJ6NYIl6/cr9OzxYL/0UQ731lIamH9oh6tJFVmP3Y5s44aQLDBt8FufaK0XgMywm261VHyolR6gCwc1eKRGfhgwhs7o0FtmEck0FTjhLkm9vImhFHwL9oKQ8bxp+h9p5WbhqP9E03nticPVhX4s+CbOb6yN9mjfKZEucH4gloZIfKpsh5hV4MWpq/1KLppDL2bv+9aUq+EzJX4ToRIVTvcL0iyf6Pa4ZbyOMVbZPs2L8XfSTjfc+MVDt/SURcF3tiM1pqzqqVqZNB3GgJZScd24MjhPgtzKfonYjbSiHireS9u7ctv3TaZBUdA/G4Qw0CmJXtHHhbkj9D0rUnO6A69ejA0a2UV2D6FfP54ENuJQcrCazWbcdsIF0dXdqNFd3vUBaDaKwIBVR4J2pHo6SDKXlM46m7rgGy/GNaVNOc27DsmLFUEQNnSqGE+ddkiSciqF3Va6S4K36og5hXdtuFI+bIpW3v7r9/e9aJLq0VvNp2ckOWv1JPaeJspAvek4k/yuI973K81K6NH+TOuFya1fJFohTYDiAc6g3JgKXKOIQjrOAapY9veDj3vkO26jahPQGuAnLr8pYoFU1FI8sM5VEARjj7g4RTdudb5XZW+32XkH5tqbJ0qxIN0tXnp33Dg39GPOyTNeQu7/vqMVO47wVkONFznHrdI6pT8/VzCmB3OHsx1814aL+uTbhCVVldBnmOB39rFaQE7neEPa7PoBLKkqGzIUNAobLudgvIstzNJbkRRI5NdQeLCzGTRhUouWEDy16IUluWYxz7FFj0apQpu4GToSisQ1yR5vNLVrL5dyENYJ5qZGBkiG8+KUqxw0cN/C9XW72Tp97ONEuk2BS9a4tD2pr4ripuDkXJNWQl5mk06pLCytXojuKcWWKebamxsmI5nI+8XE/UYjaXhXwlJEFWAaa7ovZG7oYN2QqnFPQXiXjCv+QeWxR9KvlgRELSoW7UxtDh98sSmYmT+G6gVvI+TyzFdeeFGOcDonqpBmxKDogHAcm5ZacLTh+f84DAJ1qprbAPQCXUJTEGlcP9VARp0REazFYY64s7jRBt1PmhLrUnzZzCauM0yzut5q9eg53L86UataD1CtcCqwpNbAHq1fMFFhTa2UPXr+jq1ZQs5a0wnWInjbpXUJl3Zh1Q/1Ym97ASrl9p90QPgwafGrt7qkawbxYvh25qP/Gr4aakmbDQ6DE4lzpJGtjftN7Re8RQzn7De1K6QVcUsuX3K6j+5Jas6B6FkkeqsobzCar99aR0ipXcVIixLpWZN9vJS6A3g5DPFVoGpbuMCb/SMKUMFh5mNY0CPeUQscXjduAmk3jDR9kI+c9NRqU1WYbv6qIGqRvAJs9mniiWnLL328G4Hyr3zSQPcR5UZXniTZFvg+kDOSEYY1kg5Nbg2I2jOZUhYqn19LHik91vaOTpkDKZ5y2cA0rKApMdcahay6tIw25WtZR87gpfpoKq0GKcqvMShBgq82npwj/X6r8OW5afGNZByEcEO+jsoFGyLvK0Sz2dSrJ/bbmV5NTId3avd7wGAHDAsPhsQq9H5LgC4Qzv3TtkpRqAfuV0TQa5P2e6m92fNpM0CBVkhG9frjK7gI9VW54LNhHZIm7gzp1tviowR2WN0ZmKnX+GBvF4zLJXdCnyigPnYHDUD5NjpkW80myzhjEVPlnRKOfIg+NDekhGWnEy5w4M40h74+bu/i+r1w1MpoDFT159jqo5UfnsVHT/Bvz2ZOkCU+c4UZVfzjX7cX8JDlvn0odm/3ujuJ7z4Kbbq399qyL8WHbeL7c/fFvcNT7n/O18M/52v/087Wb0zJUaYZsVnY2Ij/Gzm8qovDJUz3c5lur39J2D8wM7Vvds6vzo6cWjho0+a0BUn8SrfNCfBdsr0tqg+vbdnrAxtMG5vY+w/qvOcFxxouLNz+fj1+Pz8dvfjzrRbmzcJkap2Mwhq/eu9WbQcO8DeM/BPyO4aQGHzseuQ3zqrhkTKMxZ1EN9RvX33dP5w1D3AOv/f2urg1dtb/D6NgGkavBUz8N1mKiiZx3JRqg9tzcg/XGveLiwtXvZu/po5ZYn9ez//qHNz89j6LV3CxSWf4NN4vKno+1cro5aderidO1janpAWrogbVYwIvXr96+3NXICJprMsXuln5IYxw7qPznScbwRfq5/k1JHMG9LE1JxAhum8OwI/iViPrfr6jXm9/9Q8JlOKYfzqJ3T0pA62N8xFqU+IgxPTcNt90Tm11chird73x2vyBwnHQ9dTfbP/88MN3OBm6tq75PM9Gb8yQe1E0p0ICaGtSuRCYuNs4I9cfYZxA+IyibV7R7eo+P/+Hd237v7kdX5jnR/abVPzw+l0rjhEzVEi/gzevzt4+ZjgBjz2jcqN+9bcuq2qYp1o3UxrvjBchLYfmkz9W0ZbLz/YauQAYekErn5iJ8Uqxf6A53r7gjR5LgWFXSW1q0m2yGbOvPRFlmyCr/t84ur/lUb+tTf00Zzo6ySfSrhcc1KK83X4uqPplq+VbetXHgmIpn1VjxFAc44reCazQpOH50pA5iRomgpUg10hbfmvAAhmYjckIhh6/RDLJN99XOimf1wc4VtxkPXZteHd9pWkyStZW+aD7nkohW4dml3SztsiVqQzTHNAdMN+RCzUY0guBysam6Q78tBqU5khFBEs8k9lXeBuvPNwLZnAWqGnpApqq0QGQN6V8BAAD///eBqM4=" } diff --git a/x-pack/filebeat/module/threatintel/malwarebazaar/_meta/fields.yml b/x-pack/filebeat/module/threatintel/malwarebazaar/_meta/fields.yml index 16a50f3a0ff..ea68e4c23cb 100644 --- a/x-pack/filebeat/module/threatintel/malwarebazaar/_meta/fields.yml +++ b/x-pack/filebeat/module/threatintel/malwarebazaar/_meta/fields.yml @@ -1,4 +1,4 @@ -- name: malwarebazaar +- name: abusech.malwarebazaar type: group description: > Fields for Malware Bazaar Threat Intel diff --git a/x-pack/filebeat/module/threatintel/malwarebazaar/config/config.yml b/x-pack/filebeat/module/threatintel/malwarebazaar/config/config.yml index a8cbef0b52b..6c90f1d86dc 100644 --- a/x-pack/filebeat/module/threatintel/malwarebazaar/config/config.yml +++ b/x-pack/filebeat/module/threatintel/malwarebazaar/config/config.yml @@ -5,19 +5,14 @@ interval: {{ .interval }} request.method: POST {{ if .ssl }} - request.ssl: {{ .ssl | tojson }} {{ end }} {{ if .proxy_url }} request.proxy_url: {{ .proxy_url }} {{ end }} request.url: {{ .url }} -#request.encode_as: application/x-www-form-encoded - +request.encode_as: application/x-www-form-urlencoded request.transforms: -- set: - target: header.Content-Type - value: application/x-www-form-urlencoded - set: target: url.params.query value: get_recent @@ -39,17 +34,12 @@ exclude_files: [".gz$"] {{ end }} -tags: {{.tags | tojson}} -publisher_pipeline.disable_host: {{ inList .tags "forwarded" }} +tags: +{{if .preserve_original_event}} + - preserve_original_event +{{end}} +{{range $val := .tags}} + - {{$val}} +{{end}} -processors: - - decode_json_fields: - fields: [message] - target: json - - fingerprint: - fields: ["json.md5_hash"] - target_field: "@metadata._id" - - add_fields: - target: '' - fields: - ecs.version: 1.12.0 +publisher_pipeline.disable_host: {{ inList .tags "forwarded" }} diff --git a/x-pack/filebeat/module/threatintel/malwarebazaar/ingest/pipeline.yml b/x-pack/filebeat/module/threatintel/malwarebazaar/ingest/pipeline.yml index c2c4b51810d..0a5aca9dbb3 100644 --- a/x-pack/filebeat/module/threatintel/malwarebazaar/ingest/pipeline.yml +++ b/x-pack/filebeat/module/threatintel/malwarebazaar/ingest/pipeline.yml @@ -1,4 +1,5 @@ -description: Pipeline for parsing Malware Bazaar Threat Intel +--- +description: Pipeline for parsing Abuse.ch URL Threat Intel processors: #################### # Event ECS fields # @@ -6,6 +7,9 @@ processors: - set: field: event.ingested value: "{{_ingest.timestamp}}" + - set: + field: ecs.version + value: "1.12" - set: field: event.kind value: enrichment @@ -20,148 +24,182 @@ processors: # General ECS fields # ###################### - rename: - field: json - target_field: threatintel.malwarebazaar - ignore_missing: true + field: message + target_field: event.original + ignore_missing: true + - json: + field: event.original + target_field: abusech.malwarebazaar + - fingerprint: + fields: + - abusech.malwarebazaar.md5_hash + - abusech.malwarebazaar.sha256_hash + target_field: "_id" ##################### # Threat ECS Fields # ##################### + - set: + field: threat.feed.name + value: "[Filebeat] AbuseCH MalwareBazaar" + - set: + field: threat.feed.dashboard_id + value: "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f" - date: - field: threatintel.malwarebazaar.first_seen - target_field: threatintel.indicator.first_seen + field: abusech.malwarebazaar.first_seen + target_field: threat.indicator.first_seen formats: - "yyyy-MM-dd HH:mm:ss z" - "yyyy-MM-dd HH:mm:ss Z" - "yyyy-MM-dd HH:mm:ss" - if: "ctx?.threatintel?.malwarebazaar.first_seen != null" + if: "ctx.abusech?.malwarebazaar?.first_seen != null" - date: - field: threatintel.malwarebazaar.last_seen - target_field: threatintel.indicator.last_seen + field: abusech.malwarebazaar.last_seen + target_field: threat.indicator.last_seen formats: - "yyyy-MM-dd HH:mm:ss z" - "yyyy-MM-dd HH:mm:ss Z" - "yyyy-MM-dd HH:mm:ss" - if: "ctx?.threatintel?.malwarebazaar.last_seen != null" + if: "ctx.abusech?.malwarebazaar?.last_seen != null" - set: - field: threatintel.indicator.type + field: threat.indicator.type value: file - rename: - field: threatintel.malwarebazaar.file_name - target_field: threatintel.indicator.file.name + field: abusech.malwarebazaar.file_name + target_field: threat.indicator.file.name ignore_missing: true - rename: - field: threatintel.malwarebazaar.file_type_mime - target_field: threatintel.indicator.file.mime_type + field: abusech.malwarebazaar.file_type_mime + target_field: threat.indicator.file.mime_type ignore_missing: true - rename: - field: threatintel.malwarebazaar.reporter - target_field: threatintel.indicator.provider + field: abusech.malwarebazaar.reporter + target_field: threat.indicator.provider ignore_missing: true - rename: - field: threatintel.malwarebazaar.origin_country - target_field: threatintel.indicator.geo.country_iso_code + field: abusech.malwarebazaar.origin_country + target_field: threat.indicator.geo.country_iso_code ignore_missing: true - rename: - field: threatintel.malwarebazaar.signature - target_field: threatintel.indicator.signature + field: abusech.malwarebazaar.signature + target_field: threat.software.alias ignore_missing: true - foreach: - field: threatintel.malwarebazaar.code_sign + field: abusech.malwarebazaar.code_sign ignore_missing: true processor: rename: - field: subject_cn - target_field: threatintel.indicator.file.x509.subject.common_name + field: _ingest._value.subject_cn + target_field: threat.indicator.file.x509.subject.common_name + - foreach: + field: abusech.malwarebazaar.code_sign + ignore_missing: true + processor: rename: - field: issuer_cn - target_field: threatintel.indicator.file.x509.issuer.common_name + field: _ingest._value.issuer_cn + target_field: threat.indicator.file.x509.issuer.common_name + - foreach: + field: abusech.malwarebazaar.code_sign + ignore_missing: true + processor: rename: - field: algorithm - target_field: threatintel.indicator.file.x509.public_key_algorithm + field: _ingest._value.algorithm + target_field: threat.indicator.file.x509.public_key_algorithm + - foreach: + field: abusech.malwarebazaar.code_sign + ignore_missing: true + processor: rename: - field: valid_from - target_field: threatintel.indicator.file.x509.not_before + field: _ingest._value.valid_from + target_field: threat.indicator.file.x509.not_before + - foreach: + field: abusech.malwarebazaar.code_sign + ignore_missing: true + processor: rename: - field: valid_to - target_field: threatintel.indicator.file.x509.not_after + field: _ingest._value.valid_to + target_field: threat.indicator.file.x509.not_after + - foreach: + field: abusech.malwarebazaar.code_sign + ignore_missing: true + processor: rename: - field: serial_number - target_field: threatintel.indicator.file.x509.serial_number + field: _ingest._value.serial_number + target_field: threat.indicator.file.x509.serial_number - rename: - field: threatintel.malwarebazaar.file_size - target_field: threatintel.indicator.file.size + field: abusech.malwarebazaar.file_size + target_field: threat.indicator.file.size ignore_missing: true - rename: - field: threatintel.malwarebazaar.file_type - target_field: threatintel.indicator.file.extension + field: abusech.malwarebazaar.file_type + target_field: threat.indicator.file.extension ignore_missing: true - rename: - field: threatintel.malwarebazaar.md5_hash - target_field: threatintel.indicator.file.hash.md5 + field: abusech.malwarebazaar.md5_hash + target_field: threat.indicator.file.hash.md5 ignore_missing: true - rename: - field: threatintel.malwarebazaar.sha256_hash - target_field: threatintel.indicator.file.hash.sha256 + field: abusech.malwarebazaar.sha256_hash + target_field: threat.indicator.file.hash.sha256 ignore_missing: true - rename: - field: threatintel.malwarebazaar.sha1_hash - target_field: threatintel.indicator.file.hash.sha1 + field: abusech.malwarebazaar.sha1_hash + target_field: threat.indicator.file.hash.sha1 ignore_missing: true - rename: - field: threatintel.malwarebazaar.sha3_384_hash - target_field: threatintel.indicator.file.hash.sha384 + field: abusech.malwarebazaar.sha3_384_hash + target_field: threat.indicator.file.hash.sha384 ignore_missing: true - rename: - field: threatintel.malwarebazaar.imphash - target_field: threatintel.indicator.file.pe.imphash + field: abusech.malwarebazaar.imphash + target_field: threat.indicator.file.pe.imphash ignore_missing: true - rename: - field: threatintel.malwarebazaar.ssdeep - target_field: threatintel.indicator.file.hash.ssdeep + field: abusech.malwarebazaar.ssdeep + target_field: threat.indicator.file.hash.ssdeep ignore_missing: true - rename: - field: threatintel.malwarebazaar.tlsh - target_field: threatintel.indicator.file.hash.tlsh + field: abusech.malwarebazaar.tlsh + target_field: threat.indicator.file.hash.tlsh ignore_missing: true - rename: - field: threatintel.malwarebazaar.telfhash - target_field: threatintel.indicator.file.elf.telfhash + field: abusech.malwarebazaar.telfhash + target_field: threat.indicator.file.elf.telfhash ignore_missing: true - append: field: related.hash - value: "{{ threatintel.indicator.file.hash.md5 }}" - if: ctx?.threatintel?.indicator?.file?.hash?.md5 != null + value: "{{ threat.indicator.file.hash.md5 }}" + if: ctx?.threat?.indicator?.file?.hash?.md5 != null - append: field: related.hash - value: "{{ threatintel.indicator.file.hash.sha256 }}" - if: ctx?.threatintel?.indicator?.file?.hash?.sha256 != null + value: "{{ threat.indicator.file.hash.sha256 }}" + if: ctx?.threat?.indicator?.file?.hash?.sha256 != null - append: field: related.hash - value: "{{ threatintel.indicator.file.hash.ssdeep }}" - if: ctx?.threatintel?.indicator?.file?.hash?.ssdeep != null + value: "{{ threat.indicator.file.hash.ssdeep }}" + if: ctx?.threat?.indicator?.file?.hash?.ssdeep != null - append: field: related.hash - value: "{{ threatintel.indicator.file.pe.imphash }}" - if: ctx?.threatintel?.indicator?.file?.pe?.imphash != null + value: "{{ threat.indicator.file.pe.imphash }}" + if: ctx?.threat?.indicator?.file?.pe?.imphash != null - append: field: related.hash - value: "{{ threatintel.indicator.file.elf.telfhash }}" - if: ctx?.threatintel?.indicator?.file?.elf?.telfhash != null + value: "{{ threat.indicator.file.elf.telfhash }}" + if: ctx?.threat?.indicator?.file?.elf?.telfhash != null - append: field: related.hash - value: "{{ threatintel.indicator.file.hash.tlsh }}" - if: ctx?.threatintel?.indicator?.file?.hash?.tlsh != null + value: "{{ threat.indicator.file.hash.tlsh }}" + if: ctx?.threat?.indicator?.file?.hash?.tlsh != null - convert: - field: threatintel.indicator.file.size + field: threat.indicator.file.size type: long ignore_missing: true - convert: - field: threatintel.malwarebazaar.intelligence.downloads + field: abusech.malwarebazaar.intelligence.downloads type: long ignore_missing: true - convert: - field: threatintel.malwarebazaar.intelligence.uploads + field: abusech.malwarebazaar.intelligence.uploads type: long ignore_missing: true @@ -169,12 +207,12 @@ processors: # Cleanup processors # ###################### - set: - field: threatintel.indicator.type + field: threat.indicator.type value: unknown - if: ctx?.threatintel?.indicator?.type == null + if: ctx?.threat?.indicator?.type == null - script: lang: painless - if: ctx?.threatintel != null + if: ctx?.abusech != null source: | void handleMap(Map map) { for (def x : map.values()) { @@ -196,10 +234,15 @@ processors: } } handleMap(ctx); + - remove: + field: event.original + if: "ctx?.tags == null || !(ctx.tags.contains('preserve_original_event'))" + ignore_failure: true + ignore_missing: true - remove: field: - - threatintel.malwarebazaar.first_seen - - threatintel.malwarebazaar.last_seen + - abusech.malwarebazaar.first_seen + - abusech.malwarebazaar.last_seen - message ignore_missing: true on_failure: diff --git a/x-pack/filebeat/module/threatintel/malwarebazaar/manifest.yml b/x-pack/filebeat/module/threatintel/malwarebazaar/manifest.yml index e9294ca9e2e..b90ea0d9562 100644 --- a/x-pack/filebeat/module/threatintel/malwarebazaar/manifest.yml +++ b/x-pack/filebeat/module/threatintel/malwarebazaar/manifest.yml @@ -11,6 +11,8 @@ var: - name: tags default: [threatintel-malwarebazaar, forwarded] - name: proxy_url + - name: preserve_original_event + default: false ingest_pipeline: - ingest/pipeline.yml diff --git a/x-pack/filebeat/module/threatintel/malwarebazaar/test/malwarebazaar.ndjson.log-expected.json b/x-pack/filebeat/module/threatintel/malwarebazaar/test/malwarebazaar.ndjson.log-expected.json index 1d84eda36cb..40b3f4289ec 100644 --- a/x-pack/filebeat/module/threatintel/malwarebazaar/test/malwarebazaar.ndjson.log-expected.json +++ b/x-pack/filebeat/module/threatintel/malwarebazaar/test/malwarebazaar.ndjson.log-expected.json @@ -1,5 +1,12 @@ [ { + "abusech.malwarebazaar.anonymous": 0, + "abusech.malwarebazaar.code_sign": [], + "abusech.malwarebazaar.intelligence.downloads": 15, + "abusech.malwarebazaar.intelligence.uploads": 1, + "abusech.malwarebazaar.tags": [ + "exe" + ], "event.category": "threat", "event.dataset": "threatintel.malwarebazaar", "event.kind": "enrichment", @@ -20,30 +27,29 @@ "forwarded", "threatintel-malwarebazaar" ], - "threatintel.indicator.file.extension": "exe", - "threatintel.indicator.file.hash.md5": "0af07660056a692b7cb82fa329221ddd", - "threatintel.indicator.file.hash.sha1": "a71fd0504821092e003f350080a6bcc5fa6a972e", - "threatintel.indicator.file.hash.sha256": "5bce7d528c1363104a93fbb5a7fa9bdd991ce929cc09cc7fb29052a68d4fd24b", - "threatintel.indicator.file.hash.sha384": "3b454eb6421d17d093f19292b64d30bf918cb91e9322d0e2d2512857997f574ea2ca5b005133c16f6c33c7cee9c1bd0e", - "threatintel.indicator.file.hash.ssdeep": "3072:DsPPK3p+8r5igrL1Tq50cVBDmDJhE9yV4veedHrP6FXK7:D+PL8bronBDmDJ69JeedHriFG", - "threatintel.indicator.file.hash.tlsh": "F9848B24AF932F9BC6CCC1FE50C2D165C9A9F85DD2B1251A73B6CB89FE00544ED2C686", - "threatintel.indicator.file.mime_type": "application/x-dosexec", - "threatintel.indicator.file.name": "SALM0BRU.exe", - "threatintel.indicator.file.pe.imphash": "f34d5f2d4577ed6d9ceec516c1f5a744", - "threatintel.indicator.file.size": 399872, - "threatintel.indicator.first_seen": "2021-04-06T20:34:58.000Z", - "threatintel.indicator.geo.country_iso_code": "US", - "threatintel.indicator.provider": "James_inthe_box", - "threatintel.indicator.type": "file", - "threatintel.malwarebazaar.anonymous": 0, - "threatintel.malwarebazaar.code_sign": [], - "threatintel.malwarebazaar.intelligence.downloads": 15, - "threatintel.malwarebazaar.intelligence.uploads": 1, - "threatintel.malwarebazaar.tags": [ - "exe" - ] + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] AbuseCH MalwareBazaar", + "threat.indicator.file.extension": "exe", + "threat.indicator.file.hash.md5": "0af07660056a692b7cb82fa329221ddd", + "threat.indicator.file.hash.sha1": "a71fd0504821092e003f350080a6bcc5fa6a972e", + "threat.indicator.file.hash.sha256": "5bce7d528c1363104a93fbb5a7fa9bdd991ce929cc09cc7fb29052a68d4fd24b", + "threat.indicator.file.hash.sha384": "3b454eb6421d17d093f19292b64d30bf918cb91e9322d0e2d2512857997f574ea2ca5b005133c16f6c33c7cee9c1bd0e", + "threat.indicator.file.hash.ssdeep": "3072:DsPPK3p+8r5igrL1Tq50cVBDmDJhE9yV4veedHrP6FXK7:D+PL8bronBDmDJ69JeedHriFG", + "threat.indicator.file.hash.tlsh": "F9848B24AF932F9BC6CCC1FE50C2D165C9A9F85DD2B1251A73B6CB89FE00544ED2C686", + "threat.indicator.file.mime_type": "application/x-dosexec", + "threat.indicator.file.name": "SALM0BRU.exe", + "threat.indicator.file.pe.imphash": "f34d5f2d4577ed6d9ceec516c1f5a744", + "threat.indicator.file.size": 399872, + "threat.indicator.first_seen": "2021-04-06T20:34:58.000Z", + "threat.indicator.geo.country_iso_code": "US", + "threat.indicator.provider": "James_inthe_box", + "threat.indicator.type": "file" }, { + "abusech.malwarebazaar.anonymous": 0, + "abusech.malwarebazaar.code_sign": [], + "abusech.malwarebazaar.intelligence.downloads": 11, + "abusech.malwarebazaar.intelligence.uploads": 1, "event.category": "threat", "event.dataset": "threatintel.malwarebazaar", "event.kind": "enrichment", @@ -63,26 +69,31 @@ "forwarded", "threatintel-malwarebazaar" ], - "threatintel.indicator.file.extension": "zip", - "threatintel.indicator.file.hash.md5": "296aad7075596d21516b30bfbc17fcac", - "threatintel.indicator.file.hash.sha1": "c454be4eb0892d61a4ad6bac16f97724e73cd795", - "threatintel.indicator.file.hash.sha256": "83d0429a2c5f1b611ebc30391eeeb75bebb51212ee1af51dbcf2624b48f9d27f", - "threatintel.indicator.file.hash.sha384": "0a1536add280715320040d5ac5340d3b205d90045ff5c90993b8e909edb9b3e9338b3ffbb3febcaf82584d00d516e8c7", - "threatintel.indicator.file.hash.ssdeep": "12288:j++y4mulTPaYJSaHwvJblQpLGwYeHU9vPpNGd+Zr:j3HPaMtQxblje01pNHZr", - "threatintel.indicator.file.hash.tlsh": "74A4233B9A6D5CA02B224AA69F37537D13A8406300944EAEFD375CA431583056B9F6FF", - "threatintel.indicator.file.mime_type": "application/zip", - "threatintel.indicator.file.name": "PO_NO.ENQUIRY-210604.zip", - "threatintel.indicator.file.size": 476768, - "threatintel.indicator.first_seen": "2021-04-06T20:32:25.000Z", - "threatintel.indicator.geo.country_iso_code": "US", - "threatintel.indicator.provider": "GovCERT_CH", - "threatintel.indicator.type": "file", - "threatintel.malwarebazaar.anonymous": 0, - "threatintel.malwarebazaar.code_sign": [], - "threatintel.malwarebazaar.intelligence.downloads": 11, - "threatintel.malwarebazaar.intelligence.uploads": 1 + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] AbuseCH MalwareBazaar", + "threat.indicator.file.extension": "zip", + "threat.indicator.file.hash.md5": "296aad7075596d21516b30bfbc17fcac", + "threat.indicator.file.hash.sha1": "c454be4eb0892d61a4ad6bac16f97724e73cd795", + "threat.indicator.file.hash.sha256": "83d0429a2c5f1b611ebc30391eeeb75bebb51212ee1af51dbcf2624b48f9d27f", + "threat.indicator.file.hash.sha384": "0a1536add280715320040d5ac5340d3b205d90045ff5c90993b8e909edb9b3e9338b3ffbb3febcaf82584d00d516e8c7", + "threat.indicator.file.hash.ssdeep": "12288:j++y4mulTPaYJSaHwvJblQpLGwYeHU9vPpNGd+Zr:j3HPaMtQxblje01pNHZr", + "threat.indicator.file.hash.tlsh": "74A4233B9A6D5CA02B224AA69F37537D13A8406300944EAEFD375CA431583056B9F6FF", + "threat.indicator.file.mime_type": "application/zip", + "threat.indicator.file.name": "PO_NO.ENQUIRY-210604.zip", + "threat.indicator.file.size": 476768, + "threat.indicator.first_seen": "2021-04-06T20:32:25.000Z", + "threat.indicator.geo.country_iso_code": "US", + "threat.indicator.provider": "GovCERT_CH", + "threat.indicator.type": "file" }, { + "abusech.malwarebazaar.anonymous": 0, + "abusech.malwarebazaar.code_sign": [], + "abusech.malwarebazaar.intelligence.downloads": 30, + "abusech.malwarebazaar.intelligence.uploads": 1, + "abusech.malwarebazaar.tags": [ + "Hancitor" + ], "event.category": "threat", "event.dataset": "threatintel.malwarebazaar", "event.kind": "enrichment", @@ -103,31 +114,34 @@ "forwarded", "threatintel-malwarebazaar" ], - "threatintel.indicator.file.extension": "dll", - "threatintel.indicator.file.hash.md5": "a4838dd31c672122441bebcbf7e9d277", - "threatintel.indicator.file.hash.sha1": "bf103996196df8255881127dee103c22fc12bef3", - "threatintel.indicator.file.hash.sha256": "f4910ea08d14eeb634084de47cf590d4dc5e554552f111da20d22ae71d7b425b", - "threatintel.indicator.file.hash.sha384": "ee7586cb085fde3c14c9c1bea4635ccb30b1af2020f64e87a9983e61b05026ec9b35255670a3d9ecaab436c4ba302dcc", - "threatintel.indicator.file.hash.ssdeep": "12288:L2X/txpFDEVkUNglTovKfoLy+hqK/cEUMMlGOG:RzglgLm/9lGOG", - "threatintel.indicator.file.hash.tlsh": "0C947D11BA96C473E572163008399F6A17BE7A900B704BDBE3CC097E4E755C24B36BA7", - "threatintel.indicator.file.mime_type": "application/x-dosexec", - "threatintel.indicator.file.name": "DropDll.dat", - "threatintel.indicator.file.pe.imphash": "0b5a952a025c2783c3126cdb9bef2844", - "threatintel.indicator.file.size": 435926, - "threatintel.indicator.first_seen": "2021-04-06T20:12:29.000Z", - "threatintel.indicator.geo.country_iso_code": "DE", - "threatintel.indicator.provider": "DmitriyMelikov", - "threatintel.indicator.signature": "Hancitor", - "threatintel.indicator.type": "file", - "threatintel.malwarebazaar.anonymous": 0, - "threatintel.malwarebazaar.code_sign": [], - "threatintel.malwarebazaar.intelligence.downloads": 30, - "threatintel.malwarebazaar.intelligence.uploads": 1, - "threatintel.malwarebazaar.tags": [ - "Hancitor" - ] + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] AbuseCH MalwareBazaar", + "threat.indicator.file.extension": "dll", + "threat.indicator.file.hash.md5": "a4838dd31c672122441bebcbf7e9d277", + "threat.indicator.file.hash.sha1": "bf103996196df8255881127dee103c22fc12bef3", + "threat.indicator.file.hash.sha256": "f4910ea08d14eeb634084de47cf590d4dc5e554552f111da20d22ae71d7b425b", + "threat.indicator.file.hash.sha384": "ee7586cb085fde3c14c9c1bea4635ccb30b1af2020f64e87a9983e61b05026ec9b35255670a3d9ecaab436c4ba302dcc", + "threat.indicator.file.hash.ssdeep": "12288:L2X/txpFDEVkUNglTovKfoLy+hqK/cEUMMlGOG:RzglgLm/9lGOG", + "threat.indicator.file.hash.tlsh": "0C947D11BA96C473E572163008399F6A17BE7A900B704BDBE3CC097E4E755C24B36BA7", + "threat.indicator.file.mime_type": "application/x-dosexec", + "threat.indicator.file.name": "DropDll.dat", + "threat.indicator.file.pe.imphash": "0b5a952a025c2783c3126cdb9bef2844", + "threat.indicator.file.size": 435926, + "threat.indicator.first_seen": "2021-04-06T20:12:29.000Z", + "threat.indicator.geo.country_iso_code": "DE", + "threat.indicator.provider": "DmitriyMelikov", + "threat.indicator.type": "file", + "threat.software.alias": "Hancitor" }, { + "abusech.malwarebazaar.anonymous": 0, + "abusech.malwarebazaar.code_sign": [], + "abusech.malwarebazaar.intelligence.downloads": 27, + "abusech.malwarebazaar.intelligence.uploads": 1, + "abusech.malwarebazaar.tags": [ + "backdoor", + "python" + ], "event.category": "threat", "event.dataset": "threatintel.malwarebazaar", "event.kind": "enrichment", @@ -147,30 +161,31 @@ "forwarded", "threatintel-malwarebazaar" ], - "threatintel.indicator.file.extension": "unknown", - "threatintel.indicator.file.hash.md5": "8d7c8b55ac49d241fb7f75a27a5ef8d5", - "threatintel.indicator.file.hash.sha1": "a68ca1b41cb93fe2879bb3baeb8e19990758f099", - "threatintel.indicator.file.hash.sha256": "e45ffc61a85c2f5c0cbe9376ff215cad324bf14f925bf52ec0d2949f7d235a00", - "threatintel.indicator.file.hash.sha384": "788f61cf45bbc8cad5775de18d0d5f42c4e028af0aaa34c570645efc96af8ebc3d7fe330aaf22ef34d35360bbd4a708c", - "threatintel.indicator.file.hash.ssdeep": "192:z7X/yHo/yz/yBKiSOINLyhQMYd+LiTfq6LTf3ZoTta3Grj6rg2:z7CIKnNNLwufPfAPq7", - "threatintel.indicator.file.hash.tlsh": "AE3222515C6A881A03B3C66F7992B844FB588303C7116607F6FC86782F79568CAF1BBD", - "threatintel.indicator.file.mime_type": "text/x-script.python", - "threatintel.indicator.file.name": "vabsheche.py", - "threatintel.indicator.file.size": 11717, - "threatintel.indicator.first_seen": "2021-04-06T20:07:59.000Z", - "threatintel.indicator.geo.country_iso_code": "FR", - "threatintel.indicator.provider": "ArkbirdDevil", - "threatintel.indicator.type": "file", - "threatintel.malwarebazaar.anonymous": 0, - "threatintel.malwarebazaar.code_sign": [], - "threatintel.malwarebazaar.intelligence.downloads": 27, - "threatintel.malwarebazaar.intelligence.uploads": 1, - "threatintel.malwarebazaar.tags": [ - "backdoor", - "python" - ] + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] AbuseCH MalwareBazaar", + "threat.indicator.file.extension": "unknown", + "threat.indicator.file.hash.md5": "8d7c8b55ac49d241fb7f75a27a5ef8d5", + "threat.indicator.file.hash.sha1": "a68ca1b41cb93fe2879bb3baeb8e19990758f099", + "threat.indicator.file.hash.sha256": "e45ffc61a85c2f5c0cbe9376ff215cad324bf14f925bf52ec0d2949f7d235a00", + "threat.indicator.file.hash.sha384": "788f61cf45bbc8cad5775de18d0d5f42c4e028af0aaa34c570645efc96af8ebc3d7fe330aaf22ef34d35360bbd4a708c", + "threat.indicator.file.hash.ssdeep": "192:z7X/yHo/yz/yBKiSOINLyhQMYd+LiTfq6LTf3ZoTta3Grj6rg2:z7CIKnNNLwufPfAPq7", + "threat.indicator.file.hash.tlsh": "AE3222515C6A881A03B3C66F7992B844FB588303C7116607F6FC86782F79568CAF1BBD", + "threat.indicator.file.mime_type": "text/x-script.python", + "threat.indicator.file.name": "vabsheche.py", + "threat.indicator.file.size": 11717, + "threat.indicator.first_seen": "2021-04-06T20:07:59.000Z", + "threat.indicator.geo.country_iso_code": "FR", + "threat.indicator.provider": "ArkbirdDevil", + "threat.indicator.type": "file" }, { + "abusech.malwarebazaar.anonymous": 0, + "abusech.malwarebazaar.code_sign": [], + "abusech.malwarebazaar.intelligence.downloads": 21, + "abusech.malwarebazaar.intelligence.uploads": 1, + "abusech.malwarebazaar.tags": [ + "maldoc" + ], "event.category": "threat", "event.dataset": "threatintel.malwarebazaar", "event.kind": "enrichment", @@ -190,29 +205,32 @@ "forwarded", "threatintel-malwarebazaar" ], - "threatintel.indicator.file.extension": "docx", - "threatintel.indicator.file.hash.md5": "fe185f106730583156f39233f77f8019", - "threatintel.indicator.file.hash.sha1": "e8378aede9f26f09b7d503d79a05d67612be15f6", - "threatintel.indicator.file.hash.sha256": "42f5f5474431738f91f612d9765b3fc9b85a547274ea64aa034298ad97ad28f4", - "threatintel.indicator.file.hash.sha384": "752e5d56a166227d06f8cbd40cd3f693f543f9c3f798c673c1430957bb7e149a12d9158138fa449479105f472e70f68f", - "threatintel.indicator.file.hash.ssdeep": "196608:KQaeKLOiBEp+uc+iuYmbMdHmN1Rwyd2jecXeaH1pHE+2:oeIOTp+p+iNJC1ChjhXZ1pHz2", - "threatintel.indicator.file.hash.tlsh": "13863341B085EE2EE2CA41BA0DA9C2BD43B63D131E054F677269B72D3EB76E0E7D4144", - "threatintel.indicator.file.mime_type": "application/msword", - "threatintel.indicator.file.name": "42f5f5474431738f91f612d9765b3fc9b85a547274ea64aa034298ad97ad28f4.bin", - "threatintel.indicator.file.size": 7929856, - "threatintel.indicator.first_seen": "2021-04-06T20:00:48.000Z", - "threatintel.indicator.geo.country_iso_code": "FR", - "threatintel.indicator.provider": "ArkbirdDevil", - "threatintel.indicator.type": "file", - "threatintel.malwarebazaar.anonymous": 0, - "threatintel.malwarebazaar.code_sign": [], - "threatintel.malwarebazaar.intelligence.downloads": 21, - "threatintel.malwarebazaar.intelligence.uploads": 1, - "threatintel.malwarebazaar.tags": [ - "maldoc" - ] + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] AbuseCH MalwareBazaar", + "threat.indicator.file.extension": "docx", + "threat.indicator.file.hash.md5": "fe185f106730583156f39233f77f8019", + "threat.indicator.file.hash.sha1": "e8378aede9f26f09b7d503d79a05d67612be15f6", + "threat.indicator.file.hash.sha256": "42f5f5474431738f91f612d9765b3fc9b85a547274ea64aa034298ad97ad28f4", + "threat.indicator.file.hash.sha384": "752e5d56a166227d06f8cbd40cd3f693f543f9c3f798c673c1430957bb7e149a12d9158138fa449479105f472e70f68f", + "threat.indicator.file.hash.ssdeep": "196608:KQaeKLOiBEp+uc+iuYmbMdHmN1Rwyd2jecXeaH1pHE+2:oeIOTp+p+iNJC1ChjhXZ1pHz2", + "threat.indicator.file.hash.tlsh": "13863341B085EE2EE2CA41BA0DA9C2BD43B63D131E054F677269B72D3EB76E0E7D4144", + "threat.indicator.file.mime_type": "application/msword", + "threat.indicator.file.name": "42f5f5474431738f91f612d9765b3fc9b85a547274ea64aa034298ad97ad28f4.bin", + "threat.indicator.file.size": 7929856, + "threat.indicator.first_seen": "2021-04-06T20:00:48.000Z", + "threat.indicator.geo.country_iso_code": "FR", + "threat.indicator.provider": "ArkbirdDevil", + "threat.indicator.type": "file" }, { + "abusech.malwarebazaar.anonymous": 0, + "abusech.malwarebazaar.code_sign": [], + "abusech.malwarebazaar.intelligence.downloads": 30, + "abusech.malwarebazaar.intelligence.uploads": 1, + "abusech.malwarebazaar.tags": [ + "apt", + "tonto" + ], "event.category": "threat", "event.dataset": "threatintel.malwarebazaar", "event.kind": "enrichment", @@ -233,31 +251,29 @@ "forwarded", "threatintel-malwarebazaar" ], - "threatintel.indicator.file.extension": "dll", - "threatintel.indicator.file.hash.md5": "70da6872b6b2da9ddc94d14b02302917", - "threatintel.indicator.file.hash.sha1": "b2da45913353bfc66d189455f9ad80ef26968143", - "threatintel.indicator.file.hash.sha256": "2d705f0b76f24a18e08163db2f187140ee9f03e43697a9ea0d840c829692d43c", - "threatintel.indicator.file.hash.sha384": "c82132559381b7b3b184b4ce8c7a58c301a46001621f346b637139f5987dee968ae2ef009a17b2388852b2db15a45b58", - "threatintel.indicator.file.hash.ssdeep": "1536:2NVi7z0r0lJRn6I8+YDgr1fnWG5Ff0+adgBYlCtMiQMX1c0E4JsWjcdonPv870E1:YM7zh8+Cofnp5eRm6riQ6OZoPv870E", - "threatintel.indicator.file.hash.tlsh": "A2D38C067790C071DAAF013908799E624B7F7D70DDB49D8B77841A8E69342D0AF3AB27", - "threatintel.indicator.file.mime_type": "application/x-dosexec", - "threatintel.indicator.file.name": "winlog.wll", - "threatintel.indicator.file.pe.imphash": "6476b7c4dd55eafbdf922a7ba1e2d5f9", - "threatintel.indicator.file.size": 131584, - "threatintel.indicator.first_seen": "2021-04-06T19:58:50.000Z", - "threatintel.indicator.geo.country_iso_code": "FR", - "threatintel.indicator.provider": "ArkbirdDevil", - "threatintel.indicator.type": "file", - "threatintel.malwarebazaar.anonymous": 0, - "threatintel.malwarebazaar.code_sign": [], - "threatintel.malwarebazaar.intelligence.downloads": 30, - "threatintel.malwarebazaar.intelligence.uploads": 1, - "threatintel.malwarebazaar.tags": [ - "apt", - "tonto" - ] + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] AbuseCH MalwareBazaar", + "threat.indicator.file.extension": "dll", + "threat.indicator.file.hash.md5": "70da6872b6b2da9ddc94d14b02302917", + "threat.indicator.file.hash.sha1": "b2da45913353bfc66d189455f9ad80ef26968143", + "threat.indicator.file.hash.sha256": "2d705f0b76f24a18e08163db2f187140ee9f03e43697a9ea0d840c829692d43c", + "threat.indicator.file.hash.sha384": "c82132559381b7b3b184b4ce8c7a58c301a46001621f346b637139f5987dee968ae2ef009a17b2388852b2db15a45b58", + "threat.indicator.file.hash.ssdeep": "1536:2NVi7z0r0lJRn6I8+YDgr1fnWG5Ff0+adgBYlCtMiQMX1c0E4JsWjcdonPv870E1:YM7zh8+Cofnp5eRm6riQ6OZoPv870E", + "threat.indicator.file.hash.tlsh": "A2D38C067790C071DAAF013908799E624B7F7D70DDB49D8B77841A8E69342D0AF3AB27", + "threat.indicator.file.mime_type": "application/x-dosexec", + "threat.indicator.file.name": "winlog.wll", + "threat.indicator.file.pe.imphash": "6476b7c4dd55eafbdf922a7ba1e2d5f9", + "threat.indicator.file.size": 131584, + "threat.indicator.first_seen": "2021-04-06T19:58:50.000Z", + "threat.indicator.geo.country_iso_code": "FR", + "threat.indicator.provider": "ArkbirdDevil", + "threat.indicator.type": "file" }, { + "abusech.malwarebazaar.anonymous": 0, + "abusech.malwarebazaar.code_sign": [], + "abusech.malwarebazaar.intelligence.downloads": 32, + "abusech.malwarebazaar.intelligence.uploads": 1, "event.category": "threat", "event.dataset": "threatintel.malwarebazaar", "event.kind": "enrichment", @@ -277,26 +293,33 @@ "forwarded", "threatintel-malwarebazaar" ], - "threatintel.indicator.file.extension": "docx", - "threatintel.indicator.file.hash.md5": "de80e1d7d9f5b1c64ec9f8d4f5063989", - "threatintel.indicator.file.hash.sha1": "3d613d5678e43faeea1c636185a0b4c3ec80e742", - "threatintel.indicator.file.hash.sha256": "30787f32adc487311d764b19d4504fdeab08c0d385e2fa065bd8d5836c031606", - "threatintel.indicator.file.hash.sha384": "a3ec981ed158fe08cc2cd97303807cfbed147e59ccfd92fcaa9395c5718b4d9b892d6e9fa6337f5976dc1bd042562fe4", - "threatintel.indicator.file.hash.ssdeep": "24576:WKEiZxl3A4yJJG2dPQQCthXzglgLm/9lGO:WKEGByvGOQQC/XElga/9lGO", - "threatintel.indicator.file.hash.tlsh": "8635D001BA82C573D5621A35083ADBAA177E7D604F704ADBB3C83B2E5D355C14B32BA7", - "threatintel.indicator.file.mime_type": "application/msword", - "threatintel.indicator.file.name": "30787f32adc487311d764b19d4504fdeab08c0d385e2fa065bd8d5836c031606.bin.sample", - "threatintel.indicator.file.size": 1088000, - "threatintel.indicator.first_seen": "2021-04-06T19:58:44.000Z", - "threatintel.indicator.geo.country_iso_code": "DE", - "threatintel.indicator.provider": "DmitriyMelikov", - "threatintel.indicator.type": "file", - "threatintel.malwarebazaar.anonymous": 0, - "threatintel.malwarebazaar.code_sign": [], - "threatintel.malwarebazaar.intelligence.downloads": 32, - "threatintel.malwarebazaar.intelligence.uploads": 1 + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] AbuseCH MalwareBazaar", + "threat.indicator.file.extension": "docx", + "threat.indicator.file.hash.md5": "de80e1d7d9f5b1c64ec9f8d4f5063989", + "threat.indicator.file.hash.sha1": "3d613d5678e43faeea1c636185a0b4c3ec80e742", + "threat.indicator.file.hash.sha256": "30787f32adc487311d764b19d4504fdeab08c0d385e2fa065bd8d5836c031606", + "threat.indicator.file.hash.sha384": "a3ec981ed158fe08cc2cd97303807cfbed147e59ccfd92fcaa9395c5718b4d9b892d6e9fa6337f5976dc1bd042562fe4", + "threat.indicator.file.hash.ssdeep": "24576:WKEiZxl3A4yJJG2dPQQCthXzglgLm/9lGO:WKEGByvGOQQC/XElga/9lGO", + "threat.indicator.file.hash.tlsh": "8635D001BA82C573D5621A35083ADBAA177E7D604F704ADBB3C83B2E5D355C14B32BA7", + "threat.indicator.file.mime_type": "application/msword", + "threat.indicator.file.name": "30787f32adc487311d764b19d4504fdeab08c0d385e2fa065bd8d5836c031606.bin.sample", + "threat.indicator.file.size": 1088000, + "threat.indicator.first_seen": "2021-04-06T19:58:44.000Z", + "threat.indicator.geo.country_iso_code": "DE", + "threat.indicator.provider": "DmitriyMelikov", + "threat.indicator.type": "file" }, { + "abusech.malwarebazaar.anonymous": 0, + "abusech.malwarebazaar.code_sign": [], + "abusech.malwarebazaar.intelligence.downloads": 38, + "abusech.malwarebazaar.intelligence.mail.Generic": "low", + "abusech.malwarebazaar.intelligence.uploads": 1, + "abusech.malwarebazaar.tags": [ + "SnakeKeylogger", + "exe" + ], "event.category": "threat", "event.dataset": "threatintel.malwarebazaar", "event.kind": "enrichment", @@ -317,33 +340,35 @@ "forwarded", "threatintel-malwarebazaar" ], - "threatintel.indicator.file.extension": "exe", - "threatintel.indicator.file.hash.md5": "2759c73c986c6a757bf9d25621c5595a", - "threatintel.indicator.file.hash.sha1": "00b52e8ca1785d5086703ad8cff1d28fc3354934", - "threatintel.indicator.file.hash.sha256": "84f983067868de50e5b1553782c056c1f5b5118bb2084473ca4b6908f221cd3b", - "threatintel.indicator.file.hash.sha384": "138dc28a74d15c1f9797ce732e99097c8c6db4549cb17cb7b20c1c6738a170328e45aea2d4c3b593912f14a97f521c1d", - "threatintel.indicator.file.hash.ssdeep": "12288:8t11ulRZRLZNh4YeX6f6XmwNShqE73YXy7moh:S11gZpZNmBX06WmAcy7m0", - "threatintel.indicator.file.hash.tlsh": "23F4AE212684C9C0D93E67B4D43584F003BABD16D631F69F6E887C693EB32D2D63B646", - "threatintel.indicator.file.mime_type": "application/x-dosexec", - "threatintel.indicator.file.name": "Purchase Order.8000.scan.pdf...exe", - "threatintel.indicator.file.pe.imphash": "f34d5f2d4577ed6d9ceec516c1f5a744", - "threatintel.indicator.file.size": 752128, - "threatintel.indicator.first_seen": "2021-04-06T19:52:32.000Z", - "threatintel.indicator.geo.country_iso_code": "FR", - "threatintel.indicator.provider": "James_inthe_box", - "threatintel.indicator.signature": "SnakeKeylogger", - "threatintel.indicator.type": "file", - "threatintel.malwarebazaar.anonymous": 0, - "threatintel.malwarebazaar.code_sign": [], - "threatintel.malwarebazaar.intelligence.downloads": 38, - "threatintel.malwarebazaar.intelligence.mail.Generic": "low", - "threatintel.malwarebazaar.intelligence.uploads": 1, - "threatintel.malwarebazaar.tags": [ - "SnakeKeylogger", - "exe" - ] + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] AbuseCH MalwareBazaar", + "threat.indicator.file.extension": "exe", + "threat.indicator.file.hash.md5": "2759c73c986c6a757bf9d25621c5595a", + "threat.indicator.file.hash.sha1": "00b52e8ca1785d5086703ad8cff1d28fc3354934", + "threat.indicator.file.hash.sha256": "84f983067868de50e5b1553782c056c1f5b5118bb2084473ca4b6908f221cd3b", + "threat.indicator.file.hash.sha384": "138dc28a74d15c1f9797ce732e99097c8c6db4549cb17cb7b20c1c6738a170328e45aea2d4c3b593912f14a97f521c1d", + "threat.indicator.file.hash.ssdeep": "12288:8t11ulRZRLZNh4YeX6f6XmwNShqE73YXy7moh:S11gZpZNmBX06WmAcy7m0", + "threat.indicator.file.hash.tlsh": "23F4AE212684C9C0D93E67B4D43584F003BABD16D631F69F6E887C693EB32D2D63B646", + "threat.indicator.file.mime_type": "application/x-dosexec", + "threat.indicator.file.name": "Purchase Order.8000.scan.pdf...exe", + "threat.indicator.file.pe.imphash": "f34d5f2d4577ed6d9ceec516c1f5a744", + "threat.indicator.file.size": 752128, + "threat.indicator.first_seen": "2021-04-06T19:52:32.000Z", + "threat.indicator.geo.country_iso_code": "FR", + "threat.indicator.provider": "James_inthe_box", + "threat.indicator.type": "file", + "threat.software.alias": "SnakeKeylogger" }, { + "abusech.malwarebazaar.anonymous": 0, + "abusech.malwarebazaar.code_sign": [], + "abusech.malwarebazaar.intelligence.downloads": 40, + "abusech.malwarebazaar.intelligence.mail.Generic": "low", + "abusech.malwarebazaar.intelligence.uploads": 1, + "abusech.malwarebazaar.tags": [ + "AgentTesla", + "exe" + ], "event.category": "threat", "event.dataset": "threatintel.malwarebazaar", "event.kind": "enrichment", @@ -364,30 +389,23 @@ "forwarded", "threatintel-malwarebazaar" ], - "threatintel.indicator.file.extension": "exe", - "threatintel.indicator.file.hash.md5": "596b3dbf07a287dcf76860b5e54762c3", - "threatintel.indicator.file.hash.sha1": "a34fd5e57d75d17bc2d84055ca4752e5ee2e92f5", - "threatintel.indicator.file.hash.sha256": "0661d87116f44cbd5b5c6bec7fb06c4e5cd5b6ecbc5455d959e65f1ee46c54c8", - "threatintel.indicator.file.hash.sha384": "ed5d03454121d81adf65a01ba90af81b1a7cea052709c22bb9170508069d17242861f85e5546b2cc3efb07c10926368c", - "threatintel.indicator.file.hash.ssdeep": "12288:qRedcNeqimzAEmN03VgdZfBOMx+RVBM7pdWje9ppB5nAZGNY2:ZaNeqikqN0udZfBFUYp55nFN", - "threatintel.indicator.file.hash.tlsh": "A505CF712694C9A4FABD53B80434403007F5FE42E232FA9A6FD17C993E72782DA3B655", - "threatintel.indicator.file.mime_type": "application/x-dosexec", - "threatintel.indicator.file.name": "New Order PO#121012020_____PDF_______.exe", - "threatintel.indicator.file.pe.imphash": "f34d5f2d4577ed6d9ceec516c1f5a744", - "threatintel.indicator.file.size": 836096, - "threatintel.indicator.first_seen": "2021-04-06T19:47:13.000Z", - "threatintel.indicator.geo.country_iso_code": "FR", - "threatintel.indicator.provider": "James_inthe_box", - "threatintel.indicator.signature": "AgentTesla", - "threatintel.indicator.type": "file", - "threatintel.malwarebazaar.anonymous": 0, - "threatintel.malwarebazaar.code_sign": [], - "threatintel.malwarebazaar.intelligence.downloads": 40, - "threatintel.malwarebazaar.intelligence.mail.Generic": "low", - "threatintel.malwarebazaar.intelligence.uploads": 1, - "threatintel.malwarebazaar.tags": [ - "AgentTesla", - "exe" - ] + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] AbuseCH MalwareBazaar", + "threat.indicator.file.extension": "exe", + "threat.indicator.file.hash.md5": "596b3dbf07a287dcf76860b5e54762c3", + "threat.indicator.file.hash.sha1": "a34fd5e57d75d17bc2d84055ca4752e5ee2e92f5", + "threat.indicator.file.hash.sha256": "0661d87116f44cbd5b5c6bec7fb06c4e5cd5b6ecbc5455d959e65f1ee46c54c8", + "threat.indicator.file.hash.sha384": "ed5d03454121d81adf65a01ba90af81b1a7cea052709c22bb9170508069d17242861f85e5546b2cc3efb07c10926368c", + "threat.indicator.file.hash.ssdeep": "12288:qRedcNeqimzAEmN03VgdZfBOMx+RVBM7pdWje9ppB5nAZGNY2:ZaNeqikqN0udZfBFUYp55nFN", + "threat.indicator.file.hash.tlsh": "A505CF712694C9A4FABD53B80434403007F5FE42E232FA9A6FD17C993E72782DA3B655", + "threat.indicator.file.mime_type": "application/x-dosexec", + "threat.indicator.file.name": "New Order PO#121012020_____PDF_______.exe", + "threat.indicator.file.pe.imphash": "f34d5f2d4577ed6d9ceec516c1f5a744", + "threat.indicator.file.size": 836096, + "threat.indicator.first_seen": "2021-04-06T19:47:13.000Z", + "threat.indicator.geo.country_iso_code": "FR", + "threat.indicator.provider": "James_inthe_box", + "threat.indicator.type": "file", + "threat.software.alias": "AgentTesla" } ] \ No newline at end of file diff --git a/x-pack/filebeat/module/threatintel/misp/config/config.yml b/x-pack/filebeat/module/threatintel/misp/config/config.yml index 922f794af20..53ce56b16a2 100644 --- a/x-pack/filebeat/module/threatintel/misp/config/config.yml +++ b/x-pack/filebeat/module/threatintel/misp/config/config.yml @@ -12,18 +12,24 @@ request.proxy_url: {{ .proxy_url }} {{ end }} request.url: {{ .url }} request.body: - limit: 100 - page: 1 - returnFormat: json -{{if .filters}} - {{ range $key, $value := .filters}}{{$key}}: {{$value | tojson}}{{end}} -{{end}} +{{ if .filters }} + {{ .filters | tojson}} +{{ end }} request.transforms: {{ if .api_token }} - set: target: header.Authorization value: {{ .api_token }} -{{end}} +{{ end }} +- set: + target: body.page + value: 1 +- set: + target: body.limit + value: 10 +- set: + target: body.returnFormat + value: json - set: target: body.timestamp value: '[[.cursor.timestamp]]' @@ -63,28 +69,12 @@ exclude_files: [".gz$"] {{ end }} -tags: {{.tags | tojson}} -publisher_pipeline.disable_host: {{ inList .tags "forwarded" }} +tags: +{{if .preserve_original_event}} + - preserve_original_event +{{end}} +{{range $val := .tags}} + - {{$val}} +{{end}} -processors: - - decode_json_fields: - fields: [message] - target: json - - fingerprint: - fields: - - json.Event.Attribute.uuid - - json.Event.Object.Attribute.uuid - ignore_missing: true - target_field: "@metadata._id" - encoding: base64 - - script: - lang: javascript - id: my_filter - source: > - function process(event) { - event.Put("@metadata.op_type", "index"); - } - - add_fields: - target: '' - fields: - ecs.version: 1.12.0 +publisher_pipeline.disable_host: {{ inList .tags "forwarded" }} diff --git a/x-pack/filebeat/module/threatintel/misp/ingest/pipeline.yml b/x-pack/filebeat/module/threatintel/misp/ingest/pipeline.yml index e64379422db..f4f54c903b9 100644 --- a/x-pack/filebeat/module/threatintel/misp/ingest/pipeline.yml +++ b/x-pack/filebeat/module/threatintel/misp/ingest/pipeline.yml @@ -1,3 +1,4 @@ +--- description: Pipeline for parsing MISP Threat Intel processors: #################### @@ -6,6 +7,9 @@ processors: - set: field: event.ingested value: "{{_ingest.timestamp}}" + - set: + field: ecs.version + value: "1.12" - set: field: event.kind value: enrichment @@ -19,236 +23,253 @@ processors: ###################### # General ECS fields # ###################### + - rename: + field: message + target_field: event.original + ignore_missing: true + - json: + field: event.original + target_field: json + - fingerprint: + fields: + - json.Event.Attribute.uuid + - json.Event.Object.Attribute.uuid + target_field: "_id" + ignore_missing: true - rename: field: json.Event - target_field: threatintel.misp + target_field: misp ignore_missing: true - set: - field: threatintel.indicator.provider + field: threat.indicator.provider value: misp - if: ctx?.threatintel?.misp?.Orgc?.local != 'false' + if: ctx.misp?.Orgc?.local != 'false' - set: - field: threatintel.indicator.provider + field: threat.indicator.provider value: "{{misp.Orgc.name}}" - if: ctx?.threatintel?.misp?.Orgc?.local == 'false' + if: ctx.misp?.Orgc?.local == 'false' ignore_empty_value: true # Removing fields not needed anymore, either because its copied somewhere else, or is not relevant to this event - remove: field: - - threatintel.misp.ShadowAttribute - - threatintel.misp.RelatedEvent - - threatintel.misp.Galaxy - - threatintel.misp.Attribute.Galaxy - - threatintel.misp.Attribute.ShadowAttribute - - threatintel.misp.EventReport - - threatintel.misp.Object.Attribute.Galaxy - - threatintel.misp.Object.Attribute.ShadowAttribute - - message + - misp.ShadowAttribute + - misp.RelatedEvent + - misp.Galaxy + - misp.Attribute.Galaxy + - misp.Attribute.ShadowAttribute + - misp.EventReport + - misp.Object.Attribute.Galaxy + - misp.Object.Attribute.ShadowAttribute ignore_missing: true - remove: field: - - threatintel.misp.Attribute + - misp.Attribute ignore_missing: true - if: ctx?.threatintel?.misp?.Attribute.size() == 0 + if: ctx.misp?.Attribute.size() == 0 - remove: field: - - threatintel.misp.Object + - misp.Object ignore_missing: true - if: ctx?.threatintel?.misp?.Object.size() == 0 + if: ctx.misp?.Object.size() == 0 - date: - field: threatintel.misp.timestamp + field: misp.timestamp formats: - UNIX ignore_failure: true - rename: - field: threatintel.misp.Attribute - target_field: threatintel.misp.attribute + field: misp.Attribute + target_field: misp.attribute ignore_missing: true - rename: - field: threatintel.misp.Object - target_field: threatintel.misp.object + field: misp.Object + target_field: misp.object ignore_missing: true - rename: - field: threatintel.misp.object.Attribute - target_field: threatintel.misp.object.attribute + field: misp.object.Attribute + target_field: misp.object.attribute ignore_missing: true - rename: - field: threatintel.misp.Orgc - target_field: threatintel.misp.orgc + field: misp.Orgc + target_field: misp.orgc ignore_missing: true - rename: - field: threatintel.misp.Org - target_field: threatintel.misp.org + field: misp.Org + target_field: misp.org ignore_missing: true - rename: - field: threatintel.misp.Tag - target_field: threatintel.misp.tag + field: misp.Tag + target_field: misp.tag ignore_missing: true # # Dance around issue of not being able to split the document into two. # # Make the Object.Attribute field primary if it exists, but keep the # # outer Attribute as context. - rename: - field: threatintel.misp.attribute - target_field: threatintel.misp.context.attribute + field: misp.attribute + target_field: misp.context.attribute ignore_missing: true - if: ctx?.threatintel?.misp?.object != null + if: ctx.misp?.object != null - rename: - field: threatintel.misp.object.attribute - target_field: threatintel.misp.attribute + field: misp.object.attribute + target_field: misp.attribute ignore_missing: true - if: ctx?.threatintel?.misp?.object != null + if: ctx.misp?.object != null ##################### # Threat ECS Fields # ##################### + - set: + field: threat.feed.name + value: "[Filebeat] MISP" + - set: + field: threat.feed.dashboard_id + value: "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f" - rename: - field: threatintel.misp.attribute.first_seen - target_field: threatintel.indicator.first_seen + field: misp.attribute.first_seen + target_field: threat.indicator.first_seen ignore_missing: true - rename: - field: threatintel.misp.attribute.last_seen - target_field: threatintel.indicator.last_seen + field: misp.attribute.last_seen + target_field: threat.indicator.last_seen ignore_missing: true - convert: - field: threatintel.misp.analysis + field: misp.analysis type: long - target_field: threatintel.indicator.scanner_stats + target_field: threat.indicator.scanner_stats ignore_missing: true - convert: - field: threatintel.misp.threat_level_id + field: misp.threat_level_id type: long ignore_missing: true ## File/Hash indicator operations - set: - field: threatintel.indicator.type + field: threat.indicator.type value: file - if: "ctx?.threatintel?.misp?.attribute?.type != null && (['md5', 'impfuzzy', 'imphash', 'pehash', 'sha1', 'sha224', 'sha256', 'sha3-224', 'sha3-256', 'sha3-384', 'sha3-512', 'sha384', 'sha512', 'sha512/224', 'sha512/256', 'ssdeep', 'tlsh', 'vhash'].contains(ctx.threatintel?.misp?.attribute?.type) || ctx.threatintel?.misp?.attribute?.type.startsWith('filename'))" + if: "ctx.misp?.attribute?.type != null && (['md5', 'impfuzzy', 'imphash', 'pehash', 'sha1', 'sha224', 'sha256', 'sha3-224', 'sha3-256', 'sha3-384', 'sha3-512', 'sha384', 'sha512', 'sha512/224', 'sha512/256', 'ssdeep', 'tlsh', 'vhash'].contains(ctx.misp?.attribute?.type) || ctx.misp?.attribute?.type.startsWith('filename'))" - rename: - field: threatintel.misp.attribute.value - target_field: "threatintel.indicator.file.hash.{{threatintel.misp.attribute.type}}" + field: misp.attribute.value + target_field: "threat.indicator.file.hash.{{misp.attribute.type}}" ignore_missing: true - if: "ctx?.threatintel?.indicator?.type == 'file' && ctx?.threatintel?.misp?.attribute?.type != null && !ctx?.threatintel?.misp?.attribute?.type.startsWith('filename')" + if: "ctx.threat?.indicator?.type == 'file' && ctx.misp?.attribute?.type != null && !ctx.misp?.attribute?.type.startsWith('filename')" - rename: - field: threatintel.misp.attribute.value - target_field: threatintel.indicator.file.name + field: misp.attribute.value + target_field: threat.indicator.file.name ignore_missing: true - if: "ctx?.threatintel?.indicator?.type == 'file' && ctx?.threatintel?.misp?.attribute?.type == 'filename'" + if: "ctx.threat?.indicator?.type == 'file' && ctx.misp?.attribute?.type == 'filename'" - grok: - field: threatintel.misp.attribute.type + field: misp.attribute.type patterns: - "%{WORD}\\|%{WORD:_tmp.hashtype}" ignore_missing: true - if: ctx?.threatintel?.misp?.attribute?.type != null && ctx?.threatintel?.misp?.attribute?.type.startsWith('filename|') + if: ctx.misp?.attribute?.type != null && ctx.misp?.attribute?.type.startsWith('filename|') - grok: - field: threatintel.misp.attribute.value + field: misp.attribute.value patterns: - - "%{DATA:threatintel.indicator.file.name}\\|%{GREEDYDATA:_tmp.hashvalue}" + - "%{DATA:threat.indicator.file.name}\\|%{GREEDYDATA:_tmp.hashvalue}" ignore_missing: true - if: ctx?.threatintel?.misp?.attribute?.type != null && ctx?.threatintel?.misp?.attribute?.type.startsWith('filename|') + if: ctx.misp?.attribute?.type != null && ctx.misp?.attribute?.type.startsWith('filename|') - set: - field: threatintel.indicator.file.hash.{{_tmp.hashtype}} + field: threat.indicator.file.hash.{{_tmp.hashtype}} value: "{{_tmp.hashvalue}}" - if: "ctx?.threatintel?.misp?.attribute?.type != null && ctx?.threatintel?.misp?.attribute?.type.startsWith('filename|') && ctx?._tmp?.hashvalue != null && ctx?._tmp?.hashtype != null" + if: "ctx.misp?.attribute?.type != null && ctx.misp?.attribute?.type.startsWith('filename|') && ctx?._tmp?.hashvalue != null && ctx?._tmp?.hashtype != null" ## URL/URI indicator operations - set: - field: threatintel.indicator.type + field: threat.indicator.type value: url - if: "ctx?.threatintel?.misp?.attribute?.type != null && ['url', 'link', 'uri'].contains(ctx?.threatintel?.misp?.attribute?.type)" + if: "ctx.misp?.attribute?.type != null && ['url', 'link', 'uri'].contains(ctx.misp?.attribute?.type)" - uri_parts: - field: threatintel.misp.attribute.value - target_field: threatintel.indicator.url + field: misp.attribute.value + target_field: threat.indicator.url keep_original: true remove_if_successful: true - if: ctx?.threatintel?.indicator?.type == 'url' && ctx?.threatintel?.misp?.attribute?.type != 'uri' - + if: ctx.threat?.indicator?.type == 'url' && ctx.misp?.attribute?.type != 'uri' - set: - field: threatintel.indicator.url.full - value: "{{{threatintel.indicator.url.original}}}" + field: threat.indicator.url.full + value: "{{{threat.indicator.url.original}}}" ignore_empty_value: true - if: "ctx?.threatintel?.indicator?.type == 'url' && ctx?.threatintel?.misp?.attribute?.type != 'uri'" + if: "ctx.threat?.indicator?.type == 'url' && ctx.misp?.attribute?.type != 'uri'" ## Regkey indicator operations - set: - field: threatintel.indicator.type + field: threat.indicator.type value: windows-registry-key - if: "ctx?.threatintel?.misp?.attribute?.type != null && ctx?.threatintel?.misp?.attribute?.type.startsWith('regkey')" + if: "ctx.misp?.attribute?.type != null && ctx.misp?.attribute?.type.startsWith('regkey')" - rename: - field: threatintel.misp.attribute.value - target_field: threatintel.indicator.registry.key + field: misp.attribute.value + target_field: threat.indicator.registry.key ignore_missing: true - if: "ctx?.threatintel?.indicator?.type == 'windows-registry-key' && ctx?.threatintel?.misp?.attribute?.type == 'regkey'" + if: "ctx.threat?.indicator?.type == 'windows-registry-key' && ctx.misp?.attribute?.type == 'regkey'" - grok: - field: threatintel.misp.attribute.value + field: misp.attribute.value patterns: - - "%{DATA:threatintel.indicator.registry.key}\\|%{DATA:threatintel.indicator.registry.value}" + - "%{DATA:threat.indicator.registry.key}\\|%{DATA:threat.indicator.registry.value}" ignore_missing: true - if: "ctx?.threatintel?.misp?.attribute?.type == 'regkey|value'" + if: "ctx.misp?.attribute?.type == 'regkey|value'" ## AS indicator operations - set: - field: threatintel.indicator.type + field: threat.indicator.type value: autonomous-system - if: "ctx?.threatintel?.misp?.attribute?.type != null && ctx?.threatintel?.misp?.attribute?.type == 'AS'" + if: "ctx.misp?.attribute?.type != null && ctx.misp?.attribute?.type == 'AS'" - convert: - field: threatintel.misp.attribute.value + field: misp.attribute.value type: long - target_field: threatintel.indicator.as.number + target_field: threat.indicator.as.number ignore_missing: true - if: ctx?.threatintel?.indicator?.type == 'autonomous-system' + if: ctx.threat?.indicator?.type == 'autonomous-system' ## Domain/IP/Port indicator operations - set: - field: threatintel.indicator.type + field: threat.indicator.type value: domain-name - if: "ctx?.threatintel?.misp?.attribute?.type != null && (ctx?.threatintel?.misp?.attribute?.type == 'hostname' || ctx?.threatintel?.misp?.attribute?.type.startsWith('domain'))" + if: "ctx.misp?.attribute?.type != null && (ctx.misp?.attribute?.type == 'hostname' || ctx.misp?.attribute?.type.startsWith('domain'))" - set: - field: threatintel.indicator.type + field: threat.indicator.type value: ipv4-addr - if: "ctx?.threatintel?.misp?.attribute?.type != null && ['ip-src', 'ip-src|port', 'ip-dst', 'ip-dst|port'].contains(ctx?.threatintel?.misp?.attribute?.type)" + if: "ctx.misp?.attribute?.type != null && ['ip-src', 'ip-src|port', 'ip-dst', 'ip-dst|port'].contains(ctx.misp?.attribute?.type)" - rename: - field: threatintel.misp.attribute.value - target_field: threatintel.indicator.url.domain + field: misp.attribute.value + target_field: threat.indicator.url.domain ignore_missing: true - if: "ctx?.threatintel?.indicator?.type == 'domain-name' && ctx?.threatintel?.misp?.attribute?.type != 'domain|ip' && ctx.threatintel?.indicator?.url?.domain == null" + if: "ctx.threat?.indicator?.type == 'domain-name' && ctx.misp?.attribute?.type != 'domain|ip' && ctx.threat?.indicator?.url?.domain == null" - rename: - field: threatintel.misp.attribute.value - target_field: threatintel.indicator.ip + field: misp.attribute.value + target_field: threat.indicator.ip ignore_missing: true - if: "ctx?.threatintel?.indicator?.type == 'ipv4-addr' && ctx?.threatintel?.misp?.attribute?.type != 'domain|ip' && !['ip-src|port', 'ip-dst|port'].contains(ctx?.threatintel?.misp?.attribute?.type)" + if: "ctx.threat?.indicator?.type == 'ipv4-addr' && ctx.misp?.attribute?.type != 'domain|ip' && !['ip-src|port', 'ip-dst|port'].contains(ctx.misp?.attribute?.type)" - grok: - field: threatintel.misp.attribute.value + field: misp.attribute.value patterns: - - "%{DATA:threatintel.indicator.url.domain}\\|%{IP:threatintel.indicator.ip}" + - "%{DATA:threat.indicator.url.domain}\\|%{IP:threat.indicator.ip}" ignore_missing: true - if: ctx.threatintel?.misp?.attribute?.type == 'domain|ip' && ctx.threatintel?.indicator?.url?.domain == null + if: ctx.misp?.attribute?.type == 'domain|ip' && ctx.threat?.indicator?.url?.domain == null - grok: - field: threatintel.misp.attribute.value + field: misp.attribute.value patterns: - - "%{IP:threatintel.indicator.ip}\\|%{NUMBER:threatintel.indicator.port}" + - "%{IP:threat.indicator.ip}\\|%{NUMBER:threat.indicator.port}" ignore_missing: true - if: "['ip-src|port', 'ip-dst|port'].contains(ctx.threatintel?.misp?.attribute?.type)" + if: "['ip-src|port', 'ip-dst|port'].contains(ctx.misp?.attribute?.type)" ## Email indicator operations # Currently this ignores email-message, except setting the type it will leave the rest of the fields under misp. - set: - field: threatintel.indicator.type + field: threat.indicator.type value: email-addr - if: "ctx?.threatintel?.misp?.attribute?.type != null && ['email-dst', 'email-src'].contains(ctx.threatintel?.misp?.attribute?.type)" + if: "ctx.misp?.attribute?.type != null && ['email-dst', 'email-src'].contains(ctx.misp?.attribute?.type)" - set: - field: threatintel.indicator.type + field: threat.indicator.type value: email-message - if: "ctx?.threatintel?.misp?.attribute?.type != null && ctx.threatintel?.misp?.attribute?.type.startsWith('email') && !['email-dst', 'email-src'].contains(ctx.threatintel?.misp?.attribute?.type)" + if: "ctx.misp?.attribute?.type != null && ctx.misp?.attribute?.type.startsWith('email') && !['email-dst', 'email-src'].contains(ctx.misp?.attribute?.type)" - rename: - field: threatintel.misp.attribute.value - target_field: threatintel.indicator.email.address + field: misp.attribute.value + target_field: threat.indicator.email.address ignore_missing: true - if: ctx?.threatintel?.indicator?.type == 'email-addr' + if: ctx.threat?.indicator?.type == 'email-addr' - rename: - field: threatintel.misp.event_creator_email + field: misp.event_creator_email target_field: user.email ignore_missing: true - append: @@ -258,14 +279,14 @@ processors: ## MAC Address indicator operations - set: - field: threatintel.indicator.type + field: threat.indicator.type value: mac-addr - if: "ctx?.threatintel?.misp?.attribute?.type != null && ['mac-address', 'mac-eui-64'].contains(ctx.threatintel?.misp?.attribute?.type)" + if: "ctx.misp?.attribute?.type != null && ['mac-address', 'mac-eui-64'].contains(ctx.misp?.attribute?.type)" - rename: - field: threatintel.misp.attribute.value - target_field: threatintel.indicator.mac + field: misp.attribute.value + target_field: threat.indicator.mac ignore_missing: true - if: ctx?.threatintel?.indicator?.type == 'mac-addr' + if: ctx.threat?.indicator?.type == 'mac-addr' ################### # Tags ECS fields # @@ -273,9 +294,9 @@ processors: # Stripping special characters from tags - script: lang: painless - if: ctx?.threatintel?.misp?.tag != null + if: ctx.misp?.tag != null source: | - def tags = ctx.threatintel.misp.tag.stream() + def tags = ctx.misp.tag.stream() .map(t -> t.name.replace('\\', '').replace('"', '')) .collect(Collectors.toList()); def tlpTags = tags.stream() @@ -284,20 +305,45 @@ processors: .collect(Collectors.toList()); ctx.tags = tags; - ctx.threatintel.indicator.marking = [ 'tlp': tlpTags ]; + ctx.threat.indicator.marking = [ 'tlp': tlpTags ]; # Setting indicator type to unknown if it does not match anything - set: - field: threatintel.indicator.type + field: threat.indicator.type value: unknown - if: ctx?.threatintel?.indicator?.type == null + if: ctx.threat?.indicator?.type == null + + ################# + # Convert types # + ################# + - convert: + field: misp.attribute.distribution + type: long + ignore_missing: true + - convert: + field: misp.context.attribute.distribution + type: long + ignore_missing: true + - convert: + field: threat.indicator.port + type: long + ignore_missing: true + - convert: + field: misp.attribute_count + type: long + ignore_missing: true ###################### # Cleanup processors # ###################### + - remove: + field: event.original + if: "ctx?.tags == null || !(ctx.tags.contains('preserve_original_event'))" + ignore_failure: true + ignore_missing: true - script: lang: painless - if: ctx?.threatintel != null + if: ctx?.misp != null source: | void handleMap(Map map) { for (def x : map.values()) { @@ -322,24 +368,24 @@ processors: # Removing fields not needed anymore, either because its copied somewhere else, or is not relevant to this event - remove: field: - - threatintel.misp.attribute.value + - misp.attribute.value ignore_missing: true - if: ctx?.threatintel?.indicator?.type != 'unknown' + if: ctx.threat?.indicator?.type != 'unknown' - remove: field: # This removes a number of fields that may be wanted in the future when - # threatintel.misp.attribute and threatintel.misp.object.attribute can + # misp.attribute and misp.object.attribute can # be separated. At the root of .object are fields that mirror fields at - # the root of threatintel.misp. - - threatintel.misp.object + # the root of misp. + - misp.object ignore_missing: true - remove: field: - - threatintel.misp.Attribute.timestamp - - threatintel.misp.timestamp - - threatintel.misp.tag - - threatintel.misp.org - - threatintel.misp.analysis + - misp.Attribute.timestamp + - misp.timestamp + - misp.tag + - misp.org + - misp.analysis - _tmp - json ignore_missing: true diff --git a/x-pack/filebeat/module/threatintel/misp/manifest.yml b/x-pack/filebeat/module/threatintel/misp/manifest.yml index 41443c01df8..3a91b68f4fe 100644 --- a/x-pack/filebeat/module/threatintel/misp/manifest.yml +++ b/x-pack/filebeat/module/threatintel/misp/manifest.yml @@ -15,6 +15,8 @@ var: - name: tags default: [threatintel-misp, forwarded] - name: proxy_url + - name: preserve_original_event + default: false ingest_pipeline: - ingest/pipeline.yml diff --git a/x-pack/filebeat/module/threatintel/misp/test/misp_sample.ndjson.log-expected.json b/x-pack/filebeat/module/threatintel/misp/test/misp_sample.ndjson.log-expected.json index 9f4dbc50fc8..04e12fc0323 100644 --- a/x-pack/filebeat/module/threatintel/misp/test/misp_sample.ndjson.log-expected.json +++ b/x-pack/filebeat/module/threatintel/misp/test/misp_sample.ndjson.log-expected.json @@ -9,6 +9,39 @@ "fileset.name": "misp", "input.type": "log", "log.offset": 0, + "misp.attribute.category": "Payload delivery", + "misp.attribute.comment": "- Xchecked via VT: a683494fc0d017fd3b4638f8b84caaaac145cc28bc211bd7361723368b4bb21e", + "misp.attribute.deleted": false, + "misp.attribute.disable_correlation": false, + "misp.attribute.distribution": 5, + "misp.attribute.event_id": "5", + "misp.attribute.id": "351", + "misp.attribute.object_id": "0", + "misp.attribute.sharing_group_id": "0", + "misp.attribute.timestamp": "1503930272", + "misp.attribute.to_ids": true, + "misp.attribute.type": "md5", + "misp.attribute.uuid": "59a427a0-f6f8-4178-9e7d-dfd702de0b81", + "misp.attribute_count": 7, + "misp.date": "2017-08-25", + "misp.disable_correlation": false, + "misp.distribution": "3", + "misp.extends_uuid": "", + "misp.id": "5", + "misp.info": "OSINT - New Arena Crysis Ransomware Variant Released", + "misp.locked": false, + "misp.org_id": "1", + "misp.orgc.id": "2", + "misp.orgc.local": false, + "misp.orgc.name": "CIRCL", + "misp.orgc.uuid": "55f6ea5e-2c60-40e5-964f-47a8950d210f", + "misp.orgc_id": "2", + "misp.proposal_email_lock": false, + "misp.publish_timestamp": "1603226331", + "misp.published": true, + "misp.sharing_group_id": "0", + "misp.threat_level_id": 3, + "misp.uuid": "59a3d08d-5dc8-4153-bc7c-456d950d210f", "service.type": "threatintel", "tags": [ "malware_classification:malware-category=Ransomware", @@ -17,46 +50,15 @@ "tlp:white", "type:OSINT" ], - "threatintel.indicator.file.hash.md5": "f2679bdabe46e10edc6352fff3c829bc", - "threatintel.indicator.marking.tlp": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] MISP", + "threat.indicator.file.hash.md5": "f2679bdabe46e10edc6352fff3c829bc", + "threat.indicator.marking.tlp": [ "white" ], - "threatintel.indicator.provider": "misp", - "threatintel.indicator.scanner_stats": 2, - "threatintel.indicator.type": "file", - "threatintel.misp.attribute.category": "Payload delivery", - "threatintel.misp.attribute.comment": "- Xchecked via VT: a683494fc0d017fd3b4638f8b84caaaac145cc28bc211bd7361723368b4bb21e", - "threatintel.misp.attribute.deleted": false, - "threatintel.misp.attribute.disable_correlation": false, - "threatintel.misp.attribute.distribution": "5", - "threatintel.misp.attribute.event_id": "5", - "threatintel.misp.attribute.id": "351", - "threatintel.misp.attribute.object_id": "0", - "threatintel.misp.attribute.sharing_group_id": "0", - "threatintel.misp.attribute.timestamp": "1503930272", - "threatintel.misp.attribute.to_ids": true, - "threatintel.misp.attribute.type": "md5", - "threatintel.misp.attribute.uuid": "59a427a0-f6f8-4178-9e7d-dfd702de0b81", - "threatintel.misp.attribute_count": "7", - "threatintel.misp.date": "2017-08-25", - "threatintel.misp.disable_correlation": false, - "threatintel.misp.distribution": "3", - "threatintel.misp.extends_uuid": "", - "threatintel.misp.id": "5", - "threatintel.misp.info": "OSINT - New Arena Crysis Ransomware Variant Released", - "threatintel.misp.locked": false, - "threatintel.misp.org_id": "1", - "threatintel.misp.orgc.id": "2", - "threatintel.misp.orgc.local": false, - "threatintel.misp.orgc.name": "CIRCL", - "threatintel.misp.orgc.uuid": "55f6ea5e-2c60-40e5-964f-47a8950d210f", - "threatintel.misp.orgc_id": "2", - "threatintel.misp.proposal_email_lock": false, - "threatintel.misp.publish_timestamp": "1603226331", - "threatintel.misp.published": true, - "threatintel.misp.sharing_group_id": "0", - "threatintel.misp.threat_level_id": 3, - "threatintel.misp.uuid": "59a3d08d-5dc8-4153-bc7c-456d950d210f" + "threat.indicator.provider": "misp", + "threat.indicator.scanner_stats": 2, + "threat.indicator.type": "file" }, { "@timestamp": "2017-08-28T14:24:36.000Z", @@ -68,6 +70,39 @@ "fileset.name": "misp", "input.type": "log", "log.offset": 8248, + "misp.attribute.category": "Network activity", + "misp.attribute.comment": "1st stage", + "misp.attribute.deleted": false, + "misp.attribute.disable_correlation": false, + "misp.attribute.distribution": 5, + "misp.attribute.event_id": "14", + "misp.attribute.id": "10794", + "misp.attribute.object_id": "0", + "misp.attribute.sharing_group_id": "0", + "misp.attribute.timestamp": "1542652482", + "misp.attribute.to_ids": false, + "misp.attribute.type": "domain|ip", + "misp.attribute.uuid": "5bf30242-8ef4-4c52-a2d7-0b7b0a016219", + "misp.attribute_count": 7, + "misp.date": "2017-08-25", + "misp.disable_correlation": false, + "misp.distribution": "3", + "misp.extends_uuid": "", + "misp.id": "5", + "misp.info": "OSINT - New Arena Crysis Ransomware Variant Released", + "misp.locked": false, + "misp.org_id": "1", + "misp.orgc.id": "2", + "misp.orgc.local": false, + "misp.orgc.name": "CIRCL", + "misp.orgc.uuid": "55f6ea5e-2c60-40e5-964f-47a8950d210f", + "misp.orgc_id": "2", + "misp.proposal_email_lock": false, + "misp.publish_timestamp": "1603226331", + "misp.published": true, + "misp.sharing_group_id": "0", + "misp.threat_level_id": 3, + "misp.uuid": "59a3d08d-5dc8-4153-bc7c-456d950d210f", "service.type": "threatintel", "tags": [ "malware_classification:malware-category=Ransomware", @@ -76,47 +111,16 @@ "tlp:white", "type:OSINT" ], - "threatintel.indicator.ip": "178.128.103.74", - "threatintel.indicator.marking.tlp": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] MISP", + "threat.indicator.ip": "178.128.103.74", + "threat.indicator.marking.tlp": [ "white" ], - "threatintel.indicator.provider": "misp", - "threatintel.indicator.scanner_stats": 2, - "threatintel.indicator.type": "domain-name", - "threatintel.indicator.url.domain": "your-ip.getmyip.com", - "threatintel.misp.attribute.category": "Network activity", - "threatintel.misp.attribute.comment": "1st stage", - "threatintel.misp.attribute.deleted": false, - "threatintel.misp.attribute.disable_correlation": false, - "threatintel.misp.attribute.distribution": "5", - "threatintel.misp.attribute.event_id": "14", - "threatintel.misp.attribute.id": "10794", - "threatintel.misp.attribute.object_id": "0", - "threatintel.misp.attribute.sharing_group_id": "0", - "threatintel.misp.attribute.timestamp": "1542652482", - "threatintel.misp.attribute.to_ids": false, - "threatintel.misp.attribute.type": "domain|ip", - "threatintel.misp.attribute.uuid": "5bf30242-8ef4-4c52-a2d7-0b7b0a016219", - "threatintel.misp.attribute_count": "7", - "threatintel.misp.date": "2017-08-25", - "threatintel.misp.disable_correlation": false, - "threatintel.misp.distribution": "3", - "threatintel.misp.extends_uuid": "", - "threatintel.misp.id": "5", - "threatintel.misp.info": "OSINT - New Arena Crysis Ransomware Variant Released", - "threatintel.misp.locked": false, - "threatintel.misp.org_id": "1", - "threatintel.misp.orgc.id": "2", - "threatintel.misp.orgc.local": false, - "threatintel.misp.orgc.name": "CIRCL", - "threatintel.misp.orgc.uuid": "55f6ea5e-2c60-40e5-964f-47a8950d210f", - "threatintel.misp.orgc_id": "2", - "threatintel.misp.proposal_email_lock": false, - "threatintel.misp.publish_timestamp": "1603226331", - "threatintel.misp.published": true, - "threatintel.misp.sharing_group_id": "0", - "threatintel.misp.threat_level_id": 3, - "threatintel.misp.uuid": "59a3d08d-5dc8-4153-bc7c-456d950d210f" + "threat.indicator.provider": "misp", + "threat.indicator.scanner_stats": 2, + "threat.indicator.type": "domain-name", + "threat.indicator.url.domain": "your-ip.getmyip.com" }, { "@timestamp": "2017-04-28T18:23:44.000Z", @@ -128,55 +132,57 @@ "fileset.name": "misp", "input.type": "log", "log.offset": 16434, + "misp.attribute.category": "External analysis", + "misp.attribute.comment": "Carbon sample - Xchecked via VT: a08b8371ead1919500a4759c2f46553620d5a9d9", + "misp.attribute.deleted": false, + "misp.attribute.disable_correlation": false, + "misp.attribute.distribution": 5, + "misp.attribute.event_id": "4", + "misp.attribute.id": "342", + "misp.attribute.object_id": "0", + "misp.attribute.sharing_group_id": "0", + "misp.attribute.timestamp": "1490878550", + "misp.attribute.to_ids": false, + "misp.attribute.type": "link", + "misp.attribute.uuid": "58dd0056-6e74-43d5-b58b-494802de0b81", + "misp.attribute_count": 100, + "misp.date": "2017-03-30", + "misp.disable_correlation": false, + "misp.distribution": "3", + "misp.extends_uuid": "", + "misp.id": "4", + "misp.info": "OSINT - Carbon Paper: Peering into Turla\u2019s second stage backdoor", + "misp.locked": false, + "misp.org_id": "1", + "misp.orgc.id": "2", + "misp.orgc.local": false, + "misp.orgc.name": "CIRCL", + "misp.orgc.uuid": "55f6ea5e-2c60-40e5-964f-47a8950d210f", + "misp.orgc_id": "2", + "misp.proposal_email_lock": false, + "misp.publish_timestamp": "1603226330", + "misp.published": true, + "misp.sharing_group_id": "0", + "misp.threat_level_id": 3, + "misp.uuid": "58dcfe62-ed84-4e5e-b293-4991950d210f", "service.type": "threatintel", "tags": [ "misp-galaxy:tool=Turla", "tlp:white" ], - "threatintel.indicator.marking.tlp": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] MISP", + "threat.indicator.marking.tlp": [ "white" ], - "threatintel.indicator.provider": "misp", - "threatintel.indicator.scanner_stats": 2, - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "www.virustotal.com", - "threatintel.indicator.url.full": "https://www.virustotal.com/file/7fa4482bfbca550ce296d8e791b1091d60d733ea8042167fd0eb853530584452/analysis/1486030116/", - "threatintel.indicator.url.original": "https://www.virustotal.com/file/7fa4482bfbca550ce296d8e791b1091d60d733ea8042167fd0eb853530584452/analysis/1486030116/", - "threatintel.indicator.url.path": "/file/7fa4482bfbca550ce296d8e791b1091d60d733ea8042167fd0eb853530584452/analysis/1486030116/", - "threatintel.indicator.url.scheme": "https", - "threatintel.misp.attribute.category": "External analysis", - "threatintel.misp.attribute.comment": "Carbon sample - Xchecked via VT: a08b8371ead1919500a4759c2f46553620d5a9d9", - "threatintel.misp.attribute.deleted": false, - "threatintel.misp.attribute.disable_correlation": false, - "threatintel.misp.attribute.distribution": "5", - "threatintel.misp.attribute.event_id": "4", - "threatintel.misp.attribute.id": "342", - "threatintel.misp.attribute.object_id": "0", - "threatintel.misp.attribute.sharing_group_id": "0", - "threatintel.misp.attribute.timestamp": "1490878550", - "threatintel.misp.attribute.to_ids": false, - "threatintel.misp.attribute.type": "link", - "threatintel.misp.attribute.uuid": "58dd0056-6e74-43d5-b58b-494802de0b81", - "threatintel.misp.attribute_count": "100", - "threatintel.misp.date": "2017-03-30", - "threatintel.misp.disable_correlation": false, - "threatintel.misp.distribution": "3", - "threatintel.misp.extends_uuid": "", - "threatintel.misp.id": "4", - "threatintel.misp.info": "OSINT - Carbon Paper: Peering into Turla\u2019s second stage backdoor", - "threatintel.misp.locked": false, - "threatintel.misp.org_id": "1", - "threatintel.misp.orgc.id": "2", - "threatintel.misp.orgc.local": false, - "threatintel.misp.orgc.name": "CIRCL", - "threatintel.misp.orgc.uuid": "55f6ea5e-2c60-40e5-964f-47a8950d210f", - "threatintel.misp.orgc_id": "2", - "threatintel.misp.proposal_email_lock": false, - "threatintel.misp.publish_timestamp": "1603226330", - "threatintel.misp.published": true, - "threatintel.misp.sharing_group_id": "0", - "threatintel.misp.threat_level_id": 3, - "threatintel.misp.uuid": "58dcfe62-ed84-4e5e-b293-4991950d210f" + "threat.indicator.provider": "misp", + "threat.indicator.scanner_stats": 2, + "threat.indicator.type": "url", + "threat.indicator.url.domain": "www.virustotal.com", + "threat.indicator.url.full": "https://www.virustotal.com/file/7fa4482bfbca550ce296d8e791b1091d60d733ea8042167fd0eb853530584452/analysis/1486030116/", + "threat.indicator.url.original": "https://www.virustotal.com/file/7fa4482bfbca550ce296d8e791b1091d60d733ea8042167fd0eb853530584452/analysis/1486030116/", + "threat.indicator.url.path": "/file/7fa4482bfbca550ce296d8e791b1091d60d733ea8042167fd0eb853530584452/analysis/1486030116/", + "threat.indicator.url.scheme": "https" }, { "@timestamp": "2014-10-06T07:12:57.000Z", @@ -188,51 +194,53 @@ "fileset.name": "misp", "input.type": "log", "log.offset": 20139, + "misp.attribute.category": "External analysis", + "misp.attribute.comment": "", + "misp.attribute.deleted": false, + "misp.attribute.disable_correlation": false, + "misp.attribute.distribution": 5, + "misp.attribute.event_id": "2", + "misp.attribute.id": "1077", + "misp.attribute.object_id": "0", + "misp.attribute.sharing_group_id": "0", + "misp.attribute.timestamp": "1412579394", + "misp.attribute.to_ids": true, + "misp.attribute.type": "sha256", + "misp.attribute.uuid": "54324042-49fc-4628-a95e-44da950d210b", + "misp.attribute_count": 29, + "misp.date": "2014-10-03", + "misp.disable_correlation": false, + "misp.distribution": "3", + "misp.extends_uuid": "", + "misp.id": "2", + "misp.info": "OSINT New Indicators of Compromise for APT Group Nitro Uncovered blog post by Palo Alto Networks", + "misp.locked": false, + "misp.org_id": "1", + "misp.orgc.id": "2", + "misp.orgc.local": false, + "misp.orgc.name": "CthulhuSPRL.be", + "misp.orgc.uuid": "55f6ea5f-fd34-43b8-ac1d-40cb950d210f", + "misp.orgc_id": "2", + "misp.proposal_email_lock": false, + "misp.publish_timestamp": "1610622316", + "misp.published": true, + "misp.sharing_group_id": "0", + "misp.threat_level_id": 2, + "misp.uuid": "54323f2c-e50c-4268-896c-4867950d210b", "service.type": "threatintel", "tags": [ "tlp:green", "type:OSINT" ], - "threatintel.indicator.file.hash.sha256": "0a1103bc90725d4665b932f88e81d39eafa5823b0de3ab146e2d4548b7da79a0", - "threatintel.indicator.marking.tlp": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] MISP", + "threat.indicator.file.hash.sha256": "0a1103bc90725d4665b932f88e81d39eafa5823b0de3ab146e2d4548b7da79a0", + "threat.indicator.marking.tlp": [ "green" ], - "threatintel.indicator.provider": "misp", - "threatintel.indicator.scanner_stats": 2, - "threatintel.indicator.type": "file", - "threatintel.misp.attribute.category": "External analysis", - "threatintel.misp.attribute.comment": "", - "threatintel.misp.attribute.deleted": false, - "threatintel.misp.attribute.disable_correlation": false, - "threatintel.misp.attribute.distribution": "5", - "threatintel.misp.attribute.event_id": "2", - "threatintel.misp.attribute.id": "1077", - "threatintel.misp.attribute.object_id": "0", - "threatintel.misp.attribute.sharing_group_id": "0", - "threatintel.misp.attribute.timestamp": "1412579394", - "threatintel.misp.attribute.to_ids": true, - "threatintel.misp.attribute.type": "sha256", - "threatintel.misp.attribute.uuid": "54324042-49fc-4628-a95e-44da950d210b", - "threatintel.misp.attribute_count": "29", - "threatintel.misp.date": "2014-10-03", - "threatintel.misp.disable_correlation": false, - "threatintel.misp.distribution": "3", - "threatintel.misp.extends_uuid": "", - "threatintel.misp.id": "2", - "threatintel.misp.info": "OSINT New Indicators of Compromise for APT Group Nitro Uncovered blog post by Palo Alto Networks", - "threatintel.misp.locked": false, - "threatintel.misp.org_id": "1", - "threatintel.misp.orgc.id": "2", - "threatintel.misp.orgc.local": false, - "threatintel.misp.orgc.name": "CthulhuSPRL.be", - "threatintel.misp.orgc.uuid": "55f6ea5f-fd34-43b8-ac1d-40cb950d210f", - "threatintel.misp.orgc_id": "2", - "threatintel.misp.proposal_email_lock": false, - "threatintel.misp.publish_timestamp": "1610622316", - "threatintel.misp.published": true, - "threatintel.misp.sharing_group_id": "0", - "threatintel.misp.threat_level_id": 2, - "threatintel.misp.uuid": "54323f2c-e50c-4268-896c-4867950d210b" + "threat.indicator.provider": "misp", + "threat.indicator.scanner_stats": 2, + "threat.indicator.type": "file" }, { "@timestamp": "2014-10-06T07:12:57.000Z", @@ -244,51 +252,53 @@ "fileset.name": "misp", "input.type": "log", "log.offset": 21711, + "misp.attribute.category": "Network activity", + "misp.attribute.comment": "", + "misp.attribute.deleted": false, + "misp.attribute.disable_correlation": false, + "misp.attribute.distribution": 5, + "misp.attribute.event_id": "2", + "misp.attribute.id": "1084", + "misp.attribute.object_id": "0", + "misp.attribute.sharing_group_id": "0", + "misp.attribute.timestamp": "1412579457", + "misp.attribute.to_ids": true, + "misp.attribute.type": "ip-dst", + "misp.attribute.uuid": "54324081-3308-4f1f-8674-4953950d210b", + "misp.attribute_count": 29, + "misp.date": "2014-10-03", + "misp.disable_correlation": false, + "misp.distribution": "3", + "misp.extends_uuid": "", + "misp.id": "2", + "misp.info": "OSINT New Indicators of Compromise for APT Group Nitro Uncovered blog post by Palo Alto Networks", + "misp.locked": false, + "misp.org_id": "1", + "misp.orgc.id": "2", + "misp.orgc.local": false, + "misp.orgc.name": "CthulhuSPRL.be", + "misp.orgc.uuid": "55f6ea5f-fd34-43b8-ac1d-40cb950d210f", + "misp.orgc_id": "2", + "misp.proposal_email_lock": false, + "misp.publish_timestamp": "1610622316", + "misp.published": true, + "misp.sharing_group_id": "0", + "misp.threat_level_id": 2, + "misp.uuid": "54323f2c-e50c-4268-896c-4867950d210b", "service.type": "threatintel", "tags": [ "tlp:green", "type:OSINT" ], - "threatintel.indicator.ip": "223.25.233.248", - "threatintel.indicator.marking.tlp": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] MISP", + "threat.indicator.ip": "223.25.233.248", + "threat.indicator.marking.tlp": [ "green" ], - "threatintel.indicator.provider": "misp", - "threatintel.indicator.scanner_stats": 2, - "threatintel.indicator.type": "ipv4-addr", - "threatintel.misp.attribute.category": "Network activity", - "threatintel.misp.attribute.comment": "", - "threatintel.misp.attribute.deleted": false, - "threatintel.misp.attribute.disable_correlation": false, - "threatintel.misp.attribute.distribution": "5", - "threatintel.misp.attribute.event_id": "2", - "threatintel.misp.attribute.id": "1084", - "threatintel.misp.attribute.object_id": "0", - "threatintel.misp.attribute.sharing_group_id": "0", - "threatintel.misp.attribute.timestamp": "1412579457", - "threatintel.misp.attribute.to_ids": true, - "threatintel.misp.attribute.type": "ip-dst", - "threatintel.misp.attribute.uuid": "54324081-3308-4f1f-8674-4953950d210b", - "threatintel.misp.attribute_count": "29", - "threatintel.misp.date": "2014-10-03", - "threatintel.misp.disable_correlation": false, - "threatintel.misp.distribution": "3", - "threatintel.misp.extends_uuid": "", - "threatintel.misp.id": "2", - "threatintel.misp.info": "OSINT New Indicators of Compromise for APT Group Nitro Uncovered blog post by Palo Alto Networks", - "threatintel.misp.locked": false, - "threatintel.misp.org_id": "1", - "threatintel.misp.orgc.id": "2", - "threatintel.misp.orgc.local": false, - "threatintel.misp.orgc.name": "CthulhuSPRL.be", - "threatintel.misp.orgc.uuid": "55f6ea5f-fd34-43b8-ac1d-40cb950d210f", - "threatintel.misp.orgc_id": "2", - "threatintel.misp.proposal_email_lock": false, - "threatintel.misp.publish_timestamp": "1610622316", - "threatintel.misp.published": true, - "threatintel.misp.sharing_group_id": "0", - "threatintel.misp.threat_level_id": 2, - "threatintel.misp.uuid": "54323f2c-e50c-4268-896c-4867950d210b" + "threat.indicator.provider": "misp", + "threat.indicator.scanner_stats": 2, + "threat.indicator.type": "ipv4-addr" }, { "@timestamp": "2014-10-06T07:12:57.000Z", @@ -300,51 +310,53 @@ "fileset.name": "misp", "input.type": "log", "log.offset": 23232, + "misp.attribute.category": "Network activity", + "misp.attribute.comment": "", + "misp.attribute.deleted": false, + "misp.attribute.disable_correlation": false, + "misp.attribute.distribution": 5, + "misp.attribute.event_id": "2", + "misp.attribute.id": "1086", + "misp.attribute.object_id": "0", + "misp.attribute.sharing_group_id": "0", + "misp.attribute.timestamp": "1412579548", + "misp.attribute.to_ids": true, + "misp.attribute.type": "hostname", + "misp.attribute.uuid": "543240dc-f068-437a-baa9-48f2950d210b", + "misp.attribute_count": 29, + "misp.date": "2014-10-03", + "misp.disable_correlation": false, + "misp.distribution": "3", + "misp.extends_uuid": "", + "misp.id": "2", + "misp.info": "OSINT New Indicators of Compromise for APT Group Nitro Uncovered blog post by Palo Alto Networks", + "misp.locked": false, + "misp.org_id": "1", + "misp.orgc.id": "2", + "misp.orgc.local": false, + "misp.orgc.name": "CthulhuSPRL.be", + "misp.orgc.uuid": "55f6ea5f-fd34-43b8-ac1d-40cb950d210f", + "misp.orgc_id": "2", + "misp.proposal_email_lock": false, + "misp.publish_timestamp": "1610622316", + "misp.published": true, + "misp.sharing_group_id": "0", + "misp.threat_level_id": 2, + "misp.uuid": "54323f2c-e50c-4268-896c-4867950d210b", "service.type": "threatintel", "tags": [ "tlp:green", "type:OSINT" ], - "threatintel.indicator.marking.tlp": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] MISP", + "threat.indicator.marking.tlp": [ "green" ], - "threatintel.indicator.provider": "misp", - "threatintel.indicator.scanner_stats": 2, - "threatintel.indicator.type": "domain-name", - "threatintel.indicator.url.domain": "xenserver.ddns.net", - "threatintel.misp.attribute.category": "Network activity", - "threatintel.misp.attribute.comment": "", - "threatintel.misp.attribute.deleted": false, - "threatintel.misp.attribute.disable_correlation": false, - "threatintel.misp.attribute.distribution": "5", - "threatintel.misp.attribute.event_id": "2", - "threatintel.misp.attribute.id": "1086", - "threatintel.misp.attribute.object_id": "0", - "threatintel.misp.attribute.sharing_group_id": "0", - "threatintel.misp.attribute.timestamp": "1412579548", - "threatintel.misp.attribute.to_ids": true, - "threatintel.misp.attribute.type": "hostname", - "threatintel.misp.attribute.uuid": "543240dc-f068-437a-baa9-48f2950d210b", - "threatintel.misp.attribute_count": "29", - "threatintel.misp.date": "2014-10-03", - "threatintel.misp.disable_correlation": false, - "threatintel.misp.distribution": "3", - "threatintel.misp.extends_uuid": "", - "threatintel.misp.id": "2", - "threatintel.misp.info": "OSINT New Indicators of Compromise for APT Group Nitro Uncovered blog post by Palo Alto Networks", - "threatintel.misp.locked": false, - "threatintel.misp.org_id": "1", - "threatintel.misp.orgc.id": "2", - "threatintel.misp.orgc.local": false, - "threatintel.misp.orgc.name": "CthulhuSPRL.be", - "threatintel.misp.orgc.uuid": "55f6ea5f-fd34-43b8-ac1d-40cb950d210f", - "threatintel.misp.orgc_id": "2", - "threatintel.misp.proposal_email_lock": false, - "threatintel.misp.publish_timestamp": "1610622316", - "threatintel.misp.published": true, - "threatintel.misp.sharing_group_id": "0", - "threatintel.misp.threat_level_id": 2, - "threatintel.misp.uuid": "54323f2c-e50c-4268-896c-4867950d210b" + "threat.indicator.provider": "misp", + "threat.indicator.scanner_stats": 2, + "threat.indicator.type": "domain-name", + "threat.indicator.url.domain": "xenserver.ddns.net" }, { "@timestamp": "2014-10-06T07:12:57.000Z", @@ -356,51 +368,53 @@ "fileset.name": "misp", "input.type": "log", "log.offset": 24759, + "misp.attribute.category": "External analysis", + "misp.attribute.comment": "", + "misp.attribute.deleted": false, + "misp.attribute.disable_correlation": false, + "misp.attribute.distribution": 5, + "misp.attribute.event_id": "2", + "misp.attribute.id": "1089", + "misp.attribute.object_id": "0", + "misp.attribute.sharing_group_id": "0", + "misp.attribute.timestamp": "1412579577", + "misp.attribute.to_ids": false, + "misp.attribute.type": "text", + "misp.attribute.uuid": "543240f9-64e8-41f2-958f-4e21950d210b", + "misp.attribute.value": "Nitro", + "misp.attribute_count": 29, + "misp.date": "2014-10-03", + "misp.disable_correlation": false, + "misp.distribution": "3", + "misp.extends_uuid": "", + "misp.id": "2", + "misp.info": "OSINT New Indicators of Compromise for APT Group Nitro Uncovered blog post by Palo Alto Networks", + "misp.locked": false, + "misp.org_id": "1", + "misp.orgc.id": "2", + "misp.orgc.local": false, + "misp.orgc.name": "CthulhuSPRL.be", + "misp.orgc.uuid": "55f6ea5f-fd34-43b8-ac1d-40cb950d210f", + "misp.orgc_id": "2", + "misp.proposal_email_lock": false, + "misp.publish_timestamp": "1610622316", + "misp.published": true, + "misp.sharing_group_id": "0", + "misp.threat_level_id": 2, + "misp.uuid": "54323f2c-e50c-4268-896c-4867950d210b", "service.type": "threatintel", "tags": [ "tlp:green", "type:OSINT" ], - "threatintel.indicator.marking.tlp": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] MISP", + "threat.indicator.marking.tlp": [ "green" ], - "threatintel.indicator.provider": "misp", - "threatintel.indicator.scanner_stats": 2, - "threatintel.indicator.type": "unknown", - "threatintel.misp.attribute.category": "External analysis", - "threatintel.misp.attribute.comment": "", - "threatintel.misp.attribute.deleted": false, - "threatintel.misp.attribute.disable_correlation": false, - "threatintel.misp.attribute.distribution": "5", - "threatintel.misp.attribute.event_id": "2", - "threatintel.misp.attribute.id": "1089", - "threatintel.misp.attribute.object_id": "0", - "threatintel.misp.attribute.sharing_group_id": "0", - "threatintel.misp.attribute.timestamp": "1412579577", - "threatintel.misp.attribute.to_ids": false, - "threatintel.misp.attribute.type": "text", - "threatintel.misp.attribute.uuid": "543240f9-64e8-41f2-958f-4e21950d210b", - "threatintel.misp.attribute.value": "Nitro", - "threatintel.misp.attribute_count": "29", - "threatintel.misp.date": "2014-10-03", - "threatintel.misp.disable_correlation": false, - "threatintel.misp.distribution": "3", - "threatintel.misp.extends_uuid": "", - "threatintel.misp.id": "2", - "threatintel.misp.info": "OSINT New Indicators of Compromise for APT Group Nitro Uncovered blog post by Palo Alto Networks", - "threatintel.misp.locked": false, - "threatintel.misp.org_id": "1", - "threatintel.misp.orgc.id": "2", - "threatintel.misp.orgc.local": false, - "threatintel.misp.orgc.name": "CthulhuSPRL.be", - "threatintel.misp.orgc.uuid": "55f6ea5f-fd34-43b8-ac1d-40cb950d210f", - "threatintel.misp.orgc_id": "2", - "threatintel.misp.proposal_email_lock": false, - "threatintel.misp.publish_timestamp": "1610622316", - "threatintel.misp.published": true, - "threatintel.misp.sharing_group_id": "0", - "threatintel.misp.threat_level_id": 2, - "threatintel.misp.uuid": "54323f2c-e50c-4268-896c-4867950d210b" + "threat.indicator.provider": "misp", + "threat.indicator.scanner_stats": 2, + "threat.indicator.type": "unknown" }, { "@timestamp": "2014-10-06T07:12:57.000Z", @@ -412,51 +426,53 @@ "fileset.name": "misp", "input.type": "log", "log.offset": 26271, + "misp.attribute.category": "External analysis", + "misp.attribute.comment": "Automatically added (via 7915aabb2e66ff14841e4ef0fbff7486)", + "misp.attribute.deleted": false, + "misp.attribute.disable_correlation": false, + "misp.attribute.distribution": 5, + "misp.attribute.event_id": "2", + "misp.attribute.id": "1090", + "misp.attribute.object_id": "0", + "misp.attribute.sharing_group_id": "0", + "misp.attribute.timestamp": "1455826343", + "misp.attribute.to_ids": true, + "misp.attribute.type": "sha1", + "misp.attribute.uuid": "56c625a7-f31c-460c-9ea1-c652950d210f", + "misp.attribute_count": 29, + "misp.date": "2014-10-03", + "misp.disable_correlation": false, + "misp.distribution": "3", + "misp.extends_uuid": "", + "misp.id": "2", + "misp.info": "OSINT New Indicators of Compromise for APT Group Nitro Uncovered blog post by Palo Alto Networks", + "misp.locked": false, + "misp.org_id": "1", + "misp.orgc.id": "2", + "misp.orgc.local": false, + "misp.orgc.name": "CthulhuSPRL.be", + "misp.orgc.uuid": "55f6ea5f-fd34-43b8-ac1d-40cb950d210f", + "misp.orgc_id": "2", + "misp.proposal_email_lock": false, + "misp.publish_timestamp": "1610622316", + "misp.published": true, + "misp.sharing_group_id": "0", + "misp.threat_level_id": 2, + "misp.uuid": "54323f2c-e50c-4268-896c-4867950d210b", "service.type": "threatintel", "tags": [ "tlp:green", "type:OSINT" ], - "threatintel.indicator.file.hash.sha1": "0ea76f1586c008932d90c991dfdd5042f3aac8ea", - "threatintel.indicator.marking.tlp": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] MISP", + "threat.indicator.file.hash.sha1": "0ea76f1586c008932d90c991dfdd5042f3aac8ea", + "threat.indicator.marking.tlp": [ "green" ], - "threatintel.indicator.provider": "misp", - "threatintel.indicator.scanner_stats": 2, - "threatintel.indicator.type": "file", - "threatintel.misp.attribute.category": "External analysis", - "threatintel.misp.attribute.comment": "Automatically added (via 7915aabb2e66ff14841e4ef0fbff7486)", - "threatintel.misp.attribute.deleted": false, - "threatintel.misp.attribute.disable_correlation": false, - "threatintel.misp.attribute.distribution": "5", - "threatintel.misp.attribute.event_id": "2", - "threatintel.misp.attribute.id": "1090", - "threatintel.misp.attribute.object_id": "0", - "threatintel.misp.attribute.sharing_group_id": "0", - "threatintel.misp.attribute.timestamp": "1455826343", - "threatintel.misp.attribute.to_ids": true, - "threatintel.misp.attribute.type": "sha1", - "threatintel.misp.attribute.uuid": "56c625a7-f31c-460c-9ea1-c652950d210f", - "threatintel.misp.attribute_count": "29", - "threatintel.misp.date": "2014-10-03", - "threatintel.misp.disable_correlation": false, - "threatintel.misp.distribution": "3", - "threatintel.misp.extends_uuid": "", - "threatintel.misp.id": "2", - "threatintel.misp.info": "OSINT New Indicators of Compromise for APT Group Nitro Uncovered blog post by Palo Alto Networks", - "threatintel.misp.locked": false, - "threatintel.misp.org_id": "1", - "threatintel.misp.orgc.id": "2", - "threatintel.misp.orgc.local": false, - "threatintel.misp.orgc.name": "CthulhuSPRL.be", - "threatintel.misp.orgc.uuid": "55f6ea5f-fd34-43b8-ac1d-40cb950d210f", - "threatintel.misp.orgc_id": "2", - "threatintel.misp.proposal_email_lock": false, - "threatintel.misp.publish_timestamp": "1610622316", - "threatintel.misp.published": true, - "threatintel.misp.sharing_group_id": "0", - "threatintel.misp.threat_level_id": 2, - "threatintel.misp.uuid": "54323f2c-e50c-4268-896c-4867950d210b" + "threat.indicator.provider": "misp", + "threat.indicator.scanner_stats": 2, + "threat.indicator.type": "file" }, { "@timestamp": "2014-10-06T07:12:57.000Z", @@ -468,51 +484,53 @@ "fileset.name": "misp", "input.type": "log", "log.offset": 27875, + "misp.attribute.category": "Network activity", + "misp.attribute.comment": "", + "misp.attribute.deleted": false, + "misp.attribute.disable_correlation": false, + "misp.attribute.distribution": 5, + "misp.attribute.event_id": "22", + "misp.attribute.id": "12394", + "misp.attribute.object_id": "0", + "misp.attribute.sharing_group_id": "0", + "misp.attribute.timestamp": "1462454963", + "misp.attribute.to_ids": false, + "misp.attribute.type": "domain", + "misp.attribute.uuid": "572b4ab3-1af0-4d91-9cd5-07a1c0a8ab16", + "misp.attribute_count": 29, + "misp.date": "2014-10-03", + "misp.disable_correlation": false, + "misp.distribution": "3", + "misp.extends_uuid": "", + "misp.id": "2", + "misp.info": "OSINT New Indicators of Compromise for APT Group Nitro Uncovered blog post by Palo Alto Networks", + "misp.locked": false, + "misp.org_id": "1", + "misp.orgc.id": "2", + "misp.orgc.local": false, + "misp.orgc.name": "CthulhuSPRL.be", + "misp.orgc.uuid": "55f6ea5f-fd34-43b8-ac1d-40cb950d210f", + "misp.orgc_id": "2", + "misp.proposal_email_lock": false, + "misp.publish_timestamp": "1610622316", + "misp.published": true, + "misp.sharing_group_id": "0", + "misp.threat_level_id": 2, + "misp.uuid": "54323f2c-e50c-4268-896c-4867950d210b", "service.type": "threatintel", "tags": [ "tlp:green", "type:OSINT" ], - "threatintel.indicator.marking.tlp": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] MISP", + "threat.indicator.marking.tlp": [ "green" ], - "threatintel.indicator.provider": "misp", - "threatintel.indicator.scanner_stats": 2, - "threatintel.indicator.type": "domain-name", - "threatintel.indicator.url.domain": "whatsapp.com", - "threatintel.misp.attribute.category": "Network activity", - "threatintel.misp.attribute.comment": "", - "threatintel.misp.attribute.deleted": false, - "threatintel.misp.attribute.disable_correlation": false, - "threatintel.misp.attribute.distribution": "5", - "threatintel.misp.attribute.event_id": "22", - "threatintel.misp.attribute.id": "12394", - "threatintel.misp.attribute.object_id": "0", - "threatintel.misp.attribute.sharing_group_id": "0", - "threatintel.misp.attribute.timestamp": "1462454963", - "threatintel.misp.attribute.to_ids": false, - "threatintel.misp.attribute.type": "domain", - "threatintel.misp.attribute.uuid": "572b4ab3-1af0-4d91-9cd5-07a1c0a8ab16", - "threatintel.misp.attribute_count": "29", - "threatintel.misp.date": "2014-10-03", - "threatintel.misp.disable_correlation": false, - "threatintel.misp.distribution": "3", - "threatintel.misp.extends_uuid": "", - "threatintel.misp.id": "2", - "threatintel.misp.info": "OSINT New Indicators of Compromise for APT Group Nitro Uncovered blog post by Palo Alto Networks", - "threatintel.misp.locked": false, - "threatintel.misp.org_id": "1", - "threatintel.misp.orgc.id": "2", - "threatintel.misp.orgc.local": false, - "threatintel.misp.orgc.name": "CthulhuSPRL.be", - "threatintel.misp.orgc.uuid": "55f6ea5f-fd34-43b8-ac1d-40cb950d210f", - "threatintel.misp.orgc_id": "2", - "threatintel.misp.proposal_email_lock": false, - "threatintel.misp.publish_timestamp": "1610622316", - "threatintel.misp.published": true, - "threatintel.misp.sharing_group_id": "0", - "threatintel.misp.threat_level_id": 2, - "threatintel.misp.uuid": "54323f2c-e50c-4268-896c-4867950d210b" + "threat.indicator.provider": "misp", + "threat.indicator.scanner_stats": 2, + "threat.indicator.type": "domain-name", + "threat.indicator.url.domain": "whatsapp.com" }, { "@timestamp": "2018-08-28T13:20:17.000Z", @@ -524,57 +542,59 @@ "fileset.name": "misp", "input.type": "log", "log.offset": 29397, + "misp.attribute.category": "Network activity", + "misp.attribute.comment": "Fake adobe URL", + "misp.attribute.deleted": false, + "misp.attribute.disable_correlation": false, + "misp.attribute.distribution": 5, + "misp.attribute.event_id": "158", + "misp.attribute.id": "17299", + "misp.attribute.object_id": "0", + "misp.attribute.sharing_group_id": "0", + "misp.attribute.timestamp": "1515427692", + "misp.attribute.to_ids": false, + "misp.attribute.type": "url", + "misp.attribute.uuid": "5a53976c-e7c8-480d-a68a-2fc50a016219", + "misp.attribute_count": 61, + "misp.date": "2018-01-08", + "misp.disable_correlation": false, + "misp.distribution": "3", + "misp.extends_uuid": "", + "misp.id": "158", + "misp.info": "Turla: Mosquito Whitepaper", + "misp.locked": false, + "misp.org_id": "1", + "misp.orgc.id": "5", + "misp.orgc.local": false, + "misp.orgc.name": "ESET", + "misp.orgc.uuid": "55f6ea5e-51ac-4344-bc8c-4170950d210f", + "misp.orgc_id": "5", + "misp.proposal_email_lock": false, + "misp.publish_timestamp": "1610637953", + "misp.published": true, + "misp.sharing_group_id": "0", + "misp.threat_level_id": 1, + "misp.uuid": "5a5395d1-40a0-45fc-b692-334a0a016219", "service.type": "threatintel", "tags": [ "Turla", "misp-galaxy:threat-actor=Turla Group", "tlp:white" ], - "threatintel.indicator.marking.tlp": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] MISP", + "threat.indicator.marking.tlp": [ "white" ], - "threatintel.indicator.provider": "misp", - "threatintel.indicator.scanner_stats": 0, - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "get.adobe.com", - "threatintel.indicator.url.full": "http://get.adobe.com/stats/AbfFcBebD/?q=", - "threatintel.indicator.url.original": "http://get.adobe.com/stats/AbfFcBebD/?q=", - "threatintel.indicator.url.path": "/stats/AbfFcBebD/", - "threatintel.indicator.url.query": "q=", - "threatintel.indicator.url.scheme": "http", - "threatintel.misp.attribute.category": "Network activity", - "threatintel.misp.attribute.comment": "Fake adobe URL", - "threatintel.misp.attribute.deleted": false, - "threatintel.misp.attribute.disable_correlation": false, - "threatintel.misp.attribute.distribution": "5", - "threatintel.misp.attribute.event_id": "158", - "threatintel.misp.attribute.id": "17299", - "threatintel.misp.attribute.object_id": "0", - "threatintel.misp.attribute.sharing_group_id": "0", - "threatintel.misp.attribute.timestamp": "1515427692", - "threatintel.misp.attribute.to_ids": false, - "threatintel.misp.attribute.type": "url", - "threatintel.misp.attribute.uuid": "5a53976c-e7c8-480d-a68a-2fc50a016219", - "threatintel.misp.attribute_count": "61", - "threatintel.misp.date": "2018-01-08", - "threatintel.misp.disable_correlation": false, - "threatintel.misp.distribution": "3", - "threatintel.misp.extends_uuid": "", - "threatintel.misp.id": "158", - "threatintel.misp.info": "Turla: Mosquito Whitepaper", - "threatintel.misp.locked": false, - "threatintel.misp.org_id": "1", - "threatintel.misp.orgc.id": "5", - "threatintel.misp.orgc.local": false, - "threatintel.misp.orgc.name": "ESET", - "threatintel.misp.orgc.uuid": "55f6ea5e-51ac-4344-bc8c-4170950d210f", - "threatintel.misp.orgc_id": "5", - "threatintel.misp.proposal_email_lock": false, - "threatintel.misp.publish_timestamp": "1610637953", - "threatintel.misp.published": true, - "threatintel.misp.sharing_group_id": "0", - "threatintel.misp.threat_level_id": 1, - "threatintel.misp.uuid": "5a5395d1-40a0-45fc-b692-334a0a016219" + "threat.indicator.provider": "misp", + "threat.indicator.scanner_stats": 0, + "threat.indicator.type": "url", + "threat.indicator.url.domain": "get.adobe.com", + "threat.indicator.url.full": "http://get.adobe.com/stats/AbfFcBebD/?q=", + "threat.indicator.url.original": "http://get.adobe.com/stats/AbfFcBebD/?q=", + "threat.indicator.url.path": "/stats/AbfFcBebD/", + "threat.indicator.url.query": "q=", + "threat.indicator.url.scheme": "http" }, { "@timestamp": "2018-08-28T13:20:17.000Z", @@ -586,51 +606,53 @@ "fileset.name": "misp", "input.type": "log", "log.offset": 31486, + "misp.attribute.category": "Network activity", + "misp.attribute.comment": "Win32 backdoor C&C URI", + "misp.attribute.deleted": false, + "misp.attribute.disable_correlation": false, + "misp.attribute.distribution": 5, + "misp.attribute.event_id": "158", + "misp.attribute.id": "17330", + "misp.attribute.object_id": "0", + "misp.attribute.sharing_group_id": "0", + "misp.attribute.timestamp": "1515429089", + "misp.attribute.to_ids": false, + "misp.attribute.type": "uri", + "misp.attribute.uuid": "5a539ce1-3de0-4e34-8fc4-2fc50a016219", + "misp.attribute_count": 61, + "misp.date": "2018-01-08", + "misp.disable_correlation": false, + "misp.distribution": "3", + "misp.extends_uuid": "", + "misp.id": "158", + "misp.info": "Turla: Mosquito Whitepaper", + "misp.locked": false, + "misp.org_id": "1", + "misp.orgc.id": "5", + "misp.orgc.local": false, + "misp.orgc.name": "ESET", + "misp.orgc.uuid": "55f6ea5e-51ac-4344-bc8c-4170950d210f", + "misp.orgc_id": "5", + "misp.proposal_email_lock": false, + "misp.publish_timestamp": "1610637953", + "misp.published": true, + "misp.sharing_group_id": "0", + "misp.threat_level_id": 1, + "misp.uuid": "5a5395d1-40a0-45fc-b692-334a0a016219", "service.type": "threatintel", "tags": [ "Turla", "misp-galaxy:threat-actor=Turla Group", "tlp:white" ], - "threatintel.indicator.marking.tlp": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] MISP", + "threat.indicator.marking.tlp": [ "white" ], - "threatintel.indicator.provider": "misp", - "threatintel.indicator.scanner_stats": 0, - "threatintel.indicator.type": "url", - "threatintel.misp.attribute.category": "Network activity", - "threatintel.misp.attribute.comment": "Win32 backdoor C&C URI", - "threatintel.misp.attribute.deleted": false, - "threatintel.misp.attribute.disable_correlation": false, - "threatintel.misp.attribute.distribution": "5", - "threatintel.misp.attribute.event_id": "158", - "threatintel.misp.attribute.id": "17330", - "threatintel.misp.attribute.object_id": "0", - "threatintel.misp.attribute.sharing_group_id": "0", - "threatintel.misp.attribute.timestamp": "1515429089", - "threatintel.misp.attribute.to_ids": false, - "threatintel.misp.attribute.type": "uri", - "threatintel.misp.attribute.uuid": "5a539ce1-3de0-4e34-8fc4-2fc50a016219", - "threatintel.misp.attribute_count": "61", - "threatintel.misp.date": "2018-01-08", - "threatintel.misp.disable_correlation": false, - "threatintel.misp.distribution": "3", - "threatintel.misp.extends_uuid": "", - "threatintel.misp.id": "158", - "threatintel.misp.info": "Turla: Mosquito Whitepaper", - "threatintel.misp.locked": false, - "threatintel.misp.org_id": "1", - "threatintel.misp.orgc.id": "5", - "threatintel.misp.orgc.local": false, - "threatintel.misp.orgc.name": "ESET", - "threatintel.misp.orgc.uuid": "55f6ea5e-51ac-4344-bc8c-4170950d210f", - "threatintel.misp.orgc_id": "5", - "threatintel.misp.proposal_email_lock": false, - "threatintel.misp.publish_timestamp": "1610637953", - "threatintel.misp.published": true, - "threatintel.misp.sharing_group_id": "0", - "threatintel.misp.threat_level_id": 1, - "threatintel.misp.uuid": "5a5395d1-40a0-45fc-b692-334a0a016219" + "threat.indicator.provider": "misp", + "threat.indicator.scanner_stats": 0, + "threat.indicator.type": "url" }, { "@timestamp": "2018-08-28T13:20:17.000Z", @@ -642,53 +664,55 @@ "fileset.name": "misp", "input.type": "log", "log.offset": 33567, + "misp.attribute.category": "Artifacts dropped", + "misp.attribute.comment": "JavaScript backdoor", + "misp.attribute.deleted": false, + "misp.attribute.disable_correlation": false, + "misp.attribute.distribution": 5, + "misp.attribute.event_id": "158", + "misp.attribute.id": "17322", + "misp.attribute.object_id": "0", + "misp.attribute.sharing_group_id": "0", + "misp.attribute.timestamp": "1515429089", + "misp.attribute.to_ids": false, + "misp.attribute.type": "filename|sha1", + "misp.attribute.uuid": "5a539ce1-e6a0-426a-942c-2fc50a016219", + "misp.attribute_count": 61, + "misp.date": "2018-01-08", + "misp.disable_correlation": false, + "misp.distribution": "3", + "misp.extends_uuid": "", + "misp.id": "158", + "misp.info": "Turla: Mosquito Whitepaper", + "misp.locked": false, + "misp.org_id": "1", + "misp.orgc.id": "5", + "misp.orgc.local": false, + "misp.orgc.name": "ESET", + "misp.orgc.uuid": "55f6ea5e-51ac-4344-bc8c-4170950d210f", + "misp.orgc_id": "5", + "misp.proposal_email_lock": false, + "misp.publish_timestamp": "1610637953", + "misp.published": true, + "misp.sharing_group_id": "0", + "misp.threat_level_id": 1, + "misp.uuid": "5a5395d1-40a0-45fc-b692-334a0a016219", "service.type": "threatintel", "tags": [ "Turla", "misp-galaxy:threat-actor=Turla Group", "tlp:white" ], - "threatintel.indicator.file.hash.sha1": "c51d288469df9f25e2fb7ac491918b3e579282ea", - "threatintel.indicator.file.name": "google_update_checker.js", - "threatintel.indicator.marking.tlp": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] MISP", + "threat.indicator.file.hash.sha1": "c51d288469df9f25e2fb7ac491918b3e579282ea", + "threat.indicator.file.name": "google_update_checker.js", + "threat.indicator.marking.tlp": [ "white" ], - "threatintel.indicator.provider": "misp", - "threatintel.indicator.scanner_stats": 0, - "threatintel.indicator.type": "file", - "threatintel.misp.attribute.category": "Artifacts dropped", - "threatintel.misp.attribute.comment": "JavaScript backdoor", - "threatintel.misp.attribute.deleted": false, - "threatintel.misp.attribute.disable_correlation": false, - "threatintel.misp.attribute.distribution": "5", - "threatintel.misp.attribute.event_id": "158", - "threatintel.misp.attribute.id": "17322", - "threatintel.misp.attribute.object_id": "0", - "threatintel.misp.attribute.sharing_group_id": "0", - "threatintel.misp.attribute.timestamp": "1515429089", - "threatintel.misp.attribute.to_ids": false, - "threatintel.misp.attribute.type": "filename|sha1", - "threatintel.misp.attribute.uuid": "5a539ce1-e6a0-426a-942c-2fc50a016219", - "threatintel.misp.attribute_count": "61", - "threatintel.misp.date": "2018-01-08", - "threatintel.misp.disable_correlation": false, - "threatintel.misp.distribution": "3", - "threatintel.misp.extends_uuid": "", - "threatintel.misp.id": "158", - "threatintel.misp.info": "Turla: Mosquito Whitepaper", - "threatintel.misp.locked": false, - "threatintel.misp.org_id": "1", - "threatintel.misp.orgc.id": "5", - "threatintel.misp.orgc.local": false, - "threatintel.misp.orgc.name": "ESET", - "threatintel.misp.orgc.uuid": "55f6ea5e-51ac-4344-bc8c-4170950d210f", - "threatintel.misp.orgc_id": "5", - "threatintel.misp.proposal_email_lock": false, - "threatintel.misp.publish_timestamp": "1610637953", - "threatintel.misp.published": true, - "threatintel.misp.sharing_group_id": "0", - "threatintel.misp.threat_level_id": 1, - "threatintel.misp.uuid": "5a5395d1-40a0-45fc-b692-334a0a016219" + "threat.indicator.provider": "misp", + "threat.indicator.scanner_stats": 0, + "threat.indicator.type": "file" }, { "@timestamp": "2018-01-23T16:09:56.000Z", @@ -700,50 +724,52 @@ "fileset.name": "misp", "input.type": "log", "log.offset": 35697, + "misp.attribute.category": "Payload delivery", + "misp.attribute.comment": "", + "misp.attribute.deleted": false, + "misp.attribute.disable_correlation": false, + "misp.attribute.distribution": 5, + "misp.attribute.event_id": "22", + "misp.attribute.id": "12268", + "misp.attribute.object_id": "0", + "misp.attribute.sharing_group_id": "0", + "misp.attribute.timestamp": "1456266422", + "misp.attribute.to_ids": true, + "misp.attribute.type": "email-src", + "misp.attribute.uuid": "56ccdcb6-4d6c-4e48-b955-52849062e56a", + "misp.attribute_count": 133, + "misp.date": "2015-12-08", + "misp.disable_correlation": false, + "misp.distribution": "3", + "misp.extends_uuid": "", + "misp.id": "22", + "misp.info": "Packrat: Seven Years of a South American Threat Actor", + "misp.locked": false, + "misp.org_id": "1", + "misp.orgc.id": "4", + "misp.orgc.local": false, + "misp.orgc.name": "CUDESO", + "misp.orgc.uuid": "56c42374-fdb8-4544-a218-41ffc0a8ab16", + "misp.orgc_id": "4", + "misp.proposal_email_lock": false, + "misp.publish_timestamp": "1610637901", + "misp.published": true, + "misp.sharing_group_id": "0", + "misp.threat_level_id": 3, + "misp.uuid": "56ccdcaf-f7e4-40d8-bca1-51299062e56a", "service.type": "threatintel", "tags": [ "tlp:white" ], - "threatintel.indicator.email.address": "claudiobonadio88@gmail.com", - "threatintel.indicator.marking.tlp": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] MISP", + "threat.indicator.email.address": "claudiobonadio88@gmail.com", + "threat.indicator.marking.tlp": [ "white" ], - "threatintel.indicator.provider": "misp", - "threatintel.indicator.scanner_stats": 2, - "threatintel.indicator.type": "email-addr", - "threatintel.misp.attribute.category": "Payload delivery", - "threatintel.misp.attribute.comment": "", - "threatintel.misp.attribute.deleted": false, - "threatintel.misp.attribute.disable_correlation": false, - "threatintel.misp.attribute.distribution": "5", - "threatintel.misp.attribute.event_id": "22", - "threatintel.misp.attribute.id": "12268", - "threatintel.misp.attribute.object_id": "0", - "threatintel.misp.attribute.sharing_group_id": "0", - "threatintel.misp.attribute.timestamp": "1456266422", - "threatintel.misp.attribute.to_ids": true, - "threatintel.misp.attribute.type": "email-src", - "threatintel.misp.attribute.uuid": "56ccdcb6-4d6c-4e48-b955-52849062e56a", - "threatintel.misp.attribute_count": "133", - "threatintel.misp.date": "2015-12-08", - "threatintel.misp.disable_correlation": false, - "threatintel.misp.distribution": "3", - "threatintel.misp.extends_uuid": "", - "threatintel.misp.id": "22", - "threatintel.misp.info": "Packrat: Seven Years of a South American Threat Actor", - "threatintel.misp.locked": false, - "threatintel.misp.org_id": "1", - "threatintel.misp.orgc.id": "4", - "threatintel.misp.orgc.local": false, - "threatintel.misp.orgc.name": "CUDESO", - "threatintel.misp.orgc.uuid": "56c42374-fdb8-4544-a218-41ffc0a8ab16", - "threatintel.misp.orgc_id": "4", - "threatintel.misp.proposal_email_lock": false, - "threatintel.misp.publish_timestamp": "1610637901", - "threatintel.misp.published": true, - "threatintel.misp.sharing_group_id": "0", - "threatintel.misp.threat_level_id": 3, - "threatintel.misp.uuid": "56ccdcaf-f7e4-40d8-bca1-51299062e56a" + "threat.indicator.provider": "misp", + "threat.indicator.scanner_stats": 2, + "threat.indicator.type": "email-addr" }, { "@timestamp": "2018-01-23T16:09:56.000Z", @@ -755,50 +781,52 @@ "fileset.name": "misp", "input.type": "log", "log.offset": 37011, + "misp.attribute.category": "Artifacts dropped", + "misp.attribute.comment": "", + "misp.attribute.deleted": false, + "misp.attribute.disable_correlation": false, + "misp.attribute.distribution": 5, + "misp.attribute.event_id": "22", + "misp.attribute.id": "12298", + "misp.attribute.object_id": "0", + "misp.attribute.sharing_group_id": "0", + "misp.attribute.timestamp": "1456266454", + "misp.attribute.to_ids": true, + "misp.attribute.type": "regkey", + "misp.attribute.uuid": "56ccdcd6-f4b8-4383-9624-52849062e56a", + "misp.attribute_count": 133, + "misp.date": "2015-12-08", + "misp.disable_correlation": false, + "misp.distribution": "3", + "misp.extends_uuid": "", + "misp.id": "22", + "misp.info": "Packrat: Seven Years of a South American Threat Actor", + "misp.locked": false, + "misp.org_id": "1", + "misp.orgc.id": "4", + "misp.orgc.local": false, + "misp.orgc.name": "CUDESO", + "misp.orgc.uuid": "56c42374-fdb8-4544-a218-41ffc0a8ab16", + "misp.orgc_id": "4", + "misp.proposal_email_lock": false, + "misp.publish_timestamp": "1610637901", + "misp.published": true, + "misp.sharing_group_id": "0", + "misp.threat_level_id": 3, + "misp.uuid": "56ccdcaf-f7e4-40d8-bca1-51299062e56a", "service.type": "threatintel", "tags": [ "tlp:white" ], - "threatintel.indicator.marking.tlp": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] MISP", + "threat.indicator.marking.tlp": [ "white" ], - "threatintel.indicator.provider": "misp", - "threatintel.indicator.registry.key": "HKLM\\SOFTWARE\\Microsoft\\Active", - "threatintel.indicator.scanner_stats": 2, - "threatintel.indicator.type": "windows-registry-key", - "threatintel.misp.attribute.category": "Artifacts dropped", - "threatintel.misp.attribute.comment": "", - "threatintel.misp.attribute.deleted": false, - "threatintel.misp.attribute.disable_correlation": false, - "threatintel.misp.attribute.distribution": "5", - "threatintel.misp.attribute.event_id": "22", - "threatintel.misp.attribute.id": "12298", - "threatintel.misp.attribute.object_id": "0", - "threatintel.misp.attribute.sharing_group_id": "0", - "threatintel.misp.attribute.timestamp": "1456266454", - "threatintel.misp.attribute.to_ids": true, - "threatintel.misp.attribute.type": "regkey", - "threatintel.misp.attribute.uuid": "56ccdcd6-f4b8-4383-9624-52849062e56a", - "threatintel.misp.attribute_count": "133", - "threatintel.misp.date": "2015-12-08", - "threatintel.misp.disable_correlation": false, - "threatintel.misp.distribution": "3", - "threatintel.misp.extends_uuid": "", - "threatintel.misp.id": "22", - "threatintel.misp.info": "Packrat: Seven Years of a South American Threat Actor", - "threatintel.misp.locked": false, - "threatintel.misp.org_id": "1", - "threatintel.misp.orgc.id": "4", - "threatintel.misp.orgc.local": false, - "threatintel.misp.orgc.name": "CUDESO", - "threatintel.misp.orgc.uuid": "56c42374-fdb8-4544-a218-41ffc0a8ab16", - "threatintel.misp.orgc_id": "4", - "threatintel.misp.proposal_email_lock": false, - "threatintel.misp.publish_timestamp": "1610637901", - "threatintel.misp.published": true, - "threatintel.misp.sharing_group_id": "0", - "threatintel.misp.threat_level_id": 3, - "threatintel.misp.uuid": "56ccdcaf-f7e4-40d8-bca1-51299062e56a" + "threat.indicator.provider": "misp", + "threat.indicator.registry.key": "HKLM\\SOFTWARE\\Microsoft\\Active", + "threat.indicator.scanner_stats": 2, + "threat.indicator.type": "windows-registry-key" }, { "@timestamp": "2020-12-13T14:03:16.000Z", @@ -810,51 +838,53 @@ "fileset.name": "misp", "input.type": "log", "log.offset": 38330, + "misp.attribute.category": "Network activity", + "misp.attribute.comment": "On port 2222", + "misp.attribute.deleted": false, + "misp.attribute.disable_correlation": false, + "misp.attribute.distribution": 5, + "misp.attribute.event_id": "10", + "misp.attribute.id": "10686", + "misp.attribute.object_id": "0", + "misp.attribute.sharing_group_id": "0", + "misp.attribute.timestamp": "1607517728", + "misp.attribute.to_ids": true, + "misp.attribute.type": "ip-dst|port", + "misp.attribute.uuid": "5fd0c620-a844-4ace-9710-a37bc0a8ab16", + "misp.attribute_count": 15, + "misp.date": "2020-12-09", + "misp.disable_correlation": false, + "misp.distribution": "3", + "misp.extends_uuid": "", + "misp.id": "10", + "misp.info": "Recent Qakbot (Qbot) activity", + "misp.locked": false, + "misp.org_id": "1", + "misp.orgc.id": "4", + "misp.orgc.local": false, + "misp.orgc.name": "CUDESO", + "misp.orgc.uuid": "56c42374-fdb8-4544-a218-41ffc0a8ab16", + "misp.orgc_id": "4", + "misp.proposal_email_lock": false, + "misp.publish_timestamp": "1610637888", + "misp.published": true, + "misp.sharing_group_id": "0", + "misp.threat_level_id": 3, + "misp.uuid": "5fd0c599-ab6c-4ba1-a69a-df9ec0a8ab16", "service.type": "threatintel", "tags": [ "misp-galaxy:banker=Qakbot", "tlp:white" ], - "threatintel.indicator.ip": "62.38.114.12", - "threatintel.indicator.marking.tlp": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] MISP", + "threat.indicator.ip": "62.38.114.12", + "threat.indicator.marking.tlp": [ "white" ], - "threatintel.indicator.port": "2222", - "threatintel.indicator.provider": "misp", - "threatintel.indicator.scanner_stats": 2, - "threatintel.indicator.type": "ipv4-addr", - "threatintel.misp.attribute.category": "Network activity", - "threatintel.misp.attribute.comment": "On port 2222", - "threatintel.misp.attribute.deleted": false, - "threatintel.misp.attribute.disable_correlation": false, - "threatintel.misp.attribute.distribution": "5", - "threatintel.misp.attribute.event_id": "10", - "threatintel.misp.attribute.id": "10686", - "threatintel.misp.attribute.object_id": "0", - "threatintel.misp.attribute.sharing_group_id": "0", - "threatintel.misp.attribute.timestamp": "1607517728", - "threatintel.misp.attribute.to_ids": true, - "threatintel.misp.attribute.type": "ip-dst|port", - "threatintel.misp.attribute.uuid": "5fd0c620-a844-4ace-9710-a37bc0a8ab16", - "threatintel.misp.attribute_count": "15", - "threatintel.misp.date": "2020-12-09", - "threatintel.misp.disable_correlation": false, - "threatintel.misp.distribution": "3", - "threatintel.misp.extends_uuid": "", - "threatintel.misp.id": "10", - "threatintel.misp.info": "Recent Qakbot (Qbot) activity", - "threatintel.misp.locked": false, - "threatintel.misp.org_id": "1", - "threatintel.misp.orgc.id": "4", - "threatintel.misp.orgc.local": false, - "threatintel.misp.orgc.name": "CUDESO", - "threatintel.misp.orgc.uuid": "56c42374-fdb8-4544-a218-41ffc0a8ab16", - "threatintel.misp.orgc_id": "4", - "threatintel.misp.proposal_email_lock": false, - "threatintel.misp.publish_timestamp": "1610637888", - "threatintel.misp.published": true, - "threatintel.misp.sharing_group_id": "0", - "threatintel.misp.threat_level_id": 3, - "threatintel.misp.uuid": "5fd0c599-ab6c-4ba1-a69a-df9ec0a8ab16" + "threat.indicator.port": 2222, + "threat.indicator.provider": "misp", + "threat.indicator.scanner_stats": 2, + "threat.indicator.type": "ipv4-addr" } ] \ No newline at end of file diff --git a/x-pack/filebeat/module/threatintel/misp/test/misp_sample_with_ext_attributes.ndjson.log-expected.json b/x-pack/filebeat/module/threatintel/misp/test/misp_sample_with_ext_attributes.ndjson.log-expected.json index 6db06ab777c..ae03f9bce95 100644 --- a/x-pack/filebeat/module/threatintel/misp/test/misp_sample_with_ext_attributes.ndjson.log-expected.json +++ b/x-pack/filebeat/module/threatintel/misp/test/misp_sample_with_ext_attributes.ndjson.log-expected.json @@ -9,48 +9,50 @@ "fileset.name": "misp", "input.type": "log", "log.offset": 0, + "misp.attribute.category": "Payload installation", + "misp.attribute.comment": "Contextual comment for the file md5 attribute", + "misp.attribute.deleted": false, + "misp.attribute.disable_correlation": false, + "misp.attribute.distribution": 5, + "misp.attribute.event_id": "3631", + "misp.attribute.id": "266258", + "misp.attribute.object_id": "0", + "misp.attribute.sharing_group_id": "0", + "misp.attribute.timestamp": "1621588162", + "misp.attribute.to_ids": false, + "misp.attribute.type": "md5", + "misp.attribute.uuid": "34c59b06-d35d-4808-919c-4b452f185c52", + "misp.attribute_count": 1, + "misp.date": "2021-05-21", + "misp.disable_correlation": false, + "misp.distribution": "1", + "misp.extends_uuid": "", + "misp.id": "3631", + "misp.info": "Test event 1 just atrributes", + "misp.locked": false, + "misp.org_id": "1", + "misp.orgc.id": "1", + "misp.orgc.local": true, + "misp.orgc.name": "ORGNAME", + "misp.orgc.uuid": "78acad2d-cc2d-4785-94d6-b428a0070488", + "misp.orgc_id": "1", + "misp.proposal_email_lock": false, + "misp.publish_timestamp": "0", + "misp.published": false, + "misp.sharing_group_id": "0", + "misp.threat_level_id": 1, + "misp.uuid": "8ca56ae9-3747-4172-93d2-808da1a4eaf3", "service.type": "threatintel", "tags": [ "forwarded", "threatintel-misp" ], - "threatintel.indicator.file.hash.md5": "70461da8b94c6ca5d2fda3260c5a8c3b", - "threatintel.indicator.provider": "misp", - "threatintel.indicator.scanner_stats": 0, - "threatintel.indicator.type": "file", - "threatintel.misp.attribute.category": "Payload installation", - "threatintel.misp.attribute.comment": "Contextual comment for the file md5 attribute", - "threatintel.misp.attribute.deleted": false, - "threatintel.misp.attribute.disable_correlation": false, - "threatintel.misp.attribute.distribution": "5", - "threatintel.misp.attribute.event_id": "3631", - "threatintel.misp.attribute.id": "266258", - "threatintel.misp.attribute.object_id": "0", - "threatintel.misp.attribute.sharing_group_id": "0", - "threatintel.misp.attribute.timestamp": "1621588162", - "threatintel.misp.attribute.to_ids": false, - "threatintel.misp.attribute.type": "md5", - "threatintel.misp.attribute.uuid": "34c59b06-d35d-4808-919c-4b452f185c52", - "threatintel.misp.attribute_count": "1", - "threatintel.misp.date": "2021-05-21", - "threatintel.misp.disable_correlation": false, - "threatintel.misp.distribution": "1", - "threatintel.misp.extends_uuid": "", - "threatintel.misp.id": "3631", - "threatintel.misp.info": "Test event 1 just atrributes", - "threatintel.misp.locked": false, - "threatintel.misp.org_id": "1", - "threatintel.misp.orgc.id": "1", - "threatintel.misp.orgc.local": true, - "threatintel.misp.orgc.name": "ORGNAME", - "threatintel.misp.orgc.uuid": "78acad2d-cc2d-4785-94d6-b428a0070488", - "threatintel.misp.orgc_id": "1", - "threatintel.misp.proposal_email_lock": false, - "threatintel.misp.publish_timestamp": "0", - "threatintel.misp.published": false, - "threatintel.misp.sharing_group_id": "0", - "threatintel.misp.threat_level_id": 1, - "threatintel.misp.uuid": "8ca56ae9-3747-4172-93d2-808da1a4eaf3", + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] MISP", + "threat.indicator.file.hash.md5": "70461da8b94c6ca5d2fda3260c5a8c3b", + "threat.indicator.provider": "misp", + "threat.indicator.scanner_stats": 0, + "threat.indicator.type": "file", "user.email": "admin@admin.test", "user.roles": [ "reporting_user" @@ -66,48 +68,50 @@ "fileset.name": "misp", "input.type": "log", "log.offset": 1614, + "misp.attribute.category": "Artifacts dropped", + "misp.attribute.comment": "Artefact dropped for test 2", + "misp.attribute.deleted": false, + "misp.attribute.disable_correlation": false, + "misp.attribute.distribution": 5, + "misp.attribute.event_id": "3632", + "misp.attribute.id": "266259", + "misp.attribute.object_id": "0", + "misp.attribute.sharing_group_id": "0", + "misp.attribute.timestamp": "1621588675", + "misp.attribute.to_ids": true, + "misp.attribute.type": "md5", + "misp.attribute.uuid": "73102a1c-7432-47b7-9644-6f9d46b6887c", + "misp.attribute_count": 4, + "misp.date": "2021-05-21", + "misp.disable_correlation": false, + "misp.distribution": "1", + "misp.extends_uuid": "", + "misp.id": "3632", + "misp.info": "Test event 2 just more atrributes", + "misp.locked": false, + "misp.org_id": "1", + "misp.orgc.id": "1", + "misp.orgc.local": true, + "misp.orgc.name": "ORGNAME", + "misp.orgc.uuid": "78acad2d-cc2d-4785-94d6-b428a0070488", + "misp.orgc_id": "1", + "misp.proposal_email_lock": false, + "misp.publish_timestamp": "0", + "misp.published": false, + "misp.sharing_group_id": "0", + "misp.threat_level_id": 2, + "misp.uuid": "efbca287-edb5-4ad7-b8e4-fe9da514a763", "service.type": "threatintel", "tags": [ "forwarded", "threatintel-misp" ], - "threatintel.indicator.file.hash.md5": "60461da8b94c6ca5d2fda3260c5a8c3b", - "threatintel.indicator.provider": "misp", - "threatintel.indicator.scanner_stats": 0, - "threatintel.indicator.type": "file", - "threatintel.misp.attribute.category": "Artifacts dropped", - "threatintel.misp.attribute.comment": "Artefact dropped for test 2", - "threatintel.misp.attribute.deleted": false, - "threatintel.misp.attribute.disable_correlation": false, - "threatintel.misp.attribute.distribution": "5", - "threatintel.misp.attribute.event_id": "3632", - "threatintel.misp.attribute.id": "266259", - "threatintel.misp.attribute.object_id": "0", - "threatintel.misp.attribute.sharing_group_id": "0", - "threatintel.misp.attribute.timestamp": "1621588675", - "threatintel.misp.attribute.to_ids": true, - "threatintel.misp.attribute.type": "md5", - "threatintel.misp.attribute.uuid": "73102a1c-7432-47b7-9644-6f9d46b6887c", - "threatintel.misp.attribute_count": "4", - "threatintel.misp.date": "2021-05-21", - "threatintel.misp.disable_correlation": false, - "threatintel.misp.distribution": "1", - "threatintel.misp.extends_uuid": "", - "threatintel.misp.id": "3632", - "threatintel.misp.info": "Test event 2 just more atrributes", - "threatintel.misp.locked": false, - "threatintel.misp.org_id": "1", - "threatintel.misp.orgc.id": "1", - "threatintel.misp.orgc.local": true, - "threatintel.misp.orgc.name": "ORGNAME", - "threatintel.misp.orgc.uuid": "78acad2d-cc2d-4785-94d6-b428a0070488", - "threatintel.misp.orgc_id": "1", - "threatintel.misp.proposal_email_lock": false, - "threatintel.misp.publish_timestamp": "0", - "threatintel.misp.published": false, - "threatintel.misp.sharing_group_id": "0", - "threatintel.misp.threat_level_id": 2, - "threatintel.misp.uuid": "efbca287-edb5-4ad7-b8e4-fe9da514a763", + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] MISP", + "threat.indicator.file.hash.md5": "60461da8b94c6ca5d2fda3260c5a8c3b", + "threat.indicator.provider": "misp", + "threat.indicator.scanner_stats": 0, + "threat.indicator.type": "file", "user.email": "admin@admin.test", "user.roles": [ "reporting_user" @@ -123,48 +127,50 @@ "fileset.name": "misp", "input.type": "log", "log.offset": 3241, + "misp.attribute.category": "Network activity", + "misp.attribute.comment": "Conext for domain type attribute event 2", + "misp.attribute.deleted": false, + "misp.attribute.disable_correlation": false, + "misp.attribute.distribution": 5, + "misp.attribute.event_id": "3632", + "misp.attribute.id": "266260", + "misp.attribute.object_id": "0", + "misp.attribute.sharing_group_id": "0", + "misp.attribute.timestamp": "1621588744", + "misp.attribute.to_ids": true, + "misp.attribute.type": "domain", + "misp.attribute.uuid": "a52a1b47-a580-4f33-96ba-939cf9146c9b", + "misp.attribute_count": 4, + "misp.date": "2021-05-21", + "misp.disable_correlation": false, + "misp.distribution": "1", + "misp.extends_uuid": "", + "misp.id": "3632", + "misp.info": "Test event 2 just more atrributes", + "misp.locked": false, + "misp.org_id": "1", + "misp.orgc.id": "1", + "misp.orgc.local": true, + "misp.orgc.name": "ORGNAME", + "misp.orgc.uuid": "78acad2d-cc2d-4785-94d6-b428a0070488", + "misp.orgc_id": "1", + "misp.proposal_email_lock": false, + "misp.publish_timestamp": "0", + "misp.published": false, + "misp.sharing_group_id": "0", + "misp.threat_level_id": 2, + "misp.uuid": "efbca287-edb5-4ad7-b8e4-fe9da514a763", "service.type": "threatintel", "tags": [ "forwarded", "threatintel-misp" ], - "threatintel.indicator.provider": "misp", - "threatintel.indicator.scanner_stats": 0, - "threatintel.indicator.type": "domain-name", - "threatintel.indicator.url.domain": "baddom.madeup.local", - "threatintel.misp.attribute.category": "Network activity", - "threatintel.misp.attribute.comment": "Conext for domain type attribute event 2", - "threatintel.misp.attribute.deleted": false, - "threatintel.misp.attribute.disable_correlation": false, - "threatintel.misp.attribute.distribution": "5", - "threatintel.misp.attribute.event_id": "3632", - "threatintel.misp.attribute.id": "266260", - "threatintel.misp.attribute.object_id": "0", - "threatintel.misp.attribute.sharing_group_id": "0", - "threatintel.misp.attribute.timestamp": "1621588744", - "threatintel.misp.attribute.to_ids": true, - "threatintel.misp.attribute.type": "domain", - "threatintel.misp.attribute.uuid": "a52a1b47-a580-4f33-96ba-939cf9146c9b", - "threatintel.misp.attribute_count": "4", - "threatintel.misp.date": "2021-05-21", - "threatintel.misp.disable_correlation": false, - "threatintel.misp.distribution": "1", - "threatintel.misp.extends_uuid": "", - "threatintel.misp.id": "3632", - "threatintel.misp.info": "Test event 2 just more atrributes", - "threatintel.misp.locked": false, - "threatintel.misp.org_id": "1", - "threatintel.misp.orgc.id": "1", - "threatintel.misp.orgc.local": true, - "threatintel.misp.orgc.name": "ORGNAME", - "threatintel.misp.orgc.uuid": "78acad2d-cc2d-4785-94d6-b428a0070488", - "threatintel.misp.orgc_id": "1", - "threatintel.misp.proposal_email_lock": false, - "threatintel.misp.publish_timestamp": "0", - "threatintel.misp.published": false, - "threatintel.misp.sharing_group_id": "0", - "threatintel.misp.threat_level_id": 2, - "threatintel.misp.uuid": "efbca287-edb5-4ad7-b8e4-fe9da514a763", + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] MISP", + "threat.indicator.provider": "misp", + "threat.indicator.scanner_stats": 0, + "threat.indicator.type": "domain-name", + "threat.indicator.url.domain": "baddom.madeup.local", "user.email": "admin@admin.test", "user.roles": [ "reporting_user" @@ -180,48 +186,50 @@ "fileset.name": "misp", "input.type": "log", "log.offset": 4870, + "misp.attribute.category": "Network activity", + "misp.attribute.comment": "Ip-src attribute context for event2", + "misp.attribute.deleted": false, + "misp.attribute.disable_correlation": false, + "misp.attribute.distribution": 5, + "misp.attribute.event_id": "3632", + "misp.attribute.id": "266261", + "misp.attribute.object_id": "0", + "misp.attribute.sharing_group_id": "0", + "misp.attribute.timestamp": "1621588800", + "misp.attribute.to_ids": false, + "misp.attribute.type": "ip-src", + "misp.attribute.uuid": "3dbf224b-7c84-4c4b-9f95-80f28954bd10", + "misp.attribute_count": 4, + "misp.date": "2021-05-21", + "misp.disable_correlation": false, + "misp.distribution": "1", + "misp.extends_uuid": "", + "misp.id": "3632", + "misp.info": "Test event 2 just more atrributes", + "misp.locked": false, + "misp.org_id": "1", + "misp.orgc.id": "1", + "misp.orgc.local": true, + "misp.orgc.name": "ORGNAME", + "misp.orgc.uuid": "78acad2d-cc2d-4785-94d6-b428a0070488", + "misp.orgc_id": "1", + "misp.proposal_email_lock": false, + "misp.publish_timestamp": "0", + "misp.published": false, + "misp.sharing_group_id": "0", + "misp.threat_level_id": 2, + "misp.uuid": "efbca287-edb5-4ad7-b8e4-fe9da514a763", "service.type": "threatintel", "tags": [ "forwarded", "threatintel-misp" ], - "threatintel.indicator.ip": "10.0.0.1", - "threatintel.indicator.provider": "misp", - "threatintel.indicator.scanner_stats": 0, - "threatintel.indicator.type": "ipv4-addr", - "threatintel.misp.attribute.category": "Network activity", - "threatintel.misp.attribute.comment": "Ip-src attribute context for event2", - "threatintel.misp.attribute.deleted": false, - "threatintel.misp.attribute.disable_correlation": false, - "threatintel.misp.attribute.distribution": "5", - "threatintel.misp.attribute.event_id": "3632", - "threatintel.misp.attribute.id": "266261", - "threatintel.misp.attribute.object_id": "0", - "threatintel.misp.attribute.sharing_group_id": "0", - "threatintel.misp.attribute.timestamp": "1621588800", - "threatintel.misp.attribute.to_ids": false, - "threatintel.misp.attribute.type": "ip-src", - "threatintel.misp.attribute.uuid": "3dbf224b-7c84-4c4b-9f95-80f28954bd10", - "threatintel.misp.attribute_count": "4", - "threatintel.misp.date": "2021-05-21", - "threatintel.misp.disable_correlation": false, - "threatintel.misp.distribution": "1", - "threatintel.misp.extends_uuid": "", - "threatintel.misp.id": "3632", - "threatintel.misp.info": "Test event 2 just more atrributes", - "threatintel.misp.locked": false, - "threatintel.misp.org_id": "1", - "threatintel.misp.orgc.id": "1", - "threatintel.misp.orgc.local": true, - "threatintel.misp.orgc.name": "ORGNAME", - "threatintel.misp.orgc.uuid": "78acad2d-cc2d-4785-94d6-b428a0070488", - "threatintel.misp.orgc_id": "1", - "threatintel.misp.proposal_email_lock": false, - "threatintel.misp.publish_timestamp": "0", - "threatintel.misp.published": false, - "threatintel.misp.sharing_group_id": "0", - "threatintel.misp.threat_level_id": 2, - "threatintel.misp.uuid": "efbca287-edb5-4ad7-b8e4-fe9da514a763", + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] MISP", + "threat.indicator.ip": "10.0.0.1", + "threat.indicator.provider": "misp", + "threat.indicator.scanner_stats": 0, + "threat.indicator.type": "ipv4-addr", "user.email": "admin@admin.test", "user.roles": [ "reporting_user" @@ -237,48 +245,50 @@ "fileset.name": "misp", "input.type": "log", "log.offset": 6484, + "misp.attribute.category": "Network activity", + "misp.attribute.comment": "ip-dst context for event id 2", + "misp.attribute.deleted": false, + "misp.attribute.disable_correlation": false, + "misp.attribute.distribution": 5, + "misp.attribute.event_id": "3632", + "misp.attribute.id": "266262", + "misp.attribute.object_id": "0", + "misp.attribute.sharing_group_id": "0", + "misp.attribute.timestamp": "1621588836", + "misp.attribute.to_ids": true, + "misp.attribute.type": "ip-dst", + "misp.attribute.uuid": "db4bfd36-7374-4f8c-9031-60e56d4bba30", + "misp.attribute_count": 4, + "misp.date": "2021-05-21", + "misp.disable_correlation": false, + "misp.distribution": "1", + "misp.extends_uuid": "", + "misp.id": "3632", + "misp.info": "Test event 2 just more atrributes", + "misp.locked": false, + "misp.org_id": "1", + "misp.orgc.id": "1", + "misp.orgc.local": true, + "misp.orgc.name": "ORGNAME", + "misp.orgc.uuid": "78acad2d-cc2d-4785-94d6-b428a0070488", + "misp.orgc_id": "1", + "misp.proposal_email_lock": false, + "misp.publish_timestamp": "0", + "misp.published": false, + "misp.sharing_group_id": "0", + "misp.threat_level_id": 2, + "misp.uuid": "efbca287-edb5-4ad7-b8e4-fe9da514a763", "service.type": "threatintel", "tags": [ "forwarded", "threatintel-misp" ], - "threatintel.indicator.ip": "192.168.1.50", - "threatintel.indicator.provider": "misp", - "threatintel.indicator.scanner_stats": 0, - "threatintel.indicator.type": "ipv4-addr", - "threatintel.misp.attribute.category": "Network activity", - "threatintel.misp.attribute.comment": "ip-dst context for event id 2", - "threatintel.misp.attribute.deleted": false, - "threatintel.misp.attribute.disable_correlation": false, - "threatintel.misp.attribute.distribution": "5", - "threatintel.misp.attribute.event_id": "3632", - "threatintel.misp.attribute.id": "266262", - "threatintel.misp.attribute.object_id": "0", - "threatintel.misp.attribute.sharing_group_id": "0", - "threatintel.misp.attribute.timestamp": "1621588836", - "threatintel.misp.attribute.to_ids": true, - "threatintel.misp.attribute.type": "ip-dst", - "threatintel.misp.attribute.uuid": "db4bfd36-7374-4f8c-9031-60e56d4bba30", - "threatintel.misp.attribute_count": "4", - "threatintel.misp.date": "2021-05-21", - "threatintel.misp.disable_correlation": false, - "threatintel.misp.distribution": "1", - "threatintel.misp.extends_uuid": "", - "threatintel.misp.id": "3632", - "threatintel.misp.info": "Test event 2 just more atrributes", - "threatintel.misp.locked": false, - "threatintel.misp.org_id": "1", - "threatintel.misp.orgc.id": "1", - "threatintel.misp.orgc.local": true, - "threatintel.misp.orgc.name": "ORGNAME", - "threatintel.misp.orgc.uuid": "78acad2d-cc2d-4785-94d6-b428a0070488", - "threatintel.misp.orgc_id": "1", - "threatintel.misp.proposal_email_lock": false, - "threatintel.misp.publish_timestamp": "0", - "threatintel.misp.published": false, - "threatintel.misp.sharing_group_id": "0", - "threatintel.misp.threat_level_id": 2, - "threatintel.misp.uuid": "efbca287-edb5-4ad7-b8e4-fe9da514a763", + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] MISP", + "threat.indicator.ip": "192.168.1.50", + "threat.indicator.provider": "misp", + "threat.indicator.scanner_stats": 0, + "threat.indicator.type": "ipv4-addr", "user.email": "admin@admin.test", "user.roles": [ "reporting_user" @@ -294,63 +304,65 @@ "fileset.name": "misp", "input.type": "log", "log.offset": 8095, + "misp.attribute.category": "Other", + "misp.attribute.comment": "", + "misp.attribute.deleted": false, + "misp.attribute.disable_correlation": false, + "misp.attribute.distribution": 5, + "misp.attribute.event_id": "3633", + "misp.attribute.id": "266267", + "misp.attribute.object_id": "18207", + "misp.attribute.object_relation": "fullpath", + "misp.attribute.sharing_group_id": "0", + "misp.attribute.timestamp": "1621589548", + "misp.attribute.to_ids": false, + "misp.attribute.type": "text", + "misp.attribute.uuid": "ff97cc32-815e-4fc9-9d4b-cab9822027a6", + "misp.attribute.value": "\\the\\fullpath\\to the file\\filenameofobject.txt", + "misp.attribute_count": 6, + "misp.context.attribute.category": "Payload delivery", + "misp.context.attribute.comment": "filename contect for test event 3", + "misp.context.attribute.deleted": false, + "misp.context.attribute.disable_correlation": false, + "misp.context.attribute.distribution": 5, + "misp.context.attribute.event_id": "3633", + "misp.context.attribute.id": "266263", + "misp.context.attribute.object_id": "0", + "misp.context.attribute.sharing_group_id": "0", + "misp.context.attribute.timestamp": "1621589229", + "misp.context.attribute.to_ids": false, + "misp.context.attribute.type": "filename", + "misp.context.attribute.uuid": "3b322e1a-1dd8-490c-ab96-12e1bc3ee6a3", + "misp.context.attribute.value": "thetestfile.txt", + "misp.date": "2021-05-21", + "misp.disable_correlation": false, + "misp.distribution": "1", + "misp.extends_uuid": "", + "misp.id": "3633", + "misp.info": "Test event 3 objects and attributes", + "misp.locked": false, + "misp.org_id": "1", + "misp.orgc.id": "1", + "misp.orgc.local": true, + "misp.orgc.name": "ORGNAME", + "misp.orgc.uuid": "78acad2d-cc2d-4785-94d6-b428a0070488", + "misp.orgc_id": "1", + "misp.proposal_email_lock": false, + "misp.publish_timestamp": "0", + "misp.published": false, + "misp.sharing_group_id": "0", + "misp.threat_level_id": 1, + "misp.uuid": "4edb20c7-8175-484d-bdcd-fce6872c1ef3", "service.type": "threatintel", "tags": [ "forwarded", "threatintel-misp" ], - "threatintel.indicator.provider": "misp", - "threatintel.indicator.scanner_stats": 0, - "threatintel.indicator.type": "unknown", - "threatintel.misp.attribute.category": "Other", - "threatintel.misp.attribute.comment": "", - "threatintel.misp.attribute.deleted": false, - "threatintel.misp.attribute.disable_correlation": false, - "threatintel.misp.attribute.distribution": "5", - "threatintel.misp.attribute.event_id": "3633", - "threatintel.misp.attribute.id": "266267", - "threatintel.misp.attribute.object_id": "18207", - "threatintel.misp.attribute.object_relation": "fullpath", - "threatintel.misp.attribute.sharing_group_id": "0", - "threatintel.misp.attribute.timestamp": "1621589548", - "threatintel.misp.attribute.to_ids": false, - "threatintel.misp.attribute.type": "text", - "threatintel.misp.attribute.uuid": "ff97cc32-815e-4fc9-9d4b-cab9822027a6", - "threatintel.misp.attribute.value": "\\the\\fullpath\\to the file\\filenameofobject.txt", - "threatintel.misp.attribute_count": "6", - "threatintel.misp.context.attribute.category": "Payload delivery", - "threatintel.misp.context.attribute.comment": "filename contect for test event 3", - "threatintel.misp.context.attribute.deleted": false, - "threatintel.misp.context.attribute.disable_correlation": false, - "threatintel.misp.context.attribute.distribution": "5", - "threatintel.misp.context.attribute.event_id": "3633", - "threatintel.misp.context.attribute.id": "266263", - "threatintel.misp.context.attribute.object_id": "0", - "threatintel.misp.context.attribute.sharing_group_id": "0", - "threatintel.misp.context.attribute.timestamp": "1621589229", - "threatintel.misp.context.attribute.to_ids": false, - "threatintel.misp.context.attribute.type": "filename", - "threatintel.misp.context.attribute.uuid": "3b322e1a-1dd8-490c-ab96-12e1bc3ee6a3", - "threatintel.misp.context.attribute.value": "thetestfile.txt", - "threatintel.misp.date": "2021-05-21", - "threatintel.misp.disable_correlation": false, - "threatintel.misp.distribution": "1", - "threatintel.misp.extends_uuid": "", - "threatintel.misp.id": "3633", - "threatintel.misp.info": "Test event 3 objects and attributes", - "threatintel.misp.locked": false, - "threatintel.misp.org_id": "1", - "threatintel.misp.orgc.id": "1", - "threatintel.misp.orgc.local": true, - "threatintel.misp.orgc.name": "ORGNAME", - "threatintel.misp.orgc.uuid": "78acad2d-cc2d-4785-94d6-b428a0070488", - "threatintel.misp.orgc_id": "1", - "threatintel.misp.proposal_email_lock": false, - "threatintel.misp.publish_timestamp": "0", - "threatintel.misp.published": false, - "threatintel.misp.sharing_group_id": "0", - "threatintel.misp.threat_level_id": 1, - "threatintel.misp.uuid": "4edb20c7-8175-484d-bdcd-fce6872c1ef3", + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] MISP", + "threat.indicator.provider": "misp", + "threat.indicator.scanner_stats": 0, + "threat.indicator.type": "unknown", "user.email": "admin@admin.test", "user.roles": [ "reporting_user" @@ -366,63 +378,65 @@ "fileset.name": "misp", "input.type": "log", "log.offset": 10558, + "misp.attribute.category": "Other", + "misp.attribute.comment": "", + "misp.attribute.deleted": false, + "misp.attribute.disable_correlation": true, + "misp.attribute.distribution": 5, + "misp.attribute.event_id": "3633", + "misp.attribute.id": "266268", + "misp.attribute.object_id": "18207", + "misp.attribute.object_relation": "size-in-bytes", + "misp.attribute.sharing_group_id": "0", + "misp.attribute.timestamp": "1621589548", + "misp.attribute.to_ids": false, + "misp.attribute.type": "size-in-bytes", + "misp.attribute.uuid": "e378b4d9-43e1-4c64-bd4e-70fce2b4e581", + "misp.attribute.value": "505050", + "misp.attribute_count": 6, + "misp.context.attribute.category": "Payload delivery", + "misp.context.attribute.comment": "filename contect for test event 3", + "misp.context.attribute.deleted": false, + "misp.context.attribute.disable_correlation": false, + "misp.context.attribute.distribution": 5, + "misp.context.attribute.event_id": "3633", + "misp.context.attribute.id": "266263", + "misp.context.attribute.object_id": "0", + "misp.context.attribute.sharing_group_id": "0", + "misp.context.attribute.timestamp": "1621589229", + "misp.context.attribute.to_ids": false, + "misp.context.attribute.type": "filename", + "misp.context.attribute.uuid": "3b322e1a-1dd8-490c-ab96-12e1bc3ee6a3", + "misp.context.attribute.value": "thetestfile.txt", + "misp.date": "2021-05-21", + "misp.disable_correlation": false, + "misp.distribution": "1", + "misp.extends_uuid": "", + "misp.id": "3633", + "misp.info": "Test event 3 objects and attributes", + "misp.locked": false, + "misp.org_id": "1", + "misp.orgc.id": "1", + "misp.orgc.local": true, + "misp.orgc.name": "ORGNAME", + "misp.orgc.uuid": "78acad2d-cc2d-4785-94d6-b428a0070488", + "misp.orgc_id": "1", + "misp.proposal_email_lock": false, + "misp.publish_timestamp": "0", + "misp.published": false, + "misp.sharing_group_id": "0", + "misp.threat_level_id": 1, + "misp.uuid": "4edb20c7-8175-484d-bdcd-fce6872c1ef3", "service.type": "threatintel", "tags": [ "forwarded", "threatintel-misp" ], - "threatintel.indicator.provider": "misp", - "threatintel.indicator.scanner_stats": 0, - "threatintel.indicator.type": "unknown", - "threatintel.misp.attribute.category": "Other", - "threatintel.misp.attribute.comment": "", - "threatintel.misp.attribute.deleted": false, - "threatintel.misp.attribute.disable_correlation": true, - "threatintel.misp.attribute.distribution": "5", - "threatintel.misp.attribute.event_id": "3633", - "threatintel.misp.attribute.id": "266268", - "threatintel.misp.attribute.object_id": "18207", - "threatintel.misp.attribute.object_relation": "size-in-bytes", - "threatintel.misp.attribute.sharing_group_id": "0", - "threatintel.misp.attribute.timestamp": "1621589548", - "threatintel.misp.attribute.to_ids": false, - "threatintel.misp.attribute.type": "size-in-bytes", - "threatintel.misp.attribute.uuid": "e378b4d9-43e1-4c64-bd4e-70fce2b4e581", - "threatintel.misp.attribute.value": "505050", - "threatintel.misp.attribute_count": "6", - "threatintel.misp.context.attribute.category": "Payload delivery", - "threatintel.misp.context.attribute.comment": "filename contect for test event 3", - "threatintel.misp.context.attribute.deleted": false, - "threatintel.misp.context.attribute.disable_correlation": false, - "threatintel.misp.context.attribute.distribution": "5", - "threatintel.misp.context.attribute.event_id": "3633", - "threatintel.misp.context.attribute.id": "266263", - "threatintel.misp.context.attribute.object_id": "0", - "threatintel.misp.context.attribute.sharing_group_id": "0", - "threatintel.misp.context.attribute.timestamp": "1621589229", - "threatintel.misp.context.attribute.to_ids": false, - "threatintel.misp.context.attribute.type": "filename", - "threatintel.misp.context.attribute.uuid": "3b322e1a-1dd8-490c-ab96-12e1bc3ee6a3", - "threatintel.misp.context.attribute.value": "thetestfile.txt", - "threatintel.misp.date": "2021-05-21", - "threatintel.misp.disable_correlation": false, - "threatintel.misp.distribution": "1", - "threatintel.misp.extends_uuid": "", - "threatintel.misp.id": "3633", - "threatintel.misp.info": "Test event 3 objects and attributes", - "threatintel.misp.locked": false, - "threatintel.misp.org_id": "1", - "threatintel.misp.orgc.id": "1", - "threatintel.misp.orgc.local": true, - "threatintel.misp.orgc.name": "ORGNAME", - "threatintel.misp.orgc.uuid": "78acad2d-cc2d-4785-94d6-b428a0070488", - "threatintel.misp.orgc_id": "1", - "threatintel.misp.proposal_email_lock": false, - "threatintel.misp.publish_timestamp": "0", - "threatintel.misp.published": false, - "threatintel.misp.sharing_group_id": "0", - "threatintel.misp.threat_level_id": 1, - "threatintel.misp.uuid": "4edb20c7-8175-484d-bdcd-fce6872c1ef3", + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] MISP", + "threat.indicator.provider": "misp", + "threat.indicator.scanner_stats": 0, + "threat.indicator.type": "unknown", "user.email": "admin@admin.test", "user.roles": [ "reporting_user" @@ -438,63 +452,65 @@ "fileset.name": "misp", "input.type": "log", "log.offset": 12990, + "misp.attribute.category": "Payload delivery", + "misp.attribute.comment": "", + "misp.attribute.deleted": false, + "misp.attribute.disable_correlation": false, + "misp.attribute.distribution": 5, + "misp.attribute.event_id": "3633", + "misp.attribute.id": "266264", + "misp.attribute.object_id": "18207", + "misp.attribute.object_relation": "md5", + "misp.attribute.sharing_group_id": "0", + "misp.attribute.timestamp": "1621589548", + "misp.attribute.to_ids": true, + "misp.attribute.type": "md5", + "misp.attribute.uuid": "787b3822-0bec-4278-b34a-5d649e7bce05", + "misp.attribute_count": 6, + "misp.context.attribute.category": "Payload delivery", + "misp.context.attribute.comment": "filename contect for test event 3", + "misp.context.attribute.deleted": false, + "misp.context.attribute.disable_correlation": false, + "misp.context.attribute.distribution": 5, + "misp.context.attribute.event_id": "3633", + "misp.context.attribute.id": "266263", + "misp.context.attribute.object_id": "0", + "misp.context.attribute.sharing_group_id": "0", + "misp.context.attribute.timestamp": "1621589229", + "misp.context.attribute.to_ids": false, + "misp.context.attribute.type": "filename", + "misp.context.attribute.uuid": "3b322e1a-1dd8-490c-ab96-12e1bc3ee6a3", + "misp.context.attribute.value": "thetestfile.txt", + "misp.date": "2021-05-21", + "misp.disable_correlation": false, + "misp.distribution": "1", + "misp.extends_uuid": "", + "misp.id": "3633", + "misp.info": "Test event 3 objects and attributes", + "misp.locked": false, + "misp.org_id": "1", + "misp.orgc.id": "1", + "misp.orgc.local": true, + "misp.orgc.name": "ORGNAME", + "misp.orgc.uuid": "78acad2d-cc2d-4785-94d6-b428a0070488", + "misp.orgc_id": "1", + "misp.proposal_email_lock": false, + "misp.publish_timestamp": "0", + "misp.published": false, + "misp.sharing_group_id": "0", + "misp.threat_level_id": 1, + "misp.uuid": "4edb20c7-8175-484d-bdcd-fce6872c1ef3", "service.type": "threatintel", "tags": [ "forwarded", "threatintel-misp" ], - "threatintel.indicator.file.hash.md5": "70461da8b94c6ca5d2fda3260c5a8c3b", - "threatintel.indicator.provider": "misp", - "threatintel.indicator.scanner_stats": 0, - "threatintel.indicator.type": "file", - "threatintel.misp.attribute.category": "Payload delivery", - "threatintel.misp.attribute.comment": "", - "threatintel.misp.attribute.deleted": false, - "threatintel.misp.attribute.disable_correlation": false, - "threatintel.misp.attribute.distribution": "5", - "threatintel.misp.attribute.event_id": "3633", - "threatintel.misp.attribute.id": "266264", - "threatintel.misp.attribute.object_id": "18207", - "threatintel.misp.attribute.object_relation": "md5", - "threatintel.misp.attribute.sharing_group_id": "0", - "threatintel.misp.attribute.timestamp": "1621589548", - "threatintel.misp.attribute.to_ids": true, - "threatintel.misp.attribute.type": "md5", - "threatintel.misp.attribute.uuid": "787b3822-0bec-4278-b34a-5d649e7bce05", - "threatintel.misp.attribute_count": "6", - "threatintel.misp.context.attribute.category": "Payload delivery", - "threatintel.misp.context.attribute.comment": "filename contect for test event 3", - "threatintel.misp.context.attribute.deleted": false, - "threatintel.misp.context.attribute.disable_correlation": false, - "threatintel.misp.context.attribute.distribution": "5", - "threatintel.misp.context.attribute.event_id": "3633", - "threatintel.misp.context.attribute.id": "266263", - "threatintel.misp.context.attribute.object_id": "0", - "threatintel.misp.context.attribute.sharing_group_id": "0", - "threatintel.misp.context.attribute.timestamp": "1621589229", - "threatintel.misp.context.attribute.to_ids": false, - "threatintel.misp.context.attribute.type": "filename", - "threatintel.misp.context.attribute.uuid": "3b322e1a-1dd8-490c-ab96-12e1bc3ee6a3", - "threatintel.misp.context.attribute.value": "thetestfile.txt", - "threatintel.misp.date": "2021-05-21", - "threatintel.misp.disable_correlation": false, - "threatintel.misp.distribution": "1", - "threatintel.misp.extends_uuid": "", - "threatintel.misp.id": "3633", - "threatintel.misp.info": "Test event 3 objects and attributes", - "threatintel.misp.locked": false, - "threatintel.misp.org_id": "1", - "threatintel.misp.orgc.id": "1", - "threatintel.misp.orgc.local": true, - "threatintel.misp.orgc.name": "ORGNAME", - "threatintel.misp.orgc.uuid": "78acad2d-cc2d-4785-94d6-b428a0070488", - "threatintel.misp.orgc_id": "1", - "threatintel.misp.proposal_email_lock": false, - "threatintel.misp.publish_timestamp": "0", - "threatintel.misp.published": false, - "threatintel.misp.sharing_group_id": "0", - "threatintel.misp.threat_level_id": 1, - "threatintel.misp.uuid": "4edb20c7-8175-484d-bdcd-fce6872c1ef3", + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] MISP", + "threat.indicator.file.hash.md5": "70461da8b94c6ca5d2fda3260c5a8c3b", + "threat.indicator.provider": "misp", + "threat.indicator.scanner_stats": 0, + "threat.indicator.type": "file", "user.email": "admin@admin.test", "user.roles": [ "reporting_user" @@ -510,63 +526,65 @@ "fileset.name": "misp", "input.type": "log", "log.offset": 15439, + "misp.attribute.category": "Payload delivery", + "misp.attribute.comment": "", + "misp.attribute.deleted": false, + "misp.attribute.disable_correlation": false, + "misp.attribute.distribution": 5, + "misp.attribute.event_id": "3633", + "misp.attribute.id": "266265", + "misp.attribute.object_id": "18207", + "misp.attribute.object_relation": "sha256", + "misp.attribute.sharing_group_id": "0", + "misp.attribute.timestamp": "1621589548", + "misp.attribute.to_ids": true, + "misp.attribute.type": "sha256", + "misp.attribute.uuid": "657c5f2b-9d68-4ff7-a9ad-ab9e6a6c953e", + "misp.attribute_count": 6, + "misp.context.attribute.category": "Payload delivery", + "misp.context.attribute.comment": "filename contect for test event 3", + "misp.context.attribute.deleted": false, + "misp.context.attribute.disable_correlation": false, + "misp.context.attribute.distribution": 5, + "misp.context.attribute.event_id": "3633", + "misp.context.attribute.id": "266263", + "misp.context.attribute.object_id": "0", + "misp.context.attribute.sharing_group_id": "0", + "misp.context.attribute.timestamp": "1621589229", + "misp.context.attribute.to_ids": false, + "misp.context.attribute.type": "filename", + "misp.context.attribute.uuid": "3b322e1a-1dd8-490c-ab96-12e1bc3ee6a3", + "misp.context.attribute.value": "thetestfile.txt", + "misp.date": "2021-05-21", + "misp.disable_correlation": false, + "misp.distribution": "1", + "misp.extends_uuid": "", + "misp.id": "3633", + "misp.info": "Test event 3 objects and attributes", + "misp.locked": false, + "misp.org_id": "1", + "misp.orgc.id": "1", + "misp.orgc.local": true, + "misp.orgc.name": "ORGNAME", + "misp.orgc.uuid": "78acad2d-cc2d-4785-94d6-b428a0070488", + "misp.orgc_id": "1", + "misp.proposal_email_lock": false, + "misp.publish_timestamp": "0", + "misp.published": false, + "misp.sharing_group_id": "0", + "misp.threat_level_id": 1, + "misp.uuid": "4edb20c7-8175-484d-bdcd-fce6872c1ef3", "service.type": "threatintel", "tags": [ "forwarded", "threatintel-misp" ], - "threatintel.indicator.file.hash.sha256": "f33c27745f2bd87344be790465ef984a972fd539dc83bd4f61d4242c607ef1ee", - "threatintel.indicator.provider": "misp", - "threatintel.indicator.scanner_stats": 0, - "threatintel.indicator.type": "file", - "threatintel.misp.attribute.category": "Payload delivery", - "threatintel.misp.attribute.comment": "", - "threatintel.misp.attribute.deleted": false, - "threatintel.misp.attribute.disable_correlation": false, - "threatintel.misp.attribute.distribution": "5", - "threatintel.misp.attribute.event_id": "3633", - "threatintel.misp.attribute.id": "266265", - "threatintel.misp.attribute.object_id": "18207", - "threatintel.misp.attribute.object_relation": "sha256", - "threatintel.misp.attribute.sharing_group_id": "0", - "threatintel.misp.attribute.timestamp": "1621589548", - "threatintel.misp.attribute.to_ids": true, - "threatintel.misp.attribute.type": "sha256", - "threatintel.misp.attribute.uuid": "657c5f2b-9d68-4ff7-a9ad-ab9e6a6c953e", - "threatintel.misp.attribute_count": "6", - "threatintel.misp.context.attribute.category": "Payload delivery", - "threatintel.misp.context.attribute.comment": "filename contect for test event 3", - "threatintel.misp.context.attribute.deleted": false, - "threatintel.misp.context.attribute.disable_correlation": false, - "threatintel.misp.context.attribute.distribution": "5", - "threatintel.misp.context.attribute.event_id": "3633", - "threatintel.misp.context.attribute.id": "266263", - "threatintel.misp.context.attribute.object_id": "0", - "threatintel.misp.context.attribute.sharing_group_id": "0", - "threatintel.misp.context.attribute.timestamp": "1621589229", - "threatintel.misp.context.attribute.to_ids": false, - "threatintel.misp.context.attribute.type": "filename", - "threatintel.misp.context.attribute.uuid": "3b322e1a-1dd8-490c-ab96-12e1bc3ee6a3", - "threatintel.misp.context.attribute.value": "thetestfile.txt", - "threatintel.misp.date": "2021-05-21", - "threatintel.misp.disable_correlation": false, - "threatintel.misp.distribution": "1", - "threatintel.misp.extends_uuid": "", - "threatintel.misp.id": "3633", - "threatintel.misp.info": "Test event 3 objects and attributes", - "threatintel.misp.locked": false, - "threatintel.misp.org_id": "1", - "threatintel.misp.orgc.id": "1", - "threatintel.misp.orgc.local": true, - "threatintel.misp.orgc.name": "ORGNAME", - "threatintel.misp.orgc.uuid": "78acad2d-cc2d-4785-94d6-b428a0070488", - "threatintel.misp.orgc_id": "1", - "threatintel.misp.proposal_email_lock": false, - "threatintel.misp.publish_timestamp": "0", - "threatintel.misp.published": false, - "threatintel.misp.sharing_group_id": "0", - "threatintel.misp.threat_level_id": 1, - "threatintel.misp.uuid": "4edb20c7-8175-484d-bdcd-fce6872c1ef3", + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] MISP", + "threat.indicator.file.hash.sha256": "f33c27745f2bd87344be790465ef984a972fd539dc83bd4f61d4242c607ef1ee", + "threat.indicator.provider": "misp", + "threat.indicator.scanner_stats": 0, + "threat.indicator.type": "file", "user.email": "admin@admin.test", "user.roles": [ "reporting_user" @@ -582,63 +600,65 @@ "fileset.name": "misp", "input.type": "log", "log.offset": 17926, + "misp.attribute.category": "Payload delivery", + "misp.attribute.comment": "", + "misp.attribute.deleted": false, + "misp.attribute.disable_correlation": true, + "misp.attribute.distribution": 5, + "misp.attribute.event_id": "3633", + "misp.attribute.id": "266266", + "misp.attribute.object_id": "18207", + "misp.attribute.object_relation": "filename", + "misp.attribute.sharing_group_id": "0", + "misp.attribute.timestamp": "1621589548", + "misp.attribute.to_ids": true, + "misp.attribute.type": "filename", + "misp.attribute.uuid": "6648d129-9200-431b-9b41-263a84f7c9d2", + "misp.attribute_count": 6, + "misp.context.attribute.category": "Payload delivery", + "misp.context.attribute.comment": "filename contect for test event 3", + "misp.context.attribute.deleted": false, + "misp.context.attribute.disable_correlation": false, + "misp.context.attribute.distribution": 5, + "misp.context.attribute.event_id": "3633", + "misp.context.attribute.id": "266263", + "misp.context.attribute.object_id": "0", + "misp.context.attribute.sharing_group_id": "0", + "misp.context.attribute.timestamp": "1621589229", + "misp.context.attribute.to_ids": false, + "misp.context.attribute.type": "filename", + "misp.context.attribute.uuid": "3b322e1a-1dd8-490c-ab96-12e1bc3ee6a3", + "misp.context.attribute.value": "thetestfile.txt", + "misp.date": "2021-05-21", + "misp.disable_correlation": false, + "misp.distribution": "1", + "misp.extends_uuid": "", + "misp.id": "3633", + "misp.info": "Test event 3 objects and attributes", + "misp.locked": false, + "misp.org_id": "1", + "misp.orgc.id": "1", + "misp.orgc.local": true, + "misp.orgc.name": "ORGNAME", + "misp.orgc.uuid": "78acad2d-cc2d-4785-94d6-b428a0070488", + "misp.orgc_id": "1", + "misp.proposal_email_lock": false, + "misp.publish_timestamp": "0", + "misp.published": false, + "misp.sharing_group_id": "0", + "misp.threat_level_id": 1, + "misp.uuid": "4edb20c7-8175-484d-bdcd-fce6872c1ef3", "service.type": "threatintel", "tags": [ "forwarded", "threatintel-misp" ], - "threatintel.indicator.file.name": "filenameofobject.txt", - "threatintel.indicator.provider": "misp", - "threatintel.indicator.scanner_stats": 0, - "threatintel.indicator.type": "file", - "threatintel.misp.attribute.category": "Payload delivery", - "threatintel.misp.attribute.comment": "", - "threatintel.misp.attribute.deleted": false, - "threatintel.misp.attribute.disable_correlation": true, - "threatintel.misp.attribute.distribution": "5", - "threatintel.misp.attribute.event_id": "3633", - "threatintel.misp.attribute.id": "266266", - "threatintel.misp.attribute.object_id": "18207", - "threatintel.misp.attribute.object_relation": "filename", - "threatintel.misp.attribute.sharing_group_id": "0", - "threatintel.misp.attribute.timestamp": "1621589548", - "threatintel.misp.attribute.to_ids": true, - "threatintel.misp.attribute.type": "filename", - "threatintel.misp.attribute.uuid": "6648d129-9200-431b-9b41-263a84f7c9d2", - "threatintel.misp.attribute_count": "6", - "threatintel.misp.context.attribute.category": "Payload delivery", - "threatintel.misp.context.attribute.comment": "filename contect for test event 3", - "threatintel.misp.context.attribute.deleted": false, - "threatintel.misp.context.attribute.disable_correlation": false, - "threatintel.misp.context.attribute.distribution": "5", - "threatintel.misp.context.attribute.event_id": "3633", - "threatintel.misp.context.attribute.id": "266263", - "threatintel.misp.context.attribute.object_id": "0", - "threatintel.misp.context.attribute.sharing_group_id": "0", - "threatintel.misp.context.attribute.timestamp": "1621589229", - "threatintel.misp.context.attribute.to_ids": false, - "threatintel.misp.context.attribute.type": "filename", - "threatintel.misp.context.attribute.uuid": "3b322e1a-1dd8-490c-ab96-12e1bc3ee6a3", - "threatintel.misp.context.attribute.value": "thetestfile.txt", - "threatintel.misp.date": "2021-05-21", - "threatintel.misp.disable_correlation": false, - "threatintel.misp.distribution": "1", - "threatintel.misp.extends_uuid": "", - "threatintel.misp.id": "3633", - "threatintel.misp.info": "Test event 3 objects and attributes", - "threatintel.misp.locked": false, - "threatintel.misp.org_id": "1", - "threatintel.misp.orgc.id": "1", - "threatintel.misp.orgc.local": true, - "threatintel.misp.orgc.name": "ORGNAME", - "threatintel.misp.orgc.uuid": "78acad2d-cc2d-4785-94d6-b428a0070488", - "threatintel.misp.orgc_id": "1", - "threatintel.misp.proposal_email_lock": false, - "threatintel.misp.publish_timestamp": "0", - "threatintel.misp.published": false, - "threatintel.misp.sharing_group_id": "0", - "threatintel.misp.threat_level_id": 1, - "threatintel.misp.uuid": "4edb20c7-8175-484d-bdcd-fce6872c1ef3", + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] MISP", + "threat.indicator.file.name": "filenameofobject.txt", + "threat.indicator.provider": "misp", + "threat.indicator.scanner_stats": 0, + "threat.indicator.type": "file", "user.email": "admin@admin.test", "user.roles": [ "reporting_user" @@ -654,49 +674,51 @@ "fileset.name": "misp", "input.type": "log", "log.offset": 20372, + "misp.attribute.category": "Other", + "misp.attribute.comment": "", + "misp.attribute.deleted": false, + "misp.attribute.disable_correlation": true, + "misp.attribute.distribution": 5, + "misp.attribute.event_id": "3634", + "misp.attribute.id": "266269", + "misp.attribute.object_id": "18208", + "misp.attribute.object_relation": "text", + "misp.attribute.sharing_group_id": "0", + "misp.attribute.timestamp": "1621591770", + "misp.attribute.to_ids": false, + "misp.attribute.type": "text", + "misp.attribute.uuid": "25d2f181-26ae-4d6f-b4fd-85b9d1f82e67", + "misp.attribute.value": "Free text in the file object", + "misp.attribute_count": 3, + "misp.date": "2021-05-21", + "misp.disable_correlation": false, + "misp.distribution": "1", + "misp.extends_uuid": "", + "misp.id": "3634", + "misp.info": "Test event 4 with object", + "misp.locked": false, + "misp.org_id": "1", + "misp.orgc.id": "1", + "misp.orgc.local": true, + "misp.orgc.name": "ORGNAME", + "misp.orgc.uuid": "78acad2d-cc2d-4785-94d6-b428a0070488", + "misp.orgc_id": "1", + "misp.proposal_email_lock": false, + "misp.publish_timestamp": "0", + "misp.published": false, + "misp.sharing_group_id": "0", + "misp.threat_level_id": 3, + "misp.uuid": "d98a8418-9f90-4b50-a623-6921ca5b356d", "service.type": "threatintel", "tags": [ "forwarded", "threatintel-misp" ], - "threatintel.indicator.provider": "misp", - "threatintel.indicator.scanner_stats": 0, - "threatintel.indicator.type": "unknown", - "threatintel.misp.attribute.category": "Other", - "threatintel.misp.attribute.comment": "", - "threatintel.misp.attribute.deleted": false, - "threatintel.misp.attribute.disable_correlation": true, - "threatintel.misp.attribute.distribution": "5", - "threatintel.misp.attribute.event_id": "3634", - "threatintel.misp.attribute.id": "266269", - "threatintel.misp.attribute.object_id": "18208", - "threatintel.misp.attribute.object_relation": "text", - "threatintel.misp.attribute.sharing_group_id": "0", - "threatintel.misp.attribute.timestamp": "1621591770", - "threatintel.misp.attribute.to_ids": false, - "threatintel.misp.attribute.type": "text", - "threatintel.misp.attribute.uuid": "25d2f181-26ae-4d6f-b4fd-85b9d1f82e67", - "threatintel.misp.attribute.value": "Free text in the file object", - "threatintel.misp.attribute_count": "3", - "threatintel.misp.date": "2021-05-21", - "threatintel.misp.disable_correlation": false, - "threatintel.misp.distribution": "1", - "threatintel.misp.extends_uuid": "", - "threatintel.misp.id": "3634", - "threatintel.misp.info": "Test event 4 with object", - "threatintel.misp.locked": false, - "threatintel.misp.org_id": "1", - "threatintel.misp.orgc.id": "1", - "threatintel.misp.orgc.local": true, - "threatintel.misp.orgc.name": "ORGNAME", - "threatintel.misp.orgc.uuid": "78acad2d-cc2d-4785-94d6-b428a0070488", - "threatintel.misp.orgc_id": "1", - "threatintel.misp.proposal_email_lock": false, - "threatintel.misp.publish_timestamp": "0", - "threatintel.misp.published": false, - "threatintel.misp.sharing_group_id": "0", - "threatintel.misp.threat_level_id": 3, - "threatintel.misp.uuid": "d98a8418-9f90-4b50-a623-6921ca5b356d", + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] MISP", + "threat.indicator.provider": "misp", + "threat.indicator.scanner_stats": 0, + "threat.indicator.type": "unknown", "user.email": "admin@admin.test", "user.roles": [ "reporting_user" @@ -712,49 +734,51 @@ "fileset.name": "misp", "input.type": "log", "log.offset": 21959, + "misp.attribute.category": "Payload delivery", + "misp.attribute.comment": "", + "misp.attribute.deleted": false, + "misp.attribute.disable_correlation": false, + "misp.attribute.distribution": 5, + "misp.attribute.event_id": "3634", + "misp.attribute.id": "266270", + "misp.attribute.object_id": "18208", + "misp.attribute.object_relation": "sha256", + "misp.attribute.sharing_group_id": "0", + "misp.attribute.timestamp": "1621591770", + "misp.attribute.to_ids": true, + "misp.attribute.type": "sha256", + "misp.attribute.uuid": "4e579782-346b-44b3-b72c-1cae8d87cb25", + "misp.attribute_count": 3, + "misp.date": "2021-05-21", + "misp.disable_correlation": false, + "misp.distribution": "1", + "misp.extends_uuid": "", + "misp.id": "3634", + "misp.info": "Test event 4 with object", + "misp.locked": false, + "misp.org_id": "1", + "misp.orgc.id": "1", + "misp.orgc.local": true, + "misp.orgc.name": "ORGNAME", + "misp.orgc.uuid": "78acad2d-cc2d-4785-94d6-b428a0070488", + "misp.orgc_id": "1", + "misp.proposal_email_lock": false, + "misp.publish_timestamp": "0", + "misp.published": false, + "misp.sharing_group_id": "0", + "misp.threat_level_id": 3, + "misp.uuid": "d98a8418-9f90-4b50-a623-6921ca5b356d", "service.type": "threatintel", "tags": [ "forwarded", "threatintel-misp" ], - "threatintel.indicator.file.hash.sha256": "567caa7653723f8818ec9eb6f2e27f6d9d8c0aca0c96fc457659340e7bbdc666", - "threatintel.indicator.provider": "misp", - "threatintel.indicator.scanner_stats": 0, - "threatintel.indicator.type": "file", - "threatintel.misp.attribute.category": "Payload delivery", - "threatintel.misp.attribute.comment": "", - "threatintel.misp.attribute.deleted": false, - "threatintel.misp.attribute.disable_correlation": false, - "threatintel.misp.attribute.distribution": "5", - "threatintel.misp.attribute.event_id": "3634", - "threatintel.misp.attribute.id": "266270", - "threatintel.misp.attribute.object_id": "18208", - "threatintel.misp.attribute.object_relation": "sha256", - "threatintel.misp.attribute.sharing_group_id": "0", - "threatintel.misp.attribute.timestamp": "1621591770", - "threatintel.misp.attribute.to_ids": true, - "threatintel.misp.attribute.type": "sha256", - "threatintel.misp.attribute.uuid": "4e579782-346b-44b3-b72c-1cae8d87cb25", - "threatintel.misp.attribute_count": "3", - "threatintel.misp.date": "2021-05-21", - "threatintel.misp.disable_correlation": false, - "threatintel.misp.distribution": "1", - "threatintel.misp.extends_uuid": "", - "threatintel.misp.id": "3634", - "threatintel.misp.info": "Test event 4 with object", - "threatintel.misp.locked": false, - "threatintel.misp.org_id": "1", - "threatintel.misp.orgc.id": "1", - "threatintel.misp.orgc.local": true, - "threatintel.misp.orgc.name": "ORGNAME", - "threatintel.misp.orgc.uuid": "78acad2d-cc2d-4785-94d6-b428a0070488", - "threatintel.misp.orgc_id": "1", - "threatintel.misp.proposal_email_lock": false, - "threatintel.misp.publish_timestamp": "0", - "threatintel.misp.published": false, - "threatintel.misp.sharing_group_id": "0", - "threatintel.misp.threat_level_id": 3, - "threatintel.misp.uuid": "d98a8418-9f90-4b50-a623-6921ca5b356d", + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] MISP", + "threat.indicator.file.hash.sha256": "567caa7653723f8818ec9eb6f2e27f6d9d8c0aca0c96fc457659340e7bbdc666", + "threat.indicator.provider": "misp", + "threat.indicator.scanner_stats": 0, + "threat.indicator.type": "file", "user.email": "admin@admin.test", "user.roles": [ "reporting_user" @@ -770,49 +794,51 @@ "fileset.name": "misp", "input.type": "log", "log.offset": 23597, + "misp.attribute.category": "Payload delivery", + "misp.attribute.comment": "", + "misp.attribute.deleted": false, + "misp.attribute.disable_correlation": true, + "misp.attribute.distribution": 5, + "misp.attribute.event_id": "3634", + "misp.attribute.id": "266271", + "misp.attribute.object_id": "18208", + "misp.attribute.object_relation": "filename", + "misp.attribute.sharing_group_id": "0", + "misp.attribute.timestamp": "1621591770", + "misp.attribute.to_ids": true, + "misp.attribute.type": "filename", + "misp.attribute.uuid": "a40343b5-a480-4288-9b0c-7ae074a77140", + "misp.attribute_count": 3, + "misp.date": "2021-05-21", + "misp.disable_correlation": false, + "misp.distribution": "1", + "misp.extends_uuid": "", + "misp.id": "3634", + "misp.info": "Test event 4 with object", + "misp.locked": false, + "misp.org_id": "1", + "misp.orgc.id": "1", + "misp.orgc.local": true, + "misp.orgc.name": "ORGNAME", + "misp.orgc.uuid": "78acad2d-cc2d-4785-94d6-b428a0070488", + "misp.orgc_id": "1", + "misp.proposal_email_lock": false, + "misp.publish_timestamp": "0", + "misp.published": false, + "misp.sharing_group_id": "0", + "misp.threat_level_id": 3, + "misp.uuid": "d98a8418-9f90-4b50-a623-6921ca5b356d", "service.type": "threatintel", "tags": [ "forwarded", "threatintel-misp" ], - "threatintel.indicator.file.name": "filenameinmispobject.txt", - "threatintel.indicator.provider": "misp", - "threatintel.indicator.scanner_stats": 0, - "threatintel.indicator.type": "file", - "threatintel.misp.attribute.category": "Payload delivery", - "threatintel.misp.attribute.comment": "", - "threatintel.misp.attribute.deleted": false, - "threatintel.misp.attribute.disable_correlation": true, - "threatintel.misp.attribute.distribution": "5", - "threatintel.misp.attribute.event_id": "3634", - "threatintel.misp.attribute.id": "266271", - "threatintel.misp.attribute.object_id": "18208", - "threatintel.misp.attribute.object_relation": "filename", - "threatintel.misp.attribute.sharing_group_id": "0", - "threatintel.misp.attribute.timestamp": "1621591770", - "threatintel.misp.attribute.to_ids": true, - "threatintel.misp.attribute.type": "filename", - "threatintel.misp.attribute.uuid": "a40343b5-a480-4288-9b0c-7ae074a77140", - "threatintel.misp.attribute_count": "3", - "threatintel.misp.date": "2021-05-21", - "threatintel.misp.disable_correlation": false, - "threatintel.misp.distribution": "1", - "threatintel.misp.extends_uuid": "", - "threatintel.misp.id": "3634", - "threatintel.misp.info": "Test event 4 with object", - "threatintel.misp.locked": false, - "threatintel.misp.org_id": "1", - "threatintel.misp.orgc.id": "1", - "threatintel.misp.orgc.local": true, - "threatintel.misp.orgc.name": "ORGNAME", - "threatintel.misp.orgc.uuid": "78acad2d-cc2d-4785-94d6-b428a0070488", - "threatintel.misp.orgc_id": "1", - "threatintel.misp.proposal_email_lock": false, - "threatintel.misp.publish_timestamp": "0", - "threatintel.misp.published": false, - "threatintel.misp.sharing_group_id": "0", - "threatintel.misp.threat_level_id": 3, - "threatintel.misp.uuid": "d98a8418-9f90-4b50-a623-6921ca5b356d", + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] MISP", + "threat.indicator.file.name": "filenameinmispobject.txt", + "threat.indicator.provider": "misp", + "threat.indicator.scanner_stats": 0, + "threat.indicator.type": "file", "user.email": "admin@admin.test", "user.roles": [ "reporting_user" @@ -828,49 +854,51 @@ "fileset.name": "misp", "input.type": "log", "log.offset": 25198, + "misp.attribute.category": "Other", + "misp.attribute.comment": "", + "misp.attribute.deleted": false, + "misp.attribute.disable_correlation": true, + "misp.attribute.distribution": 5, + "misp.attribute.event_id": "3635", + "misp.attribute.id": "266272", + "misp.attribute.object_id": "18209", + "misp.attribute.object_relation": "text", + "misp.attribute.sharing_group_id": "0", + "misp.attribute.timestamp": "1621592379", + "misp.attribute.to_ids": false, + "misp.attribute.type": "text", + "misp.attribute.uuid": "188a6a15-5704-4e4f-acba-22c55ab08fe8", + "misp.attribute.value": "Object 5 free text attribute in object", + "misp.attribute_count": 5, + "misp.date": "2021-05-21", + "misp.disable_correlation": false, + "misp.distribution": "1", + "misp.extends_uuid": "", + "misp.id": "3635", + "misp.info": "Test event 5 with an object", + "misp.locked": false, + "misp.org_id": "1", + "misp.orgc.id": "1", + "misp.orgc.local": true, + "misp.orgc.name": "ORGNAME", + "misp.orgc.uuid": "78acad2d-cc2d-4785-94d6-b428a0070488", + "misp.orgc_id": "1", + "misp.proposal_email_lock": false, + "misp.publish_timestamp": "0", + "misp.published": false, + "misp.sharing_group_id": "0", + "misp.threat_level_id": 1, + "misp.uuid": "8b8786f1-07f2-4bfc-a3f0-e63c22fcc25e", "service.type": "threatintel", "tags": [ "forwarded", "threatintel-misp" ], - "threatintel.indicator.provider": "misp", - "threatintel.indicator.scanner_stats": 0, - "threatintel.indicator.type": "unknown", - "threatintel.misp.attribute.category": "Other", - "threatintel.misp.attribute.comment": "", - "threatintel.misp.attribute.deleted": false, - "threatintel.misp.attribute.disable_correlation": true, - "threatintel.misp.attribute.distribution": "5", - "threatintel.misp.attribute.event_id": "3635", - "threatintel.misp.attribute.id": "266272", - "threatintel.misp.attribute.object_id": "18209", - "threatintel.misp.attribute.object_relation": "text", - "threatintel.misp.attribute.sharing_group_id": "0", - "threatintel.misp.attribute.timestamp": "1621592379", - "threatintel.misp.attribute.to_ids": false, - "threatintel.misp.attribute.type": "text", - "threatintel.misp.attribute.uuid": "188a6a15-5704-4e4f-acba-22c55ab08fe8", - "threatintel.misp.attribute.value": "Object 5 free text attribute in object", - "threatintel.misp.attribute_count": "5", - "threatintel.misp.date": "2021-05-21", - "threatintel.misp.disable_correlation": false, - "threatintel.misp.distribution": "1", - "threatintel.misp.extends_uuid": "", - "threatintel.misp.id": "3635", - "threatintel.misp.info": "Test event 5 with an object", - "threatintel.misp.locked": false, - "threatintel.misp.org_id": "1", - "threatintel.misp.orgc.id": "1", - "threatintel.misp.orgc.local": true, - "threatintel.misp.orgc.name": "ORGNAME", - "threatintel.misp.orgc.uuid": "78acad2d-cc2d-4785-94d6-b428a0070488", - "threatintel.misp.orgc_id": "1", - "threatintel.misp.proposal_email_lock": false, - "threatintel.misp.publish_timestamp": "0", - "threatintel.misp.published": false, - "threatintel.misp.sharing_group_id": "0", - "threatintel.misp.threat_level_id": 1, - "threatintel.misp.uuid": "8b8786f1-07f2-4bfc-a3f0-e63c22fcc25e", + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] MISP", + "threat.indicator.provider": "misp", + "threat.indicator.scanner_stats": 0, + "threat.indicator.type": "unknown", "user.email": "admin@admin.test", "user.roles": [ "reporting_user" @@ -886,49 +914,51 @@ "fileset.name": "misp", "input.type": "log", "log.offset": 26791, + "misp.attribute.category": "Other", + "misp.attribute.comment": "", + "misp.attribute.deleted": false, + "misp.attribute.disable_correlation": true, + "misp.attribute.distribution": 5, + "misp.attribute.event_id": "3635", + "misp.attribute.id": "266275", + "misp.attribute.object_id": "18209", + "misp.attribute.object_relation": "entropy", + "misp.attribute.sharing_group_id": "0", + "misp.attribute.timestamp": "1621592379", + "misp.attribute.to_ids": false, + "misp.attribute.type": "float", + "misp.attribute.uuid": "2400b103-4a33-4f92-ac04-a558b6c6e252", + "misp.attribute.value": "0.53535445", + "misp.attribute_count": 5, + "misp.date": "2021-05-21", + "misp.disable_correlation": false, + "misp.distribution": "1", + "misp.extends_uuid": "", + "misp.id": "3635", + "misp.info": "Test event 5 with an object", + "misp.locked": false, + "misp.org_id": "1", + "misp.orgc.id": "1", + "misp.orgc.local": true, + "misp.orgc.name": "ORGNAME", + "misp.orgc.uuid": "78acad2d-cc2d-4785-94d6-b428a0070488", + "misp.orgc_id": "1", + "misp.proposal_email_lock": false, + "misp.publish_timestamp": "0", + "misp.published": false, + "misp.sharing_group_id": "0", + "misp.threat_level_id": 1, + "misp.uuid": "8b8786f1-07f2-4bfc-a3f0-e63c22fcc25e", "service.type": "threatintel", "tags": [ "forwarded", "threatintel-misp" ], - "threatintel.indicator.provider": "misp", - "threatintel.indicator.scanner_stats": 0, - "threatintel.indicator.type": "unknown", - "threatintel.misp.attribute.category": "Other", - "threatintel.misp.attribute.comment": "", - "threatintel.misp.attribute.deleted": false, - "threatintel.misp.attribute.disable_correlation": true, - "threatintel.misp.attribute.distribution": "5", - "threatintel.misp.attribute.event_id": "3635", - "threatintel.misp.attribute.id": "266275", - "threatintel.misp.attribute.object_id": "18209", - "threatintel.misp.attribute.object_relation": "entropy", - "threatintel.misp.attribute.sharing_group_id": "0", - "threatintel.misp.attribute.timestamp": "1621592379", - "threatintel.misp.attribute.to_ids": false, - "threatintel.misp.attribute.type": "float", - "threatintel.misp.attribute.uuid": "2400b103-4a33-4f92-ac04-a558b6c6e252", - "threatintel.misp.attribute.value": "0.53535445", - "threatintel.misp.attribute_count": "5", - "threatintel.misp.date": "2021-05-21", - "threatintel.misp.disable_correlation": false, - "threatintel.misp.distribution": "1", - "threatintel.misp.extends_uuid": "", - "threatintel.misp.id": "3635", - "threatintel.misp.info": "Test event 5 with an object", - "threatintel.misp.locked": false, - "threatintel.misp.org_id": "1", - "threatintel.misp.orgc.id": "1", - "threatintel.misp.orgc.local": true, - "threatintel.misp.orgc.name": "ORGNAME", - "threatintel.misp.orgc.uuid": "78acad2d-cc2d-4785-94d6-b428a0070488", - "threatintel.misp.orgc_id": "1", - "threatintel.misp.proposal_email_lock": false, - "threatintel.misp.publish_timestamp": "0", - "threatintel.misp.published": false, - "threatintel.misp.sharing_group_id": "0", - "threatintel.misp.threat_level_id": 1, - "threatintel.misp.uuid": "8b8786f1-07f2-4bfc-a3f0-e63c22fcc25e", + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] MISP", + "threat.indicator.provider": "misp", + "threat.indicator.scanner_stats": 0, + "threat.indicator.type": "unknown", "user.email": "admin@admin.test", "user.roles": [ "reporting_user" @@ -944,49 +974,51 @@ "fileset.name": "misp", "input.type": "log", "log.offset": 28360, + "misp.attribute.category": "Other", + "misp.attribute.comment": "", + "misp.attribute.deleted": false, + "misp.attribute.disable_correlation": true, + "misp.attribute.distribution": 5, + "misp.attribute.event_id": "3635", + "misp.attribute.id": "266276", + "misp.attribute.object_id": "18209", + "misp.attribute.object_relation": "size-in-bytes", + "misp.attribute.sharing_group_id": "0", + "misp.attribute.timestamp": "1621592379", + "misp.attribute.to_ids": false, + "misp.attribute.type": "size-in-bytes", + "misp.attribute.uuid": "e5ea3ec0-cdf4-4d3e-bd66-a7bf384fd3d7", + "misp.attribute.value": "55555", + "misp.attribute_count": 5, + "misp.date": "2021-05-21", + "misp.disable_correlation": false, + "misp.distribution": "1", + "misp.extends_uuid": "", + "misp.id": "3635", + "misp.info": "Test event 5 with an object", + "misp.locked": false, + "misp.org_id": "1", + "misp.orgc.id": "1", + "misp.orgc.local": true, + "misp.orgc.name": "ORGNAME", + "misp.orgc.uuid": "78acad2d-cc2d-4785-94d6-b428a0070488", + "misp.orgc_id": "1", + "misp.proposal_email_lock": false, + "misp.publish_timestamp": "0", + "misp.published": false, + "misp.sharing_group_id": "0", + "misp.threat_level_id": 1, + "misp.uuid": "8b8786f1-07f2-4bfc-a3f0-e63c22fcc25e", "service.type": "threatintel", "tags": [ "forwarded", "threatintel-misp" ], - "threatintel.indicator.provider": "misp", - "threatintel.indicator.scanner_stats": 0, - "threatintel.indicator.type": "unknown", - "threatintel.misp.attribute.category": "Other", - "threatintel.misp.attribute.comment": "", - "threatintel.misp.attribute.deleted": false, - "threatintel.misp.attribute.disable_correlation": true, - "threatintel.misp.attribute.distribution": "5", - "threatintel.misp.attribute.event_id": "3635", - "threatintel.misp.attribute.id": "266276", - "threatintel.misp.attribute.object_id": "18209", - "threatintel.misp.attribute.object_relation": "size-in-bytes", - "threatintel.misp.attribute.sharing_group_id": "0", - "threatintel.misp.attribute.timestamp": "1621592379", - "threatintel.misp.attribute.to_ids": false, - "threatintel.misp.attribute.type": "size-in-bytes", - "threatintel.misp.attribute.uuid": "e5ea3ec0-cdf4-4d3e-bd66-a7bf384fd3d7", - "threatintel.misp.attribute.value": "55555", - "threatintel.misp.attribute_count": "5", - "threatintel.misp.date": "2021-05-21", - "threatintel.misp.disable_correlation": false, - "threatintel.misp.distribution": "1", - "threatintel.misp.extends_uuid": "", - "threatintel.misp.id": "3635", - "threatintel.misp.info": "Test event 5 with an object", - "threatintel.misp.locked": false, - "threatintel.misp.org_id": "1", - "threatintel.misp.orgc.id": "1", - "threatintel.misp.orgc.local": true, - "threatintel.misp.orgc.name": "ORGNAME", - "threatintel.misp.orgc.uuid": "78acad2d-cc2d-4785-94d6-b428a0070488", - "threatintel.misp.orgc_id": "1", - "threatintel.misp.proposal_email_lock": false, - "threatintel.misp.publish_timestamp": "0", - "threatintel.misp.published": false, - "threatintel.misp.sharing_group_id": "0", - "threatintel.misp.threat_level_id": 1, - "threatintel.misp.uuid": "8b8786f1-07f2-4bfc-a3f0-e63c22fcc25e", + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] MISP", + "threat.indicator.provider": "misp", + "threat.indicator.scanner_stats": 0, + "threat.indicator.type": "unknown", "user.email": "admin@admin.test", "user.roles": [ "reporting_user" @@ -1002,49 +1034,51 @@ "fileset.name": "misp", "input.type": "log", "log.offset": 29938, + "misp.attribute.category": "Payload delivery", + "misp.attribute.comment": "", + "misp.attribute.deleted": false, + "misp.attribute.disable_correlation": false, + "misp.attribute.distribution": 5, + "misp.attribute.event_id": "3635", + "misp.attribute.id": "266273", + "misp.attribute.object_id": "18209", + "misp.attribute.object_relation": "sha256", + "misp.attribute.sharing_group_id": "0", + "misp.attribute.timestamp": "1621592379", + "misp.attribute.to_ids": true, + "misp.attribute.type": "sha256", + "misp.attribute.uuid": "803f10bd-9087-4169-8699-277579a92693", + "misp.attribute_count": 5, + "misp.date": "2021-05-21", + "misp.disable_correlation": false, + "misp.distribution": "1", + "misp.extends_uuid": "", + "misp.id": "3635", + "misp.info": "Test event 5 with an object", + "misp.locked": false, + "misp.org_id": "1", + "misp.orgc.id": "1", + "misp.orgc.local": true, + "misp.orgc.name": "ORGNAME", + "misp.orgc.uuid": "78acad2d-cc2d-4785-94d6-b428a0070488", + "misp.orgc_id": "1", + "misp.proposal_email_lock": false, + "misp.publish_timestamp": "0", + "misp.published": false, + "misp.sharing_group_id": "0", + "misp.threat_level_id": 1, + "misp.uuid": "8b8786f1-07f2-4bfc-a3f0-e63c22fcc25e", "service.type": "threatintel", "tags": [ "forwarded", "threatintel-misp" ], - "threatintel.indicator.file.hash.sha256": "567caa7653723f8818ec9eb6f2e27f6d9d8c0aca0c96fc457659340e7bbdc665", - "threatintel.indicator.provider": "misp", - "threatintel.indicator.scanner_stats": 0, - "threatintel.indicator.type": "file", - "threatintel.misp.attribute.category": "Payload delivery", - "threatintel.misp.attribute.comment": "", - "threatintel.misp.attribute.deleted": false, - "threatintel.misp.attribute.disable_correlation": false, - "threatintel.misp.attribute.distribution": "5", - "threatintel.misp.attribute.event_id": "3635", - "threatintel.misp.attribute.id": "266273", - "threatintel.misp.attribute.object_id": "18209", - "threatintel.misp.attribute.object_relation": "sha256", - "threatintel.misp.attribute.sharing_group_id": "0", - "threatintel.misp.attribute.timestamp": "1621592379", - "threatintel.misp.attribute.to_ids": true, - "threatintel.misp.attribute.type": "sha256", - "threatintel.misp.attribute.uuid": "803f10bd-9087-4169-8699-277579a92693", - "threatintel.misp.attribute_count": "5", - "threatintel.misp.date": "2021-05-21", - "threatintel.misp.disable_correlation": false, - "threatintel.misp.distribution": "1", - "threatintel.misp.extends_uuid": "", - "threatintel.misp.id": "3635", - "threatintel.misp.info": "Test event 5 with an object", - "threatintel.misp.locked": false, - "threatintel.misp.org_id": "1", - "threatintel.misp.orgc.id": "1", - "threatintel.misp.orgc.local": true, - "threatintel.misp.orgc.name": "ORGNAME", - "threatintel.misp.orgc.uuid": "78acad2d-cc2d-4785-94d6-b428a0070488", - "threatintel.misp.orgc_id": "1", - "threatintel.misp.proposal_email_lock": false, - "threatintel.misp.publish_timestamp": "0", - "threatintel.misp.published": false, - "threatintel.misp.sharing_group_id": "0", - "threatintel.misp.threat_level_id": 1, - "threatintel.misp.uuid": "8b8786f1-07f2-4bfc-a3f0-e63c22fcc25e", + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] MISP", + "threat.indicator.file.hash.sha256": "567caa7653723f8818ec9eb6f2e27f6d9d8c0aca0c96fc457659340e7bbdc665", + "threat.indicator.provider": "misp", + "threat.indicator.scanner_stats": 0, + "threat.indicator.type": "file", "user.email": "admin@admin.test", "user.roles": [ "reporting_user" @@ -1060,49 +1094,51 @@ "fileset.name": "misp", "input.type": "log", "log.offset": 31572, + "misp.attribute.category": "Payload delivery", + "misp.attribute.comment": "", + "misp.attribute.deleted": false, + "misp.attribute.disable_correlation": true, + "misp.attribute.distribution": 5, + "misp.attribute.event_id": "3635", + "misp.attribute.id": "266274", + "misp.attribute.object_id": "18209", + "misp.attribute.object_relation": "filename", + "misp.attribute.sharing_group_id": "0", + "misp.attribute.timestamp": "1621592379", + "misp.attribute.to_ids": true, + "misp.attribute.type": "filename", + "misp.attribute.uuid": "e5c7a9f0-c0e1-4024-9ab8-de8a1b403e4f", + "misp.attribute_count": 5, + "misp.date": "2021-05-21", + "misp.disable_correlation": false, + "misp.distribution": "1", + "misp.extends_uuid": "", + "misp.id": "3635", + "misp.info": "Test event 5 with an object", + "misp.locked": false, + "misp.org_id": "1", + "misp.orgc.id": "1", + "misp.orgc.local": true, + "misp.orgc.name": "ORGNAME", + "misp.orgc.uuid": "78acad2d-cc2d-4785-94d6-b428a0070488", + "misp.orgc_id": "1", + "misp.proposal_email_lock": false, + "misp.publish_timestamp": "0", + "misp.published": false, + "misp.sharing_group_id": "0", + "misp.threat_level_id": 1, + "misp.uuid": "8b8786f1-07f2-4bfc-a3f0-e63c22fcc25e", "service.type": "threatintel", "tags": [ "forwarded", "threatintel-misp" ], - "threatintel.indicator.file.name": "object5.txt", - "threatintel.indicator.provider": "misp", - "threatintel.indicator.scanner_stats": 0, - "threatintel.indicator.type": "file", - "threatintel.misp.attribute.category": "Payload delivery", - "threatintel.misp.attribute.comment": "", - "threatintel.misp.attribute.deleted": false, - "threatintel.misp.attribute.disable_correlation": true, - "threatintel.misp.attribute.distribution": "5", - "threatintel.misp.attribute.event_id": "3635", - "threatintel.misp.attribute.id": "266274", - "threatintel.misp.attribute.object_id": "18209", - "threatintel.misp.attribute.object_relation": "filename", - "threatintel.misp.attribute.sharing_group_id": "0", - "threatintel.misp.attribute.timestamp": "1621592379", - "threatintel.misp.attribute.to_ids": true, - "threatintel.misp.attribute.type": "filename", - "threatintel.misp.attribute.uuid": "e5c7a9f0-c0e1-4024-9ab8-de8a1b403e4f", - "threatintel.misp.attribute_count": "5", - "threatintel.misp.date": "2021-05-21", - "threatintel.misp.disable_correlation": false, - "threatintel.misp.distribution": "1", - "threatintel.misp.extends_uuid": "", - "threatintel.misp.id": "3635", - "threatintel.misp.info": "Test event 5 with an object", - "threatintel.misp.locked": false, - "threatintel.misp.org_id": "1", - "threatintel.misp.orgc.id": "1", - "threatintel.misp.orgc.local": true, - "threatintel.misp.orgc.name": "ORGNAME", - "threatintel.misp.orgc.uuid": "78acad2d-cc2d-4785-94d6-b428a0070488", - "threatintel.misp.orgc_id": "1", - "threatintel.misp.proposal_email_lock": false, - "threatintel.misp.publish_timestamp": "0", - "threatintel.misp.published": false, - "threatintel.misp.sharing_group_id": "0", - "threatintel.misp.threat_level_id": 1, - "threatintel.misp.uuid": "8b8786f1-07f2-4bfc-a3f0-e63c22fcc25e", + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] MISP", + "threat.indicator.file.name": "object5.txt", + "threat.indicator.provider": "misp", + "threat.indicator.scanner_stats": 0, + "threat.indicator.type": "file", "user.email": "admin@admin.test", "user.roles": [ "reporting_user" @@ -1118,63 +1154,65 @@ "fileset.name": "misp", "input.type": "log", "log.offset": 33156, + "misp.attribute.category": "Other", + "misp.attribute.comment": "", + "misp.attribute.deleted": false, + "misp.attribute.disable_correlation": true, + "misp.attribute.distribution": 5, + "misp.attribute.event_id": "3636", + "misp.attribute.id": "266278", + "misp.attribute.object_id": "18210", + "misp.attribute.object_relation": "text", + "misp.attribute.sharing_group_id": "0", + "misp.attribute.timestamp": "1622200348", + "misp.attribute.to_ids": false, + "misp.attribute.type": "text", + "misp.attribute.uuid": "955e34a5-a630-42c9-868d-6e3dcb575987", + "misp.attribute.value": "Excutable create bad pipe", + "misp.attribute_count": 9, + "misp.context.attribute.category": "Artifacts dropped", + "misp.context.attribute.comment": "", + "misp.context.attribute.deleted": false, + "misp.context.attribute.disable_correlation": false, + "misp.context.attribute.distribution": 5, + "misp.context.attribute.event_id": "3636", + "misp.context.attribute.id": "266277", + "misp.context.attribute.object_id": "0", + "misp.context.attribute.sharing_group_id": "0", + "misp.context.attribute.timestamp": "1622200249", + "misp.context.attribute.to_ids": false, + "misp.context.attribute.type": "windows-service-name", + "misp.context.attribute.uuid": "3bd56a61-77f0-4885-8d1c-8bd2e39b65fb", + "misp.context.attribute.value": "badmojopipe", + "misp.date": "2021-05-28", + "misp.disable_correlation": false, + "misp.distribution": "0", + "misp.extends_uuid": "", + "misp.id": "3636", + "misp.info": "Test event 6 with multiple objects and multiple attributes", + "misp.locked": false, + "misp.org_id": "1", + "misp.orgc.id": "1", + "misp.orgc.local": true, + "misp.orgc.name": "ORGNAME", + "misp.orgc.uuid": "78acad2d-cc2d-4785-94d6-b428a0070488", + "misp.orgc_id": "1", + "misp.proposal_email_lock": false, + "misp.publish_timestamp": "0", + "misp.published": false, + "misp.sharing_group_id": "0", + "misp.threat_level_id": 1, + "misp.uuid": "81aea1d1-bb23-4bcd-9b0c-496e9ce028df", "service.type": "threatintel", "tags": [ "forwarded", "threatintel-misp" ], - "threatintel.indicator.provider": "misp", - "threatintel.indicator.scanner_stats": 0, - "threatintel.indicator.type": "unknown", - "threatintel.misp.attribute.category": "Other", - "threatintel.misp.attribute.comment": "", - "threatintel.misp.attribute.deleted": false, - "threatintel.misp.attribute.disable_correlation": true, - "threatintel.misp.attribute.distribution": "5", - "threatintel.misp.attribute.event_id": "3636", - "threatintel.misp.attribute.id": "266278", - "threatintel.misp.attribute.object_id": "18210", - "threatintel.misp.attribute.object_relation": "text", - "threatintel.misp.attribute.sharing_group_id": "0", - "threatintel.misp.attribute.timestamp": "1622200348", - "threatintel.misp.attribute.to_ids": false, - "threatintel.misp.attribute.type": "text", - "threatintel.misp.attribute.uuid": "955e34a5-a630-42c9-868d-6e3dcb575987", - "threatintel.misp.attribute.value": "Excutable create bad pipe", - "threatintel.misp.attribute_count": "9", - "threatintel.misp.context.attribute.category": "Artifacts dropped", - "threatintel.misp.context.attribute.comment": "", - "threatintel.misp.context.attribute.deleted": false, - "threatintel.misp.context.attribute.disable_correlation": false, - "threatintel.misp.context.attribute.distribution": "5", - "threatintel.misp.context.attribute.event_id": "3636", - "threatintel.misp.context.attribute.id": "266277", - "threatintel.misp.context.attribute.object_id": "0", - "threatintel.misp.context.attribute.sharing_group_id": "0", - "threatintel.misp.context.attribute.timestamp": "1622200249", - "threatintel.misp.context.attribute.to_ids": false, - "threatintel.misp.context.attribute.type": "windows-service-name", - "threatintel.misp.context.attribute.uuid": "3bd56a61-77f0-4885-8d1c-8bd2e39b65fb", - "threatintel.misp.context.attribute.value": "badmojopipe", - "threatintel.misp.date": "2021-05-28", - "threatintel.misp.disable_correlation": false, - "threatintel.misp.distribution": "0", - "threatintel.misp.extends_uuid": "", - "threatintel.misp.id": "3636", - "threatintel.misp.info": "Test event 6 with multiple objects and multiple attributes", - "threatintel.misp.locked": false, - "threatintel.misp.org_id": "1", - "threatintel.misp.orgc.id": "1", - "threatintel.misp.orgc.local": true, - "threatintel.misp.orgc.name": "ORGNAME", - "threatintel.misp.orgc.uuid": "78acad2d-cc2d-4785-94d6-b428a0070488", - "threatintel.misp.orgc_id": "1", - "threatintel.misp.proposal_email_lock": false, - "threatintel.misp.publish_timestamp": "0", - "threatintel.misp.published": false, - "threatintel.misp.sharing_group_id": "0", - "threatintel.misp.threat_level_id": 1, - "threatintel.misp.uuid": "81aea1d1-bb23-4bcd-9b0c-496e9ce028df", + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] MISP", + "threat.indicator.provider": "misp", + "threat.indicator.scanner_stats": 0, + "threat.indicator.type": "unknown", "user.email": "admin@admin.test", "user.roles": [ "reporting_user" @@ -1190,63 +1228,65 @@ "fileset.name": "misp", "input.type": "log", "log.offset": 35151, + "misp.attribute.category": "Other", + "misp.attribute.comment": "", + "misp.attribute.deleted": false, + "misp.attribute.disable_correlation": true, + "misp.attribute.distribution": 5, + "misp.attribute.event_id": "3636", + "misp.attribute.id": "266281", + "misp.attribute.object_id": "18211", + "misp.attribute.object_relation": "size-in-bytes", + "misp.attribute.sharing_group_id": "0", + "misp.attribute.timestamp": "1622200780", + "misp.attribute.to_ids": false, + "misp.attribute.type": "size-in-bytes", + "misp.attribute.uuid": "2fa7721b-ad73-4914-b082-8d44233ced98", + "misp.attribute.value": "3892", + "misp.attribute_count": 9, + "misp.context.attribute.category": "Artifacts dropped", + "misp.context.attribute.comment": "", + "misp.context.attribute.deleted": false, + "misp.context.attribute.disable_correlation": false, + "misp.context.attribute.distribution": 5, + "misp.context.attribute.event_id": "3636", + "misp.context.attribute.id": "266277", + "misp.context.attribute.object_id": "0", + "misp.context.attribute.sharing_group_id": "0", + "misp.context.attribute.timestamp": "1622200249", + "misp.context.attribute.to_ids": false, + "misp.context.attribute.type": "windows-service-name", + "misp.context.attribute.uuid": "3bd56a61-77f0-4885-8d1c-8bd2e39b65fb", + "misp.context.attribute.value": "badmojopipe", + "misp.date": "2021-05-28", + "misp.disable_correlation": false, + "misp.distribution": "0", + "misp.extends_uuid": "", + "misp.id": "3636", + "misp.info": "Test event 6 with multiple objects and multiple attributes", + "misp.locked": false, + "misp.org_id": "1", + "misp.orgc.id": "1", + "misp.orgc.local": true, + "misp.orgc.name": "ORGNAME", + "misp.orgc.uuid": "78acad2d-cc2d-4785-94d6-b428a0070488", + "misp.orgc_id": "1", + "misp.proposal_email_lock": false, + "misp.publish_timestamp": "0", + "misp.published": false, + "misp.sharing_group_id": "0", + "misp.threat_level_id": 1, + "misp.uuid": "81aea1d1-bb23-4bcd-9b0c-496e9ce028df", "service.type": "threatintel", "tags": [ "forwarded", "threatintel-misp" ], - "threatintel.indicator.provider": "misp", - "threatintel.indicator.scanner_stats": 0, - "threatintel.indicator.type": "unknown", - "threatintel.misp.attribute.category": "Other", - "threatintel.misp.attribute.comment": "", - "threatintel.misp.attribute.deleted": false, - "threatintel.misp.attribute.disable_correlation": true, - "threatintel.misp.attribute.distribution": "5", - "threatintel.misp.attribute.event_id": "3636", - "threatintel.misp.attribute.id": "266281", - "threatintel.misp.attribute.object_id": "18211", - "threatintel.misp.attribute.object_relation": "size-in-bytes", - "threatintel.misp.attribute.sharing_group_id": "0", - "threatintel.misp.attribute.timestamp": "1622200780", - "threatintel.misp.attribute.to_ids": false, - "threatintel.misp.attribute.type": "size-in-bytes", - "threatintel.misp.attribute.uuid": "2fa7721b-ad73-4914-b082-8d44233ced98", - "threatintel.misp.attribute.value": "3892", - "threatintel.misp.attribute_count": "9", - "threatintel.misp.context.attribute.category": "Artifacts dropped", - "threatintel.misp.context.attribute.comment": "", - "threatintel.misp.context.attribute.deleted": false, - "threatintel.misp.context.attribute.disable_correlation": false, - "threatintel.misp.context.attribute.distribution": "5", - "threatintel.misp.context.attribute.event_id": "3636", - "threatintel.misp.context.attribute.id": "266277", - "threatintel.misp.context.attribute.object_id": "0", - "threatintel.misp.context.attribute.sharing_group_id": "0", - "threatintel.misp.context.attribute.timestamp": "1622200249", - "threatintel.misp.context.attribute.to_ids": false, - "threatintel.misp.context.attribute.type": "windows-service-name", - "threatintel.misp.context.attribute.uuid": "3bd56a61-77f0-4885-8d1c-8bd2e39b65fb", - "threatintel.misp.context.attribute.value": "badmojopipe", - "threatintel.misp.date": "2021-05-28", - "threatintel.misp.disable_correlation": false, - "threatintel.misp.distribution": "0", - "threatintel.misp.extends_uuid": "", - "threatintel.misp.id": "3636", - "threatintel.misp.info": "Test event 6 with multiple objects and multiple attributes", - "threatintel.misp.locked": false, - "threatintel.misp.org_id": "1", - "threatintel.misp.orgc.id": "1", - "threatintel.misp.orgc.local": true, - "threatintel.misp.orgc.name": "ORGNAME", - "threatintel.misp.orgc.uuid": "78acad2d-cc2d-4785-94d6-b428a0070488", - "threatintel.misp.orgc_id": "1", - "threatintel.misp.proposal_email_lock": false, - "threatintel.misp.publish_timestamp": "0", - "threatintel.misp.published": false, - "threatintel.misp.sharing_group_id": "0", - "threatintel.misp.threat_level_id": 1, - "threatintel.misp.uuid": "81aea1d1-bb23-4bcd-9b0c-496e9ce028df", + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] MISP", + "threat.indicator.provider": "misp", + "threat.indicator.scanner_stats": 0, + "threat.indicator.type": "unknown", "user.email": "admin@admin.test", "user.roles": [ "reporting_user" @@ -1262,63 +1302,65 @@ "fileset.name": "misp", "input.type": "log", "log.offset": 37149, + "misp.attribute.category": "Other", + "misp.attribute.comment": "", + "misp.attribute.deleted": false, + "misp.attribute.disable_correlation": true, + "misp.attribute.distribution": 5, + "misp.attribute.event_id": "3636", + "misp.attribute.id": "266283", + "misp.attribute.object_id": "18211", + "misp.attribute.object_relation": "name", + "misp.attribute.sharing_group_id": "0", + "misp.attribute.timestamp": "1622200780", + "misp.attribute.to_ids": false, + "misp.attribute.type": "text", + "misp.attribute.uuid": "d35c1ff8-a69c-482b-8fb0-1182988d9468", + "misp.attribute.value": ".data", + "misp.attribute_count": 9, + "misp.context.attribute.category": "Artifacts dropped", + "misp.context.attribute.comment": "", + "misp.context.attribute.deleted": false, + "misp.context.attribute.disable_correlation": false, + "misp.context.attribute.distribution": 5, + "misp.context.attribute.event_id": "3636", + "misp.context.attribute.id": "266277", + "misp.context.attribute.object_id": "0", + "misp.context.attribute.sharing_group_id": "0", + "misp.context.attribute.timestamp": "1622200249", + "misp.context.attribute.to_ids": false, + "misp.context.attribute.type": "windows-service-name", + "misp.context.attribute.uuid": "3bd56a61-77f0-4885-8d1c-8bd2e39b65fb", + "misp.context.attribute.value": "badmojopipe", + "misp.date": "2021-05-28", + "misp.disable_correlation": false, + "misp.distribution": "0", + "misp.extends_uuid": "", + "misp.id": "3636", + "misp.info": "Test event 6 with multiple objects and multiple attributes", + "misp.locked": false, + "misp.org_id": "1", + "misp.orgc.id": "1", + "misp.orgc.local": true, + "misp.orgc.name": "ORGNAME", + "misp.orgc.uuid": "78acad2d-cc2d-4785-94d6-b428a0070488", + "misp.orgc_id": "1", + "misp.proposal_email_lock": false, + "misp.publish_timestamp": "0", + "misp.published": false, + "misp.sharing_group_id": "0", + "misp.threat_level_id": 1, + "misp.uuid": "81aea1d1-bb23-4bcd-9b0c-496e9ce028df", "service.type": "threatintel", "tags": [ "forwarded", "threatintel-misp" ], - "threatintel.indicator.provider": "misp", - "threatintel.indicator.scanner_stats": 0, - "threatintel.indicator.type": "unknown", - "threatintel.misp.attribute.category": "Other", - "threatintel.misp.attribute.comment": "", - "threatintel.misp.attribute.deleted": false, - "threatintel.misp.attribute.disable_correlation": true, - "threatintel.misp.attribute.distribution": "5", - "threatintel.misp.attribute.event_id": "3636", - "threatintel.misp.attribute.id": "266283", - "threatintel.misp.attribute.object_id": "18211", - "threatintel.misp.attribute.object_relation": "name", - "threatintel.misp.attribute.sharing_group_id": "0", - "threatintel.misp.attribute.timestamp": "1622200780", - "threatintel.misp.attribute.to_ids": false, - "threatintel.misp.attribute.type": "text", - "threatintel.misp.attribute.uuid": "d35c1ff8-a69c-482b-8fb0-1182988d9468", - "threatintel.misp.attribute.value": ".data", - "threatintel.misp.attribute_count": "9", - "threatintel.misp.context.attribute.category": "Artifacts dropped", - "threatintel.misp.context.attribute.comment": "", - "threatintel.misp.context.attribute.deleted": false, - "threatintel.misp.context.attribute.disable_correlation": false, - "threatintel.misp.context.attribute.distribution": "5", - "threatintel.misp.context.attribute.event_id": "3636", - "threatintel.misp.context.attribute.id": "266277", - "threatintel.misp.context.attribute.object_id": "0", - "threatintel.misp.context.attribute.sharing_group_id": "0", - "threatintel.misp.context.attribute.timestamp": "1622200249", - "threatintel.misp.context.attribute.to_ids": false, - "threatintel.misp.context.attribute.type": "windows-service-name", - "threatintel.misp.context.attribute.uuid": "3bd56a61-77f0-4885-8d1c-8bd2e39b65fb", - "threatintel.misp.context.attribute.value": "badmojopipe", - "threatintel.misp.date": "2021-05-28", - "threatintel.misp.disable_correlation": false, - "threatintel.misp.distribution": "0", - "threatintel.misp.extends_uuid": "", - "threatintel.misp.id": "3636", - "threatintel.misp.info": "Test event 6 with multiple objects and multiple attributes", - "threatintel.misp.locked": false, - "threatintel.misp.org_id": "1", - "threatintel.misp.orgc.id": "1", - "threatintel.misp.orgc.local": true, - "threatintel.misp.orgc.name": "ORGNAME", - "threatintel.misp.orgc.uuid": "78acad2d-cc2d-4785-94d6-b428a0070488", - "threatintel.misp.orgc_id": "1", - "threatintel.misp.proposal_email_lock": false, - "threatintel.misp.publish_timestamp": "0", - "threatintel.misp.published": false, - "threatintel.misp.sharing_group_id": "0", - "threatintel.misp.threat_level_id": 1, - "threatintel.misp.uuid": "81aea1d1-bb23-4bcd-9b0c-496e9ce028df", + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] MISP", + "threat.indicator.provider": "misp", + "threat.indicator.scanner_stats": 0, + "threat.indicator.type": "unknown", "user.email": "admin@admin.test", "user.roles": [ "reporting_user" @@ -1334,63 +1376,65 @@ "fileset.name": "misp", "input.type": "log", "log.offset": 39130, + "misp.attribute.category": "Other", + "misp.attribute.comment": "", + "misp.attribute.deleted": false, + "misp.attribute.disable_correlation": true, + "misp.attribute.distribution": 5, + "misp.attribute.event_id": "3636", + "misp.attribute.id": "266284", + "misp.attribute.object_id": "18211", + "misp.attribute.object_relation": "text", + "misp.attribute.sharing_group_id": "0", + "misp.attribute.timestamp": "1622200780", + "misp.attribute.to_ids": false, + "misp.attribute.type": "text", + "misp.attribute.uuid": "dc11971a-a676-4676-b24c-a45a8791e0b0", + "misp.attribute.value": "Extracted zip archive data", + "misp.attribute_count": 9, + "misp.context.attribute.category": "Artifacts dropped", + "misp.context.attribute.comment": "", + "misp.context.attribute.deleted": false, + "misp.context.attribute.disable_correlation": false, + "misp.context.attribute.distribution": 5, + "misp.context.attribute.event_id": "3636", + "misp.context.attribute.id": "266277", + "misp.context.attribute.object_id": "0", + "misp.context.attribute.sharing_group_id": "0", + "misp.context.attribute.timestamp": "1622200249", + "misp.context.attribute.to_ids": false, + "misp.context.attribute.type": "windows-service-name", + "misp.context.attribute.uuid": "3bd56a61-77f0-4885-8d1c-8bd2e39b65fb", + "misp.context.attribute.value": "badmojopipe", + "misp.date": "2021-05-28", + "misp.disable_correlation": false, + "misp.distribution": "0", + "misp.extends_uuid": "", + "misp.id": "3636", + "misp.info": "Test event 6 with multiple objects and multiple attributes", + "misp.locked": false, + "misp.org_id": "1", + "misp.orgc.id": "1", + "misp.orgc.local": true, + "misp.orgc.name": "ORGNAME", + "misp.orgc.uuid": "78acad2d-cc2d-4785-94d6-b428a0070488", + "misp.orgc_id": "1", + "misp.proposal_email_lock": false, + "misp.publish_timestamp": "0", + "misp.published": false, + "misp.sharing_group_id": "0", + "misp.threat_level_id": 1, + "misp.uuid": "81aea1d1-bb23-4bcd-9b0c-496e9ce028df", "service.type": "threatintel", "tags": [ "forwarded", "threatintel-misp" ], - "threatintel.indicator.provider": "misp", - "threatintel.indicator.scanner_stats": 0, - "threatintel.indicator.type": "unknown", - "threatintel.misp.attribute.category": "Other", - "threatintel.misp.attribute.comment": "", - "threatintel.misp.attribute.deleted": false, - "threatintel.misp.attribute.disable_correlation": true, - "threatintel.misp.attribute.distribution": "5", - "threatintel.misp.attribute.event_id": "3636", - "threatintel.misp.attribute.id": "266284", - "threatintel.misp.attribute.object_id": "18211", - "threatintel.misp.attribute.object_relation": "text", - "threatintel.misp.attribute.sharing_group_id": "0", - "threatintel.misp.attribute.timestamp": "1622200780", - "threatintel.misp.attribute.to_ids": false, - "threatintel.misp.attribute.type": "text", - "threatintel.misp.attribute.uuid": "dc11971a-a676-4676-b24c-a45a8791e0b0", - "threatintel.misp.attribute.value": "Extracted zip archive data", - "threatintel.misp.attribute_count": "9", - "threatintel.misp.context.attribute.category": "Artifacts dropped", - "threatintel.misp.context.attribute.comment": "", - "threatintel.misp.context.attribute.deleted": false, - "threatintel.misp.context.attribute.disable_correlation": false, - "threatintel.misp.context.attribute.distribution": "5", - "threatintel.misp.context.attribute.event_id": "3636", - "threatintel.misp.context.attribute.id": "266277", - "threatintel.misp.context.attribute.object_id": "0", - "threatintel.misp.context.attribute.sharing_group_id": "0", - "threatintel.misp.context.attribute.timestamp": "1622200249", - "threatintel.misp.context.attribute.to_ids": false, - "threatintel.misp.context.attribute.type": "windows-service-name", - "threatintel.misp.context.attribute.uuid": "3bd56a61-77f0-4885-8d1c-8bd2e39b65fb", - "threatintel.misp.context.attribute.value": "badmojopipe", - "threatintel.misp.date": "2021-05-28", - "threatintel.misp.disable_correlation": false, - "threatintel.misp.distribution": "0", - "threatintel.misp.extends_uuid": "", - "threatintel.misp.id": "3636", - "threatintel.misp.info": "Test event 6 with multiple objects and multiple attributes", - "threatintel.misp.locked": false, - "threatintel.misp.org_id": "1", - "threatintel.misp.orgc.id": "1", - "threatintel.misp.orgc.local": true, - "threatintel.misp.orgc.name": "ORGNAME", - "threatintel.misp.orgc.uuid": "78acad2d-cc2d-4785-94d6-b428a0070488", - "threatintel.misp.orgc_id": "1", - "threatintel.misp.proposal_email_lock": false, - "threatintel.misp.publish_timestamp": "0", - "threatintel.misp.published": false, - "threatintel.misp.sharing_group_id": "0", - "threatintel.misp.threat_level_id": 1, - "threatintel.misp.uuid": "81aea1d1-bb23-4bcd-9b0c-496e9ce028df", + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] MISP", + "threat.indicator.provider": "misp", + "threat.indicator.scanner_stats": 0, + "threat.indicator.type": "unknown", "user.email": "admin@admin.test", "user.roles": [ "reporting_user" @@ -1406,63 +1450,65 @@ "fileset.name": "misp", "input.type": "log", "log.offset": 41132, + "misp.attribute.category": "Other", + "misp.attribute.comment": "", + "misp.attribute.deleted": false, + "misp.attribute.disable_correlation": true, + "misp.attribute.distribution": 5, + "misp.attribute.event_id": "3636", + "misp.attribute.id": "266285", + "misp.attribute.object_id": "18211", + "misp.attribute.object_relation": "entropy", + "misp.attribute.sharing_group_id": "0", + "misp.attribute.timestamp": "1622200780", + "misp.attribute.to_ids": false, + "misp.attribute.type": "float", + "misp.attribute.uuid": "a85c0cbb-25a8-4bc9-b146-3cba1020e5bb", + "misp.attribute.value": "7.93280431051", + "misp.attribute_count": 9, + "misp.context.attribute.category": "Artifacts dropped", + "misp.context.attribute.comment": "", + "misp.context.attribute.deleted": false, + "misp.context.attribute.disable_correlation": false, + "misp.context.attribute.distribution": 5, + "misp.context.attribute.event_id": "3636", + "misp.context.attribute.id": "266277", + "misp.context.attribute.object_id": "0", + "misp.context.attribute.sharing_group_id": "0", + "misp.context.attribute.timestamp": "1622200249", + "misp.context.attribute.to_ids": false, + "misp.context.attribute.type": "windows-service-name", + "misp.context.attribute.uuid": "3bd56a61-77f0-4885-8d1c-8bd2e39b65fb", + "misp.context.attribute.value": "badmojopipe", + "misp.date": "2021-05-28", + "misp.disable_correlation": false, + "misp.distribution": "0", + "misp.extends_uuid": "", + "misp.id": "3636", + "misp.info": "Test event 6 with multiple objects and multiple attributes", + "misp.locked": false, + "misp.org_id": "1", + "misp.orgc.id": "1", + "misp.orgc.local": true, + "misp.orgc.name": "ORGNAME", + "misp.orgc.uuid": "78acad2d-cc2d-4785-94d6-b428a0070488", + "misp.orgc_id": "1", + "misp.proposal_email_lock": false, + "misp.publish_timestamp": "0", + "misp.published": false, + "misp.sharing_group_id": "0", + "misp.threat_level_id": 1, + "misp.uuid": "81aea1d1-bb23-4bcd-9b0c-496e9ce028df", "service.type": "threatintel", "tags": [ "forwarded", "threatintel-misp" ], - "threatintel.indicator.provider": "misp", - "threatintel.indicator.scanner_stats": 0, - "threatintel.indicator.type": "unknown", - "threatintel.misp.attribute.category": "Other", - "threatintel.misp.attribute.comment": "", - "threatintel.misp.attribute.deleted": false, - "threatintel.misp.attribute.disable_correlation": true, - "threatintel.misp.attribute.distribution": "5", - "threatintel.misp.attribute.event_id": "3636", - "threatintel.misp.attribute.id": "266285", - "threatintel.misp.attribute.object_id": "18211", - "threatintel.misp.attribute.object_relation": "entropy", - "threatintel.misp.attribute.sharing_group_id": "0", - "threatintel.misp.attribute.timestamp": "1622200780", - "threatintel.misp.attribute.to_ids": false, - "threatintel.misp.attribute.type": "float", - "threatintel.misp.attribute.uuid": "a85c0cbb-25a8-4bc9-b146-3cba1020e5bb", - "threatintel.misp.attribute.value": "7.93280431051", - "threatintel.misp.attribute_count": "9", - "threatintel.misp.context.attribute.category": "Artifacts dropped", - "threatintel.misp.context.attribute.comment": "", - "threatintel.misp.context.attribute.deleted": false, - "threatintel.misp.context.attribute.disable_correlation": false, - "threatintel.misp.context.attribute.distribution": "5", - "threatintel.misp.context.attribute.event_id": "3636", - "threatintel.misp.context.attribute.id": "266277", - "threatintel.misp.context.attribute.object_id": "0", - "threatintel.misp.context.attribute.sharing_group_id": "0", - "threatintel.misp.context.attribute.timestamp": "1622200249", - "threatintel.misp.context.attribute.to_ids": false, - "threatintel.misp.context.attribute.type": "windows-service-name", - "threatintel.misp.context.attribute.uuid": "3bd56a61-77f0-4885-8d1c-8bd2e39b65fb", - "threatintel.misp.context.attribute.value": "badmojopipe", - "threatintel.misp.date": "2021-05-28", - "threatintel.misp.disable_correlation": false, - "threatintel.misp.distribution": "0", - "threatintel.misp.extends_uuid": "", - "threatintel.misp.id": "3636", - "threatintel.misp.info": "Test event 6 with multiple objects and multiple attributes", - "threatintel.misp.locked": false, - "threatintel.misp.org_id": "1", - "threatintel.misp.orgc.id": "1", - "threatintel.misp.orgc.local": true, - "threatintel.misp.orgc.name": "ORGNAME", - "threatintel.misp.orgc.uuid": "78acad2d-cc2d-4785-94d6-b428a0070488", - "threatintel.misp.orgc_id": "1", - "threatintel.misp.proposal_email_lock": false, - "threatintel.misp.publish_timestamp": "0", - "threatintel.misp.published": false, - "threatintel.misp.sharing_group_id": "0", - "threatintel.misp.threat_level_id": 1, - "threatintel.misp.uuid": "81aea1d1-bb23-4bcd-9b0c-496e9ce028df", + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] MISP", + "threat.indicator.provider": "misp", + "threat.indicator.scanner_stats": 0, + "threat.indicator.type": "unknown", "user.email": "admin@admin.test", "user.roles": [ "reporting_user" @@ -1478,63 +1524,65 @@ "fileset.name": "misp", "input.type": "log", "log.offset": 43125, + "misp.attribute.category": "Payload delivery", + "misp.attribute.comment": "", + "misp.attribute.deleted": false, + "misp.attribute.disable_correlation": false, + "misp.attribute.distribution": 5, + "misp.attribute.event_id": "3636", + "misp.attribute.id": "266279", + "misp.attribute.object_id": "18210", + "misp.attribute.object_relation": "md5", + "misp.attribute.sharing_group_id": "0", + "misp.attribute.timestamp": "1622200348", + "misp.attribute.to_ids": true, + "misp.attribute.type": "md5", + "misp.attribute.uuid": "1c97c043-5de2-41a1-b591-3237174cd290", + "misp.attribute_count": 9, + "misp.context.attribute.category": "Artifacts dropped", + "misp.context.attribute.comment": "", + "misp.context.attribute.deleted": false, + "misp.context.attribute.disable_correlation": false, + "misp.context.attribute.distribution": 5, + "misp.context.attribute.event_id": "3636", + "misp.context.attribute.id": "266277", + "misp.context.attribute.object_id": "0", + "misp.context.attribute.sharing_group_id": "0", + "misp.context.attribute.timestamp": "1622200249", + "misp.context.attribute.to_ids": false, + "misp.context.attribute.type": "windows-service-name", + "misp.context.attribute.uuid": "3bd56a61-77f0-4885-8d1c-8bd2e39b65fb", + "misp.context.attribute.value": "badmojopipe", + "misp.date": "2021-05-28", + "misp.disable_correlation": false, + "misp.distribution": "0", + "misp.extends_uuid": "", + "misp.id": "3636", + "misp.info": "Test event 6 with multiple objects and multiple attributes", + "misp.locked": false, + "misp.org_id": "1", + "misp.orgc.id": "1", + "misp.orgc.local": true, + "misp.orgc.name": "ORGNAME", + "misp.orgc.uuid": "78acad2d-cc2d-4785-94d6-b428a0070488", + "misp.orgc_id": "1", + "misp.proposal_email_lock": false, + "misp.publish_timestamp": "0", + "misp.published": false, + "misp.sharing_group_id": "0", + "misp.threat_level_id": 1, + "misp.uuid": "81aea1d1-bb23-4bcd-9b0c-496e9ce028df", "service.type": "threatintel", "tags": [ "forwarded", "threatintel-misp" ], - "threatintel.indicator.file.hash.md5": "7392463caf95534d56460bc9f360adc1", - "threatintel.indicator.provider": "misp", - "threatintel.indicator.scanner_stats": 0, - "threatintel.indicator.type": "file", - "threatintel.misp.attribute.category": "Payload delivery", - "threatintel.misp.attribute.comment": "", - "threatintel.misp.attribute.deleted": false, - "threatintel.misp.attribute.disable_correlation": false, - "threatintel.misp.attribute.distribution": "5", - "threatintel.misp.attribute.event_id": "3636", - "threatintel.misp.attribute.id": "266279", - "threatintel.misp.attribute.object_id": "18210", - "threatintel.misp.attribute.object_relation": "md5", - "threatintel.misp.attribute.sharing_group_id": "0", - "threatintel.misp.attribute.timestamp": "1622200348", - "threatintel.misp.attribute.to_ids": true, - "threatintel.misp.attribute.type": "md5", - "threatintel.misp.attribute.uuid": "1c97c043-5de2-41a1-b591-3237174cd290", - "threatintel.misp.attribute_count": "9", - "threatintel.misp.context.attribute.category": "Artifacts dropped", - "threatintel.misp.context.attribute.comment": "", - "threatintel.misp.context.attribute.deleted": false, - "threatintel.misp.context.attribute.disable_correlation": false, - "threatintel.misp.context.attribute.distribution": "5", - "threatintel.misp.context.attribute.event_id": "3636", - "threatintel.misp.context.attribute.id": "266277", - "threatintel.misp.context.attribute.object_id": "0", - "threatintel.misp.context.attribute.sharing_group_id": "0", - "threatintel.misp.context.attribute.timestamp": "1622200249", - "threatintel.misp.context.attribute.to_ids": false, - "threatintel.misp.context.attribute.type": "windows-service-name", - "threatintel.misp.context.attribute.uuid": "3bd56a61-77f0-4885-8d1c-8bd2e39b65fb", - "threatintel.misp.context.attribute.value": "badmojopipe", - "threatintel.misp.date": "2021-05-28", - "threatintel.misp.disable_correlation": false, - "threatintel.misp.distribution": "0", - "threatintel.misp.extends_uuid": "", - "threatintel.misp.id": "3636", - "threatintel.misp.info": "Test event 6 with multiple objects and multiple attributes", - "threatintel.misp.locked": false, - "threatintel.misp.org_id": "1", - "threatintel.misp.orgc.id": "1", - "threatintel.misp.orgc.local": true, - "threatintel.misp.orgc.name": "ORGNAME", - "threatintel.misp.orgc.uuid": "78acad2d-cc2d-4785-94d6-b428a0070488", - "threatintel.misp.orgc_id": "1", - "threatintel.misp.proposal_email_lock": false, - "threatintel.misp.publish_timestamp": "0", - "threatintel.misp.published": false, - "threatintel.misp.sharing_group_id": "0", - "threatintel.misp.threat_level_id": 1, - "threatintel.misp.uuid": "81aea1d1-bb23-4bcd-9b0c-496e9ce028df", + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] MISP", + "threat.indicator.file.hash.md5": "7392463caf95534d56460bc9f360adc1", + "threat.indicator.provider": "misp", + "threat.indicator.scanner_stats": 0, + "threat.indicator.type": "file", "user.email": "admin@admin.test", "user.roles": [ "reporting_user" @@ -1550,63 +1598,65 @@ "fileset.name": "misp", "input.type": "log", "log.offset": 45136, + "misp.attribute.category": "Payload delivery", + "misp.attribute.comment": "", + "misp.attribute.deleted": false, + "misp.attribute.disable_correlation": false, + "misp.attribute.distribution": 5, + "misp.attribute.event_id": "3636", + "misp.attribute.id": "266282", + "misp.attribute.object_id": "18211", + "misp.attribute.object_relation": "md5", + "misp.attribute.sharing_group_id": "0", + "misp.attribute.timestamp": "1622200780", + "misp.attribute.to_ids": true, + "misp.attribute.type": "md5", + "misp.attribute.uuid": "f3b8696e-5390-4383-ace2-6e06bfae497d", + "misp.attribute_count": 9, + "misp.context.attribute.category": "Artifacts dropped", + "misp.context.attribute.comment": "", + "misp.context.attribute.deleted": false, + "misp.context.attribute.disable_correlation": false, + "misp.context.attribute.distribution": 5, + "misp.context.attribute.event_id": "3636", + "misp.context.attribute.id": "266277", + "misp.context.attribute.object_id": "0", + "misp.context.attribute.sharing_group_id": "0", + "misp.context.attribute.timestamp": "1622200249", + "misp.context.attribute.to_ids": false, + "misp.context.attribute.type": "windows-service-name", + "misp.context.attribute.uuid": "3bd56a61-77f0-4885-8d1c-8bd2e39b65fb", + "misp.context.attribute.value": "badmojopipe", + "misp.date": "2021-05-28", + "misp.disable_correlation": false, + "misp.distribution": "0", + "misp.extends_uuid": "", + "misp.id": "3636", + "misp.info": "Test event 6 with multiple objects and multiple attributes", + "misp.locked": false, + "misp.org_id": "1", + "misp.orgc.id": "1", + "misp.orgc.local": true, + "misp.orgc.name": "ORGNAME", + "misp.orgc.uuid": "78acad2d-cc2d-4785-94d6-b428a0070488", + "misp.orgc_id": "1", + "misp.proposal_email_lock": false, + "misp.publish_timestamp": "0", + "misp.published": false, + "misp.sharing_group_id": "0", + "misp.threat_level_id": 1, + "misp.uuid": "81aea1d1-bb23-4bcd-9b0c-496e9ce028df", "service.type": "threatintel", "tags": [ "forwarded", "threatintel-misp" ], - "threatintel.indicator.file.hash.md5": "7295463caf95534d56460bc9f360adc1", - "threatintel.indicator.provider": "misp", - "threatintel.indicator.scanner_stats": 0, - "threatintel.indicator.type": "file", - "threatintel.misp.attribute.category": "Payload delivery", - "threatintel.misp.attribute.comment": "", - "threatintel.misp.attribute.deleted": false, - "threatintel.misp.attribute.disable_correlation": false, - "threatintel.misp.attribute.distribution": "5", - "threatintel.misp.attribute.event_id": "3636", - "threatintel.misp.attribute.id": "266282", - "threatintel.misp.attribute.object_id": "18211", - "threatintel.misp.attribute.object_relation": "md5", - "threatintel.misp.attribute.sharing_group_id": "0", - "threatintel.misp.attribute.timestamp": "1622200780", - "threatintel.misp.attribute.to_ids": true, - "threatintel.misp.attribute.type": "md5", - "threatintel.misp.attribute.uuid": "f3b8696e-5390-4383-ace2-6e06bfae497d", - "threatintel.misp.attribute_count": "9", - "threatintel.misp.context.attribute.category": "Artifacts dropped", - "threatintel.misp.context.attribute.comment": "", - "threatintel.misp.context.attribute.deleted": false, - "threatintel.misp.context.attribute.disable_correlation": false, - "threatintel.misp.context.attribute.distribution": "5", - "threatintel.misp.context.attribute.event_id": "3636", - "threatintel.misp.context.attribute.id": "266277", - "threatintel.misp.context.attribute.object_id": "0", - "threatintel.misp.context.attribute.sharing_group_id": "0", - "threatintel.misp.context.attribute.timestamp": "1622200249", - "threatintel.misp.context.attribute.to_ids": false, - "threatintel.misp.context.attribute.type": "windows-service-name", - "threatintel.misp.context.attribute.uuid": "3bd56a61-77f0-4885-8d1c-8bd2e39b65fb", - "threatintel.misp.context.attribute.value": "badmojopipe", - "threatintel.misp.date": "2021-05-28", - "threatintel.misp.disable_correlation": false, - "threatintel.misp.distribution": "0", - "threatintel.misp.extends_uuid": "", - "threatintel.misp.id": "3636", - "threatintel.misp.info": "Test event 6 with multiple objects and multiple attributes", - "threatintel.misp.locked": false, - "threatintel.misp.org_id": "1", - "threatintel.misp.orgc.id": "1", - "threatintel.misp.orgc.local": true, - "threatintel.misp.orgc.name": "ORGNAME", - "threatintel.misp.orgc.uuid": "78acad2d-cc2d-4785-94d6-b428a0070488", - "threatintel.misp.orgc_id": "1", - "threatintel.misp.proposal_email_lock": false, - "threatintel.misp.publish_timestamp": "0", - "threatintel.misp.published": false, - "threatintel.misp.sharing_group_id": "0", - "threatintel.misp.threat_level_id": 1, - "threatintel.misp.uuid": "81aea1d1-bb23-4bcd-9b0c-496e9ce028df", + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] MISP", + "threat.indicator.file.hash.md5": "7295463caf95534d56460bc9f360adc1", + "threat.indicator.provider": "misp", + "threat.indicator.scanner_stats": 0, + "threat.indicator.type": "file", "user.email": "admin@admin.test", "user.roles": [ "reporting_user" @@ -1622,63 +1672,65 @@ "fileset.name": "misp", "input.type": "log", "log.offset": 47153, + "misp.attribute.category": "Payload delivery", + "misp.attribute.comment": "", + "misp.attribute.deleted": false, + "misp.attribute.disable_correlation": true, + "misp.attribute.distribution": 5, + "misp.attribute.event_id": "3636", + "misp.attribute.id": "266280", + "misp.attribute.object_id": "18210", + "misp.attribute.object_relation": "filename", + "misp.attribute.sharing_group_id": "0", + "misp.attribute.timestamp": "1622200348", + "misp.attribute.to_ids": true, + "misp.attribute.type": "filename", + "misp.attribute.uuid": "2dfcb937-e6af-4b5d-ad50-f8eb975990f3", + "misp.attribute_count": 9, + "misp.context.attribute.category": "Artifacts dropped", + "misp.context.attribute.comment": "", + "misp.context.attribute.deleted": false, + "misp.context.attribute.disable_correlation": false, + "misp.context.attribute.distribution": 5, + "misp.context.attribute.event_id": "3636", + "misp.context.attribute.id": "266277", + "misp.context.attribute.object_id": "0", + "misp.context.attribute.sharing_group_id": "0", + "misp.context.attribute.timestamp": "1622200249", + "misp.context.attribute.to_ids": false, + "misp.context.attribute.type": "windows-service-name", + "misp.context.attribute.uuid": "3bd56a61-77f0-4885-8d1c-8bd2e39b65fb", + "misp.context.attribute.value": "badmojopipe", + "misp.date": "2021-05-28", + "misp.disable_correlation": false, + "misp.distribution": "0", + "misp.extends_uuid": "", + "misp.id": "3636", + "misp.info": "Test event 6 with multiple objects and multiple attributes", + "misp.locked": false, + "misp.org_id": "1", + "misp.orgc.id": "1", + "misp.orgc.local": true, + "misp.orgc.name": "ORGNAME", + "misp.orgc.uuid": "78acad2d-cc2d-4785-94d6-b428a0070488", + "misp.orgc_id": "1", + "misp.proposal_email_lock": false, + "misp.publish_timestamp": "0", + "misp.published": false, + "misp.sharing_group_id": "0", + "misp.threat_level_id": 1, + "misp.uuid": "81aea1d1-bb23-4bcd-9b0c-496e9ce028df", "service.type": "threatintel", "tags": [ "forwarded", "threatintel-misp" ], - "threatintel.indicator.file.name": "badmojopipe.exe", - "threatintel.indicator.provider": "misp", - "threatintel.indicator.scanner_stats": 0, - "threatintel.indicator.type": "file", - "threatintel.misp.attribute.category": "Payload delivery", - "threatintel.misp.attribute.comment": "", - "threatintel.misp.attribute.deleted": false, - "threatintel.misp.attribute.disable_correlation": true, - "threatintel.misp.attribute.distribution": "5", - "threatintel.misp.attribute.event_id": "3636", - "threatintel.misp.attribute.id": "266280", - "threatintel.misp.attribute.object_id": "18210", - "threatintel.misp.attribute.object_relation": "filename", - "threatintel.misp.attribute.sharing_group_id": "0", - "threatintel.misp.attribute.timestamp": "1622200348", - "threatintel.misp.attribute.to_ids": true, - "threatintel.misp.attribute.type": "filename", - "threatintel.misp.attribute.uuid": "2dfcb937-e6af-4b5d-ad50-f8eb975990f3", - "threatintel.misp.attribute_count": "9", - "threatintel.misp.context.attribute.category": "Artifacts dropped", - "threatintel.misp.context.attribute.comment": "", - "threatintel.misp.context.attribute.deleted": false, - "threatintel.misp.context.attribute.disable_correlation": false, - "threatintel.misp.context.attribute.distribution": "5", - "threatintel.misp.context.attribute.event_id": "3636", - "threatintel.misp.context.attribute.id": "266277", - "threatintel.misp.context.attribute.object_id": "0", - "threatintel.misp.context.attribute.sharing_group_id": "0", - "threatintel.misp.context.attribute.timestamp": "1622200249", - "threatintel.misp.context.attribute.to_ids": false, - "threatintel.misp.context.attribute.type": "windows-service-name", - "threatintel.misp.context.attribute.uuid": "3bd56a61-77f0-4885-8d1c-8bd2e39b65fb", - "threatintel.misp.context.attribute.value": "badmojopipe", - "threatintel.misp.date": "2021-05-28", - "threatintel.misp.disable_correlation": false, - "threatintel.misp.distribution": "0", - "threatintel.misp.extends_uuid": "", - "threatintel.misp.id": "3636", - "threatintel.misp.info": "Test event 6 with multiple objects and multiple attributes", - "threatintel.misp.locked": false, - "threatintel.misp.org_id": "1", - "threatintel.misp.orgc.id": "1", - "threatintel.misp.orgc.local": true, - "threatintel.misp.orgc.name": "ORGNAME", - "threatintel.misp.orgc.uuid": "78acad2d-cc2d-4785-94d6-b428a0070488", - "threatintel.misp.orgc_id": "1", - "threatintel.misp.proposal_email_lock": false, - "threatintel.misp.publish_timestamp": "0", - "threatintel.misp.published": false, - "threatintel.misp.sharing_group_id": "0", - "threatintel.misp.threat_level_id": 1, - "threatintel.misp.uuid": "81aea1d1-bb23-4bcd-9b0c-496e9ce028df", + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] MISP", + "threat.indicator.file.name": "badmojopipe.exe", + "threat.indicator.provider": "misp", + "threat.indicator.scanner_stats": 0, + "threat.indicator.type": "file", "user.email": "admin@admin.test", "user.roles": [ "reporting_user" diff --git a/x-pack/filebeat/module/threatintel/otx/config/config.yml b/x-pack/filebeat/module/threatintel/otx/config/config.yml index 9e2f5169e6f..fe18e1141d3 100644 --- a/x-pack/filebeat/module/threatintel/otx/config/config.yml +++ b/x-pack/filebeat/module/threatintel/otx/config/config.yml @@ -55,17 +55,12 @@ exclude_files: [".gz$"] {{ end }} -tags: {{.tags | tojson}} -publisher_pipeline.disable_host: {{ inList .tags "forwarded" }} +tags: +{{if .preserve_original_event}} + - preserve_original_event +{{end}} +{{range $val := .tags}} + - {{$val}} +{{end}} -processors: - - decode_json_fields: - fields: [message] - target: json - - fingerprint: - fields: ["json.id"] - target_field: "@metadata._id" - - add_fields: - target: '' - fields: - ecs.version: 1.12.0 +publisher_pipeline.disable_host: {{ inList .tags "forwarded" }} diff --git a/x-pack/filebeat/module/threatintel/otx/ingest/pipeline.yml b/x-pack/filebeat/module/threatintel/otx/ingest/pipeline.yml index 4cb3ed37aef..4b3f6aeaea6 100644 --- a/x-pack/filebeat/module/threatintel/otx/ingest/pipeline.yml +++ b/x-pack/filebeat/module/threatintel/otx/ingest/pipeline.yml @@ -1,4 +1,5 @@ -description: Pipeline for parsing MISP Threat Intel +--- +description: Pipeline for parsing Abuse.ch URL Threat Intel processors: #################### # Event ECS fields # @@ -6,6 +7,9 @@ processors: - set: field: event.ingested value: "{{_ingest.timestamp}}" + - set: + field: ecs.version + value: "1.12" - set: field: event.kind value: enrichment @@ -20,108 +24,126 @@ processors: # General ECS fields # ###################### - rename: - field: json - target_field: threatintel.otx + field: message + target_field: event.original ignore_missing: true + - json: + field: event.original + target_field: otx + - fingerprint: + fields: + - otx.id + target_field: "_id" ##################### # Threat ECS Fields # ##################### + - set: + field: threat.feed.name + value: "[Filebeat] Alienvault OTX" + - set: + field: threat.feed.dashboard_id + value: "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f" ## File indicator operations - set: - field: threatintel.indicator.type + field: threat.indicator.type value: file - if: "ctx.threatintel?.otx?.type.startsWith('FileHash') || ctx.threatintel?.otx?.type == 'filepath'" + if: "ctx.otx?.type.startsWith('FileHash') || ctx.otx?.type == 'filepath'" - rename: - field: threatintel.otx.indicator - target_field: threatintel.indicator.file.hash.md5 + field: otx.indicator + target_field: threat.indicator.file.hash.md5 ignore_missing: true - if: "ctx.threatintel?.otx?.type == 'FileHash-MD5'" + if: "ctx.otx?.type == 'FileHash-MD5'" - rename: - field: threatintel.otx.indicator - target_field: threatintel.indicator.file.hash.sha1 + field: otx.indicator + target_field: threat.indicator.file.hash.sha1 ignore_missing: true - if: "ctx.threatintel?.otx?.type == 'FileHash-SHA1'" + if: "ctx.otx?.type == 'FileHash-SHA1'" - rename: - field: threatintel.otx.indicator - target_field: threatintel.indicator.file.hash.sha256 + field: otx.indicator + target_field: threat.indicator.file.hash.sha256 ignore_missing: true - if: "ctx.threatintel?.otx?.type == 'FileHash-SHA256'" + if: "ctx.otx?.type == 'FileHash-SHA256'" - rename: - field: threatintel.otx.indicator - target_field: threatintel.indicator.file.hash.pehash + field: otx.indicator + target_field: threat.indicator.file.hash.pehash ignore_missing: true - if: "ctx.threatintel?.otx?.type == 'FileHash-PEHASH'" + if: "ctx.otx?.type == 'FileHash-PEHASH'" - rename: - field: threatintel.otx.indicator - target_field: threatintel.indicator.file.hash.imphash + field: otx.indicator + target_field: threat.indicator.file.hash.imphash ignore_missing: true - if: "ctx.threatintel?.otx?.type == 'FileHash-IMPHASH'" + if: "ctx.otx?.type == 'FileHash-IMPHASH'" ## IP indicator operations - set: - field: threatintel.indicator.type + field: threat.indicator.type value: ipv4-addr - if: ctx.threatintel?.otx?.type == 'IPv4' + if: ctx.otx?.type == 'IPv4' - set: - field: threatintel.indicator.type + field: threat.indicator.type value: ipv6-addr - if: ctx.threatintel?.otx?.type == 'IPv6' + if: ctx.otx?.type == 'IPv6' - rename: - field: threatintel.otx.indicator - target_field: threatintel.indicator.ip + field: otx.indicator + target_field: threat.indicator.ip ignore_missing: true - if: "ctx?.threatintel?.indicator?.type != null && ['ipv4-addr', 'ipv6-addr'].contains(ctx?.threatintel?.indicator?.type)" + if: "ctx.threat?.indicator?.type != null && ['ipv4-addr', 'ipv6-addr'].contains(ctx.threat?.indicator?.type)" ## URL indicator operations - set: - field: threatintel.indicator.type + field: threat.indicator.type value: url - if: "ctx?.threatintel?.indicator?.type == null && ['URL', 'URI'].contains(ctx.threatintel?.otx?.type)" + if: "ctx.threat?.indicator?.type == null && ['URL', 'URI'].contains(ctx.otx?.type)" - uri_parts: - field: threatintel.otx.indicator - target_field: threatintel.indicator.url + field: otx.indicator + target_field: threat.indicator.url keep_original: true remove_if_successful: true - if: ctx?.threatintel?.indicator?.type == 'url' + if: ctx.threat?.indicator?.type == 'url' - set: - field: threatintel.indicator.url.full - value: "{{{threatintel.indicator.url.original}}}" + field: threat.indicator.url.full + value: "{{{threat.indicator.url.original}}}" ignore_empty_value: true - if: "ctx?.threatintel?.otx?.type == 'URL'" + if: "ctx.otx?.type == 'URL'" ## Email indicator operations - set: - field: threatintel.indicator.type + field: threat.indicator.type value: email-addr - if: ctx?.threatintel?.otx?.type == 'email' + if: ctx.otx?.type == 'email' - rename: - field: threatintel.otx.indicator - target_field: threatintel.indicator.email.address + field: otx.indicator + target_field: threat.indicator.email.address ignore_missing: true - if: "ctx?.threatintel?.indicator?.type == 'email-addr'" + if: "ctx.threat?.indicator?.type == 'email-addr'" ## Domain indicator operations - set: - field: threatintel.indicator.type + field: threat.indicator.type value: domain-name - if: "ctx?.threatintel?.indicator?.type == null && ['domain', 'hostname'].contains(ctx.threatintel?.otx?.type)" + if: "ctx.threat?.indicator?.type == null && ['domain', 'hostname'].contains(ctx.otx?.type)" - rename: - field: threatintel.otx.indicator - target_field: threatintel.indicator.url.domain + field: otx.indicator + target_field: threat.indicator.url.domain ignore_missing: true - if: "ctx?.threatintel?.indicator?.type == 'domain-name' && ctx.threatintel?.indicator?.url?.domain == null" + if: "ctx.threat?.indicator?.type == 'domain-name' && ctx.threat?.indicator?.url?.domain == null" ###################### # Cleanup processors # ###################### + - remove: + field: event.original + if: "ctx?.tags == null || !(ctx.tags.contains('preserve_original_event'))" + ignore_failure: true + ignore_missing: true - set: - field: threatintel.indicator.type + field: threat.indicator.type value: unknown - if: ctx?.threatintel?.indicator?.type == null + if: ctx.threat?.indicator?.type == null - script: lang: painless - if: ctx?.threatintel != null + if: ctx.otx != null source: | void handleMap(Map map) { for (def x : map.values()) { @@ -145,16 +167,16 @@ processors: handleMap(ctx); - remove: field: - - threatintel.otx.content + - otx.content ignore_missing: true - if: ctx?.threatintel?.otx?.content == "" + if: ctx.otx?.content == "" - remove: field: - - threatintel.otx.type - - threatintel.otx.id + - otx.type + - otx.id - message ignore_missing: true - if: ctx?.threatintel?.indicator?.type != null + if: ctx.threat?.indicator?.type != null on_failure: - set: field: error.message diff --git a/x-pack/filebeat/module/threatintel/otx/manifest.yml b/x-pack/filebeat/module/threatintel/otx/manifest.yml index 0fdefa51d76..72830224984 100644 --- a/x-pack/filebeat/module/threatintel/otx/manifest.yml +++ b/x-pack/filebeat/module/threatintel/otx/manifest.yml @@ -20,6 +20,8 @@ var: - name: tags default: [threatintel-otx, forwarded] - name: proxy_url + - name: preserve_original_event + default: false ingest_pipeline: - ingest/pipeline.yml diff --git a/x-pack/filebeat/module/threatintel/otx/test/otx_sample.ndjson.log-expected.json b/x-pack/filebeat/module/threatintel/otx/test/otx_sample.ndjson.log-expected.json index e56752d47c3..590bc64bfbc 100644 --- a/x-pack/filebeat/module/threatintel/otx/test/otx_sample.ndjson.log-expected.json +++ b/x-pack/filebeat/module/threatintel/otx/test/otx_sample.ndjson.log-expected.json @@ -13,8 +13,10 @@ "forwarded", "threatintel-otx" ], - "threatintel.indicator.ip": "86.104.194.30", - "threatintel.indicator.type": "ipv4-addr" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Alienvault OTX", + "threat.indicator.ip": "86.104.194.30", + "threat.indicator.type": "ipv4-addr" }, { "event.category": "threat", @@ -25,15 +27,17 @@ "fileset.name": "otx", "input.type": "log", "log.offset": 102, + "otx.description": "MD5 of a5725af4391d21a232dc6d4ad33d7d915bd190bdac9b1826b73f364dc5c1aa65", + "otx.title": "Win32:Hoblig-B", "service.type": "threatintel", "tags": [ "forwarded", "threatintel-otx" ], - "threatintel.indicator.file.hash.md5": "90421f8531f963d81cf54245b72cde80", - "threatintel.indicator.type": "file", - "threatintel.otx.description": "MD5 of a5725af4391d21a232dc6d4ad33d7d915bd190bdac9b1826b73f364dc5c1aa65", - "threatintel.otx.title": "Win32:Hoblig-B" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Alienvault OTX", + "threat.indicator.file.hash.md5": "90421f8531f963d81cf54245b72cde80", + "threat.indicator.type": "file" }, { "event.category": "threat", @@ -49,8 +53,10 @@ "forwarded", "threatintel-otx" ], - "threatintel.indicator.type": "domain-name", - "threatintel.indicator.url.domain": "ip.anysrc.net" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Alienvault OTX", + "threat.indicator.type": "domain-name", + "threat.indicator.url.domain": "ip.anysrc.net" }, { "event.category": "threat", @@ -66,8 +72,10 @@ "forwarded", "threatintel-otx" ], - "threatintel.indicator.ip": "107.173.58.176", - "threatintel.indicator.type": "ipv4-addr" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Alienvault OTX", + "threat.indicator.ip": "107.173.58.176", + "threat.indicator.type": "ipv4-addr" }, { "event.category": "threat", @@ -83,8 +91,10 @@ "forwarded", "threatintel-otx" ], - "threatintel.indicator.file.hash.sha256": "d8c70ca70fd3555a0828fede6cc1f59e2c320ede80157039b6a2f09c336d5f7a", - "threatintel.indicator.type": "file" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Alienvault OTX", + "threat.indicator.file.hash.sha256": "d8c70ca70fd3555a0828fede6cc1f59e2c320ede80157039b6a2f09c336d5f7a", + "threat.indicator.type": "file" }, { "event.category": "threat", @@ -95,14 +105,16 @@ "fileset.name": "otx", "input.type": "log", "log.offset": 688, + "otx.description": "MD5 of df9b37477a83189cd4541674e64ce29bf7bf98338ed0d635276660e0c6419d09", "service.type": "threatintel", "tags": [ "forwarded", "threatintel-otx" ], - "threatintel.indicator.file.hash.md5": "f8e58af3ffefd4037fef246e93a55dc8", - "threatintel.indicator.type": "file", - "threatintel.otx.description": "MD5 of df9b37477a83189cd4541674e64ce29bf7bf98338ed0d635276660e0c6419d09" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Alienvault OTX", + "threat.indicator.file.hash.md5": "f8e58af3ffefd4037fef246e93a55dc8", + "threat.indicator.type": "file" }, { "event.category": "threat", @@ -118,8 +130,10 @@ "forwarded", "threatintel-otx" ], - "threatintel.indicator.file.hash.sha256": "1c62f004d0c9b91d3467b1b8106772e667e7e2075470c2ec7982b63573c90c54", - "threatintel.indicator.type": "file" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Alienvault OTX", + "threat.indicator.file.hash.sha256": "1c62f004d0c9b91d3467b1b8106772e667e7e2075470c2ec7982b63573c90c54", + "threat.indicator.type": "file" }, { "event.category": "threat", @@ -130,14 +144,16 @@ "fileset.name": "otx", "input.type": "log", "log.offset": 1053, + "otx.title": "Win64:Malware-gen", "service.type": "threatintel", "tags": [ "forwarded", "threatintel-otx" ], - "threatintel.indicator.file.hash.sha256": "8d24a14f2600482d0231396b6350cf21773335ec2f0b8919763317fdab78baae", - "threatintel.indicator.type": "file", - "threatintel.otx.title": "Win64:Malware-gen" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Alienvault OTX", + "threat.indicator.file.hash.sha256": "8d24a14f2600482d0231396b6350cf21773335ec2f0b8919763317fdab78baae", + "threat.indicator.type": "file" }, { "event.category": "threat", @@ -153,8 +169,10 @@ "forwarded", "threatintel-otx" ], - "threatintel.indicator.ip": "213.252.244.38", - "threatintel.indicator.type": "ipv4-addr" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Alienvault OTX", + "threat.indicator.ip": "213.252.244.38", + "threat.indicator.type": "ipv4-addr" }, { "event.category": "threat", @@ -170,8 +188,10 @@ "forwarded", "threatintel-otx" ], - "threatintel.indicator.file.hash.sha256": "c758ec922b173820374e552c2f015ac53cc5d9f99cc92080e608652aaa63695b", - "threatintel.indicator.type": "file" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Alienvault OTX", + "threat.indicator.file.hash.sha256": "c758ec922b173820374e552c2f015ac53cc5d9f99cc92080e608652aaa63695b", + "threat.indicator.type": "file" }, { "event.category": "threat", @@ -187,8 +207,10 @@ "forwarded", "threatintel-otx" ], - "threatintel.indicator.file.hash.sha256": "0df586aa0334dcbe047d24ce859d00e537fdb5e0ca41886dab27479b6fc61ba6", - "threatintel.indicator.type": "file" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Alienvault OTX", + "threat.indicator.file.hash.sha256": "0df586aa0334dcbe047d24ce859d00e537fdb5e0ca41886dab27479b6fc61ba6", + "threat.indicator.type": "file" }, { "event.category": "threat", @@ -199,14 +221,16 @@ "fileset.name": "otx", "input.type": "log", "log.offset": 1671, + "otx.description": "MD5 of 0df586aa0334dcbe047d24ce859d00e537fdb5e0ca41886dab27479b6fc61ba6", "service.type": "threatintel", "tags": [ "forwarded", "threatintel-otx" ], - "threatintel.indicator.file.hash.md5": "aeb08b0651bc8a13dcf5e5f6c0d482f8", - "threatintel.indicator.type": "file", - "threatintel.otx.description": "MD5 of 0df586aa0334dcbe047d24ce859d00e537fdb5e0ca41886dab27479b6fc61ba6" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Alienvault OTX", + "threat.indicator.file.hash.md5": "aeb08b0651bc8a13dcf5e5f6c0d482f8", + "threat.indicator.type": "file" }, { "event.category": "threat", @@ -222,8 +246,10 @@ "forwarded", "threatintel-otx" ], - "threatintel.indicator.file.hash.sha256": "6df5e1a017dff52020c7ff6ad92fdd37494e31769e1be242f6b23d1ea2d60140", - "threatintel.indicator.type": "file" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Alienvault OTX", + "threat.indicator.file.hash.sha256": "6df5e1a017dff52020c7ff6ad92fdd37494e31769e1be242f6b23d1ea2d60140", + "threat.indicator.type": "file" }, { "event.category": "threat", @@ -239,8 +265,10 @@ "forwarded", "threatintel-otx" ], - "threatintel.indicator.file.hash.sha256": "c72fef3835f65cb380f6920b22c3488554d1af6d298562ccee92284f265c9619", - "threatintel.indicator.type": "file" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Alienvault OTX", + "threat.indicator.file.hash.sha256": "c72fef3835f65cb380f6920b22c3488554d1af6d298562ccee92284f265c9619", + "threat.indicator.type": "file" }, { "event.category": "threat", @@ -256,8 +284,10 @@ "forwarded", "threatintel-otx" ], - "threatintel.indicator.file.hash.sha256": "e711fcd0f182b214c6ec74011a395f4c853068d59eb7c57f90c4a3e1de64434a", - "threatintel.indicator.type": "file" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Alienvault OTX", + "threat.indicator.file.hash.sha256": "e711fcd0f182b214c6ec74011a395f4c853068d59eb7c57f90c4a3e1de64434a", + "threat.indicator.type": "file" }, { "event.category": "threat", @@ -273,8 +303,10 @@ "forwarded", "threatintel-otx" ], - "threatintel.indicator.file.hash.sha256": "d3ec8f4a46b21fb189fc3d58f3d87bf9897653ecdf90b7952dcc71f3b4023b4e", - "threatintel.indicator.type": "file" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Alienvault OTX", + "threat.indicator.file.hash.sha256": "d3ec8f4a46b21fb189fc3d58f3d87bf9897653ecdf90b7952dcc71f3b4023b4e", + "threat.indicator.type": "file" }, { "event.category": "threat", @@ -290,8 +322,10 @@ "forwarded", "threatintel-otx" ], - "threatintel.indicator.file.hash.sha256": "70447996722e5c04514d20b7a429d162b46546002fb0c87f512b40f16bac99bb", - "threatintel.indicator.type": "file" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Alienvault OTX", + "threat.indicator.file.hash.sha256": "70447996722e5c04514d20b7a429d162b46546002fb0c87f512b40f16bac99bb", + "threat.indicator.type": "file" }, { "event.category": "threat", @@ -302,15 +336,17 @@ "fileset.name": "otx", "input.type": "log", "log.offset": 2703, + "otx.description": "MD5 of 113af75f13547be184822f1268f984b79f35965a1b1f963d23b50a09741b0aec", + "otx.title": "Win64:Malware-gen", "service.type": "threatintel", "tags": [ "forwarded", "threatintel-otx" ], - "threatintel.indicator.file.hash.md5": "29340643ca2e6677c19e1d3bf351d654", - "threatintel.indicator.type": "file", - "threatintel.otx.description": "MD5 of 113af75f13547be184822f1268f984b79f35965a1b1f963d23b50a09741b0aec", - "threatintel.otx.title": "Win64:Malware-gen" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Alienvault OTX", + "threat.indicator.file.hash.md5": "29340643ca2e6677c19e1d3bf351d654", + "threat.indicator.type": "file" }, { "event.category": "threat", @@ -321,15 +357,17 @@ "fileset.name": "otx", "input.type": "log", "log.offset": 2919, + "otx.description": "MD5 of 9b86a50b36aea5cc4cb60573a3660cf799a9ec1f69a3d4572d3dc277361a0ad2", + "otx.title": "Win64:Malware-gen", "service.type": "threatintel", "tags": [ "forwarded", "threatintel-otx" ], - "threatintel.indicator.file.hash.md5": "86c314bc2dc37ba84f7364acd5108c2b", - "threatintel.indicator.type": "file", - "threatintel.otx.description": "MD5 of 9b86a50b36aea5cc4cb60573a3660cf799a9ec1f69a3d4572d3dc277361a0ad2", - "threatintel.otx.title": "Win64:Malware-gen" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Alienvault OTX", + "threat.indicator.file.hash.md5": "86c314bc2dc37ba84f7364acd5108c2b", + "threat.indicator.type": "file" }, { "event.category": "threat", @@ -340,15 +378,17 @@ "fileset.name": "otx", "input.type": "log", "log.offset": 3135, + "otx.description": "MD5 of 1455091954ecf9ccd6fe60cb8e982d9cfb4b3dc8414443ccfdfc444079829d56", + "otx.title": "Trojan:Win32/Occamy.B", "service.type": "threatintel", "tags": [ "forwarded", "threatintel-otx" ], - "threatintel.indicator.file.hash.md5": "cb0c1248d3899358a375888bb4e8f3fe", - "threatintel.indicator.type": "file", - "threatintel.otx.description": "MD5 of 1455091954ecf9ccd6fe60cb8e982d9cfb4b3dc8414443ccfdfc444079829d56", - "threatintel.otx.title": "Trojan:Win32/Occamy.B" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Alienvault OTX", + "threat.indicator.file.hash.md5": "cb0c1248d3899358a375888bb4e8f3fe", + "threat.indicator.type": "file" }, { "event.category": "threat", @@ -359,15 +399,17 @@ "fileset.name": "otx", "input.type": "log", "log.offset": 3355, + "otx.description": "MD5 of 3012f472969327d5f8c9dac63b8ea9c5cb0de002d16c120a6bba4685120f58b4", + "otx.title": "Win64:Malware-gen", "service.type": "threatintel", "tags": [ "forwarded", "threatintel-otx" ], - "threatintel.indicator.file.hash.md5": "d348f536e214a47655af387408b4fca5", - "threatintel.indicator.type": "file", - "threatintel.otx.description": "MD5 of 3012f472969327d5f8c9dac63b8ea9c5cb0de002d16c120a6bba4685120f58b4", - "threatintel.otx.title": "Win64:Malware-gen" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Alienvault OTX", + "threat.indicator.file.hash.md5": "d348f536e214a47655af387408b4fca5", + "threat.indicator.type": "file" }, { "event.category": "threat", @@ -378,14 +420,16 @@ "fileset.name": "otx", "input.type": "log", "log.offset": 3571, + "otx.title": "vad_contains_network_strings", "service.type": "threatintel", "tags": [ "forwarded", "threatintel-otx" ], - "threatintel.indicator.file.hash.sha256": "29ff1903832827e328ad9ec05fdf268eadd6db8b613597cf65f8740c211be413", - "threatintel.indicator.type": "file", - "threatintel.otx.title": "vad_contains_network_strings" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Alienvault OTX", + "threat.indicator.file.hash.sha256": "29ff1903832827e328ad9ec05fdf268eadd6db8b613597cf65f8740c211be413", + "threat.indicator.type": "file" }, { "event.category": "threat", @@ -401,8 +445,10 @@ "forwarded", "threatintel-otx" ], - "threatintel.indicator.file.hash.sha256": "b105891f90b2a8730bbadf02b5adeccbba539883bf75dec2ff7a5a97625dd222", - "threatintel.indicator.type": "file" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Alienvault OTX", + "threat.indicator.file.hash.sha256": "b105891f90b2a8730bbadf02b5adeccbba539883bf75dec2ff7a5a97625dd222", + "threat.indicator.type": "file" }, { "event.category": "threat", @@ -418,8 +464,10 @@ "forwarded", "threatintel-otx" ], - "threatintel.indicator.file.hash.sha256": "e4db5405ac7ab517d43722e1ca8d653ea4a32802bc8a5410d032275eedc7b7ee", - "threatintel.indicator.type": "file" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Alienvault OTX", + "threat.indicator.file.hash.sha256": "e4db5405ac7ab517d43722e1ca8d653ea4a32802bc8a5410d032275eedc7b7ee", + "threat.indicator.type": "file" }, { "event.category": "threat", @@ -430,14 +478,16 @@ "fileset.name": "otx", "input.type": "log", "log.offset": 4098, + "otx.title": "Win.Malware.TrickbotSystemInfo-6335590-0", "service.type": "threatintel", "tags": [ "forwarded", "threatintel-otx" ], - "threatintel.indicator.file.hash.sha256": "465e7c1e36899284da5c4425dfd687af2496f397fe60c85ea2b4d85dff5a08aa", - "threatintel.indicator.type": "file", - "threatintel.otx.title": "Win.Malware.TrickbotSystemInfo-6335590-0" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Alienvault OTX", + "threat.indicator.file.hash.sha256": "465e7c1e36899284da5c4425dfd687af2496f397fe60c85ea2b4d85dff5a08aa", + "threat.indicator.type": "file" }, { "event.category": "threat", @@ -453,8 +503,10 @@ "forwarded", "threatintel-otx" ], - "threatintel.indicator.file.hash.sha256": "5051906d6ed1b2ae9c9a9f070ef73c9be8f591d2e41d144649a0dc96e28d0400", - "threatintel.indicator.type": "file" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Alienvault OTX", + "threat.indicator.file.hash.sha256": "5051906d6ed1b2ae9c9a9f070ef73c9be8f591d2e41d144649a0dc96e28d0400", + "threat.indicator.type": "file" }, { "event.category": "threat", @@ -465,15 +517,17 @@ "fileset.name": "otx", "input.type": "log", "log.offset": 4470, + "otx.description": "MD5 of 465e7c1e36899284da5c4425dfd687af2496f397fe60c85ea2b4d85dff5a08aa", + "otx.title": "Win.Malware.TrickbotSystemInfo-6335590-0", "service.type": "threatintel", "tags": [ "forwarded", "threatintel-otx" ], - "threatintel.indicator.file.hash.md5": "14b74cb9be8cad8eb5fa8842d00bb692", - "threatintel.indicator.type": "file", - "threatintel.otx.description": "MD5 of 465e7c1e36899284da5c4425dfd687af2496f397fe60c85ea2b4d85dff5a08aa", - "threatintel.otx.title": "Win.Malware.TrickbotSystemInfo-6335590-0" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Alienvault OTX", + "threat.indicator.file.hash.md5": "14b74cb9be8cad8eb5fa8842d00bb692", + "threat.indicator.type": "file" }, { "event.category": "threat", @@ -484,15 +538,17 @@ "fileset.name": "otx", "input.type": "log", "log.offset": 4709, + "otx.description": "SHA1 of 465e7c1e36899284da5c4425dfd687af2496f397fe60c85ea2b4d85dff5a08aa", + "otx.title": "Win.Malware.TrickbotSystemInfo-6335590-0", "service.type": "threatintel", "tags": [ "forwarded", "threatintel-otx" ], - "threatintel.indicator.file.hash.sha1": "a5b59f7d133e354dfc73f40517aab730f322f0ef", - "threatintel.indicator.type": "file", - "threatintel.otx.description": "SHA1 of 465e7c1e36899284da5c4425dfd687af2496f397fe60c85ea2b4d85dff5a08aa", - "threatintel.otx.title": "Win.Malware.TrickbotSystemInfo-6335590-0" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Alienvault OTX", + "threat.indicator.file.hash.sha1": "a5b59f7d133e354dfc73f40517aab730f322f0ef", + "threat.indicator.type": "file" }, { "event.category": "threat", @@ -508,8 +564,10 @@ "forwarded", "threatintel-otx" ], - "threatintel.indicator.file.hash.sha256": "8d3f68b16f0710f858d8c1d2c699260e6f43161a5510abb0e7ba567bd72c965b", - "threatintel.indicator.type": "file" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Alienvault OTX", + "threat.indicator.file.hash.sha256": "8d3f68b16f0710f858d8c1d2c699260e6f43161a5510abb0e7ba567bd72c965b", + "threat.indicator.type": "file" }, { "event.category": "threat", @@ -520,15 +578,17 @@ "fileset.name": "otx", "input.type": "log", "log.offset": 5125, + "otx.description": "MD5 of 5cb822616d2c9435c9ddd060d6abdbc286ab57cfcf6dc64768c52976029a925b", + "otx.title": "vad_contains_network_strings", "service.type": "threatintel", "tags": [ "forwarded", "threatintel-otx" ], - "threatintel.indicator.file.hash.md5": "ff2dcea4963e060a658f4dffbb119529", - "threatintel.indicator.type": "file", - "threatintel.otx.description": "MD5 of 5cb822616d2c9435c9ddd060d6abdbc286ab57cfcf6dc64768c52976029a925b", - "threatintel.otx.title": "vad_contains_network_strings" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Alienvault OTX", + "threat.indicator.file.hash.md5": "ff2dcea4963e060a658f4dffbb119529", + "threat.indicator.type": "file" }, { "event.category": "threat", @@ -539,15 +599,17 @@ "fileset.name": "otx", "input.type": "log", "log.offset": 5352, + "otx.description": "MD5 of 29ff1903832827e328ad9ec05fdf268eadd6db8b613597cf65f8740c211be413", + "otx.title": "vad_contains_network_strings", "service.type": "threatintel", "tags": [ "forwarded", "threatintel-otx" ], - "threatintel.indicator.file.hash.md5": "0d73f1a1c4b2f8723fffc83eb3d00f31", - "threatintel.indicator.type": "file", - "threatintel.otx.description": "MD5 of 29ff1903832827e328ad9ec05fdf268eadd6db8b613597cf65f8740c211be413", - "threatintel.otx.title": "vad_contains_network_strings" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Alienvault OTX", + "threat.indicator.file.hash.md5": "0d73f1a1c4b2f8723fffc83eb3d00f31", + "threat.indicator.type": "file" }, { "event.category": "threat", @@ -563,8 +625,10 @@ "forwarded", "threatintel-otx" ], - "threatintel.indicator.ip": "185.25.50.167", - "threatintel.indicator.type": "ipv4-addr" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Alienvault OTX", + "threat.indicator.ip": "185.25.50.167", + "threat.indicator.type": "ipv4-addr" }, { "event.category": "threat", @@ -580,8 +644,10 @@ "forwarded", "threatintel-otx" ], - "threatintel.indicator.file.hash.sha256": "d35a30264c0698709ad554489004e0077e263d354ced0c54552a0b500f91ecc0", - "threatintel.indicator.type": "file" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Alienvault OTX", + "threat.indicator.file.hash.sha256": "d35a30264c0698709ad554489004e0077e263d354ced0c54552a0b500f91ecc0", + "threat.indicator.type": "file" }, { "event.category": "threat", @@ -597,8 +663,10 @@ "forwarded", "threatintel-otx" ], - "threatintel.indicator.file.hash.sha256": "5264b455f453820be629a324196131492ff03c80491e823ac06657c9387250dd", - "threatintel.indicator.type": "file" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Alienvault OTX", + "threat.indicator.file.hash.sha256": "5264b455f453820be629a324196131492ff03c80491e823ac06657c9387250dd", + "threat.indicator.type": "file" }, { "event.category": "threat", @@ -609,14 +677,16 @@ "fileset.name": "otx", "input.type": "log", "log.offset": 6018, + "otx.title": "Trojan:Win32/Occamy.B", "service.type": "threatintel", "tags": [ "forwarded", "threatintel-otx" ], - "threatintel.indicator.file.hash.sha256": "1455091954ecf9ccd6fe60cb8e982d9cfb4b3dc8414443ccfdfc444079829d56", - "threatintel.indicator.type": "file", - "threatintel.otx.title": "Trojan:Win32/Occamy.B" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Alienvault OTX", + "threat.indicator.file.hash.sha256": "1455091954ecf9ccd6fe60cb8e982d9cfb4b3dc8414443ccfdfc444079829d56", + "threat.indicator.type": "file" }, { "event.category": "threat", @@ -627,14 +697,16 @@ "fileset.name": "otx", "input.type": "log", "log.offset": 6204, + "otx.title": "Win64:Malware-gen", "service.type": "threatintel", "tags": [ "forwarded", "threatintel-otx" ], - "threatintel.indicator.file.hash.sha256": "3012f472969327d5f8c9dac63b8ea9c5cb0de002d16c120a6bba4685120f58b4", - "threatintel.indicator.type": "file", - "threatintel.otx.title": "Win64:Malware-gen" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Alienvault OTX", + "threat.indicator.file.hash.sha256": "3012f472969327d5f8c9dac63b8ea9c5cb0de002d16c120a6bba4685120f58b4", + "threat.indicator.type": "file" }, { "event.category": "threat", @@ -650,8 +722,10 @@ "forwarded", "threatintel-otx" ], - "threatintel.indicator.file.hash.sha256": "b8e463789a076b16a90d1aae73cea9d3880ac0ead1fd16587b8cd79e37a1a3d8", - "threatintel.indicator.type": "file" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Alienvault OTX", + "threat.indicator.file.hash.sha256": "b8e463789a076b16a90d1aae73cea9d3880ac0ead1fd16587b8cd79e37a1a3d8", + "threat.indicator.type": "file" }, { "event.category": "threat", @@ -662,14 +736,16 @@ "fileset.name": "otx", "input.type": "log", "log.offset": 6553, + "otx.title": "Win64:Malware-gen", "service.type": "threatintel", "tags": [ "forwarded", "threatintel-otx" ], - "threatintel.indicator.file.hash.sha256": "113af75f13547be184822f1268f984b79f35965a1b1f963d23b50a09741b0aec", - "threatintel.indicator.type": "file", - "threatintel.otx.title": "Win64:Malware-gen" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Alienvault OTX", + "threat.indicator.file.hash.sha256": "113af75f13547be184822f1268f984b79f35965a1b1f963d23b50a09741b0aec", + "threat.indicator.type": "file" }, { "event.category": "threat", @@ -680,14 +756,16 @@ "fileset.name": "otx", "input.type": "log", "log.offset": 6735, + "otx.title": "Win64:Malware-gen", "service.type": "threatintel", "tags": [ "forwarded", "threatintel-otx" ], - "threatintel.indicator.file.hash.sha256": "9b86a50b36aea5cc4cb60573a3660cf799a9ec1f69a3d4572d3dc277361a0ad2", - "threatintel.indicator.type": "file", - "threatintel.otx.title": "Win64:Malware-gen" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Alienvault OTX", + "threat.indicator.file.hash.sha256": "9b86a50b36aea5cc4cb60573a3660cf799a9ec1f69a3d4572d3dc277361a0ad2", + "threat.indicator.type": "file" }, { "event.category": "threat", @@ -703,8 +781,10 @@ "forwarded", "threatintel-otx" ], - "threatintel.indicator.file.hash.sha256": "c51024bb119211c335f95e731cfa9a744fcdb645a57d35fb379d01b7dbdd098e", - "threatintel.indicator.type": "file" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Alienvault OTX", + "threat.indicator.file.hash.sha256": "c51024bb119211c335f95e731cfa9a744fcdb645a57d35fb379d01b7dbdd098e", + "threat.indicator.type": "file" }, { "event.category": "threat", @@ -715,15 +795,17 @@ "fileset.name": "otx", "input.type": "log", "log.offset": 7084, + "otx.description": "SHA1 of 9b86a50b36aea5cc4cb60573a3660cf799a9ec1f69a3d4572d3dc277361a0ad2", + "otx.title": "Win64:Malware-gen", "service.type": "threatintel", "tags": [ "forwarded", "threatintel-otx" ], - "threatintel.indicator.file.hash.sha1": "ad20c6fac565f901c82a21b70f9739037eb54818", - "threatintel.indicator.type": "file", - "threatintel.otx.description": "SHA1 of 9b86a50b36aea5cc4cb60573a3660cf799a9ec1f69a3d4572d3dc277361a0ad2", - "threatintel.otx.title": "Win64:Malware-gen" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Alienvault OTX", + "threat.indicator.file.hash.sha1": "ad20c6fac565f901c82a21b70f9739037eb54818", + "threat.indicator.type": "file" }, { "event.category": "threat", @@ -734,15 +816,17 @@ "fileset.name": "otx", "input.type": "log", "log.offset": 7310, + "otx.description": "SHA1 of 3012f472969327d5f8c9dac63b8ea9c5cb0de002d16c120a6bba4685120f58b4", + "otx.title": "Win64:Malware-gen", "service.type": "threatintel", "tags": [ "forwarded", "threatintel-otx" ], - "threatintel.indicator.file.hash.sha1": "13f11e273f9a4a56557f03821c3bfd591cca6ebc", - "threatintel.indicator.type": "file", - "threatintel.otx.description": "SHA1 of 3012f472969327d5f8c9dac63b8ea9c5cb0de002d16c120a6bba4685120f58b4", - "threatintel.otx.title": "Win64:Malware-gen" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Alienvault OTX", + "threat.indicator.file.hash.sha1": "13f11e273f9a4a56557f03821c3bfd591cca6ebc", + "threat.indicator.type": "file" }, { "event.category": "threat", @@ -753,15 +837,17 @@ "fileset.name": "otx", "input.type": "log", "log.offset": 7536, + "otx.description": "SHA1 of 113af75f13547be184822f1268f984b79f35965a1b1f963d23b50a09741b0aec", + "otx.title": "Win64:Malware-gen", "service.type": "threatintel", "tags": [ "forwarded", "threatintel-otx" ], - "threatintel.indicator.file.hash.sha1": "1581fe76e3c96dc33182daafd09c8cf5c17004e0", - "threatintel.indicator.type": "file", - "threatintel.otx.description": "SHA1 of 113af75f13547be184822f1268f984b79f35965a1b1f963d23b50a09741b0aec", - "threatintel.otx.title": "Win64:Malware-gen" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Alienvault OTX", + "threat.indicator.file.hash.sha1": "1581fe76e3c96dc33182daafd09c8cf5c17004e0", + "threat.indicator.type": "file" }, { "event.category": "threat", @@ -772,15 +858,17 @@ "fileset.name": "otx", "input.type": "log", "log.offset": 7762, + "otx.description": "SHA1 of 1455091954ecf9ccd6fe60cb8e982d9cfb4b3dc8414443ccfdfc444079829d56", + "otx.title": "Trojan:Win32/Occamy.B", "service.type": "threatintel", "tags": [ "forwarded", "threatintel-otx" ], - "threatintel.indicator.file.hash.sha1": "b72e75e9e901a44b655a5cf89cf0eadcaff46037", - "threatintel.indicator.type": "file", - "threatintel.otx.description": "SHA1 of 1455091954ecf9ccd6fe60cb8e982d9cfb4b3dc8414443ccfdfc444079829d56", - "threatintel.otx.title": "Trojan:Win32/Occamy.B" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Alienvault OTX", + "threat.indicator.file.hash.sha1": "b72e75e9e901a44b655a5cf89cf0eadcaff46037", + "threat.indicator.type": "file" }, { "event.category": "threat", @@ -796,8 +884,10 @@ "forwarded", "threatintel-otx" ], - "threatintel.indicator.type": "domain-name", - "threatintel.indicator.url.domain": "maper.info" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Alienvault OTX", + "threat.indicator.type": "domain-name", + "threat.indicator.url.domain": "maper.info" }, { "event.category": "threat", @@ -813,8 +903,10 @@ "forwarded", "threatintel-otx" ], - "threatintel.indicator.ip": "213.252.244.126", - "threatintel.indicator.type": "ipv4-addr" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Alienvault OTX", + "threat.indicator.ip": "213.252.244.126", + "threat.indicator.type": "ipv4-addr" }, { "event.category": "threat", @@ -830,8 +922,10 @@ "forwarded", "threatintel-otx" ], - "threatintel.indicator.ip": "78.129.139.131", - "threatintel.indicator.type": "ipv4-addr" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Alienvault OTX", + "threat.indicator.ip": "78.129.139.131", + "threat.indicator.type": "ipv4-addr" }, { "event.category": "threat", @@ -842,14 +936,16 @@ "fileset.name": "otx", "input.type": "log", "log.offset": 8309, + "otx.title": "xor_0x20_xord_javascript", "service.type": "threatintel", "tags": [ "forwarded", "threatintel-otx" ], - "threatintel.indicator.file.hash.sha256": "9af8a93519d22ed04ffb9ccf6861c9df1b77dc5d22e0aeaff4a582dbf8660ba6", - "threatintel.indicator.type": "file", - "threatintel.otx.title": "xor_0x20_xord_javascript" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Alienvault OTX", + "threat.indicator.file.hash.sha256": "9af8a93519d22ed04ffb9ccf6861c9df1b77dc5d22e0aeaff4a582dbf8660ba6", + "threat.indicator.type": "file" }, { "event.category": "threat", @@ -860,14 +956,16 @@ "fileset.name": "otx", "input.type": "log", "log.offset": 8498, + "otx.title": "xor_0x20_xord_javascript", "service.type": "threatintel", "tags": [ "forwarded", "threatintel-otx" ], - "threatintel.indicator.file.hash.sha256": "be9fb556a3c7aef0329e768d7f903e7dd42a821abc663e11fb637ce33b007087", - "threatintel.indicator.type": "file", - "threatintel.otx.title": "xor_0x20_xord_javascript" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Alienvault OTX", + "threat.indicator.file.hash.sha256": "be9fb556a3c7aef0329e768d7f903e7dd42a821abc663e11fb637ce33b007087", + "threat.indicator.type": "file" }, { "event.category": "threat", @@ -878,14 +976,16 @@ "fileset.name": "otx", "input.type": "log", "log.offset": 8687, + "otx.title": "xor_0x20_xord_javascript", "service.type": "threatintel", "tags": [ "forwarded", "threatintel-otx" ], - "threatintel.indicator.file.hash.sha256": "3bfec096c4837d1e6485fe0ae0ea6f1c0b44edc611d4f2204cc9cf73c985cbc2", - "threatintel.indicator.type": "file", - "threatintel.otx.title": "xor_0x20_xord_javascript" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Alienvault OTX", + "threat.indicator.file.hash.sha256": "3bfec096c4837d1e6485fe0ae0ea6f1c0b44edc611d4f2204cc9cf73c985cbc2", + "threat.indicator.type": "file" }, { "event.category": "threat", @@ -896,14 +996,16 @@ "fileset.name": "otx", "input.type": "log", "log.offset": 8876, + "otx.title": "xor_0x20_xord_javascript", "service.type": "threatintel", "tags": [ "forwarded", "threatintel-otx" ], - "threatintel.indicator.file.hash.sha256": "dff2e39b2e008ea89a3d6b36dcd9b8c927fb501d60c1ad5a52ed1ffe225da2e2", - "threatintel.indicator.type": "file", - "threatintel.otx.title": "xor_0x20_xord_javascript" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Alienvault OTX", + "threat.indicator.file.hash.sha256": "dff2e39b2e008ea89a3d6b36dcd9b8c927fb501d60c1ad5a52ed1ffe225da2e2", + "threat.indicator.type": "file" }, { "event.category": "threat", @@ -914,14 +1016,16 @@ "fileset.name": "otx", "input.type": "log", "log.offset": 9065, + "otx.title": "xor_0x20_xord_javascript", "service.type": "threatintel", "tags": [ "forwarded", "threatintel-otx" ], - "threatintel.indicator.file.hash.sha256": "6b4d271a48d118843aee3dee4481fa2930732ed7075db3241a8991418f00d92b", - "threatintel.indicator.type": "file", - "threatintel.otx.title": "xor_0x20_xord_javascript" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Alienvault OTX", + "threat.indicator.file.hash.sha256": "6b4d271a48d118843aee3dee4481fa2930732ed7075db3241a8991418f00d92b", + "threat.indicator.type": "file" }, { "event.category": "threat", @@ -932,14 +1036,16 @@ "fileset.name": "otx", "input.type": "log", "log.offset": 9254, + "otx.title": "xor_0x20_xord_javascript", "service.type": "threatintel", "tags": [ "forwarded", "threatintel-otx" ], - "threatintel.indicator.file.hash.sha256": "26de4265303491bed1424d85b263481ac153c2b3513f9ee48ffb42c12312ac43", - "threatintel.indicator.type": "file", - "threatintel.otx.title": "xor_0x20_xord_javascript" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Alienvault OTX", + "threat.indicator.file.hash.sha256": "26de4265303491bed1424d85b263481ac153c2b3513f9ee48ffb42c12312ac43", + "threat.indicator.type": "file" }, { "event.category": "threat", @@ -950,14 +1056,16 @@ "fileset.name": "otx", "input.type": "log", "log.offset": 9443, + "otx.title": "xor_0x20_xord_javascript", "service.type": "threatintel", "tags": [ "forwarded", "threatintel-otx" ], - "threatintel.indicator.file.hash.sha256": "02f54da6c6f2f87ff7b713d46e058dedac1cedabd693643bb7f6dfe994b2105d", - "threatintel.indicator.type": "file", - "threatintel.otx.title": "xor_0x20_xord_javascript" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Alienvault OTX", + "threat.indicator.file.hash.sha256": "02f54da6c6f2f87ff7b713d46e058dedac1cedabd693643bb7f6dfe994b2105d", + "threat.indicator.type": "file" }, { "event.category": "threat", @@ -973,8 +1081,10 @@ "forwarded", "threatintel-otx" ], - "threatintel.indicator.ip": "103.13.67.4", - "threatintel.indicator.type": "ipv4-addr" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Alienvault OTX", + "threat.indicator.ip": "103.13.67.4", + "threat.indicator.type": "ipv4-addr" }, { "event.category": "threat", @@ -990,8 +1100,10 @@ "forwarded", "threatintel-otx" ], - "threatintel.indicator.ip": "80.90.87.201", - "threatintel.indicator.type": "ipv4-addr" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Alienvault OTX", + "threat.indicator.ip": "80.90.87.201", + "threat.indicator.type": "ipv4-addr" }, { "event.category": "threat", @@ -1007,8 +1119,10 @@ "forwarded", "threatintel-otx" ], - "threatintel.indicator.ip": "80.80.163.182", - "threatintel.indicator.type": "ipv4-addr" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Alienvault OTX", + "threat.indicator.ip": "80.80.163.182", + "threat.indicator.type": "ipv4-addr" }, { "event.category": "threat", @@ -1024,8 +1138,10 @@ "forwarded", "threatintel-otx" ], - "threatintel.indicator.ip": "91.187.114.210", - "threatintel.indicator.type": "ipv4-addr" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Alienvault OTX", + "threat.indicator.ip": "91.187.114.210", + "threat.indicator.type": "ipv4-addr" }, { "event.category": "threat", @@ -1041,8 +1157,10 @@ "forwarded", "threatintel-otx" ], - "threatintel.indicator.ip": "170.238.117.187", - "threatintel.indicator.type": "ipv4-addr" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Alienvault OTX", + "threat.indicator.ip": "170.238.117.187", + "threat.indicator.type": "ipv4-addr" }, { "event.category": "threat", @@ -1058,8 +1176,10 @@ "forwarded", "threatintel-otx" ], - "threatintel.indicator.file.hash.sha256": "e999b83629355ec7ff3b6fda465ef53ce6992c9327344fbf124f7eb37808389d", - "threatintel.indicator.type": "file" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Alienvault OTX", + "threat.indicator.file.hash.sha256": "e999b83629355ec7ff3b6fda465ef53ce6992c9327344fbf124f7eb37808389d", + "threat.indicator.type": "file" }, { "event.category": "threat", @@ -1075,8 +1195,10 @@ "forwarded", "threatintel-otx" ], - "threatintel.indicator.ip": "103.84.238.3", - "threatintel.indicator.type": "ipv4-addr" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Alienvault OTX", + "threat.indicator.ip": "103.84.238.3", + "threat.indicator.type": "ipv4-addr" }, { "event.category": "threat", @@ -1092,8 +1214,10 @@ "forwarded", "threatintel-otx" ], - "threatintel.indicator.ip": "179.43.158.171", - "threatintel.indicator.type": "ipv4-addr" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Alienvault OTX", + "threat.indicator.ip": "179.43.158.171", + "threat.indicator.type": "ipv4-addr" }, { "event.category": "threat", @@ -1109,8 +1233,10 @@ "forwarded", "threatintel-otx" ], - "threatintel.indicator.ip": "198.211.116.199", - "threatintel.indicator.type": "ipv4-addr" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Alienvault OTX", + "threat.indicator.ip": "198.211.116.199", + "threat.indicator.type": "ipv4-addr" }, { "event.category": "threat", @@ -1121,14 +1247,16 @@ "fileset.name": "otx", "input.type": "log", "log.offset": 10641, + "otx.title": "Trickbot", "service.type": "threatintel", "tags": [ "forwarded", "threatintel-otx" ], - "threatintel.indicator.ip": "203.176.135.102", - "threatintel.indicator.type": "ipv4-addr", - "threatintel.otx.title": "Trickbot" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Alienvault OTX", + "threat.indicator.ip": "203.176.135.102", + "threat.indicator.type": "ipv4-addr" }, { "event.category": "threat", @@ -1144,8 +1272,10 @@ "forwarded", "threatintel-otx" ], - "threatintel.indicator.type": "domain-name", - "threatintel.indicator.url.domain": "fotmailz.com" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Alienvault OTX", + "threat.indicator.type": "domain-name", + "threat.indicator.url.domain": "fotmailz.com" }, { "event.category": "threat", @@ -1161,8 +1291,10 @@ "forwarded", "threatintel-otx" ], - "threatintel.indicator.type": "domain-name", - "threatintel.indicator.url.domain": "pori89g5jqo3v8.com" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Alienvault OTX", + "threat.indicator.type": "domain-name", + "threat.indicator.url.domain": "pori89g5jqo3v8.com" }, { "event.category": "threat", @@ -1178,8 +1310,10 @@ "forwarded", "threatintel-otx" ], - "threatintel.indicator.type": "domain-name", - "threatintel.indicator.url.domain": "sebco.co.ke" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Alienvault OTX", + "threat.indicator.type": "domain-name", + "threat.indicator.url.domain": "sebco.co.ke" }, { "event.category": "threat", @@ -1190,14 +1324,16 @@ "fileset.name": "otx", "input.type": "log", "log.offset": 11077, + "otx.title": "Trickbot", "service.type": "threatintel", "tags": [ "forwarded", "threatintel-otx" ], - "threatintel.indicator.ip": "177.74.232.124", - "threatintel.indicator.type": "ipv4-addr", - "threatintel.otx.title": "Trickbot" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Alienvault OTX", + "threat.indicator.ip": "177.74.232.124", + "threat.indicator.type": "ipv4-addr" }, { "event.category": "threat", @@ -1213,8 +1349,10 @@ "forwarded", "threatintel-otx" ], - "threatintel.indicator.type": "domain-name", - "threatintel.indicator.url.domain": "chishir.com" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Alienvault OTX", + "threat.indicator.type": "domain-name", + "threat.indicator.url.domain": "chishir.com" }, { "event.category": "threat", @@ -1230,8 +1368,10 @@ "forwarded", "threatintel-otx" ], - "threatintel.indicator.type": "domain-name", - "threatintel.indicator.url.domain": "kostunivo.com" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Alienvault OTX", + "threat.indicator.type": "domain-name", + "threat.indicator.url.domain": "kostunivo.com" }, { "event.category": "threat", @@ -1247,8 +1387,10 @@ "forwarded", "threatintel-otx" ], - "threatintel.indicator.type": "domain-name", - "threatintel.indicator.url.domain": "mangoclone.com" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Alienvault OTX", + "threat.indicator.type": "domain-name", + "threat.indicator.url.domain": "mangoclone.com" }, { "event.category": "threat", @@ -1264,8 +1406,10 @@ "forwarded", "threatintel-otx" ], - "threatintel.indicator.type": "domain-name", - "threatintel.indicator.url.domain": "onixcellent.com" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Alienvault OTX", + "threat.indicator.type": "domain-name", + "threat.indicator.url.domain": "onixcellent.com" }, { "event.category": "threat", @@ -1276,14 +1420,16 @@ "fileset.name": "otx", "input.type": "log", "log.offset": 11618, + "otx.title": "Win64:Malware-gen", "service.type": "threatintel", "tags": [ "forwarded", "threatintel-otx" ], - "threatintel.indicator.file.hash.sha1": "fc0efd612ad528795472e99cae5944b68b8e26dc", - "threatintel.indicator.type": "file", - "threatintel.otx.title": "Win64:Malware-gen" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Alienvault OTX", + "threat.indicator.file.hash.sha1": "fc0efd612ad528795472e99cae5944b68b8e26dc", + "threat.indicator.type": "file" }, { "event.category": "threat", @@ -1294,14 +1440,16 @@ "fileset.name": "otx", "input.type": "log", "log.offset": 11774, + "otx.title": "Sf:ShellCode-DZ\\ [Trj]", "service.type": "threatintel", "tags": [ "forwarded", "threatintel-otx" ], - "threatintel.indicator.file.hash.sha1": "24d4bbc982a6a561f0426a683b9617de1a96a74a", - "threatintel.indicator.type": "file", - "threatintel.otx.title": "Sf:ShellCode-DZ\\ [Trj]" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Alienvault OTX", + "threat.indicator.file.hash.sha1": "24d4bbc982a6a561f0426a683b9617de1a96a74a", + "threat.indicator.type": "file" }, { "event.category": "threat", @@ -1312,14 +1460,16 @@ "fileset.name": "otx", "input.type": "log", "log.offset": 11936, + "otx.title": "Win64:Malware-gen", "service.type": "threatintel", "tags": [ "forwarded", "threatintel-otx" ], - "threatintel.indicator.file.hash.sha1": "fa98074dc18ad7e2d357b5d168c00a91256d87d1", - "threatintel.indicator.type": "file", - "threatintel.otx.title": "Win64:Malware-gen" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Alienvault OTX", + "threat.indicator.file.hash.sha1": "fa98074dc18ad7e2d357b5d168c00a91256d87d1", + "threat.indicator.type": "file" }, { "event.category": "threat", @@ -1330,14 +1480,16 @@ "fileset.name": "otx", "input.type": "log", "log.offset": 12092, + "otx.title": "Win64:Malware-gen", "service.type": "threatintel", "tags": [ "forwarded", "threatintel-otx" ], - "threatintel.indicator.file.hash.sha1": "e5dc7c8bfa285b61dda1618f0ade9c256be75d1a", - "threatintel.indicator.type": "file", - "threatintel.otx.title": "Win64:Malware-gen" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Alienvault OTX", + "threat.indicator.file.hash.sha1": "e5dc7c8bfa285b61dda1618f0ade9c256be75d1a", + "threat.indicator.type": "file" }, { "event.category": "threat", @@ -1348,14 +1500,16 @@ "fileset.name": "otx", "input.type": "log", "log.offset": 12248, + "otx.title": "Trickbot", "service.type": "threatintel", "tags": [ "forwarded", "threatintel-otx" ], - "threatintel.indicator.ip": "96.9.77.142", - "threatintel.indicator.type": "ipv4-addr", - "threatintel.otx.title": "Trickbot" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Alienvault OTX", + "threat.indicator.ip": "96.9.77.142", + "threat.indicator.type": "ipv4-addr" }, { "event.category": "threat", @@ -1371,8 +1525,10 @@ "forwarded", "threatintel-otx" ], - "threatintel.indicator.ip": "36.89.106.69", - "threatintel.indicator.type": "ipv4-addr" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Alienvault OTX", + "threat.indicator.ip": "36.89.106.69", + "threat.indicator.type": "ipv4-addr" }, { "event.category": "threat", @@ -1388,8 +1544,10 @@ "forwarded", "threatintel-otx" ], - "threatintel.indicator.ip": "96.9.73.73", - "threatintel.indicator.type": "ipv4-addr" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Alienvault OTX", + "threat.indicator.ip": "96.9.73.73", + "threat.indicator.type": "ipv4-addr" }, { "event.category": "threat", @@ -1400,15 +1558,17 @@ "fileset.name": "otx", "input.type": "log", "log.offset": 12563, + "otx.description": "MD5 of 9af8a93519d22ed04ffb9ccf6861c9df1b77dc5d22e0aeaff4a582dbf8660ba6", + "otx.title": "xor_0x20_xord_javascript", "service.type": "threatintel", "tags": [ "forwarded", "threatintel-otx" ], - "threatintel.indicator.file.hash.md5": "10ec3571596c30b9993b89f12d29d23c", - "threatintel.indicator.type": "file", - "threatintel.otx.description": "MD5 of 9af8a93519d22ed04ffb9ccf6861c9df1b77dc5d22e0aeaff4a582dbf8660ba6", - "threatintel.otx.title": "xor_0x20_xord_javascript" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Alienvault OTX", + "threat.indicator.file.hash.md5": "10ec3571596c30b9993b89f12d29d23c", + "threat.indicator.type": "file" }, { "event.category": "threat", @@ -1424,12 +1584,14 @@ "forwarded", "threatintel-otx" ], - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "www.playboysplus.com", - "threatintel.indicator.url.full": "http://www.playboysplus.com", - "threatintel.indicator.url.original": "http://www.playboysplus.com", - "threatintel.indicator.url.path": "", - "threatintel.indicator.url.scheme": "http" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Alienvault OTX", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "www.playboysplus.com", + "threat.indicator.url.full": "http://www.playboysplus.com", + "threat.indicator.url.original": "http://www.playboysplus.com", + "threat.indicator.url.path": "", + "threat.indicator.url.scheme": "http" }, { "event.category": "threat", @@ -1445,12 +1607,14 @@ "forwarded", "threatintel-otx" ], - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "join.playboysplus.com", - "threatintel.indicator.url.full": "http://join.playboysplus.com/signup/", - "threatintel.indicator.url.original": "http://join.playboysplus.com/signup/", - "threatintel.indicator.url.path": "/signup/", - "threatintel.indicator.url.scheme": "http" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Alienvault OTX", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "join.playboysplus.com", + "threat.indicator.url.full": "http://join.playboysplus.com/signup/", + "threat.indicator.url.original": "http://join.playboysplus.com/signup/", + "threat.indicator.url.path": "/signup/", + "threat.indicator.url.scheme": "http" }, { "event.category": "threat", @@ -1466,13 +1630,15 @@ "forwarded", "threatintel-otx" ], - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "api.vk.com", - "threatintel.indicator.url.extension": "get", - "threatintel.indicator.url.full": "http://api.vk.com/method/wall.get?count=1&owner_id=-81972386", - "threatintel.indicator.url.original": "http://api.vk.com/method/wall.get?count=1&owner_id=-81972386", - "threatintel.indicator.url.path": "/method/wall.get", - "threatintel.indicator.url.query": "count=1&owner_id=-81972386", - "threatintel.indicator.url.scheme": "http" + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] Alienvault OTX", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "api.vk.com", + "threat.indicator.url.extension": "get", + "threat.indicator.url.full": "http://api.vk.com/method/wall.get?count=1&owner_id=-81972386", + "threat.indicator.url.original": "http://api.vk.com/method/wall.get?count=1&owner_id=-81972386", + "threat.indicator.url.path": "/method/wall.get", + "threat.indicator.url.query": "count=1&owner_id=-81972386", + "threat.indicator.url.scheme": "http" } ] \ No newline at end of file diff --git a/x-pack/filebeat/module/threatintel/recordedfuture/config/config.yml b/x-pack/filebeat/module/threatintel/recordedfuture/config/config.yml index 08b2f682f3f..2c610e5379d 100644 --- a/x-pack/filebeat/module/threatintel/recordedfuture/config/config.yml +++ b/x-pack/filebeat/module/threatintel/recordedfuture/config/config.yml @@ -38,27 +38,12 @@ exclude_files: [".gz$"] {{ end }} -tags: {{.tags | tojson}} -publisher_pipeline.disable_host: {{ inList .tags "forwarded" }} +tags: +{{if .preserve_original_event}} + - preserve_original_event +{{end}} +{{range $val := .tags}} + - {{$val}} +{{end}} -processors: - - decode_json_fields: - fields: [message] - target: json - - fingerprint: - fields: - - event.dataset - - json.entity.id - target_field: "@metadata._id" - encoding: base64 - - add_fields: - target: '' - fields: - ecs.version: 1.12.0 - - script: - lang: javascript - id: set_opt_type - source: > - function process(event) { - event.Put("@metadata.op_type", "index"); - } +publisher_pipeline.disable_host: {{ inList .tags "forwarded" }} diff --git a/x-pack/filebeat/module/threatintel/recordedfuture/ingest/pipeline.yml b/x-pack/filebeat/module/threatintel/recordedfuture/ingest/pipeline.yml index 8e0a6d4b334..6247c0cd882 100644 --- a/x-pack/filebeat/module/threatintel/recordedfuture/ingest/pipeline.yml +++ b/x-pack/filebeat/module/threatintel/recordedfuture/ingest/pipeline.yml @@ -1,19 +1,14 @@ description: Pipeline for parsing Recorded Future threat intel. processors: - # - # Safeguard against feeding the pipeline with documents other - # that the ones generated by Filebeat's httpjson input. - # - - fail: - if: "ctx.json == null || !(ctx.json instanceof Map)" - message: "missing json object in input document" - # # Set basic ECS fields. # - set: field: event.ingested - value: "{{{ _ingest.timestamp }}}" + value: "{{_ingest.timestamp}}" + - set: + field: ecs.version + value: "1.12" - set: field: event.kind value: enrichment @@ -24,14 +19,29 @@ processors: field: event.type value: indicator + - rename: + field: message + target_field: event.original + ignore_missing: true + - json: + field: event.original + target_field: json + + - set: + field: threat.feed.name + value: "[Filebeat] RecordedFuture" + - set: + field: threat.feed.dashboard_id + value: "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f" + # - # Map itype field to STIX 2.0 Cyber Observable values (threatintel.indicator.type). + # Map itype field to STIX 2.0 Cyber Observable values (threat.indicator.type). # - script: lang: painless if: "ctx.json.entity?.type != null" description: > - Map entity.type field to STIX 2.0 Cyber Observable values (threatintel.indicator.type). + Map entity.type field to STIX 2.0 Cyber Observable values (threat.indicator.type). params: IpAddress: ipv4-addr InternetDomainName: domain-name @@ -40,7 +50,7 @@ processors: source: > String mapping = params[ctx.json.entity.type]; if (mapping != null) { - ctx["threatintel_indicator_type"] = mapping; + ctx["threat_indicator_type"] = mapping; } on_failure: - append: @@ -48,24 +58,24 @@ processors: value: 'Unable to determine indicator type from "{{{ json.entity.type }}}": {{{ _ingest.on_failure_message }}}' - rename: - field: threatintel_indicator_type - target_field: threatintel.indicator.type + field: threat_indicator_type + target_field: threat.indicator.type ignore_missing: true # # Detect ipv6 for ipv4-addr types. # - set: - field: threatintel.indicator.type + field: threat.indicator.type value: ipv6-addr - if: 'ctx.threatintel?.indicator?.type == "ipv4-addr" && ctx.json.entity.name != null && ctx.json.entity.name.contains(":")' + if: 'ctx.threat?.indicator?.type == "ipv4-addr" && ctx.json.entity.name != null && ctx.json.entity.name.contains(":")' # # Map first and last seen dates. # - date: field: json.timestamps.firstSeen - target_field: threatintel.indicator.first_seen + target_field: threat.indicator.first_seen formats: - ISO8601 if: "ctx.json.timestamps?.firstSeen != null" @@ -75,7 +85,7 @@ processors: value: 'Error parsing firstSeen field value "{{{ json.timestamps.firstSeen }}}": {{{ _ingest.on_failure_message }}}' - date: field: json.timestamps.lastSeen - target_field: threatintel.indicator.last_seen + target_field: threat.indicator.last_seen formats: - ISO8601 if: "ctx.json.timestamps?.lastSeen != null" @@ -89,20 +99,20 @@ processors: # - rename: field: json.location.location.city - target_field: threatintel.indicator.geo.city_name + target_field: threat.indicator.geo.city_name ignore_missing: true - rename: field: json.location.location.continent - target_field: threatintel.indicator.geo.continent_name + target_field: threat.indicator.geo.continent_name ignore_missing: true - rename: field: json.location.location.country - target_field: threatintel.indicator.geo.country_name + target_field: threat.indicator.geo.country_name ignore_missing: true - grok: field: json.location.asn patterns: - - "^(?:[Aa][Ss])?%{NUMBER:threatintel.indicator.as.number:long}$" + - "^(?:[Aa][Ss])?%{NUMBER:threat.indicator.as.number:long}$" ignore_missing: true on_failure: - append: @@ -110,10 +120,10 @@ processors: value: "Cannot parse asn field `{{{ json.location.asn }}}`: {{{ _ingest.on_failure_message }}}" - rename: field: json.location.organization - target_field: threatintel.indicator.as.organization.name + target_field: threat.indicator.as.organization.name ignore_missing: true - set: - field: threatintel.indicator.reference + field: threat.indicator.reference value: "{{{ json.intelCard }}}" ignore_empty_value: true - set: @@ -123,30 +133,30 @@ processors: - set: field: json.ip_range value: "{{{ json.entity.name }}}/32" - if: 'ctx.threatintel?.indicator?.type == "ipv4-addr" && ctx.json.entity.name != null && !ctx.json.entity.name.contains("/")' + if: 'ctx.threat?.indicator?.type == "ipv4-addr" && ctx.json.entity.name != null && !ctx.json.entity.name.contains("/")' - set: field: json.ip_range value: "{{{ json.entity.name }}}/128" - if: 'ctx.threatintel?.indicator?.type == "ipv6-addr" && ctx.json.entity.name != null && !ctx.json.entity.name.contains("/")' + if: 'ctx.threat?.indicator?.type == "ipv6-addr" && ctx.json.entity.name != null && !ctx.json.entity.name.contains("/")' - set: field: json.ip_range value: "{{{json.entity.name}}}" if: 'ctx.json.entity?.type == "IpAddress" && ctx.json.entity.name != null && ctx.json.entity.name.contains("/")' - rename: field: json.entity.name - target_field: threatintel.indicator.ip + target_field: threat.indicator.ip if: 'ctx.json.entity?.type == "IpAddress" && ctx.json.entity.name != null && !ctx.json.entity.name.contains("/")' - rename: field: json.entity.name - target_field: threatintel.indicator.url.domain + target_field: threat.indicator.url.domain ignore_missing: true - if: 'ctx.threatintel?.indicator?.type == "domain-name" && ctx.threatintel?.indicator?.url?.domain == null' + if: 'ctx.threat?.indicator?.type == "domain-name" && ctx.threat?.indicator?.url?.domain == null' - uri_parts: field: json.entity.name - target_field: threatintel.indicator.url + target_field: threat.indicator.url keep_original: true remove_if_successful: true - if: 'ctx.threatintel?.indicator?.type == "url"' + if: 'ctx.threat?.indicator?.type == "url"' on_failure: - append: field: error.message @@ -157,10 +167,10 @@ processors: field: json.fileHashes value: "{{{ json.entity.name }}}" allow_duplicates: false - if: 'ctx.threatintel?.indicator?.type == "file"' + if: 'ctx.threat?.indicator?.type == "file"' - remove: field: json.entity.name - if: 'ctx.threatintel?.indicator?.type == "file"' + if: 'ctx.threat?.indicator?.type == "file"' - script: lang: painless description: > @@ -187,7 +197,7 @@ processors: value: "Failed to map fileHashes field: {{ _ingest.on_failure_message }}" - rename: field: _hashes - target_field: threatintel.indicator.file.hash + target_field: threat.indicator.file.hash ignore_missing: true # @@ -213,11 +223,48 @@ processors: - message ignore_missing: true # - # Save fields without an ECS mapping under `threatintel.recordedfuture`. + # Save fields without an ECS mapping under `recordedfuture`. # - rename: field: json - target_field: threatintel.recordedfuture + target_field: recordedfuture + + ###################### + # Cleanup processors # + ###################### + - remove: + field: event.original + if: "ctx?.tags == null || !(ctx.tags.contains('preserve_original_event'))" + ignore_failure: true + ignore_missing: true + - set: + field: threat.indicator.type + value: unknown + if: ctx.threat?.indicator?.type == null + - script: + lang: painless + if: ctx.recordedfuture != null + 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); + } + void handleList(List list) { + for (def x : list) { + if (x instanceof Map) { + handleMap(x); + } else if (x instanceof List) { + handleList(x); + } + } + } + handleMap(ctx); on_failure: - append: field: error.message diff --git a/x-pack/filebeat/module/threatintel/recordedfuture/manifest.yml b/x-pack/filebeat/module/threatintel/recordedfuture/manifest.yml index 93df3884160..da8a88e19da 100644 --- a/x-pack/filebeat/module/threatintel/recordedfuture/manifest.yml +++ b/x-pack/filebeat/module/threatintel/recordedfuture/manifest.yml @@ -14,6 +14,8 @@ var: default: [threatintel-recordedfuture, forwarded] - name: proxy_url - name: api_token + - name: preserve_original_event + default: false ingest_pipeline: - ingest/pipeline.yml input: config/config.yml diff --git a/x-pack/filebeat/module/threatintel/recordedfuture/test/domain.ndjson.log-expected.json b/x-pack/filebeat/module/threatintel/recordedfuture/test/domain.ndjson.log-expected.json index 29b0a8ed4a5..7da98ffcc29 100644 --- a/x-pack/filebeat/module/threatintel/recordedfuture/test/domain.ndjson.log-expected.json +++ b/x-pack/filebeat/module/threatintel/recordedfuture/test/domain.ndjson.log-expected.json @@ -9,26 +9,28 @@ "fileset.name": "recordedfuture", "input.type": "log", "log.offset": 0, + "recordedfuture.entity.id": "idn:16url-gy.example.net", + "recordedfuture.entity.type": "InternetDomainName", + "recordedfuture.intelCard": "https://app.recordedfuture.com.local/live/sc/entity/idn%3A16url-gy.example.net", + "recordedfuture.risk.criticality": 0, + "recordedfuture.risk.criticalityLabel": "None", + "recordedfuture.risk.evidenceDetails": [], + "recordedfuture.risk.riskString": "0/44", + "recordedfuture.risk.riskSummary": "No Risk Rules are currently observed.", + "recordedfuture.risk.rules": 0, + "recordedfuture.risk.score": 0, "service.type": "threatintel", "tags": [ "forwarded", "threatintel-recordedfuture" ], - "threatintel.indicator.first_seen": "2016-07-25T20:29:32.750Z", - "threatintel.indicator.last_seen": "2021-06-20T18:23:47.901Z", - "threatintel.indicator.reference": "https://app.recordedfuture.com.local/live/sc/entity/idn%3A16url-gy.example.net", - "threatintel.indicator.type": "domain-name", - "threatintel.indicator.url.domain": "16url-gy.example.net", - "threatintel.recordedfuture.entity.id": "idn:16url-gy.example.net", - "threatintel.recordedfuture.entity.type": "InternetDomainName", - "threatintel.recordedfuture.intelCard": "https://app.recordedfuture.com.local/live/sc/entity/idn%3A16url-gy.example.net", - "threatintel.recordedfuture.risk.criticality": 0, - "threatintel.recordedfuture.risk.criticalityLabel": "None", - "threatintel.recordedfuture.risk.evidenceDetails": [], - "threatintel.recordedfuture.risk.riskString": "0/44", - "threatintel.recordedfuture.risk.riskSummary": "No Risk Rules are currently observed.", - "threatintel.recordedfuture.risk.rules": 0, - "threatintel.recordedfuture.risk.score": 0 + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] RecordedFuture", + "threat.indicator.first_seen": "2016-07-25T20:29:32.750Z", + "threat.indicator.last_seen": "2021-06-20T18:23:47.901Z", + "threat.indicator.reference": "https://app.recordedfuture.com.local/live/sc/entity/idn%3A16url-gy.example.net", + "threat.indicator.type": "domain-name", + "threat.indicator.url.domain": "16url-gy.example.net" }, { "event.category": "threat", @@ -40,26 +42,28 @@ "fileset.name": "recordedfuture", "input.type": "log", "log.offset": 482, + "recordedfuture.entity.id": "idn:b999f.example.org", + "recordedfuture.entity.type": "InternetDomainName", + "recordedfuture.intelCard": "https://app.recordedfuture.com.local/live/sc/entity/idn%3Ab999f.example.org", + "recordedfuture.risk.criticality": 0, + "recordedfuture.risk.criticalityLabel": "None", + "recordedfuture.risk.evidenceDetails": [], + "recordedfuture.risk.riskString": "0/44", + "recordedfuture.risk.riskSummary": "No Risk Rules are currently observed.", + "recordedfuture.risk.rules": 0, + "recordedfuture.risk.score": 0, "service.type": "threatintel", "tags": [ "forwarded", "threatintel-recordedfuture" ], - "threatintel.indicator.first_seen": "2012-11-21T01:54:04.292Z", - "threatintel.indicator.last_seen": "2021-06-20T18:23:47.812Z", - "threatintel.indicator.reference": "https://app.recordedfuture.com.local/live/sc/entity/idn%3Ab999f.example.org", - "threatintel.indicator.type": "domain-name", - "threatintel.indicator.url.domain": "b999f.example.org", - "threatintel.recordedfuture.entity.id": "idn:b999f.example.org", - "threatintel.recordedfuture.entity.type": "InternetDomainName", - "threatintel.recordedfuture.intelCard": "https://app.recordedfuture.com.local/live/sc/entity/idn%3Ab999f.example.org", - "threatintel.recordedfuture.risk.criticality": 0, - "threatintel.recordedfuture.risk.criticalityLabel": "None", - "threatintel.recordedfuture.risk.evidenceDetails": [], - "threatintel.recordedfuture.risk.riskString": "0/44", - "threatintel.recordedfuture.risk.riskSummary": "No Risk Rules are currently observed.", - "threatintel.recordedfuture.risk.rules": 0, - "threatintel.recordedfuture.risk.score": 0 + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] RecordedFuture", + "threat.indicator.first_seen": "2012-11-21T01:54:04.292Z", + "threat.indicator.last_seen": "2021-06-20T18:23:47.812Z", + "threat.indicator.reference": "https://app.recordedfuture.com.local/live/sc/entity/idn%3Ab999f.example.org", + "threat.indicator.type": "domain-name", + "threat.indicator.url.domain": "b999f.example.org" }, { "event.category": "threat", @@ -71,26 +75,28 @@ "fileset.name": "recordedfuture", "input.type": "log", "log.offset": 955, + "recordedfuture.entity.id": "idn:c422.example.net", + "recordedfuture.entity.type": "InternetDomainName", + "recordedfuture.intelCard": "https://app.recordedfuture.com.local/live/sc/entity/idn%3Ac422.example.net", + "recordedfuture.risk.criticality": 0, + "recordedfuture.risk.criticalityLabel": "None", + "recordedfuture.risk.evidenceDetails": [], + "recordedfuture.risk.riskString": "0/44", + "recordedfuture.risk.riskSummary": "No Risk Rules are currently observed.", + "recordedfuture.risk.rules": 0, + "recordedfuture.risk.score": 0, "service.type": "threatintel", "tags": [ "forwarded", "threatintel-recordedfuture" ], - "threatintel.indicator.first_seen": "2018-02-21T13:53:46.470Z", - "threatintel.indicator.last_seen": "2021-06-20T18:23:47.778Z", - "threatintel.indicator.reference": "https://app.recordedfuture.com.local/live/sc/entity/idn%3Ac422.example.net", - "threatintel.indicator.type": "domain-name", - "threatintel.indicator.url.domain": "c422.example.net", - "threatintel.recordedfuture.entity.id": "idn:c422.example.net", - "threatintel.recordedfuture.entity.type": "InternetDomainName", - "threatintel.recordedfuture.intelCard": "https://app.recordedfuture.com.local/live/sc/entity/idn%3Ac422.example.net", - "threatintel.recordedfuture.risk.criticality": 0, - "threatintel.recordedfuture.risk.criticalityLabel": "None", - "threatintel.recordedfuture.risk.evidenceDetails": [], - "threatintel.recordedfuture.risk.riskString": "0/44", - "threatintel.recordedfuture.risk.riskSummary": "No Risk Rules are currently observed.", - "threatintel.recordedfuture.risk.rules": 0, - "threatintel.recordedfuture.risk.score": 0 + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] RecordedFuture", + "threat.indicator.first_seen": "2018-02-21T13:53:46.470Z", + "threat.indicator.last_seen": "2021-06-20T18:23:47.778Z", + "threat.indicator.reference": "https://app.recordedfuture.com.local/live/sc/entity/idn%3Ac422.example.net", + "threat.indicator.type": "domain-name", + "threat.indicator.url.domain": "c422.example.net" }, { "event.category": "threat", @@ -102,26 +108,28 @@ "fileset.name": "recordedfuture", "input.type": "log", "log.offset": 1425, + "recordedfuture.entity.id": "idn:8rwcvgjsp.example.net", + "recordedfuture.entity.type": "InternetDomainName", + "recordedfuture.intelCard": "https://app.recordedfuture.com.local/live/sc/entity/idn%3A8rwcvgjsp.example.net", + "recordedfuture.risk.criticality": 0, + "recordedfuture.risk.criticalityLabel": "None", + "recordedfuture.risk.evidenceDetails": [], + "recordedfuture.risk.riskString": "0/44", + "recordedfuture.risk.riskSummary": "No Risk Rules are currently observed.", + "recordedfuture.risk.rules": 0, + "recordedfuture.risk.score": 0, "service.type": "threatintel", "tags": [ "forwarded", "threatintel-recordedfuture" ], - "threatintel.indicator.first_seen": "2016-08-15T11:56:24.964Z", - "threatintel.indicator.last_seen": "2021-06-20T18:23:47.747Z", - "threatintel.indicator.reference": "https://app.recordedfuture.com.local/live/sc/entity/idn%3A8rwcvgjsp.example.net", - "threatintel.indicator.type": "domain-name", - "threatintel.indicator.url.domain": "8rwcvgjsp.example.net", - "threatintel.recordedfuture.entity.id": "idn:8rwcvgjsp.example.net", - "threatintel.recordedfuture.entity.type": "InternetDomainName", - "threatintel.recordedfuture.intelCard": "https://app.recordedfuture.com.local/live/sc/entity/idn%3A8rwcvgjsp.example.net", - "threatintel.recordedfuture.risk.criticality": 0, - "threatintel.recordedfuture.risk.criticalityLabel": "None", - "threatintel.recordedfuture.risk.evidenceDetails": [], - "threatintel.recordedfuture.risk.riskString": "0/44", - "threatintel.recordedfuture.risk.riskSummary": "No Risk Rules are currently observed.", - "threatintel.recordedfuture.risk.rules": 0, - "threatintel.recordedfuture.risk.score": 0 + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] RecordedFuture", + "threat.indicator.first_seen": "2016-08-15T11:56:24.964Z", + "threat.indicator.last_seen": "2021-06-20T18:23:47.747Z", + "threat.indicator.reference": "https://app.recordedfuture.com.local/live/sc/entity/idn%3A8rwcvgjsp.example.net", + "threat.indicator.type": "domain-name", + "threat.indicator.url.domain": "8rwcvgjsp.example.net" }, { "event.category": "threat", @@ -133,26 +141,28 @@ "fileset.name": "recordedfuture", "input.type": "log", "log.offset": 1910, + "recordedfuture.entity.id": "idn:c9px.example.net", + "recordedfuture.entity.type": "InternetDomainName", + "recordedfuture.intelCard": "https://app.recordedfuture.com.local/live/sc/entity/idn%3Ac9px.example.net", + "recordedfuture.risk.criticality": 0, + "recordedfuture.risk.criticalityLabel": "None", + "recordedfuture.risk.evidenceDetails": [], + "recordedfuture.risk.riskString": "0/44", + "recordedfuture.risk.riskSummary": "No Risk Rules are currently observed.", + "recordedfuture.risk.rules": 0, + "recordedfuture.risk.score": 0, "service.type": "threatintel", "tags": [ "forwarded", "threatintel-recordedfuture" ], - "threatintel.indicator.first_seen": "2016-06-29T21:06:06.066Z", - "threatintel.indicator.last_seen": "2021-06-20T18:23:47.460Z", - "threatintel.indicator.reference": "https://app.recordedfuture.com.local/live/sc/entity/idn%3Ac9px.example.net", - "threatintel.indicator.type": "domain-name", - "threatintel.indicator.url.domain": "c9px.example.net", - "threatintel.recordedfuture.entity.id": "idn:c9px.example.net", - "threatintel.recordedfuture.entity.type": "InternetDomainName", - "threatintel.recordedfuture.intelCard": "https://app.recordedfuture.com.local/live/sc/entity/idn%3Ac9px.example.net", - "threatintel.recordedfuture.risk.criticality": 0, - "threatintel.recordedfuture.risk.criticalityLabel": "None", - "threatintel.recordedfuture.risk.evidenceDetails": [], - "threatintel.recordedfuture.risk.riskString": "0/44", - "threatintel.recordedfuture.risk.riskSummary": "No Risk Rules are currently observed.", - "threatintel.recordedfuture.risk.rules": 0, - "threatintel.recordedfuture.risk.score": 0 + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] RecordedFuture", + "threat.indicator.first_seen": "2016-06-29T21:06:06.066Z", + "threat.indicator.last_seen": "2021-06-20T18:23:47.460Z", + "threat.indicator.reference": "https://app.recordedfuture.com.local/live/sc/entity/idn%3Ac9px.example.net", + "threat.indicator.type": "domain-name", + "threat.indicator.url.domain": "c9px.example.net" }, { "event.category": "threat", @@ -164,26 +174,28 @@ "fileset.name": "recordedfuture", "input.type": "log", "log.offset": 2380, + "recordedfuture.entity.id": "idn:ttj1i9z7.example.com", + "recordedfuture.entity.type": "InternetDomainName", + "recordedfuture.intelCard": "https://app.recordedfuture.com.local/live/sc/entity/idn%3Attj1i9z7.example.com", + "recordedfuture.risk.criticality": 0, + "recordedfuture.risk.criticalityLabel": "None", + "recordedfuture.risk.evidenceDetails": [], + "recordedfuture.risk.riskString": "0/44", + "recordedfuture.risk.riskSummary": "No Risk Rules are currently observed.", + "recordedfuture.risk.rules": 0, + "recordedfuture.risk.score": 0, "service.type": "threatintel", "tags": [ "forwarded", "threatintel-recordedfuture" ], - "threatintel.indicator.first_seen": "2018-09-20T03:26:08.564Z", - "threatintel.indicator.last_seen": "2021-06-20T18:23:47.373Z", - "threatintel.indicator.reference": "https://app.recordedfuture.com.local/live/sc/entity/idn%3Attj1i9z7.example.com", - "threatintel.indicator.type": "domain-name", - "threatintel.indicator.url.domain": "ttj1i9z7.example.com", - "threatintel.recordedfuture.entity.id": "idn:ttj1i9z7.example.com", - "threatintel.recordedfuture.entity.type": "InternetDomainName", - "threatintel.recordedfuture.intelCard": "https://app.recordedfuture.com.local/live/sc/entity/idn%3Attj1i9z7.example.com", - "threatintel.recordedfuture.risk.criticality": 0, - "threatintel.recordedfuture.risk.criticalityLabel": "None", - "threatintel.recordedfuture.risk.evidenceDetails": [], - "threatintel.recordedfuture.risk.riskString": "0/44", - "threatintel.recordedfuture.risk.riskSummary": "No Risk Rules are currently observed.", - "threatintel.recordedfuture.risk.rules": 0, - "threatintel.recordedfuture.risk.score": 0 + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] RecordedFuture", + "threat.indicator.first_seen": "2018-09-20T03:26:08.564Z", + "threat.indicator.last_seen": "2021-06-20T18:23:47.373Z", + "threat.indicator.reference": "https://app.recordedfuture.com.local/live/sc/entity/idn%3Attj1i9z7.example.com", + "threat.indicator.type": "domain-name", + "threat.indicator.url.domain": "ttj1i9z7.example.com" }, { "event.category": "threat", @@ -195,26 +207,28 @@ "fileset.name": "recordedfuture", "input.type": "log", "log.offset": 2862, + "recordedfuture.entity.id": "idn:7pgc.example.org", + "recordedfuture.entity.type": "InternetDomainName", + "recordedfuture.intelCard": "https://app.recordedfuture.com.local/live/sc/entity/idn%3A7pgc.example.org", + "recordedfuture.risk.criticality": 0, + "recordedfuture.risk.criticalityLabel": "None", + "recordedfuture.risk.evidenceDetails": [], + "recordedfuture.risk.riskString": "0/44", + "recordedfuture.risk.riskSummary": "No Risk Rules are currently observed.", + "recordedfuture.risk.rules": 0, + "recordedfuture.risk.score": 0, "service.type": "threatintel", "tags": [ "forwarded", "threatintel-recordedfuture" ], - "threatintel.indicator.first_seen": "2017-02-23T17:44:16.104Z", - "threatintel.indicator.last_seen": "2021-06-20T18:23:47.373Z", - "threatintel.indicator.reference": "https://app.recordedfuture.com.local/live/sc/entity/idn%3A7pgc.example.org", - "threatintel.indicator.type": "domain-name", - "threatintel.indicator.url.domain": "7pgc.example.org", - "threatintel.recordedfuture.entity.id": "idn:7pgc.example.org", - "threatintel.recordedfuture.entity.type": "InternetDomainName", - "threatintel.recordedfuture.intelCard": "https://app.recordedfuture.com.local/live/sc/entity/idn%3A7pgc.example.org", - "threatintel.recordedfuture.risk.criticality": 0, - "threatintel.recordedfuture.risk.criticalityLabel": "None", - "threatintel.recordedfuture.risk.evidenceDetails": [], - "threatintel.recordedfuture.risk.riskString": "0/44", - "threatintel.recordedfuture.risk.riskSummary": "No Risk Rules are currently observed.", - "threatintel.recordedfuture.risk.rules": 0, - "threatintel.recordedfuture.risk.score": 0 + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] RecordedFuture", + "threat.indicator.first_seen": "2017-02-23T17:44:16.104Z", + "threat.indicator.last_seen": "2021-06-20T18:23:47.373Z", + "threat.indicator.reference": "https://app.recordedfuture.com.local/live/sc/entity/idn%3A7pgc.example.org", + "threat.indicator.type": "domain-name", + "threat.indicator.url.domain": "7pgc.example.org" }, { "event.category": "threat", @@ -226,26 +240,28 @@ "fileset.name": "recordedfuture", "input.type": "log", "log.offset": 3332, + "recordedfuture.entity.id": "idn:xm5u434.example.net", + "recordedfuture.entity.type": "InternetDomainName", + "recordedfuture.intelCard": "https://app.recordedfuture.com.local/live/sc/entity/idn%3Axm5u434.example.net", + "recordedfuture.risk.criticality": 0, + "recordedfuture.risk.criticalityLabel": "None", + "recordedfuture.risk.evidenceDetails": [], + "recordedfuture.risk.riskString": "0/44", + "recordedfuture.risk.riskSummary": "No Risk Rules are currently observed.", + "recordedfuture.risk.rules": 0, + "recordedfuture.risk.score": 0, "service.type": "threatintel", "tags": [ "forwarded", "threatintel-recordedfuture" ], - "threatintel.indicator.first_seen": "2017-04-10T06:55:27.658Z", - "threatintel.indicator.last_seen": "2021-06-20T18:23:47.373Z", - "threatintel.indicator.reference": "https://app.recordedfuture.com.local/live/sc/entity/idn%3Axm5u434.example.net", - "threatintel.indicator.type": "domain-name", - "threatintel.indicator.url.domain": "xm5u434.example.net", - "threatintel.recordedfuture.entity.id": "idn:xm5u434.example.net", - "threatintel.recordedfuture.entity.type": "InternetDomainName", - "threatintel.recordedfuture.intelCard": "https://app.recordedfuture.com.local/live/sc/entity/idn%3Axm5u434.example.net", - "threatintel.recordedfuture.risk.criticality": 0, - "threatintel.recordedfuture.risk.criticalityLabel": "None", - "threatintel.recordedfuture.risk.evidenceDetails": [], - "threatintel.recordedfuture.risk.riskString": "0/44", - "threatintel.recordedfuture.risk.riskSummary": "No Risk Rules are currently observed.", - "threatintel.recordedfuture.risk.rules": 0, - "threatintel.recordedfuture.risk.score": 0 + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] RecordedFuture", + "threat.indicator.first_seen": "2017-04-10T06:55:27.658Z", + "threat.indicator.last_seen": "2021-06-20T18:23:47.373Z", + "threat.indicator.reference": "https://app.recordedfuture.com.local/live/sc/entity/idn%3Axm5u434.example.net", + "threat.indicator.type": "domain-name", + "threat.indicator.url.domain": "xm5u434.example.net" }, { "event.category": "threat", @@ -257,26 +273,28 @@ "fileset.name": "recordedfuture", "input.type": "log", "log.offset": 3811, + "recordedfuture.entity.id": "idn:gpgju.example.com", + "recordedfuture.entity.type": "InternetDomainName", + "recordedfuture.intelCard": "https://app.recordedfuture.com.local/live/sc/entity/idn%3Agpgju.example.com", + "recordedfuture.risk.criticality": 0, + "recordedfuture.risk.criticalityLabel": "None", + "recordedfuture.risk.evidenceDetails": [], + "recordedfuture.risk.riskString": "0/44", + "recordedfuture.risk.riskSummary": "No Risk Rules are currently observed.", + "recordedfuture.risk.rules": 0, + "recordedfuture.risk.score": 0, "service.type": "threatintel", "tags": [ "forwarded", "threatintel-recordedfuture" ], - "threatintel.indicator.first_seen": "2018-07-27T15:22:39.390Z", - "threatintel.indicator.last_seen": "2021-06-20T18:23:47.373Z", - "threatintel.indicator.reference": "https://app.recordedfuture.com.local/live/sc/entity/idn%3Agpgju.example.com", - "threatintel.indicator.type": "domain-name", - "threatintel.indicator.url.domain": "gpgju.example.com", - "threatintel.recordedfuture.entity.id": "idn:gpgju.example.com", - "threatintel.recordedfuture.entity.type": "InternetDomainName", - "threatintel.recordedfuture.intelCard": "https://app.recordedfuture.com.local/live/sc/entity/idn%3Agpgju.example.com", - "threatintel.recordedfuture.risk.criticality": 0, - "threatintel.recordedfuture.risk.criticalityLabel": "None", - "threatintel.recordedfuture.risk.evidenceDetails": [], - "threatintel.recordedfuture.risk.riskString": "0/44", - "threatintel.recordedfuture.risk.riskSummary": "No Risk Rules are currently observed.", - "threatintel.recordedfuture.risk.rules": 0, - "threatintel.recordedfuture.risk.score": 0 + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] RecordedFuture", + "threat.indicator.first_seen": "2018-07-27T15:22:39.390Z", + "threat.indicator.last_seen": "2021-06-20T18:23:47.373Z", + "threat.indicator.reference": "https://app.recordedfuture.com.local/live/sc/entity/idn%3Agpgju.example.com", + "threat.indicator.type": "domain-name", + "threat.indicator.url.domain": "gpgju.example.com" }, { "event.category": "threat", @@ -288,25 +306,27 @@ "fileset.name": "recordedfuture", "input.type": "log", "log.offset": 4284, + "recordedfuture.entity.id": "idn:55g.example.com", + "recordedfuture.entity.type": "InternetDomainName", + "recordedfuture.intelCard": "https://app.recordedfuture.com.local/live/sc/entity/idn%3A55g.example.com", + "recordedfuture.risk.criticality": 0, + "recordedfuture.risk.criticalityLabel": "None", + "recordedfuture.risk.evidenceDetails": [], + "recordedfuture.risk.riskString": "0/44", + "recordedfuture.risk.riskSummary": "No Risk Rules are currently observed.", + "recordedfuture.risk.rules": 0, + "recordedfuture.risk.score": 0, "service.type": "threatintel", "tags": [ "forwarded", "threatintel-recordedfuture" ], - "threatintel.indicator.first_seen": "2021-01-10T21:24:38.353Z", - "threatintel.indicator.last_seen": "2021-06-20T18:23:45.025Z", - "threatintel.indicator.reference": "https://app.recordedfuture.com.local/live/sc/entity/idn%3A55g.example.com", - "threatintel.indicator.type": "domain-name", - "threatintel.indicator.url.domain": "55g.example.com", - "threatintel.recordedfuture.entity.id": "idn:55g.example.com", - "threatintel.recordedfuture.entity.type": "InternetDomainName", - "threatintel.recordedfuture.intelCard": "https://app.recordedfuture.com.local/live/sc/entity/idn%3A55g.example.com", - "threatintel.recordedfuture.risk.criticality": 0, - "threatintel.recordedfuture.risk.criticalityLabel": "None", - "threatintel.recordedfuture.risk.evidenceDetails": [], - "threatintel.recordedfuture.risk.riskString": "0/44", - "threatintel.recordedfuture.risk.riskSummary": "No Risk Rules are currently observed.", - "threatintel.recordedfuture.risk.rules": 0, - "threatintel.recordedfuture.risk.score": 0 + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] RecordedFuture", + "threat.indicator.first_seen": "2021-01-10T21:24:38.353Z", + "threat.indicator.last_seen": "2021-06-20T18:23:45.025Z", + "threat.indicator.reference": "https://app.recordedfuture.com.local/live/sc/entity/idn%3A55g.example.com", + "threat.indicator.type": "domain-name", + "threat.indicator.url.domain": "55g.example.com" } ] \ No newline at end of file diff --git a/x-pack/filebeat/module/threatintel/recordedfuture/test/hash.ndjson.log-expected.json b/x-pack/filebeat/module/threatintel/recordedfuture/test/hash.ndjson.log-expected.json index dbc47e31767..cf8b9c1b23e 100644 --- a/x-pack/filebeat/module/threatintel/recordedfuture/test/hash.ndjson.log-expected.json +++ b/x-pack/filebeat/module/threatintel/recordedfuture/test/hash.ndjson.log-expected.json @@ -9,24 +9,12 @@ "fileset.name": "recordedfuture", "input.type": "log", "log.offset": 0, - "service.type": "threatintel", - "tags": [ - "forwarded", - "threatintel-recordedfuture" - ], - "threatintel.indicator.file.hash.md5": "25328d1a481903f2d900479570842247", - "threatintel.indicator.file.hash.sha1": "d73c663e2ac0c7a14ca0e2681dd599b2e7a24f65", - "threatintel.indicator.file.hash.sha256": "dec3a20fa1493c8e669b26d3f8b6084b34fda9906c978f9f12fb43f76504b5d6", - "threatintel.indicator.first_seen": "2021-06-20T18:40:18.503Z", - "threatintel.indicator.last_seen": "2021-06-20T18:40:18.503Z", - "threatintel.indicator.reference": "https://app.recordedfuture.local/live/sc/entity/hash%3Adec3a20fa1493c8e669b26d3f8b6084b34fda9906c978f9f12fb43f76504b5d6", - "threatintel.indicator.type": "file", - "threatintel.recordedfuture.entity.id": "hash:dec3a20fa1493c8e669b26d3f8b6084b34fda9906c978f9f12fb43f76504b5d6", - "threatintel.recordedfuture.entity.type": "Hash", - "threatintel.recordedfuture.intelCard": "https://app.recordedfuture.local/live/sc/entity/hash%3Adec3a20fa1493c8e669b26d3f8b6084b34fda9906c978f9f12fb43f76504b5d6", - "threatintel.recordedfuture.risk.criticality": 3, - "threatintel.recordedfuture.risk.criticalityLabel": "Malicious", - "threatintel.recordedfuture.risk.evidenceDetails": [ + "recordedfuture.entity.id": "hash:dec3a20fa1493c8e669b26d3f8b6084b34fda9906c978f9f12fb43f76504b5d6", + "recordedfuture.entity.type": "Hash", + "recordedfuture.intelCard": "https://app.recordedfuture.local/live/sc/entity/hash%3Adec3a20fa1493c8e669b26d3f8b6084b34fda9906c978f9f12fb43f76504b5d6", + "recordedfuture.risk.criticality": 3, + "recordedfuture.risk.criticalityLabel": "Malicious", + "recordedfuture.risk.evidenceDetails": [ { "criticality": 3, "criticalityLabel": "Malicious", @@ -44,10 +32,24 @@ "timestamp": "2021-06-20T18:40:18.503Z" } ], - "threatintel.recordedfuture.risk.riskString": "2/14", - "threatintel.recordedfuture.risk.riskSummary": "2 of 14 Risk Rules currently observed.", - "threatintel.recordedfuture.risk.rules": 2, - "threatintel.recordedfuture.risk.score": 65 + "recordedfuture.risk.riskString": "2/14", + "recordedfuture.risk.riskSummary": "2 of 14 Risk Rules currently observed.", + "recordedfuture.risk.rules": 2, + "recordedfuture.risk.score": 65, + "service.type": "threatintel", + "tags": [ + "forwarded", + "threatintel-recordedfuture" + ], + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] RecordedFuture", + "threat.indicator.file.hash.md5": "25328d1a481903f2d900479570842247", + "threat.indicator.file.hash.sha1": "d73c663e2ac0c7a14ca0e2681dd599b2e7a24f65", + "threat.indicator.file.hash.sha256": "dec3a20fa1493c8e669b26d3f8b6084b34fda9906c978f9f12fb43f76504b5d6", + "threat.indicator.first_seen": "2021-06-20T18:40:18.503Z", + "threat.indicator.last_seen": "2021-06-20T18:40:18.503Z", + "threat.indicator.reference": "https://app.recordedfuture.local/live/sc/entity/hash%3Adec3a20fa1493c8e669b26d3f8b6084b34fda9906c978f9f12fb43f76504b5d6", + "threat.indicator.type": "file" }, { "event.category": "threat", @@ -59,24 +61,12 @@ "fileset.name": "recordedfuture", "input.type": "log", "log.offset": 1478, - "service.type": "threatintel", - "tags": [ - "forwarded", - "threatintel-recordedfuture" - ], - "threatintel.indicator.file.hash.md5": "7b8d9afd032f0c253b7dd68aca6fb50b", - "threatintel.indicator.file.hash.sha1": "f9ece49c249aabab29fd9c2193d897b7d131ed17", - "threatintel.indicator.file.hash.sha256": "4014355fdfee5fe9e01f3a84356d743c022cd75510f6c96ffe16fb332855d6f2", - "threatintel.indicator.first_seen": "2021-06-20T18:40:18.452Z", - "threatintel.indicator.last_seen": "2021-06-20T18:40:18.452Z", - "threatintel.indicator.reference": "https://app.recordedfuture.local/live/sc/entity/hash%3A4014355fdfee5fe9e01f3a84356d743c022cd75510f6c96ffe16fb332855d6f2", - "threatintel.indicator.type": "file", - "threatintel.recordedfuture.entity.id": "hash:4014355fdfee5fe9e01f3a84356d743c022cd75510f6c96ffe16fb332855d6f2", - "threatintel.recordedfuture.entity.type": "Hash", - "threatintel.recordedfuture.intelCard": "https://app.recordedfuture.local/live/sc/entity/hash%3A4014355fdfee5fe9e01f3a84356d743c022cd75510f6c96ffe16fb332855d6f2", - "threatintel.recordedfuture.risk.criticality": 3, - "threatintel.recordedfuture.risk.criticalityLabel": "Malicious", - "threatintel.recordedfuture.risk.evidenceDetails": [ + "recordedfuture.entity.id": "hash:4014355fdfee5fe9e01f3a84356d743c022cd75510f6c96ffe16fb332855d6f2", + "recordedfuture.entity.type": "Hash", + "recordedfuture.intelCard": "https://app.recordedfuture.local/live/sc/entity/hash%3A4014355fdfee5fe9e01f3a84356d743c022cd75510f6c96ffe16fb332855d6f2", + "recordedfuture.risk.criticality": 3, + "recordedfuture.risk.criticalityLabel": "Malicious", + "recordedfuture.risk.evidenceDetails": [ { "criticality": 3, "criticalityLabel": "Malicious", @@ -94,10 +84,24 @@ "timestamp": "2021-06-20T18:40:18.452Z" } ], - "threatintel.recordedfuture.risk.riskString": "2/14", - "threatintel.recordedfuture.risk.riskSummary": "2 of 14 Risk Rules currently observed.", - "threatintel.recordedfuture.risk.rules": 2, - "threatintel.recordedfuture.risk.score": 65 + "recordedfuture.risk.riskString": "2/14", + "recordedfuture.risk.riskSummary": "2 of 14 Risk Rules currently observed.", + "recordedfuture.risk.rules": 2, + "recordedfuture.risk.score": 65, + "service.type": "threatintel", + "tags": [ + "forwarded", + "threatintel-recordedfuture" + ], + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] RecordedFuture", + "threat.indicator.file.hash.md5": "7b8d9afd032f0c253b7dd68aca6fb50b", + "threat.indicator.file.hash.sha1": "f9ece49c249aabab29fd9c2193d897b7d131ed17", + "threat.indicator.file.hash.sha256": "4014355fdfee5fe9e01f3a84356d743c022cd75510f6c96ffe16fb332855d6f2", + "threat.indicator.first_seen": "2021-06-20T18:40:18.452Z", + "threat.indicator.last_seen": "2021-06-20T18:40:18.452Z", + "threat.indicator.reference": "https://app.recordedfuture.local/live/sc/entity/hash%3A4014355fdfee5fe9e01f3a84356d743c022cd75510f6c96ffe16fb332855d6f2", + "threat.indicator.type": "file" }, { "event.category": "threat", @@ -109,24 +113,12 @@ "fileset.name": "recordedfuture", "input.type": "log", "log.offset": 2954, - "service.type": "threatintel", - "tags": [ - "forwarded", - "threatintel-recordedfuture" - ], - "threatintel.indicator.file.hash.md5": "7b65b50ed4554c86cb777e35e7750209", - "threatintel.indicator.file.hash.sha1": "e10942ba3fbb937c90c7cb3e39c06a13324981a8", - "threatintel.indicator.file.hash.sha256": "299e7a30217e2137854308e7be79227635f409b0e00897cfff11806ad8449cc5", - "threatintel.indicator.first_seen": "2021-06-20T18:40:18.343Z", - "threatintel.indicator.last_seen": "2021-06-20T18:40:18.343Z", - "threatintel.indicator.reference": "https://app.recordedfuture.local/live/sc/entity/hash%3A299e7a30217e2137854308e7be79227635f409b0e00897cfff11806ad8449cc5", - "threatintel.indicator.type": "file", - "threatintel.recordedfuture.entity.id": "hash:299e7a30217e2137854308e7be79227635f409b0e00897cfff11806ad8449cc5", - "threatintel.recordedfuture.entity.type": "Hash", - "threatintel.recordedfuture.intelCard": "https://app.recordedfuture.local/live/sc/entity/hash%3A299e7a30217e2137854308e7be79227635f409b0e00897cfff11806ad8449cc5", - "threatintel.recordedfuture.risk.criticality": 3, - "threatintel.recordedfuture.risk.criticalityLabel": "Malicious", - "threatintel.recordedfuture.risk.evidenceDetails": [ + "recordedfuture.entity.id": "hash:299e7a30217e2137854308e7be79227635f409b0e00897cfff11806ad8449cc5", + "recordedfuture.entity.type": "Hash", + "recordedfuture.intelCard": "https://app.recordedfuture.local/live/sc/entity/hash%3A299e7a30217e2137854308e7be79227635f409b0e00897cfff11806ad8449cc5", + "recordedfuture.risk.criticality": 3, + "recordedfuture.risk.criticalityLabel": "Malicious", + "recordedfuture.risk.evidenceDetails": [ { "criticality": 3, "criticalityLabel": "Malicious", @@ -144,10 +136,24 @@ "timestamp": "2021-06-20T18:40:18.343Z" } ], - "threatintel.recordedfuture.risk.riskString": "2/14", - "threatintel.recordedfuture.risk.riskSummary": "2 of 14 Risk Rules currently observed.", - "threatintel.recordedfuture.risk.rules": 2, - "threatintel.recordedfuture.risk.score": 65 + "recordedfuture.risk.riskString": "2/14", + "recordedfuture.risk.riskSummary": "2 of 14 Risk Rules currently observed.", + "recordedfuture.risk.rules": 2, + "recordedfuture.risk.score": 65, + "service.type": "threatintel", + "tags": [ + "forwarded", + "threatintel-recordedfuture" + ], + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] RecordedFuture", + "threat.indicator.file.hash.md5": "7b65b50ed4554c86cb777e35e7750209", + "threat.indicator.file.hash.sha1": "e10942ba3fbb937c90c7cb3e39c06a13324981a8", + "threat.indicator.file.hash.sha256": "299e7a30217e2137854308e7be79227635f409b0e00897cfff11806ad8449cc5", + "threat.indicator.first_seen": "2021-06-20T18:40:18.343Z", + "threat.indicator.last_seen": "2021-06-20T18:40:18.343Z", + "threat.indicator.reference": "https://app.recordedfuture.local/live/sc/entity/hash%3A299e7a30217e2137854308e7be79227635f409b0e00897cfff11806ad8449cc5", + "threat.indicator.type": "file" }, { "event.category": "threat", @@ -159,24 +165,12 @@ "fileset.name": "recordedfuture", "input.type": "log", "log.offset": 4457, - "service.type": "threatintel", - "tags": [ - "forwarded", - "threatintel-recordedfuture" - ], - "threatintel.indicator.file.hash.md5": "c6353df35499ca6934da2169b7bd1635", - "threatintel.indicator.file.hash.sha1": "3e208c649da0a9efbde7bbde6eece2142fdac3f9", - "threatintel.indicator.file.hash.sha256": "e5c73c63ba71659fbb9e0670cc203532aa61e3b8fa51f70ee5ce37b66784cd61", - "threatintel.indicator.first_seen": "2021-06-20T18:40:18.258Z", - "threatintel.indicator.last_seen": "2021-06-20T18:40:18.258Z", - "threatintel.indicator.reference": "https://app.recordedfuture.local/live/sc/entity/hash%3Ae5c73c63ba71659fbb9e0670cc203532aa61e3b8fa51f70ee5ce37b66784cd61", - "threatintel.indicator.type": "file", - "threatintel.recordedfuture.entity.id": "hash:e5c73c63ba71659fbb9e0670cc203532aa61e3b8fa51f70ee5ce37b66784cd61", - "threatintel.recordedfuture.entity.type": "Hash", - "threatintel.recordedfuture.intelCard": "https://app.recordedfuture.local/live/sc/entity/hash%3Ae5c73c63ba71659fbb9e0670cc203532aa61e3b8fa51f70ee5ce37b66784cd61", - "threatintel.recordedfuture.risk.criticality": 3, - "threatintel.recordedfuture.risk.criticalityLabel": "Malicious", - "threatintel.recordedfuture.risk.evidenceDetails": [ + "recordedfuture.entity.id": "hash:e5c73c63ba71659fbb9e0670cc203532aa61e3b8fa51f70ee5ce37b66784cd61", + "recordedfuture.entity.type": "Hash", + "recordedfuture.intelCard": "https://app.recordedfuture.local/live/sc/entity/hash%3Ae5c73c63ba71659fbb9e0670cc203532aa61e3b8fa51f70ee5ce37b66784cd61", + "recordedfuture.risk.criticality": 3, + "recordedfuture.risk.criticalityLabel": "Malicious", + "recordedfuture.risk.evidenceDetails": [ { "criticality": 3, "criticalityLabel": "Malicious", @@ -194,10 +188,24 @@ "timestamp": "2021-06-20T18:40:18.257Z" } ], - "threatintel.recordedfuture.risk.riskString": "2/14", - "threatintel.recordedfuture.risk.riskSummary": "2 of 14 Risk Rules currently observed.", - "threatintel.recordedfuture.risk.rules": 2, - "threatintel.recordedfuture.risk.score": 65 + "recordedfuture.risk.riskString": "2/14", + "recordedfuture.risk.riskSummary": "2 of 14 Risk Rules currently observed.", + "recordedfuture.risk.rules": 2, + "recordedfuture.risk.score": 65, + "service.type": "threatintel", + "tags": [ + "forwarded", + "threatintel-recordedfuture" + ], + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] RecordedFuture", + "threat.indicator.file.hash.md5": "c6353df35499ca6934da2169b7bd1635", + "threat.indicator.file.hash.sha1": "3e208c649da0a9efbde7bbde6eece2142fdac3f9", + "threat.indicator.file.hash.sha256": "e5c73c63ba71659fbb9e0670cc203532aa61e3b8fa51f70ee5ce37b66784cd61", + "threat.indicator.first_seen": "2021-06-20T18:40:18.258Z", + "threat.indicator.last_seen": "2021-06-20T18:40:18.258Z", + "threat.indicator.reference": "https://app.recordedfuture.local/live/sc/entity/hash%3Ae5c73c63ba71659fbb9e0670cc203532aa61e3b8fa51f70ee5ce37b66784cd61", + "threat.indicator.type": "file" }, { "event.category": "threat", @@ -209,24 +217,12 @@ "fileset.name": "recordedfuture", "input.type": "log", "log.offset": 5932, - "service.type": "threatintel", - "tags": [ - "forwarded", - "threatintel-recordedfuture" - ], - "threatintel.indicator.file.hash.md5": "3d568bd03766a8d47c8fabb7d392c32e", - "threatintel.indicator.file.hash.sha1": "3ea8b08bc9ed3009a4d6a0ab5851b8e3fc10ead2", - "threatintel.indicator.file.hash.sha256": "184527a5436086cff0c06197330089f7964a9b6b8fc86327e6778363b7297ef1", - "threatintel.indicator.first_seen": "2021-06-20T18:40:18.131Z", - "threatintel.indicator.last_seen": "2021-06-20T18:40:18.131Z", - "threatintel.indicator.reference": "https://app.recordedfuture.local/live/sc/entity/hash%3A184527a5436086cff0c06197330089f7964a9b6b8fc86327e6778363b7297ef1", - "threatintel.indicator.type": "file", - "threatintel.recordedfuture.entity.id": "hash:184527a5436086cff0c06197330089f7964a9b6b8fc86327e6778363b7297ef1", - "threatintel.recordedfuture.entity.type": "Hash", - "threatintel.recordedfuture.intelCard": "https://app.recordedfuture.local/live/sc/entity/hash%3A184527a5436086cff0c06197330089f7964a9b6b8fc86327e6778363b7297ef1", - "threatintel.recordedfuture.risk.criticality": 3, - "threatintel.recordedfuture.risk.criticalityLabel": "Malicious", - "threatintel.recordedfuture.risk.evidenceDetails": [ + "recordedfuture.entity.id": "hash:184527a5436086cff0c06197330089f7964a9b6b8fc86327e6778363b7297ef1", + "recordedfuture.entity.type": "Hash", + "recordedfuture.intelCard": "https://app.recordedfuture.local/live/sc/entity/hash%3A184527a5436086cff0c06197330089f7964a9b6b8fc86327e6778363b7297ef1", + "recordedfuture.risk.criticality": 3, + "recordedfuture.risk.criticalityLabel": "Malicious", + "recordedfuture.risk.evidenceDetails": [ { "criticality": 3, "criticalityLabel": "Malicious", @@ -236,10 +232,24 @@ "timestamp": "2021-06-19T17:39:24.000Z" } ], - "threatintel.recordedfuture.risk.riskString": "1/14", - "threatintel.recordedfuture.risk.riskSummary": "1 of 14 Risk Rules currently observed.", - "threatintel.recordedfuture.risk.rules": 1, - "threatintel.recordedfuture.risk.score": 65 + "recordedfuture.risk.riskString": "1/14", + "recordedfuture.risk.riskSummary": "1 of 14 Risk Rules currently observed.", + "recordedfuture.risk.rules": 1, + "recordedfuture.risk.score": 65, + "service.type": "threatintel", + "tags": [ + "forwarded", + "threatintel-recordedfuture" + ], + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] RecordedFuture", + "threat.indicator.file.hash.md5": "3d568bd03766a8d47c8fabb7d392c32e", + "threat.indicator.file.hash.sha1": "3ea8b08bc9ed3009a4d6a0ab5851b8e3fc10ead2", + "threat.indicator.file.hash.sha256": "184527a5436086cff0c06197330089f7964a9b6b8fc86327e6778363b7297ef1", + "threat.indicator.first_seen": "2021-06-20T18:40:18.131Z", + "threat.indicator.last_seen": "2021-06-20T18:40:18.131Z", + "threat.indicator.reference": "https://app.recordedfuture.local/live/sc/entity/hash%3A184527a5436086cff0c06197330089f7964a9b6b8fc86327e6778363b7297ef1", + "threat.indicator.type": "file" }, { "event.category": "threat", @@ -251,24 +261,12 @@ "fileset.name": "recordedfuture", "input.type": "log", "log.offset": 7054, - "service.type": "threatintel", - "tags": [ - "forwarded", - "threatintel-recordedfuture" - ], - "threatintel.indicator.file.hash.md5": "a40e91f2d29616076114eea0f2a693af", - "threatintel.indicator.file.hash.sha1": "e38ccd47629c1b75385a83fbfbba0ea7f3b3a705", - "threatintel.indicator.file.hash.sha256": "1136b8991c6f180a6c67eaff7c2a998d67dbcadc2d9cf5a3f816de03503817a8", - "threatintel.indicator.first_seen": "2021-06-20T18:40:18.093Z", - "threatintel.indicator.last_seen": "2021-06-20T18:40:18.093Z", - "threatintel.indicator.reference": "https://app.recordedfuture.local/live/sc/entity/hash%3A1136b8991c6f180a6c67eaff7c2a998d67dbcadc2d9cf5a3f816de03503817a8", - "threatintel.indicator.type": "file", - "threatintel.recordedfuture.entity.id": "hash:1136b8991c6f180a6c67eaff7c2a998d67dbcadc2d9cf5a3f816de03503817a8", - "threatintel.recordedfuture.entity.type": "Hash", - "threatintel.recordedfuture.intelCard": "https://app.recordedfuture.local/live/sc/entity/hash%3A1136b8991c6f180a6c67eaff7c2a998d67dbcadc2d9cf5a3f816de03503817a8", - "threatintel.recordedfuture.risk.criticality": 3, - "threatintel.recordedfuture.risk.criticalityLabel": "Malicious", - "threatintel.recordedfuture.risk.evidenceDetails": [ + "recordedfuture.entity.id": "hash:1136b8991c6f180a6c67eaff7c2a998d67dbcadc2d9cf5a3f816de03503817a8", + "recordedfuture.entity.type": "Hash", + "recordedfuture.intelCard": "https://app.recordedfuture.local/live/sc/entity/hash%3A1136b8991c6f180a6c67eaff7c2a998d67dbcadc2d9cf5a3f816de03503817a8", + "recordedfuture.risk.criticality": 3, + "recordedfuture.risk.criticalityLabel": "Malicious", + "recordedfuture.risk.evidenceDetails": [ { "criticality": 3, "criticalityLabel": "Malicious", @@ -286,10 +284,24 @@ "timestamp": "2021-06-20T18:40:18.093Z" } ], - "threatintel.recordedfuture.risk.riskString": "2/14", - "threatintel.recordedfuture.risk.riskSummary": "2 of 14 Risk Rules currently observed.", - "threatintel.recordedfuture.risk.rules": 2, - "threatintel.recordedfuture.risk.score": 65 + "recordedfuture.risk.riskString": "2/14", + "recordedfuture.risk.riskSummary": "2 of 14 Risk Rules currently observed.", + "recordedfuture.risk.rules": 2, + "recordedfuture.risk.score": 65, + "service.type": "threatintel", + "tags": [ + "forwarded", + "threatintel-recordedfuture" + ], + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] RecordedFuture", + "threat.indicator.file.hash.md5": "a40e91f2d29616076114eea0f2a693af", + "threat.indicator.file.hash.sha1": "e38ccd47629c1b75385a83fbfbba0ea7f3b3a705", + "threat.indicator.file.hash.sha256": "1136b8991c6f180a6c67eaff7c2a998d67dbcadc2d9cf5a3f816de03503817a8", + "threat.indicator.first_seen": "2021-06-20T18:40:18.093Z", + "threat.indicator.last_seen": "2021-06-20T18:40:18.093Z", + "threat.indicator.reference": "https://app.recordedfuture.local/live/sc/entity/hash%3A1136b8991c6f180a6c67eaff7c2a998d67dbcadc2d9cf5a3f816de03503817a8", + "threat.indicator.type": "file" }, { "event.category": "threat", @@ -301,24 +313,12 @@ "fileset.name": "recordedfuture", "input.type": "log", "log.offset": 8550, - "service.type": "threatintel", - "tags": [ - "forwarded", - "threatintel-recordedfuture" - ], - "threatintel.indicator.file.hash.md5": "02062782c7eeaff185ea6966460f7c9a", - "threatintel.indicator.file.hash.sha1": "64355796dc38992ca5e434682ddbf63bdfabeb4e", - "threatintel.indicator.file.hash.sha256": "bf325093d87f746c297b2752c38a41a8f41b32aca01146b3632e24e90cdd14a1", - "threatintel.indicator.first_seen": "2021-06-20T18:40:18.070Z", - "threatintel.indicator.last_seen": "2021-06-20T18:40:18.070Z", - "threatintel.indicator.reference": "https://app.recordedfuture.local/live/sc/entity/hash%3Abf325093d87f746c297b2752c38a41a8f41b32aca01146b3632e24e90cdd14a1", - "threatintel.indicator.type": "file", - "threatintel.recordedfuture.entity.id": "hash:bf325093d87f746c297b2752c38a41a8f41b32aca01146b3632e24e90cdd14a1", - "threatintel.recordedfuture.entity.type": "Hash", - "threatintel.recordedfuture.intelCard": "https://app.recordedfuture.local/live/sc/entity/hash%3Abf325093d87f746c297b2752c38a41a8f41b32aca01146b3632e24e90cdd14a1", - "threatintel.recordedfuture.risk.criticality": 3, - "threatintel.recordedfuture.risk.criticalityLabel": "Malicious", - "threatintel.recordedfuture.risk.evidenceDetails": [ + "recordedfuture.entity.id": "hash:bf325093d87f746c297b2752c38a41a8f41b32aca01146b3632e24e90cdd14a1", + "recordedfuture.entity.type": "Hash", + "recordedfuture.intelCard": "https://app.recordedfuture.local/live/sc/entity/hash%3Abf325093d87f746c297b2752c38a41a8f41b32aca01146b3632e24e90cdd14a1", + "recordedfuture.risk.criticality": 3, + "recordedfuture.risk.criticalityLabel": "Malicious", + "recordedfuture.risk.evidenceDetails": [ { "criticality": 3, "criticalityLabel": "Malicious", @@ -336,10 +336,24 @@ "timestamp": "2021-06-20T18:40:18.070Z" } ], - "threatintel.recordedfuture.risk.riskString": "2/14", - "threatintel.recordedfuture.risk.riskSummary": "2 of 14 Risk Rules currently observed.", - "threatintel.recordedfuture.risk.rules": 2, - "threatintel.recordedfuture.risk.score": 65 + "recordedfuture.risk.riskString": "2/14", + "recordedfuture.risk.riskSummary": "2 of 14 Risk Rules currently observed.", + "recordedfuture.risk.rules": 2, + "recordedfuture.risk.score": 65, + "service.type": "threatintel", + "tags": [ + "forwarded", + "threatintel-recordedfuture" + ], + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] RecordedFuture", + "threat.indicator.file.hash.md5": "02062782c7eeaff185ea6966460f7c9a", + "threat.indicator.file.hash.sha1": "64355796dc38992ca5e434682ddbf63bdfabeb4e", + "threat.indicator.file.hash.sha256": "bf325093d87f746c297b2752c38a41a8f41b32aca01146b3632e24e90cdd14a1", + "threat.indicator.first_seen": "2021-06-20T18:40:18.070Z", + "threat.indicator.last_seen": "2021-06-20T18:40:18.070Z", + "threat.indicator.reference": "https://app.recordedfuture.local/live/sc/entity/hash%3Abf325093d87f746c297b2752c38a41a8f41b32aca01146b3632e24e90cdd14a1", + "threat.indicator.type": "file" }, { "event.category": "threat", @@ -351,24 +365,12 @@ "fileset.name": "recordedfuture", "input.type": "log", "log.offset": 10020, - "service.type": "threatintel", - "tags": [ - "forwarded", - "threatintel-recordedfuture" - ], - "threatintel.indicator.file.hash.md5": "bdd205ffc81c54e7cc1a9080cfa093e4", - "threatintel.indicator.file.hash.sha1": "a6b928fd6fee43495b96941ef80b25d074f6e0e2", - "threatintel.indicator.file.hash.sha256": "c06f58340d8e7b1f466942db18f67b5eb048c9adc45d843db370c836e125e3f9", - "threatintel.indicator.first_seen": "2021-06-20T18:40:18.011Z", - "threatintel.indicator.last_seen": "2021-06-20T18:40:18.011Z", - "threatintel.indicator.reference": "https://app.recordedfuture.local/live/sc/entity/hash%3Ac06f58340d8e7b1f466942db18f67b5eb048c9adc45d843db370c836e125e3f9", - "threatintel.indicator.type": "file", - "threatintel.recordedfuture.entity.id": "hash:c06f58340d8e7b1f466942db18f67b5eb048c9adc45d843db370c836e125e3f9", - "threatintel.recordedfuture.entity.type": "Hash", - "threatintel.recordedfuture.intelCard": "https://app.recordedfuture.local/live/sc/entity/hash%3Ac06f58340d8e7b1f466942db18f67b5eb048c9adc45d843db370c836e125e3f9", - "threatintel.recordedfuture.risk.criticality": 3, - "threatintel.recordedfuture.risk.criticalityLabel": "Malicious", - "threatintel.recordedfuture.risk.evidenceDetails": [ + "recordedfuture.entity.id": "hash:c06f58340d8e7b1f466942db18f67b5eb048c9adc45d843db370c836e125e3f9", + "recordedfuture.entity.type": "Hash", + "recordedfuture.intelCard": "https://app.recordedfuture.local/live/sc/entity/hash%3Ac06f58340d8e7b1f466942db18f67b5eb048c9adc45d843db370c836e125e3f9", + "recordedfuture.risk.criticality": 3, + "recordedfuture.risk.criticalityLabel": "Malicious", + "recordedfuture.risk.evidenceDetails": [ { "criticality": 3, "criticalityLabel": "Malicious", @@ -386,10 +388,24 @@ "timestamp": "2021-06-20T18:40:18.010Z" } ], - "threatintel.recordedfuture.risk.riskString": "2/14", - "threatintel.recordedfuture.risk.riskSummary": "2 of 14 Risk Rules currently observed.", - "threatintel.recordedfuture.risk.rules": 2, - "threatintel.recordedfuture.risk.score": 65 + "recordedfuture.risk.riskString": "2/14", + "recordedfuture.risk.riskSummary": "2 of 14 Risk Rules currently observed.", + "recordedfuture.risk.rules": 2, + "recordedfuture.risk.score": 65, + "service.type": "threatintel", + "tags": [ + "forwarded", + "threatintel-recordedfuture" + ], + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] RecordedFuture", + "threat.indicator.file.hash.md5": "bdd205ffc81c54e7cc1a9080cfa093e4", + "threat.indicator.file.hash.sha1": "a6b928fd6fee43495b96941ef80b25d074f6e0e2", + "threat.indicator.file.hash.sha256": "c06f58340d8e7b1f466942db18f67b5eb048c9adc45d843db370c836e125e3f9", + "threat.indicator.first_seen": "2021-06-20T18:40:18.011Z", + "threat.indicator.last_seen": "2021-06-20T18:40:18.011Z", + "threat.indicator.reference": "https://app.recordedfuture.local/live/sc/entity/hash%3Ac06f58340d8e7b1f466942db18f67b5eb048c9adc45d843db370c836e125e3f9", + "threat.indicator.type": "file" }, { "event.category": "threat", @@ -401,24 +417,12 @@ "fileset.name": "recordedfuture", "input.type": "log", "log.offset": 11492, - "service.type": "threatintel", - "tags": [ - "forwarded", - "threatintel-recordedfuture" - ], - "threatintel.indicator.file.hash.md5": "af45390e39574cdb037d684074e6a542", - "threatintel.indicator.file.hash.sha1": "f6a14c7424604cd51ba6a6d3f7594ec762f48645", - "threatintel.indicator.file.hash.sha256": "c878bdb6c62ace8f001f979f7c7b2c6b38d135ac1c69bfa63785bf86721619fc", - "threatintel.indicator.first_seen": "2021-06-20T18:40:17.964Z", - "threatintel.indicator.last_seen": "2021-06-20T18:40:17.964Z", - "threatintel.indicator.reference": "https://app.recordedfuture.local/live/sc/entity/hash%3Ac878bdb6c62ace8f001f979f7c7b2c6b38d135ac1c69bfa63785bf86721619fc", - "threatintel.indicator.type": "file", - "threatintel.recordedfuture.entity.id": "hash:c878bdb6c62ace8f001f979f7c7b2c6b38d135ac1c69bfa63785bf86721619fc", - "threatintel.recordedfuture.entity.type": "Hash", - "threatintel.recordedfuture.intelCard": "https://app.recordedfuture.local/live/sc/entity/hash%3Ac878bdb6c62ace8f001f979f7c7b2c6b38d135ac1c69bfa63785bf86721619fc", - "threatintel.recordedfuture.risk.criticality": 3, - "threatintel.recordedfuture.risk.criticalityLabel": "Malicious", - "threatintel.recordedfuture.risk.evidenceDetails": [ + "recordedfuture.entity.id": "hash:c878bdb6c62ace8f001f979f7c7b2c6b38d135ac1c69bfa63785bf86721619fc", + "recordedfuture.entity.type": "Hash", + "recordedfuture.intelCard": "https://app.recordedfuture.local/live/sc/entity/hash%3Ac878bdb6c62ace8f001f979f7c7b2c6b38d135ac1c69bfa63785bf86721619fc", + "recordedfuture.risk.criticality": 3, + "recordedfuture.risk.criticalityLabel": "Malicious", + "recordedfuture.risk.evidenceDetails": [ { "criticality": 3, "criticalityLabel": "Malicious", @@ -436,10 +440,24 @@ "timestamp": "2021-06-20T18:40:17.964Z" } ], - "threatintel.recordedfuture.risk.riskString": "2/14", - "threatintel.recordedfuture.risk.riskSummary": "2 of 14 Risk Rules currently observed.", - "threatintel.recordedfuture.risk.rules": 2, - "threatintel.recordedfuture.risk.score": 65 + "recordedfuture.risk.riskString": "2/14", + "recordedfuture.risk.riskSummary": "2 of 14 Risk Rules currently observed.", + "recordedfuture.risk.rules": 2, + "recordedfuture.risk.score": 65, + "service.type": "threatintel", + "tags": [ + "forwarded", + "threatintel-recordedfuture" + ], + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] RecordedFuture", + "threat.indicator.file.hash.md5": "af45390e39574cdb037d684074e6a542", + "threat.indicator.file.hash.sha1": "f6a14c7424604cd51ba6a6d3f7594ec762f48645", + "threat.indicator.file.hash.sha256": "c878bdb6c62ace8f001f979f7c7b2c6b38d135ac1c69bfa63785bf86721619fc", + "threat.indicator.first_seen": "2021-06-20T18:40:17.964Z", + "threat.indicator.last_seen": "2021-06-20T18:40:17.964Z", + "threat.indicator.reference": "https://app.recordedfuture.local/live/sc/entity/hash%3Ac878bdb6c62ace8f001f979f7c7b2c6b38d135ac1c69bfa63785bf86721619fc", + "threat.indicator.type": "file" }, { "event.category": "threat", @@ -451,24 +469,12 @@ "fileset.name": "recordedfuture", "input.type": "log", "log.offset": 12964, - "service.type": "threatintel", - "tags": [ - "forwarded", - "threatintel-recordedfuture" - ], - "threatintel.indicator.file.hash.md5": "5b8bcd367f802cd104210bb47abb3ab1", - "threatintel.indicator.file.hash.sha1": "b40d1796bd6974860ce6be691152ad963300c711", - "threatintel.indicator.file.hash.sha256": "0996575c7d2f07513d0dafe67ddde9805bbea35cf9d98edf8faf12c0e7f4334c", - "threatintel.indicator.first_seen": "2021-06-20T18:40:17.919Z", - "threatintel.indicator.last_seen": "2021-06-20T18:40:17.919Z", - "threatintel.indicator.reference": "https://app.recordedfuture.local/live/sc/entity/hash%3A0996575c7d2f07513d0dafe67ddde9805bbea35cf9d98edf8faf12c0e7f4334c", - "threatintel.indicator.type": "file", - "threatintel.recordedfuture.entity.id": "hash:0996575c7d2f07513d0dafe67ddde9805bbea35cf9d98edf8faf12c0e7f4334c", - "threatintel.recordedfuture.entity.type": "Hash", - "threatintel.recordedfuture.intelCard": "https://app.recordedfuture.local/live/sc/entity/hash%3A0996575c7d2f07513d0dafe67ddde9805bbea35cf9d98edf8faf12c0e7f4334c", - "threatintel.recordedfuture.risk.criticality": 3, - "threatintel.recordedfuture.risk.criticalityLabel": "Malicious", - "threatintel.recordedfuture.risk.evidenceDetails": [ + "recordedfuture.entity.id": "hash:0996575c7d2f07513d0dafe67ddde9805bbea35cf9d98edf8faf12c0e7f4334c", + "recordedfuture.entity.type": "Hash", + "recordedfuture.intelCard": "https://app.recordedfuture.local/live/sc/entity/hash%3A0996575c7d2f07513d0dafe67ddde9805bbea35cf9d98edf8faf12c0e7f4334c", + "recordedfuture.risk.criticality": 3, + "recordedfuture.risk.criticalityLabel": "Malicious", + "recordedfuture.risk.evidenceDetails": [ { "criticality": 3, "criticalityLabel": "Malicious", @@ -486,9 +492,23 @@ "timestamp": "2021-06-20T18:40:17.919Z" } ], - "threatintel.recordedfuture.risk.riskString": "2/14", - "threatintel.recordedfuture.risk.riskSummary": "2 of 14 Risk Rules currently observed.", - "threatintel.recordedfuture.risk.rules": 2, - "threatintel.recordedfuture.risk.score": 65 + "recordedfuture.risk.riskString": "2/14", + "recordedfuture.risk.riskSummary": "2 of 14 Risk Rules currently observed.", + "recordedfuture.risk.rules": 2, + "recordedfuture.risk.score": 65, + "service.type": "threatintel", + "tags": [ + "forwarded", + "threatintel-recordedfuture" + ], + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] RecordedFuture", + "threat.indicator.file.hash.md5": "5b8bcd367f802cd104210bb47abb3ab1", + "threat.indicator.file.hash.sha1": "b40d1796bd6974860ce6be691152ad963300c711", + "threat.indicator.file.hash.sha256": "0996575c7d2f07513d0dafe67ddde9805bbea35cf9d98edf8faf12c0e7f4334c", + "threat.indicator.first_seen": "2021-06-20T18:40:17.919Z", + "threat.indicator.last_seen": "2021-06-20T18:40:17.919Z", + "threat.indicator.reference": "https://app.recordedfuture.local/live/sc/entity/hash%3A0996575c7d2f07513d0dafe67ddde9805bbea35cf9d98edf8faf12c0e7f4334c", + "threat.indicator.type": "file" } ] \ No newline at end of file diff --git a/x-pack/filebeat/module/threatintel/recordedfuture/test/ip.ndjson.log-expected.json b/x-pack/filebeat/module/threatintel/recordedfuture/test/ip.ndjson.log-expected.json index 74488f715da..c46c3e2a51f 100644 --- a/x-pack/filebeat/module/threatintel/recordedfuture/test/ip.ndjson.log-expected.json +++ b/x-pack/filebeat/module/threatintel/recordedfuture/test/ip.ndjson.log-expected.json @@ -9,32 +9,34 @@ "fileset.name": "recordedfuture", "input.type": "log", "log.offset": 0, + "recordedfuture.entity.id": "ip:2001:db8:cdb4:ff33:c406:fcdc:6961:c8af/21", + "recordedfuture.entity.name": "2001:db8:cdb4:ff33:c406:fcdc:6961:c8af/21", + "recordedfuture.entity.type": "IpAddress", + "recordedfuture.intelCard": "https://app.recordedfuture.local/live/sc/entity/ip%3A2001:db8:cdb4:ff33:c406:fcdc:6961:c8af/21", + "recordedfuture.ip_range": "2001:db8:cdb4:ff33:c406:fcdc:6961:c8af/21", + "recordedfuture.risk.criticality": 0, + "recordedfuture.risk.criticalityLabel": "None", + "recordedfuture.risk.evidenceDetails": [], + "recordedfuture.risk.riskString": "0/54", + "recordedfuture.risk.riskSummary": "No Risk Rules are currently observed.", + "recordedfuture.risk.rules": 0, + "recordedfuture.risk.score": 0, "service.type": "threatintel", "tags": [ "forwarded", "threatintel-recordedfuture" ], - "threatintel.indicator.as.number": 31287, - "threatintel.indicator.as.organization.name": "IPACCT CABLE Ltd", - "threatintel.indicator.first_seen": "2021-04-18T00:11:48.512Z", - "threatintel.indicator.geo.city_name": "Radnevo", - "threatintel.indicator.geo.continent_name": "Europe", - "threatintel.indicator.geo.country_name": "Bulgaria", - "threatintel.indicator.last_seen": "2021-06-19T19:40:32.897Z", - "threatintel.indicator.reference": "https://app.recordedfuture.local/live/sc/entity/ip%3A2001:db8:cdb4:ff33:c406:fcdc:6961:c8af/21", - "threatintel.indicator.type": "ipv6-addr", - "threatintel.recordedfuture.entity.id": "ip:2001:db8:cdb4:ff33:c406:fcdc:6961:c8af/21", - "threatintel.recordedfuture.entity.name": "2001:db8:cdb4:ff33:c406:fcdc:6961:c8af/21", - "threatintel.recordedfuture.entity.type": "IpAddress", - "threatintel.recordedfuture.intelCard": "https://app.recordedfuture.local/live/sc/entity/ip%3A2001:db8:cdb4:ff33:c406:fcdc:6961:c8af/21", - "threatintel.recordedfuture.ip_range": "2001:db8:cdb4:ff33:c406:fcdc:6961:c8af/21", - "threatintel.recordedfuture.risk.criticality": 0, - "threatintel.recordedfuture.risk.criticalityLabel": "None", - "threatintel.recordedfuture.risk.evidenceDetails": [], - "threatintel.recordedfuture.risk.riskString": "0/54", - "threatintel.recordedfuture.risk.riskSummary": "No Risk Rules are currently observed.", - "threatintel.recordedfuture.risk.rules": 0, - "threatintel.recordedfuture.risk.score": 0 + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] RecordedFuture", + "threat.indicator.as.number": 31287, + "threat.indicator.as.organization.name": "IPACCT CABLE Ltd", + "threat.indicator.first_seen": "2021-04-18T00:11:48.512Z", + "threat.indicator.geo.city_name": "Radnevo", + "threat.indicator.geo.continent_name": "Europe", + "threat.indicator.geo.country_name": "Bulgaria", + "threat.indicator.last_seen": "2021-06-19T19:40:32.897Z", + "threat.indicator.reference": "https://app.recordedfuture.local/live/sc/entity/ip%3A2001:db8:cdb4:ff33:c406:fcdc:6961:c8af/21", + "threat.indicator.type": "ipv6-addr" }, { "event.category": "threat", @@ -46,32 +48,33 @@ "fileset.name": "recordedfuture", "input.type": "log", "log.offset": 763, + "recordedfuture.entity.id": "ip:2001:db8:f800:5c3f:c9f8:fbf8:d537:9071", + "recordedfuture.entity.type": "IpAddress", + "recordedfuture.intelCard": "https://app.recordedfuture.local/live/sc/entity/ip%3A2001:db8:f800:5c3f:c9f8:fbf8:d537:9071", + "recordedfuture.ip_range": "2001:db8:f800:5c3f:c9f8:fbf8:d537:9071/128", + "recordedfuture.risk.criticality": 0, + "recordedfuture.risk.criticalityLabel": "None", + "recordedfuture.risk.evidenceDetails": [], + "recordedfuture.risk.riskString": "0/54", + "recordedfuture.risk.riskSummary": "No Risk Rules are currently observed.", + "recordedfuture.risk.rules": 0, + "recordedfuture.risk.score": 0, "service.type": "threatintel", "tags": [ "forwarded", "threatintel-recordedfuture" ], - "threatintel.indicator.as.number": 197207, - "threatintel.indicator.as.organization.name": "Mobile Communication Company of Iran PLC", - "threatintel.indicator.first_seen": "2021-06-19T17:55:58.019Z", - "threatintel.indicator.geo.city_name": null, - "threatintel.indicator.geo.continent_name": "Asia", - "threatintel.indicator.geo.country_name": "Iran", - "threatintel.indicator.ip": "2001:db8:f800:5c3f:c9f8:fbf8:d537:9071", - "threatintel.indicator.last_seen": "2021-06-19T19:40:32.839Z", - "threatintel.indicator.reference": "https://app.recordedfuture.local/live/sc/entity/ip%3A2001:db8:f800:5c3f:c9f8:fbf8:d537:9071", - "threatintel.indicator.type": "ipv6-addr", - "threatintel.recordedfuture.entity.id": "ip:2001:db8:f800:5c3f:c9f8:fbf8:d537:9071", - "threatintel.recordedfuture.entity.type": "IpAddress", - "threatintel.recordedfuture.intelCard": "https://app.recordedfuture.local/live/sc/entity/ip%3A2001:db8:f800:5c3f:c9f8:fbf8:d537:9071", - "threatintel.recordedfuture.ip_range": "2001:db8:f800:5c3f:c9f8:fbf8:d537:9071/128", - "threatintel.recordedfuture.risk.criticality": 0, - "threatintel.recordedfuture.risk.criticalityLabel": "None", - "threatintel.recordedfuture.risk.evidenceDetails": [], - "threatintel.recordedfuture.risk.riskString": "0/54", - "threatintel.recordedfuture.risk.riskSummary": "No Risk Rules are currently observed.", - "threatintel.recordedfuture.risk.rules": 0, - "threatintel.recordedfuture.risk.score": 0 + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] RecordedFuture", + "threat.indicator.as.number": 197207, + "threat.indicator.as.organization.name": "Mobile Communication Company of Iran PLC", + "threat.indicator.first_seen": "2021-06-19T17:55:58.019Z", + "threat.indicator.geo.continent_name": "Asia", + "threat.indicator.geo.country_name": "Iran", + "threat.indicator.ip": "2001:db8:f800:5c3f:c9f8:fbf8:d537:9071", + "threat.indicator.last_seen": "2021-06-19T19:40:32.839Z", + "threat.indicator.reference": "https://app.recordedfuture.local/live/sc/entity/ip%3A2001:db8:f800:5c3f:c9f8:fbf8:d537:9071", + "threat.indicator.type": "ipv6-addr" }, { "event.category": "threat", @@ -83,31 +86,29 @@ "fileset.name": "recordedfuture", "input.type": "log", "log.offset": 1531, + "recordedfuture.entity.id": "ip:203.0.113.55", + "recordedfuture.entity.type": "IpAddress", + "recordedfuture.intelCard": "https://app.recordedfuture.local/live/sc/entity/ip%3A203.0.113.55", + "recordedfuture.ip_range": "203.0.113.55/32", + "recordedfuture.risk.criticality": 0, + "recordedfuture.risk.criticalityLabel": "None", + "recordedfuture.risk.evidenceDetails": [], + "recordedfuture.risk.riskString": "0/54", + "recordedfuture.risk.riskSummary": "No Risk Rules are currently observed.", + "recordedfuture.risk.rules": 0, + "recordedfuture.risk.score": 0, "service.type": "threatintel", "tags": [ "forwarded", "threatintel-recordedfuture" ], - "threatintel.indicator.as.organization.name": null, - "threatintel.indicator.first_seen": "2021-06-19T19:40:30.596Z", - "threatintel.indicator.geo.city_name": null, - "threatintel.indicator.geo.continent_name": null, - "threatintel.indicator.geo.country_name": null, - "threatintel.indicator.ip": "203.0.113.55", - "threatintel.indicator.last_seen": "2021-06-19T19:40:30.596Z", - "threatintel.indicator.reference": "https://app.recordedfuture.local/live/sc/entity/ip%3A203.0.113.55", - "threatintel.indicator.type": "ipv4-addr", - "threatintel.recordedfuture.entity.id": "ip:203.0.113.55", - "threatintel.recordedfuture.entity.type": "IpAddress", - "threatintel.recordedfuture.intelCard": "https://app.recordedfuture.local/live/sc/entity/ip%3A203.0.113.55", - "threatintel.recordedfuture.ip_range": "203.0.113.55/32", - "threatintel.recordedfuture.risk.criticality": 0, - "threatintel.recordedfuture.risk.criticalityLabel": "None", - "threatintel.recordedfuture.risk.evidenceDetails": [], - "threatintel.recordedfuture.risk.riskString": "0/54", - "threatintel.recordedfuture.risk.riskSummary": "No Risk Rules are currently observed.", - "threatintel.recordedfuture.risk.rules": 0, - "threatintel.recordedfuture.risk.score": 0 + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] RecordedFuture", + "threat.indicator.first_seen": "2021-06-19T19:40:30.596Z", + "threat.indicator.ip": "203.0.113.55", + "threat.indicator.last_seen": "2021-06-19T19:40:30.596Z", + "threat.indicator.reference": "https://app.recordedfuture.local/live/sc/entity/ip%3A203.0.113.55", + "threat.indicator.type": "ipv4-addr" }, { "event.category": "threat", @@ -119,32 +120,34 @@ "fileset.name": "recordedfuture", "input.type": "log", "log.offset": 2161, + "recordedfuture.entity.id": "ip:203.0.113.108", + "recordedfuture.entity.type": "IpAddress", + "recordedfuture.intelCard": "https://app.recordedfuture.local/live/sc/entity/ip%3A203.0.113.108", + "recordedfuture.ip_range": "203.0.113.108/32", + "recordedfuture.risk.criticality": 0, + "recordedfuture.risk.criticalityLabel": "None", + "recordedfuture.risk.evidenceDetails": [], + "recordedfuture.risk.riskString": "0/54", + "recordedfuture.risk.riskSummary": "No Risk Rules are currently observed.", + "recordedfuture.risk.rules": 0, + "recordedfuture.risk.score": 0, "service.type": "threatintel", "tags": [ "forwarded", "threatintel-recordedfuture" ], - "threatintel.indicator.as.number": 17622, - "threatintel.indicator.as.organization.name": "China Unicom Guangzhou network", - "threatintel.indicator.first_seen": "2021-06-19T19:40:20.534Z", - "threatintel.indicator.geo.city_name": "Guangzhou", - "threatintel.indicator.geo.continent_name": "Asia", - "threatintel.indicator.geo.country_name": "China", - "threatintel.indicator.ip": "203.0.113.108", - "threatintel.indicator.last_seen": "2021-06-19T19:40:20.534Z", - "threatintel.indicator.reference": "https://app.recordedfuture.local/live/sc/entity/ip%3A203.0.113.108", - "threatintel.indicator.type": "ipv4-addr", - "threatintel.recordedfuture.entity.id": "ip:203.0.113.108", - "threatintel.recordedfuture.entity.type": "IpAddress", - "threatintel.recordedfuture.intelCard": "https://app.recordedfuture.local/live/sc/entity/ip%3A203.0.113.108", - "threatintel.recordedfuture.ip_range": "203.0.113.108/32", - "threatintel.recordedfuture.risk.criticality": 0, - "threatintel.recordedfuture.risk.criticalityLabel": "None", - "threatintel.recordedfuture.risk.evidenceDetails": [], - "threatintel.recordedfuture.risk.riskString": "0/54", - "threatintel.recordedfuture.risk.riskSummary": "No Risk Rules are currently observed.", - "threatintel.recordedfuture.risk.rules": 0, - "threatintel.recordedfuture.risk.score": 0 + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] RecordedFuture", + "threat.indicator.as.number": 17622, + "threat.indicator.as.organization.name": "China Unicom Guangzhou network", + "threat.indicator.first_seen": "2021-06-19T19:40:20.534Z", + "threat.indicator.geo.city_name": "Guangzhou", + "threat.indicator.geo.continent_name": "Asia", + "threat.indicator.geo.country_name": "China", + "threat.indicator.ip": "203.0.113.108", + "threat.indicator.last_seen": "2021-06-19T19:40:20.534Z", + "threat.indicator.reference": "https://app.recordedfuture.local/live/sc/entity/ip%3A203.0.113.108", + "threat.indicator.type": "ipv4-addr" }, { "event.category": "threat", @@ -156,32 +159,33 @@ "fileset.name": "recordedfuture", "input.type": "log", "log.offset": 2851, + "recordedfuture.entity.id": "ip:203.0.113.139", + "recordedfuture.entity.type": "IpAddress", + "recordedfuture.intelCard": "https://app.recordedfuture.local/live/sc/entity/ip%3A203.0.113.139", + "recordedfuture.ip_range": "203.0.113.139/32", + "recordedfuture.risk.criticality": 0, + "recordedfuture.risk.criticalityLabel": "None", + "recordedfuture.risk.evidenceDetails": [], + "recordedfuture.risk.riskString": "0/54", + "recordedfuture.risk.riskSummary": "No Risk Rules are currently observed.", + "recordedfuture.risk.rules": 0, + "recordedfuture.risk.score": 0, "service.type": "threatintel", "tags": [ "forwarded", "threatintel-recordedfuture" ], - "threatintel.indicator.as.number": 7713, - "threatintel.indicator.as.organization.name": "PT Telekomunikasi Indonesia", - "threatintel.indicator.first_seen": "2016-06-23T07:39:06.418Z", - "threatintel.indicator.geo.city_name": null, - "threatintel.indicator.geo.continent_name": "Asia", - "threatintel.indicator.geo.country_name": "Indonesia", - "threatintel.indicator.ip": "203.0.113.139", - "threatintel.indicator.last_seen": "2021-06-19T19:40:03.882Z", - "threatintel.indicator.reference": "https://app.recordedfuture.local/live/sc/entity/ip%3A203.0.113.139", - "threatintel.indicator.type": "ipv4-addr", - "threatintel.recordedfuture.entity.id": "ip:203.0.113.139", - "threatintel.recordedfuture.entity.type": "IpAddress", - "threatintel.recordedfuture.intelCard": "https://app.recordedfuture.local/live/sc/entity/ip%3A203.0.113.139", - "threatintel.recordedfuture.ip_range": "203.0.113.139/32", - "threatintel.recordedfuture.risk.criticality": 0, - "threatintel.recordedfuture.risk.criticalityLabel": "None", - "threatintel.recordedfuture.risk.evidenceDetails": [], - "threatintel.recordedfuture.risk.riskString": "0/54", - "threatintel.recordedfuture.risk.riskSummary": "No Risk Rules are currently observed.", - "threatintel.recordedfuture.risk.rules": 0, - "threatintel.recordedfuture.risk.score": 0 + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] RecordedFuture", + "threat.indicator.as.number": 7713, + "threat.indicator.as.organization.name": "PT Telekomunikasi Indonesia", + "threat.indicator.first_seen": "2016-06-23T07:39:06.418Z", + "threat.indicator.geo.continent_name": "Asia", + "threat.indicator.geo.country_name": "Indonesia", + "threat.indicator.ip": "203.0.113.139", + "threat.indicator.last_seen": "2021-06-19T19:40:03.882Z", + "threat.indicator.reference": "https://app.recordedfuture.local/live/sc/entity/ip%3A203.0.113.139", + "threat.indicator.type": "ipv4-addr" }, { "event.category": "threat", @@ -193,32 +197,34 @@ "fileset.name": "recordedfuture", "input.type": "log", "log.offset": 3532, + "recordedfuture.entity.id": "ip:2001:db8:bf58:c5c3:7a06:5267:82e0:621a", + "recordedfuture.entity.type": "IpAddress", + "recordedfuture.intelCard": "https://app.recordedfuture.local/live/sc/entity/ip%3A2001:db8:bf58:c5c3:7a06:5267:82e0:621a", + "recordedfuture.ip_range": "2001:db8:bf58:c5c3:7a06:5267:82e0:621a/128", + "recordedfuture.risk.criticality": 0, + "recordedfuture.risk.criticalityLabel": "None", + "recordedfuture.risk.evidenceDetails": [], + "recordedfuture.risk.riskString": "0/54", + "recordedfuture.risk.riskSummary": "No Risk Rules are currently observed.", + "recordedfuture.risk.rules": 0, + "recordedfuture.risk.score": 0, "service.type": "threatintel", "tags": [ "forwarded", "threatintel-recordedfuture" ], - "threatintel.indicator.as.number": 17622, - "threatintel.indicator.as.organization.name": "China Unicom Guangzhou network", - "threatintel.indicator.first_seen": "2021-06-19T19:40:02.557Z", - "threatintel.indicator.geo.city_name": "Guangzhou", - "threatintel.indicator.geo.continent_name": "Asia", - "threatintel.indicator.geo.country_name": "China", - "threatintel.indicator.ip": "2001:db8:bf58:c5c3:7a06:5267:82e0:621a", - "threatintel.indicator.last_seen": "2021-06-19T19:40:02.557Z", - "threatintel.indicator.reference": "https://app.recordedfuture.local/live/sc/entity/ip%3A2001:db8:bf58:c5c3:7a06:5267:82e0:621a", - "threatintel.indicator.type": "ipv6-addr", - "threatintel.recordedfuture.entity.id": "ip:2001:db8:bf58:c5c3:7a06:5267:82e0:621a", - "threatintel.recordedfuture.entity.type": "IpAddress", - "threatintel.recordedfuture.intelCard": "https://app.recordedfuture.local/live/sc/entity/ip%3A2001:db8:bf58:c5c3:7a06:5267:82e0:621a", - "threatintel.recordedfuture.ip_range": "2001:db8:bf58:c5c3:7a06:5267:82e0:621a/128", - "threatintel.recordedfuture.risk.criticality": 0, - "threatintel.recordedfuture.risk.criticalityLabel": "None", - "threatintel.recordedfuture.risk.evidenceDetails": [], - "threatintel.recordedfuture.risk.riskString": "0/54", - "threatintel.recordedfuture.risk.riskSummary": "No Risk Rules are currently observed.", - "threatintel.recordedfuture.risk.rules": 0, - "threatintel.recordedfuture.risk.score": 0 + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] RecordedFuture", + "threat.indicator.as.number": 17622, + "threat.indicator.as.organization.name": "China Unicom Guangzhou network", + "threat.indicator.first_seen": "2021-06-19T19:40:02.557Z", + "threat.indicator.geo.city_name": "Guangzhou", + "threat.indicator.geo.continent_name": "Asia", + "threat.indicator.geo.country_name": "China", + "threat.indicator.ip": "2001:db8:bf58:c5c3:7a06:5267:82e0:621a", + "threat.indicator.last_seen": "2021-06-19T19:40:02.557Z", + "threat.indicator.reference": "https://app.recordedfuture.local/live/sc/entity/ip%3A2001:db8:bf58:c5c3:7a06:5267:82e0:621a", + "threat.indicator.type": "ipv6-addr" }, { "event.category": "threat", @@ -230,32 +236,34 @@ "fileset.name": "recordedfuture", "input.type": "log", "log.offset": 4295, + "recordedfuture.entity.id": "ip:192.0.2.147", + "recordedfuture.entity.type": "IpAddress", + "recordedfuture.intelCard": "https://app.recordedfuture.local/live/sc/entity/ip%3A192.0.2.147", + "recordedfuture.ip_range": "192.0.2.147/32", + "recordedfuture.risk.criticality": 0, + "recordedfuture.risk.criticalityLabel": "None", + "recordedfuture.risk.evidenceDetails": [], + "recordedfuture.risk.riskString": "0/54", + "recordedfuture.risk.riskSummary": "No Risk Rules are currently observed.", + "recordedfuture.risk.rules": 0, + "recordedfuture.risk.score": 0, "service.type": "threatintel", "tags": [ "forwarded", "threatintel-recordedfuture" ], - "threatintel.indicator.as.number": 4837, - "threatintel.indicator.as.organization.name": "CHINA UNICOM China169 Backbone", - "threatintel.indicator.first_seen": "2017-12-20T02:21:07.734Z", - "threatintel.indicator.geo.city_name": "Zhengzhou", - "threatintel.indicator.geo.continent_name": "Asia", - "threatintel.indicator.geo.country_name": "China", - "threatintel.indicator.ip": "192.0.2.147", - "threatintel.indicator.last_seen": "2021-06-19T19:39:43.160Z", - "threatintel.indicator.reference": "https://app.recordedfuture.local/live/sc/entity/ip%3A192.0.2.147", - "threatintel.indicator.type": "ipv4-addr", - "threatintel.recordedfuture.entity.id": "ip:192.0.2.147", - "threatintel.recordedfuture.entity.type": "IpAddress", - "threatintel.recordedfuture.intelCard": "https://app.recordedfuture.local/live/sc/entity/ip%3A192.0.2.147", - "threatintel.recordedfuture.ip_range": "192.0.2.147/32", - "threatintel.recordedfuture.risk.criticality": 0, - "threatintel.recordedfuture.risk.criticalityLabel": "None", - "threatintel.recordedfuture.risk.evidenceDetails": [], - "threatintel.recordedfuture.risk.riskString": "0/54", - "threatintel.recordedfuture.risk.riskSummary": "No Risk Rules are currently observed.", - "threatintel.recordedfuture.risk.rules": 0, - "threatintel.recordedfuture.risk.score": 0 + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] RecordedFuture", + "threat.indicator.as.number": 4837, + "threat.indicator.as.organization.name": "CHINA UNICOM China169 Backbone", + "threat.indicator.first_seen": "2017-12-20T02:21:07.734Z", + "threat.indicator.geo.city_name": "Zhengzhou", + "threat.indicator.geo.continent_name": "Asia", + "threat.indicator.geo.country_name": "China", + "threat.indicator.ip": "192.0.2.147", + "threat.indicator.last_seen": "2021-06-19T19:39:43.160Z", + "threat.indicator.reference": "https://app.recordedfuture.local/live/sc/entity/ip%3A192.0.2.147", + "threat.indicator.type": "ipv4-addr" }, { "event.category": "threat", @@ -267,28 +275,13 @@ "fileset.name": "recordedfuture", "input.type": "log", "log.offset": 4972, - "service.type": "threatintel", - "tags": [ - "forwarded", - "threatintel-recordedfuture" - ], - "threatintel.indicator.as.number": 9829, - "threatintel.indicator.as.organization.name": "National Internet Backbone", - "threatintel.indicator.first_seen": "2019-12-24T09:54:02.935Z", - "threatintel.indicator.geo.city_name": "Palakkad", - "threatintel.indicator.geo.continent_name": "Asia", - "threatintel.indicator.geo.country_name": "India", - "threatintel.indicator.ip": "203.0.113.198", - "threatintel.indicator.last_seen": "2021-06-19T19:39:25.532Z", - "threatintel.indicator.reference": "https://app.recordedfuture.local/live/sc/entity/ip%3A203.0.113.198", - "threatintel.indicator.type": "ipv4-addr", - "threatintel.recordedfuture.entity.id": "ip:203.0.113.198", - "threatintel.recordedfuture.entity.type": "IpAddress", - "threatintel.recordedfuture.intelCard": "https://app.recordedfuture.local/live/sc/entity/ip%3A203.0.113.198", - "threatintel.recordedfuture.ip_range": "203.0.113.198/32", - "threatintel.recordedfuture.risk.criticality": 1, - "threatintel.recordedfuture.risk.criticalityLabel": "Unusual", - "threatintel.recordedfuture.risk.evidenceDetails": [ + "recordedfuture.entity.id": "ip:203.0.113.198", + "recordedfuture.entity.type": "IpAddress", + "recordedfuture.intelCard": "https://app.recordedfuture.local/live/sc/entity/ip%3A203.0.113.198", + "recordedfuture.ip_range": "203.0.113.198/32", + "recordedfuture.risk.criticality": 1, + "recordedfuture.risk.criticalityLabel": "Unusual", + "recordedfuture.risk.evidenceDetails": [ { "criticality": 1, "criticalityLabel": "Unusual", @@ -298,10 +291,27 @@ "timestamp": "2019-12-24T09:53:13.546Z" } ], - "threatintel.recordedfuture.risk.riskString": "1/54", - "threatintel.recordedfuture.risk.riskSummary": "1 of 54 Risk Rules currently observed.", - "threatintel.recordedfuture.risk.rules": 1, - "threatintel.recordedfuture.risk.score": 5 + "recordedfuture.risk.riskString": "1/54", + "recordedfuture.risk.riskSummary": "1 of 54 Risk Rules currently observed.", + "recordedfuture.risk.rules": 1, + "recordedfuture.risk.score": 5, + "service.type": "threatintel", + "tags": [ + "forwarded", + "threatintel-recordedfuture" + ], + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] RecordedFuture", + "threat.indicator.as.number": 9829, + "threat.indicator.as.organization.name": "National Internet Backbone", + "threat.indicator.first_seen": "2019-12-24T09:54:02.935Z", + "threat.indicator.geo.city_name": "Palakkad", + "threat.indicator.geo.continent_name": "Asia", + "threat.indicator.geo.country_name": "India", + "threat.indicator.ip": "203.0.113.198", + "threat.indicator.last_seen": "2021-06-19T19:39:25.532Z", + "threat.indicator.reference": "https://app.recordedfuture.local/live/sc/entity/ip%3A203.0.113.198", + "threat.indicator.type": "ipv4-addr" }, { "event.category": "threat", @@ -313,28 +323,13 @@ "fileset.name": "recordedfuture", "input.type": "log", "log.offset": 5970, - "service.type": "threatintel", - "tags": [ - "forwarded", - "threatintel-recordedfuture" - ], - "threatintel.indicator.as.number": 9829, - "threatintel.indicator.as.organization.name": "National Internet Backbone", - "threatintel.indicator.first_seen": "2020-03-03T08:10:28.489Z", - "threatintel.indicator.geo.city_name": "Bangalore", - "threatintel.indicator.geo.continent_name": "Asia", - "threatintel.indicator.geo.country_name": "India", - "threatintel.indicator.ip": "192.0.2.179", - "threatintel.indicator.last_seen": "2021-06-19T19:39:11.694Z", - "threatintel.indicator.reference": "https://app.recordedfuture.local/live/sc/entity/ip%3A192.0.2.179", - "threatintel.indicator.type": "ipv4-addr", - "threatintel.recordedfuture.entity.id": "ip:192.0.2.179", - "threatintel.recordedfuture.entity.type": "IpAddress", - "threatintel.recordedfuture.intelCard": "https://app.recordedfuture.local/live/sc/entity/ip%3A192.0.2.179", - "threatintel.recordedfuture.ip_range": "192.0.2.179/32", - "threatintel.recordedfuture.risk.criticality": 1, - "threatintel.recordedfuture.risk.criticalityLabel": "Unusual", - "threatintel.recordedfuture.risk.evidenceDetails": [ + "recordedfuture.entity.id": "ip:192.0.2.179", + "recordedfuture.entity.type": "IpAddress", + "recordedfuture.intelCard": "https://app.recordedfuture.local/live/sc/entity/ip%3A192.0.2.179", + "recordedfuture.ip_range": "192.0.2.179/32", + "recordedfuture.risk.criticality": 1, + "recordedfuture.risk.criticalityLabel": "Unusual", + "recordedfuture.risk.evidenceDetails": [ { "criticality": 1, "criticalityLabel": "Unusual", @@ -360,10 +355,27 @@ "timestamp": "2021-06-21T19:53:19.897Z" } ], - "threatintel.recordedfuture.risk.riskString": "3/54", - "threatintel.recordedfuture.risk.riskSummary": "3 of 54 Risk Rules currently observed.", - "threatintel.recordedfuture.risk.rules": 3, - "threatintel.recordedfuture.risk.score": 15 + "recordedfuture.risk.riskString": "3/54", + "recordedfuture.risk.riskSummary": "3 of 54 Risk Rules currently observed.", + "recordedfuture.risk.rules": 3, + "recordedfuture.risk.score": 15, + "service.type": "threatintel", + "tags": [ + "forwarded", + "threatintel-recordedfuture" + ], + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] RecordedFuture", + "threat.indicator.as.number": 9829, + "threat.indicator.as.organization.name": "National Internet Backbone", + "threat.indicator.first_seen": "2020-03-03T08:10:28.489Z", + "threat.indicator.geo.city_name": "Bangalore", + "threat.indicator.geo.continent_name": "Asia", + "threat.indicator.geo.country_name": "India", + "threat.indicator.ip": "192.0.2.179", + "threat.indicator.last_seen": "2021-06-19T19:39:11.694Z", + "threat.indicator.reference": "https://app.recordedfuture.local/live/sc/entity/ip%3A192.0.2.179", + "threat.indicator.type": "ipv4-addr" }, { "event.category": "threat", @@ -375,28 +387,13 @@ "fileset.name": "recordedfuture", "input.type": "log", "log.offset": 7483, - "service.type": "threatintel", - "tags": [ - "forwarded", - "threatintel-recordedfuture" - ], - "threatintel.indicator.as.number": 45899, - "threatintel.indicator.as.organization.name": "VNPT Corp", - "threatintel.indicator.first_seen": "2021-06-19T19:38:57.372Z", - "threatintel.indicator.geo.city_name": "Long Phu", - "threatintel.indicator.geo.continent_name": "Asia", - "threatintel.indicator.geo.country_name": "Vietnam", - "threatintel.indicator.ip": "192.0.2.245", - "threatintel.indicator.last_seen": "2021-06-19T19:38:57.372Z", - "threatintel.indicator.reference": "https://app.recordedfuture.local/live/sc/entity/ip%3A192.0.2.245", - "threatintel.indicator.type": "ipv4-addr", - "threatintel.recordedfuture.entity.id": "ip:192.0.2.245", - "threatintel.recordedfuture.entity.type": "IpAddress", - "threatintel.recordedfuture.intelCard": "https://app.recordedfuture.local/live/sc/entity/ip%3A192.0.2.245", - "threatintel.recordedfuture.ip_range": "192.0.2.245/32", - "threatintel.recordedfuture.risk.criticality": 1, - "threatintel.recordedfuture.risk.criticalityLabel": "Unusual", - "threatintel.recordedfuture.risk.evidenceDetails": [ + "recordedfuture.entity.id": "ip:192.0.2.245", + "recordedfuture.entity.type": "IpAddress", + "recordedfuture.intelCard": "https://app.recordedfuture.local/live/sc/entity/ip%3A192.0.2.245", + "recordedfuture.ip_range": "192.0.2.245/32", + "recordedfuture.risk.criticality": 1, + "recordedfuture.risk.criticalityLabel": "Unusual", + "recordedfuture.risk.evidenceDetails": [ { "criticality": 1, "criticalityLabel": "Unusual", @@ -406,9 +403,26 @@ "timestamp": "2021-06-19T19:50:20.162Z" } ], - "threatintel.recordedfuture.risk.riskString": "1/54", - "threatintel.recordedfuture.risk.riskSummary": "1 of 54 Risk Rules currently observed.", - "threatintel.recordedfuture.risk.rules": 1, - "threatintel.recordedfuture.risk.score": 5 + "recordedfuture.risk.riskString": "1/54", + "recordedfuture.risk.riskSummary": "1 of 54 Risk Rules currently observed.", + "recordedfuture.risk.rules": 1, + "recordedfuture.risk.score": 5, + "service.type": "threatintel", + "tags": [ + "forwarded", + "threatintel-recordedfuture" + ], + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] RecordedFuture", + "threat.indicator.as.number": 45899, + "threat.indicator.as.organization.name": "VNPT Corp", + "threat.indicator.first_seen": "2021-06-19T19:38:57.372Z", + "threat.indicator.geo.city_name": "Long Phu", + "threat.indicator.geo.continent_name": "Asia", + "threat.indicator.geo.country_name": "Vietnam", + "threat.indicator.ip": "192.0.2.245", + "threat.indicator.last_seen": "2021-06-19T19:38:57.372Z", + "threat.indicator.reference": "https://app.recordedfuture.local/live/sc/entity/ip%3A192.0.2.245", + "threat.indicator.type": "ipv4-addr" } ] \ No newline at end of file diff --git a/x-pack/filebeat/module/threatintel/recordedfuture/test/url.ndjson.log-expected.json b/x-pack/filebeat/module/threatintel/recordedfuture/test/url.ndjson.log-expected.json index 779d86ae965..f840643fef3 100644 --- a/x-pack/filebeat/module/threatintel/recordedfuture/test/url.ndjson.log-expected.json +++ b/x-pack/filebeat/module/threatintel/recordedfuture/test/url.ndjson.log-expected.json @@ -9,26 +9,12 @@ "fileset.name": "recordedfuture", "input.type": "log", "log.offset": 0, - "service.type": "threatintel", - "tags": [ - "forwarded", - "threatintel-recordedfuture" - ], - "threatintel.indicator.first_seen": "2021-06-20T00:00:00.000Z", - "threatintel.indicator.last_seen": "2021-06-20T23:59:59.000Z", - "threatintel.indicator.reference": "https://app.recordedfuture.local/live/sc/entity/url%3Ahttps://d6s.example.net/nzy/vvc68ke?p5uxwn=1bj", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "d6s.example.net", - "threatintel.indicator.url.original": "https://d6s.example.net/nzy/vvc68ke?p5uxwn=1bj", - "threatintel.indicator.url.path": "/nzy/vvc68ke", - "threatintel.indicator.url.query": "p5uxwn=1bj", - "threatintel.indicator.url.scheme": "https", - "threatintel.recordedfuture.entity.id": "url:https://d6s.example.net/nzy/vvc68ke?p5uxwn=1bj", - "threatintel.recordedfuture.entity.type": "URL", - "threatintel.recordedfuture.intelCard": "https://app.recordedfuture.local/live/sc/entity/url%3Ahttps://d6s.example.net/nzy/vvc68ke?p5uxwn=1bj", - "threatintel.recordedfuture.risk.criticality": 1, - "threatintel.recordedfuture.risk.criticalityLabel": "Unusual", - "threatintel.recordedfuture.risk.evidenceDetails": [ + "recordedfuture.entity.id": "url:https://d6s.example.net/nzy/vvc68ke?p5uxwn=1bj", + "recordedfuture.entity.type": "URL", + "recordedfuture.intelCard": "https://app.recordedfuture.local/live/sc/entity/url%3Ahttps://d6s.example.net/nzy/vvc68ke?p5uxwn=1bj", + "recordedfuture.risk.criticality": 1, + "recordedfuture.risk.criticalityLabel": "Unusual", + "recordedfuture.risk.evidenceDetails": [ { "criticality": 1, "criticalityLabel": "Unusual", @@ -38,10 +24,26 @@ "timestamp": "2021-04-15T00:00:00.000Z" } ], - "threatintel.recordedfuture.risk.riskString": "1/25", - "threatintel.recordedfuture.risk.riskSummary": "1 of 25 Risk Rules currently observed.", - "threatintel.recordedfuture.risk.rules": 1, - "threatintel.recordedfuture.risk.score": 5 + "recordedfuture.risk.riskString": "1/25", + "recordedfuture.risk.riskSummary": "1 of 25 Risk Rules currently observed.", + "recordedfuture.risk.rules": 1, + "recordedfuture.risk.score": 5, + "service.type": "threatintel", + "tags": [ + "forwarded", + "threatintel-recordedfuture" + ], + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] RecordedFuture", + "threat.indicator.first_seen": "2021-06-20T00:00:00.000Z", + "threat.indicator.last_seen": "2021-06-20T23:59:59.000Z", + "threat.indicator.reference": "https://app.recordedfuture.local/live/sc/entity/url%3Ahttps://d6s.example.net/nzy/vvc68ke?p5uxwn=1bj", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "d6s.example.net", + "threat.indicator.url.original": "https://d6s.example.net/nzy/vvc68ke?p5uxwn=1bj", + "threat.indicator.url.path": "/nzy/vvc68ke", + "threat.indicator.url.query": "p5uxwn=1bj", + "threat.indicator.url.scheme": "https" }, { "event.category": "threat", @@ -53,26 +55,12 @@ "fileset.name": "recordedfuture", "input.type": "log", "log.offset": 874, - "service.type": "threatintel", - "tags": [ - "forwarded", - "threatintel-recordedfuture" - ], - "threatintel.indicator.first_seen": "2021-06-20T00:00:00.000Z", - "threatintel.indicator.last_seen": "2021-06-20T23:59:59.000Z", - "threatintel.indicator.reference": "https://app.recordedfuture.local/live/sc/entity/url%3Ahttps://ga7v9u.example.org/bnqv8e2v8/qb49?7kq=iw61", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "ga7v9u.example.org", - "threatintel.indicator.url.original": "https://ga7v9u.example.org/bnqv8e2v8/qb49?7kq=iw61", - "threatintel.indicator.url.path": "/bnqv8e2v8/qb49", - "threatintel.indicator.url.query": "7kq=iw61", - "threatintel.indicator.url.scheme": "https", - "threatintel.recordedfuture.entity.id": "url:https://ga7v9u.example.org/bnqv8e2v8/qb49?7kq=iw61", - "threatintel.recordedfuture.entity.type": "URL", - "threatintel.recordedfuture.intelCard": "https://app.recordedfuture.local/live/sc/entity/url%3Ahttps://ga7v9u.example.org/bnqv8e2v8/qb49?7kq=iw61", - "threatintel.recordedfuture.risk.criticality": 1, - "threatintel.recordedfuture.risk.criticalityLabel": "Unusual", - "threatintel.recordedfuture.risk.evidenceDetails": [ + "recordedfuture.entity.id": "url:https://ga7v9u.example.org/bnqv8e2v8/qb49?7kq=iw61", + "recordedfuture.entity.type": "URL", + "recordedfuture.intelCard": "https://app.recordedfuture.local/live/sc/entity/url%3Ahttps://ga7v9u.example.org/bnqv8e2v8/qb49?7kq=iw61", + "recordedfuture.risk.criticality": 1, + "recordedfuture.risk.criticalityLabel": "Unusual", + "recordedfuture.risk.evidenceDetails": [ { "criticality": 1, "criticalityLabel": "Unusual", @@ -82,10 +70,26 @@ "timestamp": "2021-02-14T00:00:00.000Z" } ], - "threatintel.recordedfuture.risk.riskString": "1/25", - "threatintel.recordedfuture.risk.riskSummary": "1 of 25 Risk Rules currently observed.", - "threatintel.recordedfuture.risk.rules": 1, - "threatintel.recordedfuture.risk.score": 5 + "recordedfuture.risk.riskString": "1/25", + "recordedfuture.risk.riskSummary": "1 of 25 Risk Rules currently observed.", + "recordedfuture.risk.rules": 1, + "recordedfuture.risk.score": 5, + "service.type": "threatintel", + "tags": [ + "forwarded", + "threatintel-recordedfuture" + ], + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] RecordedFuture", + "threat.indicator.first_seen": "2021-06-20T00:00:00.000Z", + "threat.indicator.last_seen": "2021-06-20T23:59:59.000Z", + "threat.indicator.reference": "https://app.recordedfuture.local/live/sc/entity/url%3Ahttps://ga7v9u.example.org/bnqv8e2v8/qb49?7kq=iw61", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "ga7v9u.example.org", + "threat.indicator.url.original": "https://ga7v9u.example.org/bnqv8e2v8/qb49?7kq=iw61", + "threat.indicator.url.path": "/bnqv8e2v8/qb49", + "threat.indicator.url.query": "7kq=iw61", + "threat.indicator.url.scheme": "https" }, { "event.category": "threat", @@ -97,26 +101,12 @@ "fileset.name": "recordedfuture", "input.type": "log", "log.offset": 1760, - "service.type": "threatintel", - "tags": [ - "forwarded", - "threatintel-recordedfuture" - ], - "threatintel.indicator.first_seen": "2021-06-20T00:00:00.000Z", - "threatintel.indicator.last_seen": "2021-06-20T23:59:59.000Z", - "threatintel.indicator.reference": "https://app.recordedfuture.local/live/sc/entity/url%3Ahttps://cdmw.example.net/c20fwa/wwn?dlz53=z6ovc", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "cdmw.example.net", - "threatintel.indicator.url.original": "https://cdmw.example.net/c20fwa/wwn?dlz53=z6ovc", - "threatintel.indicator.url.path": "/c20fwa/wwn", - "threatintel.indicator.url.query": "dlz53=z6ovc", - "threatintel.indicator.url.scheme": "https", - "threatintel.recordedfuture.entity.id": "url:https://cdmw.example.net/c20fwa/wwn?dlz53=z6ovc", - "threatintel.recordedfuture.entity.type": "URL", - "threatintel.recordedfuture.intelCard": "https://app.recordedfuture.local/live/sc/entity/url%3Ahttps://cdmw.example.net/c20fwa/wwn?dlz53=z6ovc", - "threatintel.recordedfuture.risk.criticality": 1, - "threatintel.recordedfuture.risk.criticalityLabel": "Unusual", - "threatintel.recordedfuture.risk.evidenceDetails": [ + "recordedfuture.entity.id": "url:https://cdmw.example.net/c20fwa/wwn?dlz53=z6ovc", + "recordedfuture.entity.type": "URL", + "recordedfuture.intelCard": "https://app.recordedfuture.local/live/sc/entity/url%3Ahttps://cdmw.example.net/c20fwa/wwn?dlz53=z6ovc", + "recordedfuture.risk.criticality": 1, + "recordedfuture.risk.criticalityLabel": "Unusual", + "recordedfuture.risk.evidenceDetails": [ { "criticality": 1, "criticalityLabel": "Unusual", @@ -126,10 +116,26 @@ "timestamp": "2021-05-15T00:00:00.000Z" } ], - "threatintel.recordedfuture.risk.riskString": "1/25", - "threatintel.recordedfuture.risk.riskSummary": "1 of 25 Risk Rules currently observed.", - "threatintel.recordedfuture.risk.rules": 1, - "threatintel.recordedfuture.risk.score": 5 + "recordedfuture.risk.riskString": "1/25", + "recordedfuture.risk.riskSummary": "1 of 25 Risk Rules currently observed.", + "recordedfuture.risk.rules": 1, + "recordedfuture.risk.score": 5, + "service.type": "threatintel", + "tags": [ + "forwarded", + "threatintel-recordedfuture" + ], + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] RecordedFuture", + "threat.indicator.first_seen": "2021-06-20T00:00:00.000Z", + "threat.indicator.last_seen": "2021-06-20T23:59:59.000Z", + "threat.indicator.reference": "https://app.recordedfuture.local/live/sc/entity/url%3Ahttps://cdmw.example.net/c20fwa/wwn?dlz53=z6ovc", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "cdmw.example.net", + "threat.indicator.url.original": "https://cdmw.example.net/c20fwa/wwn?dlz53=z6ovc", + "threat.indicator.url.path": "/c20fwa/wwn", + "threat.indicator.url.query": "dlz53=z6ovc", + "threat.indicator.url.scheme": "https" }, { "event.category": "threat", @@ -141,26 +147,12 @@ "fileset.name": "recordedfuture", "input.type": "log", "log.offset": 2627, - "service.type": "threatintel", - "tags": [ - "forwarded", - "threatintel-recordedfuture" - ], - "threatintel.indicator.first_seen": "2021-06-20T00:00:00.000Z", - "threatintel.indicator.last_seen": "2021-06-20T23:59:59.000Z", - "threatintel.indicator.reference": "https://app.recordedfuture.local/live/sc/entity/url%3Ahttps://4mne.example.local/ns2rk8f/wngtk2xz?vceuk7wl6=3p0", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "4mne.example.local", - "threatintel.indicator.url.original": "https://4mne.example.local/ns2rk8f/wngtk2xz?vceuk7wl6=3p0", - "threatintel.indicator.url.path": "/ns2rk8f/wngtk2xz", - "threatintel.indicator.url.query": "vceuk7wl6=3p0", - "threatintel.indicator.url.scheme": "https", - "threatintel.recordedfuture.entity.id": "url:https://4mne.example.local/ns2rk8f/wngtk2xz?vceuk7wl6=3p0", - "threatintel.recordedfuture.entity.type": "URL", - "threatintel.recordedfuture.intelCard": "https://app.recordedfuture.local/live/sc/entity/url%3Ahttps://4mne.example.local/ns2rk8f/wngtk2xz?vceuk7wl6=3p0", - "threatintel.recordedfuture.risk.criticality": 1, - "threatintel.recordedfuture.risk.criticalityLabel": "Unusual", - "threatintel.recordedfuture.risk.evidenceDetails": [ + "recordedfuture.entity.id": "url:https://4mne.example.local/ns2rk8f/wngtk2xz?vceuk7wl6=3p0", + "recordedfuture.entity.type": "URL", + "recordedfuture.intelCard": "https://app.recordedfuture.local/live/sc/entity/url%3Ahttps://4mne.example.local/ns2rk8f/wngtk2xz?vceuk7wl6=3p0", + "recordedfuture.risk.criticality": 1, + "recordedfuture.risk.criticalityLabel": "Unusual", + "recordedfuture.risk.evidenceDetails": [ { "criticality": 1, "criticalityLabel": "Unusual", @@ -170,10 +162,26 @@ "timestamp": "2021-02-14T00:00:00.000Z" } ], - "threatintel.recordedfuture.risk.riskString": "1/25", - "threatintel.recordedfuture.risk.riskSummary": "1 of 25 Risk Rules currently observed.", - "threatintel.recordedfuture.risk.rules": 1, - "threatintel.recordedfuture.risk.score": 5 + "recordedfuture.risk.riskString": "1/25", + "recordedfuture.risk.riskSummary": "1 of 25 Risk Rules currently observed.", + "recordedfuture.risk.rules": 1, + "recordedfuture.risk.score": 5, + "service.type": "threatintel", + "tags": [ + "forwarded", + "threatintel-recordedfuture" + ], + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] RecordedFuture", + "threat.indicator.first_seen": "2021-06-20T00:00:00.000Z", + "threat.indicator.last_seen": "2021-06-20T23:59:59.000Z", + "threat.indicator.reference": "https://app.recordedfuture.local/live/sc/entity/url%3Ahttps://4mne.example.local/ns2rk8f/wngtk2xz?vceuk7wl6=3p0", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "4mne.example.local", + "threat.indicator.url.original": "https://4mne.example.local/ns2rk8f/wngtk2xz?vceuk7wl6=3p0", + "threat.indicator.url.path": "/ns2rk8f/wngtk2xz", + "threat.indicator.url.query": "vceuk7wl6=3p0", + "threat.indicator.url.scheme": "https" }, { "event.category": "threat", @@ -185,26 +193,12 @@ "fileset.name": "recordedfuture", "input.type": "log", "log.offset": 3524, - "service.type": "threatintel", - "tags": [ - "forwarded", - "threatintel-recordedfuture" - ], - "threatintel.indicator.first_seen": "2021-06-20T00:00:00.000Z", - "threatintel.indicator.last_seen": "2021-06-20T23:59:59.000Z", - "threatintel.indicator.reference": "https://app.recordedfuture.local/live/sc/entity/url%3Ahttp://z198hloc8.example.com/f8ih39/f6kou?f6-u3=uwhii", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "z198hloc8.example.com", - "threatintel.indicator.url.original": "http://z198hloc8.example.com/f8ih39/f6kou?f6-u3=uwhii", - "threatintel.indicator.url.path": "/f8ih39/f6kou", - "threatintel.indicator.url.query": "f6-u3=uwhii", - "threatintel.indicator.url.scheme": "http", - "threatintel.recordedfuture.entity.id": "url:http://z198hloc8.example.com/f8ih39/f6kou?f6-u3=uwhii", - "threatintel.recordedfuture.entity.type": "URL", - "threatintel.recordedfuture.intelCard": "https://app.recordedfuture.local/live/sc/entity/url%3Ahttp://z198hloc8.example.com/f8ih39/f6kou?f6-u3=uwhii", - "threatintel.recordedfuture.risk.criticality": 1, - "threatintel.recordedfuture.risk.criticalityLabel": "Unusual", - "threatintel.recordedfuture.risk.evidenceDetails": [ + "recordedfuture.entity.id": "url:http://z198hloc8.example.com/f8ih39/f6kou?f6-u3=uwhii", + "recordedfuture.entity.type": "URL", + "recordedfuture.intelCard": "https://app.recordedfuture.local/live/sc/entity/url%3Ahttp://z198hloc8.example.com/f8ih39/f6kou?f6-u3=uwhii", + "recordedfuture.risk.criticality": 1, + "recordedfuture.risk.criticalityLabel": "Unusual", + "recordedfuture.risk.evidenceDetails": [ { "criticality": 1, "criticalityLabel": "Unusual", @@ -214,10 +208,26 @@ "timestamp": "2020-06-24T12:01:33.000Z" } ], - "threatintel.recordedfuture.risk.riskString": "1/25", - "threatintel.recordedfuture.risk.riskSummary": "1 of 25 Risk Rules currently observed.", - "threatintel.recordedfuture.risk.rules": 1, - "threatintel.recordedfuture.risk.score": 5 + "recordedfuture.risk.riskString": "1/25", + "recordedfuture.risk.riskSummary": "1 of 25 Risk Rules currently observed.", + "recordedfuture.risk.rules": 1, + "recordedfuture.risk.score": 5, + "service.type": "threatintel", + "tags": [ + "forwarded", + "threatintel-recordedfuture" + ], + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] RecordedFuture", + "threat.indicator.first_seen": "2021-06-20T00:00:00.000Z", + "threat.indicator.last_seen": "2021-06-20T23:59:59.000Z", + "threat.indicator.reference": "https://app.recordedfuture.local/live/sc/entity/url%3Ahttp://z198hloc8.example.com/f8ih39/f6kou?f6-u3=uwhii", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "z198hloc8.example.com", + "threat.indicator.url.original": "http://z198hloc8.example.com/f8ih39/f6kou?f6-u3=uwhii", + "threat.indicator.url.path": "/f8ih39/f6kou", + "threat.indicator.url.query": "f6-u3=uwhii", + "threat.indicator.url.scheme": "http" }, { "event.category": "threat", @@ -229,26 +239,12 @@ "fileset.name": "recordedfuture", "input.type": "log", "log.offset": 4377, - "service.type": "threatintel", - "tags": [ - "forwarded", - "threatintel-recordedfuture" - ], - "threatintel.indicator.first_seen": "2021-06-20T00:00:00.000Z", - "threatintel.indicator.last_seen": "2021-06-20T23:59:59.000Z", - "threatintel.indicator.reference": "https://app.recordedfuture.local/live/sc/entity/url%3Ahttp://y484j-fb6.example.local/b97s24xf/prz?sg-x1do=4myont", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "y484j-fb6.example.local", - "threatintel.indicator.url.original": "http://y484j-fb6.example.local/b97s24xf/prz?sg-x1do=4myont", - "threatintel.indicator.url.path": "/b97s24xf/prz", - "threatintel.indicator.url.query": "sg-x1do=4myont", - "threatintel.indicator.url.scheme": "http", - "threatintel.recordedfuture.entity.id": "url:http://y484j-fb6.example.local/b97s24xf/prz?sg-x1do=4myont", - "threatintel.recordedfuture.entity.type": "URL", - "threatintel.recordedfuture.intelCard": "https://app.recordedfuture.local/live/sc/entity/url%3Ahttp://y484j-fb6.example.local/b97s24xf/prz?sg-x1do=4myont", - "threatintel.recordedfuture.risk.criticality": 1, - "threatintel.recordedfuture.risk.criticalityLabel": "Unusual", - "threatintel.recordedfuture.risk.evidenceDetails": [ + "recordedfuture.entity.id": "url:http://y484j-fb6.example.local/b97s24xf/prz?sg-x1do=4myont", + "recordedfuture.entity.type": "URL", + "recordedfuture.intelCard": "https://app.recordedfuture.local/live/sc/entity/url%3Ahttp://y484j-fb6.example.local/b97s24xf/prz?sg-x1do=4myont", + "recordedfuture.risk.criticality": 1, + "recordedfuture.risk.criticalityLabel": "Unusual", + "recordedfuture.risk.evidenceDetails": [ { "criticality": 1, "criticalityLabel": "Unusual", @@ -258,10 +254,26 @@ "timestamp": "2021-02-14T00:00:00.000Z" } ], - "threatintel.recordedfuture.risk.riskString": "1/25", - "threatintel.recordedfuture.risk.riskSummary": "1 of 25 Risk Rules currently observed.", - "threatintel.recordedfuture.risk.rules": 1, - "threatintel.recordedfuture.risk.score": 5 + "recordedfuture.risk.riskString": "1/25", + "recordedfuture.risk.riskSummary": "1 of 25 Risk Rules currently observed.", + "recordedfuture.risk.rules": 1, + "recordedfuture.risk.score": 5, + "service.type": "threatintel", + "tags": [ + "forwarded", + "threatintel-recordedfuture" + ], + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] RecordedFuture", + "threat.indicator.first_seen": "2021-06-20T00:00:00.000Z", + "threat.indicator.last_seen": "2021-06-20T23:59:59.000Z", + "threat.indicator.reference": "https://app.recordedfuture.local/live/sc/entity/url%3Ahttp://y484j-fb6.example.local/b97s24xf/prz?sg-x1do=4myont", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "y484j-fb6.example.local", + "threat.indicator.url.original": "http://y484j-fb6.example.local/b97s24xf/prz?sg-x1do=4myont", + "threat.indicator.url.path": "/b97s24xf/prz", + "threat.indicator.url.query": "sg-x1do=4myont", + "threat.indicator.url.scheme": "http" }, { "event.category": "threat", @@ -273,26 +285,12 @@ "fileset.name": "recordedfuture", "input.type": "log", "log.offset": 5272, - "service.type": "threatintel", - "tags": [ - "forwarded", - "threatintel-recordedfuture" - ], - "threatintel.indicator.first_seen": "2021-06-20T00:00:00.000Z", - "threatintel.indicator.last_seen": "2021-06-20T23:59:59.000Z", - "threatintel.indicator.reference": "https://app.recordedfuture.local/live/sc/entity/url%3Ahttp://sp2xyqq82.example.local/zxvm093/kat1rcz?vaev0aeod=rc0513", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "sp2xyqq82.example.local", - "threatintel.indicator.url.original": "http://sp2xyqq82.example.local/zxvm093/kat1rcz?vaev0aeod=rc0513", - "threatintel.indicator.url.path": "/zxvm093/kat1rcz", - "threatintel.indicator.url.query": "vaev0aeod=rc0513", - "threatintel.indicator.url.scheme": "http", - "threatintel.recordedfuture.entity.id": "url:http://sp2xyqq82.example.local/zxvm093/kat1rcz?vaev0aeod=rc0513", - "threatintel.recordedfuture.entity.type": "URL", - "threatintel.recordedfuture.intelCard": "https://app.recordedfuture.local/live/sc/entity/url%3Ahttp://sp2xyqq82.example.local/zxvm093/kat1rcz?vaev0aeod=rc0513", - "threatintel.recordedfuture.risk.criticality": 1, - "threatintel.recordedfuture.risk.criticalityLabel": "Unusual", - "threatintel.recordedfuture.risk.evidenceDetails": [ + "recordedfuture.entity.id": "url:http://sp2xyqq82.example.local/zxvm093/kat1rcz?vaev0aeod=rc0513", + "recordedfuture.entity.type": "URL", + "recordedfuture.intelCard": "https://app.recordedfuture.local/live/sc/entity/url%3Ahttp://sp2xyqq82.example.local/zxvm093/kat1rcz?vaev0aeod=rc0513", + "recordedfuture.risk.criticality": 1, + "recordedfuture.risk.criticalityLabel": "Unusual", + "recordedfuture.risk.evidenceDetails": [ { "criticality": 1, "criticalityLabel": "Unusual", @@ -302,10 +300,26 @@ "timestamp": "2020-11-16T00:00:00.000Z" } ], - "threatintel.recordedfuture.risk.riskString": "1/25", - "threatintel.recordedfuture.risk.riskSummary": "1 of 25 Risk Rules currently observed.", - "threatintel.recordedfuture.risk.rules": 1, - "threatintel.recordedfuture.risk.score": 5 + "recordedfuture.risk.riskString": "1/25", + "recordedfuture.risk.riskSummary": "1 of 25 Risk Rules currently observed.", + "recordedfuture.risk.rules": 1, + "recordedfuture.risk.score": 5, + "service.type": "threatintel", + "tags": [ + "forwarded", + "threatintel-recordedfuture" + ], + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] RecordedFuture", + "threat.indicator.first_seen": "2021-06-20T00:00:00.000Z", + "threat.indicator.last_seen": "2021-06-20T23:59:59.000Z", + "threat.indicator.reference": "https://app.recordedfuture.local/live/sc/entity/url%3Ahttp://sp2xyqq82.example.local/zxvm093/kat1rcz?vaev0aeod=rc0513", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "sp2xyqq82.example.local", + "threat.indicator.url.original": "http://sp2xyqq82.example.local/zxvm093/kat1rcz?vaev0aeod=rc0513", + "threat.indicator.url.path": "/zxvm093/kat1rcz", + "threat.indicator.url.query": "vaev0aeod=rc0513", + "threat.indicator.url.scheme": "http" }, { "event.category": "threat", @@ -317,26 +331,12 @@ "fileset.name": "recordedfuture", "input.type": "log", "log.offset": 6187, - "service.type": "threatintel", - "tags": [ - "forwarded", - "threatintel-recordedfuture" - ], - "threatintel.indicator.first_seen": "2021-06-20T00:00:00.000Z", - "threatintel.indicator.last_seen": "2021-06-20T23:59:59.000Z", - "threatintel.indicator.reference": "https://app.recordedfuture.local/live/sc/entity/url%3Ahttps://zh4o7xc.example.com/-yiq/vg2whtxif?cb0-knk=s6poib5r", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "zh4o7xc.example.com", - "threatintel.indicator.url.original": "https://zh4o7xc.example.com/-yiq/vg2whtxif?cb0-knk=s6poib5r", - "threatintel.indicator.url.path": "/-yiq/vg2whtxif", - "threatintel.indicator.url.query": "cb0-knk=s6poib5r", - "threatintel.indicator.url.scheme": "https", - "threatintel.recordedfuture.entity.id": "url:https://zh4o7xc.example.com/-yiq/vg2whtxif?cb0-knk=s6poib5r", - "threatintel.recordedfuture.entity.type": "URL", - "threatintel.recordedfuture.intelCard": "https://app.recordedfuture.local/live/sc/entity/url%3Ahttps://zh4o7xc.example.com/-yiq/vg2whtxif?cb0-knk=s6poib5r", - "threatintel.recordedfuture.risk.criticality": 1, - "threatintel.recordedfuture.risk.criticalityLabel": "Unusual", - "threatintel.recordedfuture.risk.evidenceDetails": [ + "recordedfuture.entity.id": "url:https://zh4o7xc.example.com/-yiq/vg2whtxif?cb0-knk=s6poib5r", + "recordedfuture.entity.type": "URL", + "recordedfuture.intelCard": "https://app.recordedfuture.local/live/sc/entity/url%3Ahttps://zh4o7xc.example.com/-yiq/vg2whtxif?cb0-knk=s6poib5r", + "recordedfuture.risk.criticality": 1, + "recordedfuture.risk.criticalityLabel": "Unusual", + "recordedfuture.risk.evidenceDetails": [ { "criticality": 1, "criticalityLabel": "Unusual", @@ -346,10 +346,26 @@ "timestamp": "2021-05-15T00:00:00.000Z" } ], - "threatintel.recordedfuture.risk.riskString": "1/25", - "threatintel.recordedfuture.risk.riskSummary": "1 of 25 Risk Rules currently observed.", - "threatintel.recordedfuture.risk.rules": 1, - "threatintel.recordedfuture.risk.score": 5 + "recordedfuture.risk.riskString": "1/25", + "recordedfuture.risk.riskSummary": "1 of 25 Risk Rules currently observed.", + "recordedfuture.risk.rules": 1, + "recordedfuture.risk.score": 5, + "service.type": "threatintel", + "tags": [ + "forwarded", + "threatintel-recordedfuture" + ], + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] RecordedFuture", + "threat.indicator.first_seen": "2021-06-20T00:00:00.000Z", + "threat.indicator.last_seen": "2021-06-20T23:59:59.000Z", + "threat.indicator.reference": "https://app.recordedfuture.local/live/sc/entity/url%3Ahttps://zh4o7xc.example.com/-yiq/vg2whtxif?cb0-knk=s6poib5r", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "zh4o7xc.example.com", + "threat.indicator.url.original": "https://zh4o7xc.example.com/-yiq/vg2whtxif?cb0-knk=s6poib5r", + "threat.indicator.url.path": "/-yiq/vg2whtxif", + "threat.indicator.url.query": "cb0-knk=s6poib5r", + "threat.indicator.url.scheme": "https" }, { "event.category": "threat", @@ -361,26 +377,12 @@ "fileset.name": "recordedfuture", "input.type": "log", "log.offset": 7094, - "service.type": "threatintel", - "tags": [ - "forwarded", - "threatintel-recordedfuture" - ], - "threatintel.indicator.first_seen": "2021-06-20T00:00:00.000Z", - "threatintel.indicator.last_seen": "2021-06-20T23:59:59.000Z", - "threatintel.indicator.reference": "https://app.recordedfuture.local/live/sc/entity/url%3Ahttp://fiivf4s.example.org/8u2qi/86vfcfq7m?pfb2ensc0=h7imk8io2", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "fiivf4s.example.org", - "threatintel.indicator.url.original": "http://fiivf4s.example.org/8u2qi/86vfcfq7m?pfb2ensc0=h7imk8io2", - "threatintel.indicator.url.path": "/8u2qi/86vfcfq7m", - "threatintel.indicator.url.query": "pfb2ensc0=h7imk8io2", - "threatintel.indicator.url.scheme": "http", - "threatintel.recordedfuture.entity.id": "url:http://fiivf4s.example.org/8u2qi/86vfcfq7m?pfb2ensc0=h7imk8io2", - "threatintel.recordedfuture.entity.type": "URL", - "threatintel.recordedfuture.intelCard": "https://app.recordedfuture.local/live/sc/entity/url%3Ahttp://fiivf4s.example.org/8u2qi/86vfcfq7m?pfb2ensc0=h7imk8io2", - "threatintel.recordedfuture.risk.criticality": 1, - "threatintel.recordedfuture.risk.criticalityLabel": "Unusual", - "threatintel.recordedfuture.risk.evidenceDetails": [ + "recordedfuture.entity.id": "url:http://fiivf4s.example.org/8u2qi/86vfcfq7m?pfb2ensc0=h7imk8io2", + "recordedfuture.entity.type": "URL", + "recordedfuture.intelCard": "https://app.recordedfuture.local/live/sc/entity/url%3Ahttp://fiivf4s.example.org/8u2qi/86vfcfq7m?pfb2ensc0=h7imk8io2", + "recordedfuture.risk.criticality": 1, + "recordedfuture.risk.criticalityLabel": "Unusual", + "recordedfuture.risk.evidenceDetails": [ { "criticality": 1, "criticalityLabel": "Unusual", @@ -390,10 +392,26 @@ "timestamp": "2021-02-14T00:00:00.000Z" } ], - "threatintel.recordedfuture.risk.riskString": "1/25", - "threatintel.recordedfuture.risk.riskSummary": "1 of 25 Risk Rules currently observed.", - "threatintel.recordedfuture.risk.rules": 1, - "threatintel.recordedfuture.risk.score": 5 + "recordedfuture.risk.riskString": "1/25", + "recordedfuture.risk.riskSummary": "1 of 25 Risk Rules currently observed.", + "recordedfuture.risk.rules": 1, + "recordedfuture.risk.score": 5, + "service.type": "threatintel", + "tags": [ + "forwarded", + "threatintel-recordedfuture" + ], + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] RecordedFuture", + "threat.indicator.first_seen": "2021-06-20T00:00:00.000Z", + "threat.indicator.last_seen": "2021-06-20T23:59:59.000Z", + "threat.indicator.reference": "https://app.recordedfuture.local/live/sc/entity/url%3Ahttp://fiivf4s.example.org/8u2qi/86vfcfq7m?pfb2ensc0=h7imk8io2", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "fiivf4s.example.org", + "threat.indicator.url.original": "http://fiivf4s.example.org/8u2qi/86vfcfq7m?pfb2ensc0=h7imk8io2", + "threat.indicator.url.path": "/8u2qi/86vfcfq7m", + "threat.indicator.url.query": "pfb2ensc0=h7imk8io2", + "threat.indicator.url.scheme": "http" }, { "event.category": "threat", @@ -405,26 +423,12 @@ "fileset.name": "recordedfuture", "input.type": "log", "log.offset": 8007, - "service.type": "threatintel", - "tags": [ - "forwarded", - "threatintel-recordedfuture" - ], - "threatintel.indicator.first_seen": "2021-06-20T00:00:00.000Z", - "threatintel.indicator.last_seen": "2021-06-20T23:59:59.000Z", - "threatintel.indicator.reference": "https://app.recordedfuture.local/live/sc/entity/url%3Ahttp://abav9v.example.org/gj93q/7fs7?kcq7=pjaj1", - "threatintel.indicator.type": "url", - "threatintel.indicator.url.domain": "abav9v.example.org", - "threatintel.indicator.url.original": "http://abav9v.example.org/gj93q/7fs7?kcq7=pjaj1", - "threatintel.indicator.url.path": "/gj93q/7fs7", - "threatintel.indicator.url.query": "kcq7=pjaj1", - "threatintel.indicator.url.scheme": "http", - "threatintel.recordedfuture.entity.id": "url:http://abav9v.example.org/gj93q/7fs7?kcq7=pjaj1", - "threatintel.recordedfuture.entity.type": "URL", - "threatintel.recordedfuture.intelCard": "https://app.recordedfuture.local/live/sc/entity/url%3Ahttp://abav9v.example.org/gj93q/7fs7?kcq7=pjaj1", - "threatintel.recordedfuture.risk.criticality": 1, - "threatintel.recordedfuture.risk.criticalityLabel": "Unusual", - "threatintel.recordedfuture.risk.evidenceDetails": [ + "recordedfuture.entity.id": "url:http://abav9v.example.org/gj93q/7fs7?kcq7=pjaj1", + "recordedfuture.entity.type": "URL", + "recordedfuture.intelCard": "https://app.recordedfuture.local/live/sc/entity/url%3Ahttp://abav9v.example.org/gj93q/7fs7?kcq7=pjaj1", + "recordedfuture.risk.criticality": 1, + "recordedfuture.risk.criticalityLabel": "Unusual", + "recordedfuture.risk.evidenceDetails": [ { "criticality": 1, "criticalityLabel": "Unusual", @@ -434,9 +438,25 @@ "timestamp": "2021-02-14T00:00:00.000Z" } ], - "threatintel.recordedfuture.risk.riskString": "1/25", - "threatintel.recordedfuture.risk.riskSummary": "1 of 25 Risk Rules currently observed.", - "threatintel.recordedfuture.risk.rules": 1, - "threatintel.recordedfuture.risk.score": 5 + "recordedfuture.risk.riskString": "1/25", + "recordedfuture.risk.riskSummary": "1 of 25 Risk Rules currently observed.", + "recordedfuture.risk.rules": 1, + "recordedfuture.risk.score": 5, + "service.type": "threatintel", + "tags": [ + "forwarded", + "threatintel-recordedfuture" + ], + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] RecordedFuture", + "threat.indicator.first_seen": "2021-06-20T00:00:00.000Z", + "threat.indicator.last_seen": "2021-06-20T23:59:59.000Z", + "threat.indicator.reference": "https://app.recordedfuture.local/live/sc/entity/url%3Ahttp://abav9v.example.org/gj93q/7fs7?kcq7=pjaj1", + "threat.indicator.type": "url", + "threat.indicator.url.domain": "abav9v.example.org", + "threat.indicator.url.original": "http://abav9v.example.org/gj93q/7fs7?kcq7=pjaj1", + "threat.indicator.url.path": "/gj93q/7fs7", + "threat.indicator.url.query": "kcq7=pjaj1", + "threat.indicator.url.scheme": "http" } ] \ No newline at end of file diff --git a/x-pack/filebeat/module/threatintel/threatq/config/config.yml b/x-pack/filebeat/module/threatintel/threatq/config/config.yml index 89e8cab731e..0f520215bc8 100644 --- a/x-pack/filebeat/module/threatintel/threatq/config/config.yml +++ b/x-pack/filebeat/module/threatintel/threatq/config/config.yml @@ -1,7 +1,6 @@ {{ if eq .input "httpjson" }} type: httpjson -config_version: "2" interval: {{ .interval }} auth.oauth2: @@ -50,22 +49,12 @@ exclude_files: [".gz$"] {{ end }} -tags: {{.tags | tojson}} -publisher_pipeline.disable_host: {{ inList .tags "forwarded" }} +tags: +{{if .preserve_original_event}} + - preserve_original_event +{{end}} +{{range $val := .tags}} + - {{$val}} +{{end}} -processors: - - decode_json_fields: - fields: [message] - target: json - process_array: true - max_depth: 5 - overwrite_keys: true - add_error_key: true - - fingerprint: - fields: ["json.id", "json.indicator_id"] - target_field: "@metadata._id" - ignore_missing: true - - add_fields: - target: '' - fields: - ecs.version: 1.12.0 \ No newline at end of file +publisher_pipeline.disable_host: {{ inList .tags "forwarded" }} diff --git a/x-pack/filebeat/module/threatintel/threatq/ingest/pipeline.yml b/x-pack/filebeat/module/threatintel/threatq/ingest/pipeline.yml index 6d301f89844..96f8b224e19 100644 --- a/x-pack/filebeat/module/threatintel/threatq/ingest/pipeline.yml +++ b/x-pack/filebeat/module/threatintel/threatq/ingest/pipeline.yml @@ -1,3 +1,4 @@ +--- description: Pipeline for parsing ThreatQ Threat Intel processors: #################### @@ -6,6 +7,9 @@ processors: - set: field: event.ingested value: "{{_ingest.timestamp}}" + - set: + field: ecs.version + value: "1.12" - set: field: event.kind value: enrichment @@ -19,6 +23,19 @@ processors: ############### # Parse dates # ############### + - rename: + field: message + target_field: event.original + ignore_missing: true + - json: + field: event.original + target_field: json + - fingerprint: + fields: + - json.id + - json.indicator_id + target_field: "_id" + ignore_missing: true - date: target_field: "@timestamp" field: "json.updated_at" @@ -27,28 +44,28 @@ processors: if: "ctx.json.updated_at != null" ignore_failure: true - date: - target_field: "threatintel.threatq.created_at" + target_field: "threatq.created_at" field: "json.created_at" formats: - "yyyy-MM-dd HH:mm:ss" if: "ctx.json.created_at != null" ignore_failure: true - date: - target_field: "threatintel.threatq.expires_at" + target_field: "threatq.expires_at" field: "json.expires_at" formats: - "yyyy-MM-dd HH:mm:ss" if: "ctx.json.expires_at != null" ignore_failure: true - date: - target_field: "threatintel.threatq.expires_calculated_at" + target_field: "threatq.expires_calculated_at" field: "json.expires_calculated_at" formats: - "yyyy-MM-dd HH:mm:ss" if: "ctx.json.expires_calculated_at != null" ignore_failure: true - date: - target_field: "threatintel.threatq.published_at" + target_field: "threatq.published_at" field: "json.published_at" formats: - "yyyy-MM-dd HH:mm:ss" @@ -58,29 +75,50 @@ processors: ##################### # Threat ECS Fields # ##################### + - set: + field: threat.feed.name + value: "[Filebeat] ThreatQuotient" + - set: + field: threat.feed.dashboard_id + value: "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f" - rename: field: json.type.name - target_field: threatintel.indicator.type + target_field: threat.indicator.type ignore_missing: true - rename: field: json.description - target_field: threatintel.indicator.description + target_field: threat.indicator.description ignore_missing: true - - convert: - field: json.score - target_field: threatintel.indicator.confidence - type: integer - on_failure: - - append: - field: error.message - value: "Cannot convert json.score to integer: {{{ _ingest.on_failure_message }}}" + - script: + lang: painless + if: ctx.json?.score != null + description: > + Normalize confidence level. + source: > + def value = ctx.json.score; + if (value <= 0.0 || value > 100.0) { + ctx.threat.indicator.confidence = "None"; + return; + } + if (value >= 1.0 && value <= 29.0) { + ctx.threat.indicator.confidence = "Low"; + return; + } + if (value >= 30.0 && value <= 69.0) { + ctx.threat.indicator.confidence = "Med"; + return; + } + if (value >= 70 && value <= 100) { + ctx.threat.indicator.confidence = "High"; + return; + } - rename: field: json.status.name - target_field: threatintel.threatq.status + target_field: threatq.status ignore_missing: true - rename: field: json.value - target_field: threatintel.threatq.indicator_value + target_field: threatq.indicator_value ignore_missing: true ######################################### @@ -89,119 +127,144 @@ processors: # Indicator type: Email Address - set: - field: threatintel.indicator.email.address - value: "{{threatintel.threatq.indicator_value}}" - if: "ctx?.threatintel?.indicator?.type != null && ctx?.threatintel?.indicator?.type == 'Email Address'" + field: threat.indicator.email.address + copy_from: threatq.indicator_value + if: "ctx.threat?.indicator?.type != null && ctx.threat?.indicator?.type == 'Email Address'" + ignore_empty_value: true - set: - field: threatintel.indicator.type + field: threat.indicator.type value: email-addr - if: "ctx?.threatintel?.indicator?.type != null && ctx?.threatintel?.indicator?.type == 'Email Address'" + if: "ctx.threat?.indicator?.type != null && ctx.threat?.indicator?.type == 'Email Address'" # Indicator type: FQDN - set: - field: threatintel.indicator.domain - value: "{{threatintel.threatq.indicator_value}}" - if: "ctx?.threatintel?.indicator?.type != null && ctx?.threatintel?.indicator?.type == 'FQDN'" + field: threat.indicator.domain + copy_from: threatq.indicator_value + if: "ctx.threat?.indicator?.type != null && ctx.threat?.indicator?.type == 'FQDN'" + ignore_empty_value: true - set: - field: threatintel.indicator.type + field: threat.indicator.type value: domain-name - if: "ctx?.threatintel?.indicator?.type != null && ctx?.threatintel?.indicator?.type == 'FQDN'" + if: "ctx.threat?.indicator?.type != null && ctx.threat?.indicator?.type == 'FQDN'" # Indicator type: IP Address - set: - field: threatintel.indicator.ip - value: "{{threatintel.threatq.indicator_value}}" - if: "ctx?.threatintel?.indicator?.type != null && ctx?.threatintel?.indicator?.type == 'IP Address'" + field: threat.indicator.ip + copy_from: threatq.indicator_value + if: "ctx.threat?.indicator?.type != null && ctx.threat?.indicator?.type == 'IP Address'" + ignore_empty_value: true + - set: - field: threatintel.indicator.type + field: threat.indicator.type value: ipv4-addr - if: "ctx?.threatintel?.indicator?.type != null && ctx?.threatintel?.indicator?.type == 'IP Address'" + if: "ctx.threat?.indicator?.type != null && ctx.threat?.indicator?.type == 'IP Address'" # Indicator type: IPv6 Address - set: - field: threatintel.indicator.domain - value: "{{threatintel.threatq.indicator_value}}" - if: "ctx?.threatintel?.indicator?.type != null && ctx?.threatintel?.indicator?.type == 'IPv6 Address'" + field: threat.indicator.domain + copy_from: threatq.indicator_value + if: "ctx.threat?.indicator?.type != null && ctx.threat?.indicator?.type == 'IPv6 Address'" + ignore_empty_value: true - set: - field: threatintel.indicator.type + field: threat.indicator.type value: ipv6-addr - if: "ctx?.threatintel?.indicator?.type != null && ctx?.threatintel?.indicator?.type == 'IPv6 Address'" + if: "ctx.threat?.indicator?.type != null && ctx.threat?.indicator?.type == 'IPv6 Address'" # Indicator type: MD5 - set: - field: threatintel.indicator.file.hash.md5 - value: "{{threatintel.threatq.indicator_value}}" - if: "ctx?.threatintel?.indicator?.type != null && ctx?.threatintel?.indicator?.type == 'MD5'" + field: threat.indicator.file.hash.md5 + copy_from: threatq.indicator_value + if: "ctx.threat?.indicator?.type != null && ctx.threat?.indicator?.type == 'MD5'" + ignore_empty_value: true - set: - field: threatintel.indicator.type + field: threat.indicator.type value: file - if: "ctx?.threatintel?.indicator?.type != null && ctx?.threatintel?.indicator?.type == 'MD5'" + if: "ctx.threat?.indicator?.type != null && ctx.threat?.indicator?.type == 'MD5'" # Indicator type: SHA-1 - set: - field: threatintel.indicator.file.hash.sha1 - value: "{{threatintel.threatq.indicator_value}}" - if: "ctx?.threatintel?.indicator?.type != null && ctx?.threatintel?.indicator?.type == 'SHA-1'" + field: threat.indicator.file.hash.sha1 + copy_from: threatq.indicator_value + if: "ctx.threat?.indicator?.type != null && ctx.threat?.indicator?.type == 'SHA-1'" + ignore_empty_value: true - set: - field: threatintel.indicator.type + field: threat.indicator.type value: file - if: "ctx?.threatintel?.indicator?.type != null && ctx?.threatintel?.indicator?.type == 'SHA-1'" + if: "ctx.threat?.indicator?.type != null && ctx.threat?.indicator?.type == 'SHA-1'" # Indicator type: SHA-256 - set: - field: threatintel.indicator.file.hash.sha256 - value: "{{threatintel.threatq.indicator_value}}" - if: "ctx?.threatintel?.indicator?.type != null && ctx?.threatintel?.indicator?.type == 'SHA-256'" + field: threat.indicator.file.hash.sha256 + copy_from: threatq.indicator_value + if: "ctx.threat?.indicator?.type != null && ctx.threat?.indicator?.type == 'SHA-256'" + ignore_empty_value: true - set: - field: threatintel.indicator.type + field: threat.indicator.type value: file - if: "ctx?.threatintel?.indicator?.type != null && ctx?.threatintel?.indicator?.type == 'SHA-256'" + if: "ctx.threat?.indicator?.type != null && ctx.threat?.indicator?.type == 'SHA-256'" # Indicator type: SHA-512 - set: - field: threatintel.indicator.file.hash.sha512 - value: "{{threatintel.threatq.indicator_value}}" - if: "ctx?.threatintel?.indicator?.type != null && ctx?.threatintel?.indicator?.type == 'SHA-512'" + field: threat.indicator.file.hash.sha512 + copy_from: threatq.indicator_value + if: "ctx.threat?.indicator?.type != null && ctx.threat?.indicator?.type == 'SHA-512'" + ignore_empty_value: true - set: - field: threatintel.indicator.type + field: threat.indicator.type value: file - if: "ctx?.threatintel?.indicator?.type != null && ctx?.threatintel?.indicator?.type == 'SHA-512'" + if: "ctx.threat?.indicator?.type != null && ctx.threat?.indicator?.type == 'SHA-512'" # Indicator type: URL + - uri_parts: + field: threatq.indicator_value + target_field: threat.indicator.url + if: "ctx.threat?.indicator?.type != null && ctx.threat?.indicator?.type == 'URL' && ctx.threatq?.indicator_value != null" + remove_if_successful: true - set: - field: threatintel.indicator.url.full - value: "{{threatintel.threatq.indicator_value}}" - if: "ctx?.threatintel?.indicator?.type != null && ctx?.threatintel?.indicator?.type == 'URL'" - - set: - field: threatintel.indicator.type + field: threat.indicator.type value: url - if: "ctx?.threatintel?.indicator?.type != null && ctx?.threatintel?.indicator?.type == 'URL'" + if: "ctx.threat?.indicator?.type != null && ctx.threat?.indicator?.type == 'URL'" # Indicator type: x509 Serial - set: - field: threatintel.indicator.x509.serial_number - value: "{{threatintel.threatq.indicator_value}}" - if: "ctx?.threatintel?.indicator?.type != null && ctx?.threatintel?.indicator?.type == 'x509 Serial'" + field: threat.indicator.x509.serial_number + copy_from: threatq.indicator_value + if: "ctx.threat?.indicator?.type != null && ctx.threat?.indicator?.type == 'x509 Serial'" + ignore_empty_value: true ################################### # Map indicator providers and TLP # ################################### - - foreach: - description: Append threat intel sources - field: json.sources - ignore_missing: true - processor: - append: - field: threatintel.indicator.provider - value: "{{{ _ingest._value.name }}}" - - foreach: - description: Append threat intel source TLP values - field: json.sources - ignore_missing: true - processor: - append: - field: threatintel.indicator.marking.tlp - value: "{{{ _ingest._value.tlp_name }}}" + - script: + if: "ctx.json?.sources != null && ctx.json?.sources instanceof List && ctx.json?.sources.size() > 0" + lang: painless + description: "Extract TLP and providers from source" + source: |- + def providers = new ArrayList(); + def tlps = new ArrayList(); + for (source in ctx.json.sources) { + if (source == null) { + return; + } + if (source.containsKey("provider") && source["provider"] != null) { + providers.add(source["provider"]); + } + if (source.containsKey("tlp_name") && source["tlp_name"] != null) { + tlps.add(source["tlp_name"]); + } + } + if (tlps.size() > 0) { + if (ctx.threat.indicator.marking == null) { + ctx.threat.indicator.marking = new HashMap(); + } + ctx.threat.indicator.marking.tlp = tlps; + } + if (providers.size() > 0) { + if (ctx.threat.indicator.provider == null) { + ctx.threat.indicator.provider = new HashMap(); + } + ctx.threat.indicator.provider = providers; + } ############################ # Map indicator attributes # @@ -228,7 +291,7 @@ processors: ignore_missing: true processor: append: - field: threatintel.threatq.attributes.{{{ _ingest._value.name }}} + field: threatq.attributes.{{{ _ingest._value.name }}} value: "{{{ _ingest._value.value }}}" ############################# @@ -239,20 +302,25 @@ processors: ignore_missing: true processor: append: - field: threatintel.threatq.adversaries + field: threatq.adversaries value: "{{{ _ingest._value.name }}}" ###################### # Cleanup processors # ###################### # Setting indicator type to unknown if it does not match anything + - remove: + field: event.original + if: "ctx?.tags == null || !(ctx.tags.contains('preserve_original_event'))" + ignore_failure: true + ignore_missing: true - set: - field: threatintel.indicator.type + field: threat.indicator.type value: unknown - if: ctx?.threatintel?.indicator?.type == null + if: ctx.threat?.indicator?.type == null - script: lang: painless - if: ctx?.threatintel != null + if: ctx.threat != null source: | void handleMap(Map map) { for (def x : map.values()) { diff --git a/x-pack/filebeat/module/threatintel/threatq/manifest.yml b/x-pack/filebeat/module/threatintel/threatq/manifest.yml index dd7165b182f..d5628d2a705 100644 --- a/x-pack/filebeat/module/threatintel/threatq/manifest.yml +++ b/x-pack/filebeat/module/threatintel/threatq/manifest.yml @@ -11,11 +11,13 @@ var: - name: client_id - name: client_secret - name: host - default: "https://www.threatq.com/" + default: "https://www.threatq.com" - name: proxy_url - name: http_client_timeout - name: tags default: [threatintel-threatq, forwarded] + - name: preserve_original_event + default: false ingest_pipeline: - ingest/pipeline.yml diff --git a/x-pack/filebeat/module/threatintel/threatq/test/threatq_sample.ndjson.log-expected.json b/x-pack/filebeat/module/threatintel/threatq/test/threatq_sample.ndjson.log-expected.json index 58c61e5161c..58958850bd5 100644 --- a/x-pack/filebeat/module/threatintel/threatq/test/threatq_sample.ndjson.log-expected.json +++ b/x-pack/filebeat/module/threatintel/threatq/test/threatq_sample.ndjson.log-expected.json @@ -14,38 +14,34 @@ "forwarded", "threatintel-threatq" ], - "threatintel.indicator.confidence": 4, - "threatintel.indicator.ip": "69.44.202.220", - "threatintel.indicator.marking.tlp": [ - "" - ], - "threatintel.indicator.provider": [ - "AlienVault OTX" - ], - "threatintel.indicator.type": "ipv4-addr", - "threatintel.threatq.attributes.alienvault_reliability": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] ThreatQuotient", + "threat.indicator.confidence": "Low", + "threat.indicator.ip": "69.44.202.220", + "threat.indicator.type": "ipv4-addr", + "threatq.attributes.alienvault_reliability": [ "4" ], - "threatintel.threatq.attributes.alienvault_revision": [ + "threatq.attributes.alienvault_revision": [ "3" ], - "threatintel.threatq.attributes.alienvault_threat_level": [ + "threatq.attributes.alienvault_threat_level": [ "3" ], - "threatintel.threatq.attributes.city": [ + "threatq.attributes.city": [ "Saipan" ], - "threatintel.threatq.attributes.country": [ + "threatq.attributes.country": [ "MP" ], - "threatintel.threatq.attributes.description": [ + "threatq.attributes.description": [ "Malicious Host" ], - "threatintel.threatq.created_at": "2020-09-11T14:35:51.000Z", - "threatintel.threatq.expires_calculated_at": "2020-10-15T14:40:03.000Z", - "threatintel.threatq.indicator_value": "69.44.202.220", - "threatintel.threatq.published_at": "2020-09-11T14:35:51.000Z", - "threatintel.threatq.status": "Expired" + "threatq.created_at": "2020-09-11T14:35:51.000Z", + "threatq.expires_calculated_at": "2020-10-15T14:40:03.000Z", + "threatq.indicator_value": "69.44.202.220", + "threatq.published_at": "2020-09-11T14:35:51.000Z", + "threatq.status": "Expired" }, { "@timestamp": "2020-11-15T00:00:02.000Z", @@ -62,38 +58,34 @@ "forwarded", "threatintel-threatq" ], - "threatintel.indicator.confidence": 4, - "threatintel.indicator.ip": "69.94.155.176", - "threatintel.indicator.marking.tlp": [ - "" - ], - "threatintel.indicator.provider": [ - "AlienVault OTX" - ], - "threatintel.indicator.type": "ipv4-addr", - "threatintel.threatq.attributes.alienvault_reliability": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] ThreatQuotient", + "threat.indicator.confidence": "Low", + "threat.indicator.ip": "69.94.155.176", + "threat.indicator.type": "ipv4-addr", + "threatq.attributes.alienvault_reliability": [ "4" ], - "threatintel.threatq.attributes.alienvault_revision": [ + "threatq.attributes.alienvault_revision": [ "3" ], - "threatintel.threatq.attributes.alienvault_threat_level": [ + "threatq.attributes.alienvault_threat_level": [ "2" ], - "threatintel.threatq.attributes.city": [ + "threatq.attributes.city": [ "Sacramento" ], - "threatintel.threatq.attributes.country": [ + "threatq.attributes.country": [ "US" ], - "threatintel.threatq.attributes.description": [ + "threatq.attributes.description": [ "Malicious Host" ], - "threatintel.threatq.created_at": "2020-09-11T14:35:51.000Z", - "threatintel.threatq.expires_calculated_at": "2020-10-15T14:40:03.000Z", - "threatintel.threatq.indicator_value": "69.94.155.176", - "threatintel.threatq.published_at": "2020-09-11T14:35:51.000Z", - "threatintel.threatq.status": "Expired" + "threatq.created_at": "2020-09-11T14:35:51.000Z", + "threatq.expires_calculated_at": "2020-10-15T14:40:03.000Z", + "threatq.indicator_value": "69.94.155.176", + "threatq.published_at": "2020-09-11T14:35:51.000Z", + "threatq.status": "Expired" }, { "@timestamp": "2020-11-15T00:00:02.000Z", @@ -110,38 +102,34 @@ "forwarded", "threatintel-threatq" ], - "threatintel.indicator.confidence": 4, - "threatintel.indicator.ip": "69.42.81.68", - "threatintel.indicator.marking.tlp": [ - "" - ], - "threatintel.indicator.provider": [ - "AlienVault OTX" - ], - "threatintel.indicator.type": "ipv4-addr", - "threatintel.threatq.attributes.alienvault_reliability": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] ThreatQuotient", + "threat.indicator.confidence": "Low", + "threat.indicator.ip": "69.42.81.68", + "threat.indicator.type": "ipv4-addr", + "threatq.attributes.alienvault_reliability": [ "4" ], - "threatintel.threatq.attributes.alienvault_revision": [ + "threatq.attributes.alienvault_revision": [ "3" ], - "threatintel.threatq.attributes.alienvault_threat_level": [ + "threatq.attributes.alienvault_threat_level": [ "2" ], - "threatintel.threatq.attributes.city": [ + "threatq.attributes.city": [ "New York" ], - "threatintel.threatq.attributes.country": [ + "threatq.attributes.country": [ "US" ], - "threatintel.threatq.attributes.description": [ + "threatq.attributes.description": [ "Malicious Host" ], - "threatintel.threatq.created_at": "2020-09-11T14:35:51.000Z", - "threatintel.threatq.expires_calculated_at": "2020-10-15T14:40:03.000Z", - "threatintel.threatq.indicator_value": "69.42.81.68", - "threatintel.threatq.published_at": "2020-09-11T14:35:51.000Z", - "threatintel.threatq.status": "Expired" + "threatq.created_at": "2020-09-11T14:35:51.000Z", + "threatq.expires_calculated_at": "2020-10-15T14:40:03.000Z", + "threatq.indicator_value": "69.42.81.68", + "threatq.published_at": "2020-09-11T14:35:51.000Z", + "threatq.status": "Expired" }, { "@timestamp": "2020-11-15T00:00:02.000Z", @@ -158,32 +146,28 @@ "forwarded", "threatintel-threatq" ], - "threatintel.indicator.confidence": 4, - "threatintel.indicator.ip": "37.17.250.101", - "threatintel.indicator.marking.tlp": [ - "" - ], - "threatintel.indicator.provider": [ - "AlienVault OTX" - ], - "threatintel.indicator.type": "ipv4-addr", - "threatintel.threatq.attributes.alienvault_reliability": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] ThreatQuotient", + "threat.indicator.confidence": "Low", + "threat.indicator.ip": "37.17.250.101", + "threat.indicator.type": "ipv4-addr", + "threatq.attributes.alienvault_reliability": [ "4" ], - "threatintel.threatq.attributes.alienvault_revision": [ + "threatq.attributes.alienvault_revision": [ "3" ], - "threatintel.threatq.attributes.alienvault_threat_level": [ + "threatq.attributes.alienvault_threat_level": [ "2" ], - "threatintel.threatq.attributes.description": [ + "threatq.attributes.description": [ "Malicious Host" ], - "threatintel.threatq.created_at": "2020-09-11T14:35:41.000Z", - "threatintel.threatq.expires_calculated_at": "2020-10-15T14:40:02.000Z", - "threatintel.threatq.indicator_value": "37.17.250.101", - "threatintel.threatq.published_at": "2020-09-11T14:35:41.000Z", - "threatintel.threatq.status": "Expired" + "threatq.created_at": "2020-09-11T14:35:41.000Z", + "threatq.expires_calculated_at": "2020-10-15T14:40:02.000Z", + "threatq.indicator_value": "37.17.250.101", + "threatq.published_at": "2020-09-11T14:35:41.000Z", + "threatq.status": "Expired" }, { "@timestamp": "2020-11-15T00:00:02.000Z", @@ -200,38 +184,34 @@ "forwarded", "threatintel-threatq" ], - "threatintel.indicator.confidence": 4, - "threatintel.indicator.ip": "69.94.129.203", - "threatintel.indicator.marking.tlp": [ - "" - ], - "threatintel.indicator.provider": [ - "AlienVault OTX" - ], - "threatintel.indicator.type": "ipv4-addr", - "threatintel.threatq.attributes.alienvault_reliability": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] ThreatQuotient", + "threat.indicator.confidence": "Low", + "threat.indicator.ip": "69.94.129.203", + "threat.indicator.type": "ipv4-addr", + "threatq.attributes.alienvault_reliability": [ "4" ], - "threatintel.threatq.attributes.alienvault_revision": [ + "threatq.attributes.alienvault_revision": [ "3" ], - "threatintel.threatq.attributes.alienvault_threat_level": [ + "threatq.attributes.alienvault_threat_level": [ "2" ], - "threatintel.threatq.attributes.city": [ + "threatq.attributes.city": [ "Sacramento" ], - "threatintel.threatq.attributes.country": [ + "threatq.attributes.country": [ "US" ], - "threatintel.threatq.attributes.description": [ + "threatq.attributes.description": [ "Malicious Host" ], - "threatintel.threatq.created_at": "2020-09-11T14:35:51.000Z", - "threatintel.threatq.expires_calculated_at": "2020-10-15T14:40:03.000Z", - "threatintel.threatq.indicator_value": "69.94.129.203", - "threatintel.threatq.published_at": "2020-09-11T14:35:51.000Z", - "threatintel.threatq.status": "Expired" + "threatq.created_at": "2020-09-11T14:35:51.000Z", + "threatq.expires_calculated_at": "2020-10-15T14:40:03.000Z", + "threatq.indicator_value": "69.94.129.203", + "threatq.published_at": "2020-09-11T14:35:51.000Z", + "threatq.status": "Expired" }, { "@timestamp": "2020-11-15T00:00:02.000Z", @@ -248,38 +228,34 @@ "forwarded", "threatintel-threatq" ], - "threatintel.indicator.confidence": 4, - "threatintel.indicator.ip": "69.216.117.22", - "threatintel.indicator.marking.tlp": [ - "" - ], - "threatintel.indicator.provider": [ - "AlienVault OTX" - ], - "threatintel.indicator.type": "ipv4-addr", - "threatintel.threatq.attributes.alienvault_reliability": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] ThreatQuotient", + "threat.indicator.confidence": "Low", + "threat.indicator.ip": "69.216.117.22", + "threat.indicator.type": "ipv4-addr", + "threatq.attributes.alienvault_reliability": [ "4" ], - "threatintel.threatq.attributes.alienvault_revision": [ + "threatq.attributes.alienvault_revision": [ "3" ], - "threatintel.threatq.attributes.alienvault_threat_level": [ + "threatq.attributes.alienvault_threat_level": [ "3" ], - "threatintel.threatq.attributes.city": [ + "threatq.attributes.city": [ "Houston" ], - "threatintel.threatq.attributes.country": [ + "threatq.attributes.country": [ "US" ], - "threatintel.threatq.attributes.description": [ + "threatq.attributes.description": [ "Malicious Host" ], - "threatintel.threatq.created_at": "2020-09-11T14:35:51.000Z", - "threatintel.threatq.expires_calculated_at": "2020-10-15T14:40:03.000Z", - "threatintel.threatq.indicator_value": "69.216.117.22", - "threatintel.threatq.published_at": "2020-09-11T14:35:51.000Z", - "threatintel.threatq.status": "Expired" + "threatq.created_at": "2020-09-11T14:35:51.000Z", + "threatq.expires_calculated_at": "2020-10-15T14:40:03.000Z", + "threatq.indicator_value": "69.216.117.22", + "threatq.published_at": "2020-09-11T14:35:51.000Z", + "threatq.status": "Expired" }, { "@timestamp": "2020-11-15T00:00:02.000Z", @@ -296,38 +272,34 @@ "forwarded", "threatintel-threatq" ], - "threatintel.indicator.confidence": 4, - "threatintel.indicator.ip": "69.80.70.115", - "threatintel.indicator.marking.tlp": [ - "" - ], - "threatintel.indicator.provider": [ - "AlienVault OTX" - ], - "threatintel.indicator.type": "ipv4-addr", - "threatintel.threatq.attributes.alienvault_reliability": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] ThreatQuotient", + "threat.indicator.confidence": "Low", + "threat.indicator.ip": "69.80.70.115", + "threat.indicator.type": "ipv4-addr", + "threatq.attributes.alienvault_reliability": [ "4" ], - "threatintel.threatq.attributes.alienvault_revision": [ + "threatq.attributes.alienvault_revision": [ "3" ], - "threatintel.threatq.attributes.alienvault_threat_level": [ + "threatq.attributes.alienvault_threat_level": [ "2" ], - "threatintel.threatq.attributes.city": [ + "threatq.attributes.city": [ "Fort Lauderdale" ], - "threatintel.threatq.attributes.country": [ + "threatq.attributes.country": [ "US" ], - "threatintel.threatq.attributes.description": [ + "threatq.attributes.description": [ "Malicious Host" ], - "threatintel.threatq.created_at": "2020-09-11T14:35:51.000Z", - "threatintel.threatq.expires_calculated_at": "2020-10-15T14:40:03.000Z", - "threatintel.threatq.indicator_value": "69.80.70.115", - "threatintel.threatq.published_at": "2020-09-11T14:35:51.000Z", - "threatintel.threatq.status": "Expired" + "threatq.created_at": "2020-09-11T14:35:51.000Z", + "threatq.expires_calculated_at": "2020-10-15T14:40:03.000Z", + "threatq.indicator_value": "69.80.70.115", + "threatq.published_at": "2020-09-11T14:35:51.000Z", + "threatq.status": "Expired" }, { "@timestamp": "2020-11-15T00:00:02.000Z", @@ -344,38 +316,34 @@ "forwarded", "threatintel-threatq" ], - "threatintel.indicator.confidence": 4, - "threatintel.indicator.ip": "69.65.79.99", - "threatintel.indicator.marking.tlp": [ - "" - ], - "threatintel.indicator.provider": [ - "AlienVault OTX" - ], - "threatintel.indicator.type": "ipv4-addr", - "threatintel.threatq.attributes.alienvault_reliability": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] ThreatQuotient", + "threat.indicator.confidence": "Low", + "threat.indicator.ip": "69.65.79.99", + "threat.indicator.type": "ipv4-addr", + "threatq.attributes.alienvault_reliability": [ "4" ], - "threatintel.threatq.attributes.alienvault_revision": [ + "threatq.attributes.alienvault_revision": [ "3" ], - "threatintel.threatq.attributes.alienvault_threat_level": [ + "threatq.attributes.alienvault_threat_level": [ "2" ], - "threatintel.threatq.attributes.city": [ + "threatq.attributes.city": [ "Pompano Beach" ], - "threatintel.threatq.attributes.country": [ + "threatq.attributes.country": [ "US" ], - "threatintel.threatq.attributes.description": [ + "threatq.attributes.description": [ "Malicious Host" ], - "threatintel.threatq.created_at": "2020-09-11T14:35:51.000Z", - "threatintel.threatq.expires_calculated_at": "2020-10-15T14:40:03.000Z", - "threatintel.threatq.indicator_value": "69.65.79.99", - "threatintel.threatq.published_at": "2020-09-11T14:35:51.000Z", - "threatintel.threatq.status": "Expired" + "threatq.created_at": "2020-09-11T14:35:51.000Z", + "threatq.expires_calculated_at": "2020-10-15T14:40:03.000Z", + "threatq.indicator_value": "69.65.79.99", + "threatq.published_at": "2020-09-11T14:35:51.000Z", + "threatq.status": "Expired" }, { "@timestamp": "2020-11-15T00:00:02.000Z", @@ -392,37 +360,33 @@ "forwarded", "threatintel-threatq" ], - "threatintel.indicator.confidence": 4, - "threatintel.indicator.ip": "69.199.22.46", - "threatintel.indicator.marking.tlp": [ - "" - ], - "threatintel.indicator.provider": [ - "AlienVault OTX" - ], - "threatintel.indicator.type": "ipv4-addr", - "threatintel.threatq.attributes.alienvault_reliability": [ + "threat.feed.dashboard_id": "ad9c7430-72de-11eb-a3e3-b3cc7c78a70f", + "threat.feed.name": "[Filebeat] ThreatQuotient", + "threat.indicator.confidence": "Low", + "threat.indicator.ip": "69.199.22.46", + "threat.indicator.type": "ipv4-addr", + "threatq.attributes.alienvault_reliability": [ "4" ], - "threatintel.threatq.attributes.alienvault_revision": [ + "threatq.attributes.alienvault_revision": [ "3" ], - "threatintel.threatq.attributes.alienvault_threat_level": [ + "threatq.attributes.alienvault_threat_level": [ "2" ], - "threatintel.threatq.attributes.city": [ + "threatq.attributes.city": [ "Little Elm" ], - "threatintel.threatq.attributes.country": [ + "threatq.attributes.country": [ "US" ], - "threatintel.threatq.attributes.description": [ + "threatq.attributes.description": [ "Malicious Host" ], - "threatintel.threatq.created_at": "2020-09-11T14:35:51.000Z", - "threatintel.threatq.expires_calculated_at": "2020-10-15T14:40:03.000Z", - "threatintel.threatq.indicator_value": "69.199.22.46", - "threatintel.threatq.published_at": "2020-09-11T14:35:51.000Z", - "threatintel.threatq.status": "Expired" + "threatq.created_at": "2020-09-11T14:35:51.000Z", + "threatq.expires_calculated_at": "2020-10-15T14:40:03.000Z", + "threatq.indicator_value": "69.199.22.46", + "threatq.published_at": "2020-09-11T14:35:51.000Z", + "threatq.status": "Expired" } ] \ No newline at end of file diff --git a/x-pack/filebeat/module/tomcat/_meta/docs.asciidoc b/x-pack/filebeat/module/tomcat/_meta/docs.asciidoc index 9b7e4401204..d56df0ba01b 100644 --- a/x-pack/filebeat/module/tomcat/_meta/docs.asciidoc +++ b/x-pack/filebeat/module/tomcat/_meta/docs.asciidoc @@ -28,7 +28,7 @@ NOTE: This was converted from RSA NetWitness log parser XML "apachetomcat" devic *`var.input`*:: -The input from which messages are read. One of `file`, `tcp` or `udp`. +The input from which messages are read. One of `file`, `tcp` or `udp`. Defaults to `udp`. *`var.paths`*:: diff --git a/x-pack/filebeat/module/zscaler/_meta/docs.asciidoc b/x-pack/filebeat/module/zscaler/_meta/docs.asciidoc index 5728796de54..779c5deabc0 100644 --- a/x-pack/filebeat/module/zscaler/_meta/docs.asciidoc +++ b/x-pack/filebeat/module/zscaler/_meta/docs.asciidoc @@ -28,7 +28,7 @@ NOTE: This was converted from RSA NetWitness log parser XML "zscalernss" device *`var.input`*:: -The input from which messages are read. One of `file`, `tcp` or `udp`. +The input from which messages are read. One of `file`, `tcp` or `udp`. Defaults to `udp`. *`var.syslog_host`*:: diff --git a/x-pack/filebeat/modules.d/aws.yml.disabled b/x-pack/filebeat/modules.d/aws.yml.disabled index 3d34116d225..efca8245700 100644 --- a/x-pack/filebeat/modules.d/aws.yml.disabled +++ b/x-pack/filebeat/modules.d/aws.yml.disabled @@ -57,6 +57,9 @@ # Custom endpoint used to access AWS APIs #var.endpoint: amazonaws.com + # Default region to query if no other region is set + #var.default_region: us-east-1 + # AWS IAM Role to assume #var.role_arn: arn:aws:iam::123456789012:role/test-mb @@ -66,6 +69,12 @@ # The maximum number of messages to return from SQS. Valid values: 1 to 10. #var.max_number_of_messages: 5 + # URL to proxy AWS API calls + #var.proxy_url: http://proxy:3128 + + # Configures the SSL settings, ie. set trusted CAs, ignore certificate verification.... + #var.ssl: + cloudwatch: enabled: false @@ -109,6 +118,9 @@ # Custom endpoint used to access AWS APIs #var.endpoint: amazonaws.com + # Default region to query if no other region is set + #var.default_region: us-east-1 + # AWS IAM Role to assume #var.role_arn: arn:aws:iam::123456789012:role/test-mb @@ -118,6 +130,12 @@ # The maximum number of messages to return from SQS. Valid values: 1 to 10. #var.max_number_of_messages: 5 + # URL to proxy AWS API calls + #var.proxy_url: http://proxy:3128 + + # Configures the SSL settings, ie. set trusted CAs, ignore certificate verification.... + #var.ssl: + ec2: enabled: false @@ -161,6 +179,9 @@ # Custom endpoint used to access AWS APIs #var.endpoint: amazonaws.com + # Default region to query if no other region is set + #var.default_region: us-east-1 + # AWS IAM Role to assume #var.role_arn: arn:aws:iam::123456789012:role/test-mb @@ -170,6 +191,12 @@ # The maximum number of messages to return from SQS. Valid values: 1 to 10. #var.max_number_of_messages: 5 + # URL to proxy AWS API calls + #var.proxy_url: http://proxy:3128 + + # Configures the SSL settings, ie. set trusted CAs, ignore certificate verification.... + #var.ssl: + elb: enabled: false @@ -213,6 +240,9 @@ # Custom endpoint used to access AWS APIs #var.endpoint: amazonaws.com + # Default region to query if no other region is set + #var.default_region: us-east-1 + # AWS IAM Role to assume #var.role_arn: arn:aws:iam::123456789012:role/test-mb @@ -222,6 +252,12 @@ # The maximum number of messages to return from SQS. Valid values: 1 to 10. #var.max_number_of_messages: 5 + # URL to proxy AWS API calls + #var.proxy_url: http://proxy:3128 + + # Configures the SSL settings, ie. set trusted CAs, ignore certificate verification.... + #var.ssl: + s3access: enabled: false @@ -265,6 +301,9 @@ # Custom endpoint used to access AWS APIs #var.endpoint: amazonaws.com + # Default region to query if no other region is set + #var.default_region: us-east-1 + # AWS IAM Role to assume #var.role_arn: arn:aws:iam::123456789012:role/test-mb @@ -274,6 +313,12 @@ # The maximum number of messages to return from SQS. Valid values: 1 to 10. #var.max_number_of_messages: 5 + # URL to proxy AWS API calls + #var.proxy_url: http://proxy:3128 + + # Configures the SSL settings, ie. set trusted CAs, ignore certificate verification.... + #var.ssl: + vpcflow: enabled: false @@ -317,6 +362,9 @@ # Custom endpoint used to access AWS APIs #var.endpoint: amazonaws.com + # Default region to query if no other region is set + #var.default_region: us-east-1 + # AWS IAM Role to assume #var.role_arn: arn:aws:iam::123456789012:role/test-mb @@ -325,3 +373,9 @@ # The maximum number of messages to return from SQS. Valid values: 1 to 10. #var.max_number_of_messages: 5 + + # URL to proxy AWS API calls + #var.proxy_url: http://proxy:3128 + + # Configures the SSL settings, ie. set trusted CAs, ignore certificate verification.... + #var.ssl: diff --git a/x-pack/filebeat/modules.d/awsfargate.yml.disabled b/x-pack/filebeat/modules.d/awsfargate.yml.disabled index 225892f7fbe..57a5e419135 100644 --- a/x-pack/filebeat/modules.d/awsfargate.yml.disabled +++ b/x-pack/filebeat/modules.d/awsfargate.yml.disabled @@ -55,3 +55,9 @@ # Time used to sleep between AWS FilterLogEvents API calls inside the same collection period # Default api_sleep is 200 ms #var.api_sleep: 200ms + + # URL to proxy AWS API calls + #var.proxy_url: http://proxy:3128 + + # Configures the SSL settings, ie. set trusted CAs, ignore certificate verification.... + #var.ssl: diff --git a/x-pack/filebeat/modules.d/cisco.yml.disabled b/x-pack/filebeat/modules.d/cisco.yml.disabled index 3ad2d76a875..2d267c68a69 100644 --- a/x-pack/filebeat/modules.d/cisco.yml.disabled +++ b/x-pack/filebeat/modules.d/cisco.yml.disabled @@ -5,16 +5,23 @@ asa: enabled: false - # Set which input to use between syslog (default) or file. - #var.input: syslog + # Set which input to use between udp (default), tcp or file. + #var.input: udp - # The interface to listen to UDP based syslog traffic. Defaults to + # The interface to listen to udp or tcp syslog traffic. Defaults to # localhost. Set to 0.0.0.0 to bind to all available interfaces. #var.syslog_host: localhost - # The UDP port to listen for syslog traffic. Defaults to 9001. + # The port to listen for udp or tcp syslog traffic. Defaults to 9001. #var.syslog_port: 9001 + # With tcp input, set the optional tls configuration: + #var.ssl: + # enabled: true + # certificate: /path/to/cert.pem + # key: /path/to/privatekey.pem + # key_passphrase: 'password for my key' + # Set the log level from 1 (alerts only) to 7 (include all messages). # Messages with a log level higher than the specified will be dropped. # See https://www.cisco.com/c/en/us/td/docs/security/asa/syslog/b_syslog/syslogs-sev-level.html @@ -31,16 +38,23 @@ ftd: enabled: false - # Set which input to use between syslog (default) or file. - #var.input: syslog + # Set which input to use between udp (default), tcp or file. + #var.input: udp - # The interface to listen to UDP based syslog traffic. Defaults to + # The interface to listen to tcp or udp syslog traffic. Defaults to # localhost. Set to 0.0.0.0 to bind to all available interfaces. #var.syslog_host: localhost - # The UDP port to listen for syslog traffic. Defaults to 9003. + # The UDP port to listen for tcp or udp syslog traffic. Defaults to 9003. #var.syslog_port: 9003 + # With tcp input, set the optional tls configuration: + #var.ssl: + # enabled: true + # certificate: /path/to/cert.pem + # key: /path/to/privatekey.pem + # key_passphrase: 'password for my key' + # Set the log level from 1 (alerts only) to 7 (include all messages). # Messages with a log level higher than the specified will be dropped. # See https://www.cisco.com/c/en/us/td/docs/security/firepower/Syslogs/b_fptd_syslog_guide/syslogs-sev-level.html @@ -60,13 +74,16 @@ # Set which input to use between syslog (default) or file. #var.input: syslog - # The interface to listen to UDP based syslog traffic. Defaults to + # The interface to listen to syslog traffic. Defaults to # localhost. Set to 0.0.0.0 to bind to all available interfaces. #var.syslog_host: localhost - # The UDP port to listen for syslog traffic. Defaults to 9002. + # The port to listen on for syslog traffic. Defaults to 9002. #var.syslog_port: 9002 + # Set which protocol to use between udp (default) or tcp. + #var.syslog_protocol: udp + # Set custom paths for the log files when using file input. If left empty, # Filebeat will choose the paths depending on your OS. #var.paths: diff --git a/x-pack/filebeat/processors/decode_cef/cef/cef.go b/x-pack/filebeat/processors/decode_cef/cef/cef.go index 4c0f983aa96..73808171ace 100644 --- a/x-pack/filebeat/processors/decode_cef/cef/cef.go +++ b/x-pack/filebeat/processors/decode_cef/cef/cef.go @@ -152,32 +152,42 @@ func (e *Event) Unpack(data string, opts ...Option) error { return multierr.Combine(errs...) } -const ( - backslash = `\` - escapedBackslash = `\\` - - pipe = `|` - escapedPipe = `\|` - - equalsSign = `=` - escapedEqualsSign = `\=` -) - -var ( - headerEscapes = strings.NewReplacer(escapedBackslash, backslash, escapedPipe, pipe) - extensionEscapes = strings.NewReplacer(escapedBackslash, backslash, escapedEqualsSign, equalsSign) -) +// replaceEscapes replaces the escaped characters contained in v with their +// unescaped value. +func replaceEscapes(v string, startOffset int, escapes []int) string { + if len(escapes) == 0 { + return v + } -func replaceHeaderEscapes(b string) string { - if strings.Index(b, escapedBackslash) != -1 || strings.Index(b, escapedPipe) != -1 { - return headerEscapes.Replace(b) + // Adjust escape offsets relative to the start offset of v. + for i := 0; i < len(escapes); i++ { + escapes[i] = escapes[i] - startOffset } - return b -} -func replaceExtensionEscapes(b string) string { - if strings.Index(b, escapedBackslash) != -1 || strings.Index(b, escapedEqualsSign) != -1 { - return extensionEscapes.Replace(b) + var buf strings.Builder + var end int + + // Iterate over escapes and replace them. + for i := 0; i < len(escapes); i += 2 { + start := escapes[i] + buf.WriteString(v[end:start]) + + end = escapes[i+1] + value := v[start:end] + + switch value { + case `\n`: + buf.WriteByte('\n') + case `\r`: + buf.WriteByte('\r') + default: + // Remove leading slash. + if len(value) > 0 && value[0] == '\\' { + buf.WriteString(value[1:]) + } + } } - return b + buf.WriteString(v[end:]) + + return buf.String() } diff --git a/x-pack/filebeat/processors/decode_cef/cef/cef.rl b/x-pack/filebeat/processors/decode_cef/cef/cef.rl index a34ced7d87f..09b7fd6e962 100644 --- a/x-pack/filebeat/processors/decode_cef/cef/cef.rl +++ b/x-pack/filebeat/processors/decode_cef/cef/cef.rl @@ -18,7 +18,8 @@ import ( // unpack unpacks a CEF message. func (e *Event) unpack(data string) error { cs, p, pe, eof := 0, 0, len(data), len(data) - mark := 0 + mark, mark_slash := 0, 0 + var escapes []int // Extension key. var extKey string @@ -37,23 +38,34 @@ func (e *Event) unpack(data string) error { action mark { mark = p } + action mark_slash { + mark_slash = p + } + action mark_escape { + escapes = append(escapes, mark_slash, p) + } action version { e.Version, _ = strconv.Atoi(data[mark:p]) } action device_vendor { - e.DeviceVendor = replaceHeaderEscapes(data[mark:p]) + e.DeviceVendor = replaceEscapes(data[mark:p], mark, escapes) + escapes = escapes[:0] } action device_product { - e.DeviceProduct = replaceHeaderEscapes(data[mark:p]) + e.DeviceProduct = replaceEscapes(data[mark:p], mark, escapes) + escapes = escapes[:0] } action device_version { - e.DeviceVersion = replaceHeaderEscapes(data[mark:p]) + e.DeviceVersion = replaceEscapes(data[mark:p], mark, escapes) + escapes = escapes[:0] } action device_event_class_id { - e.DeviceEventClassID = replaceHeaderEscapes(data[mark:p]) + e.DeviceEventClassID = replaceEscapes(data[mark:p], mark, escapes) + escapes = escapes[:0] } action name { - e.Name = replaceHeaderEscapes(data[mark:p]) + e.Name = replaceEscapes(data[mark:p], mark, escapes) + escapes = escapes[:0] } action severity { e.Severity = data[mark:p] @@ -61,8 +73,8 @@ func (e *Event) unpack(data string) error { action extension_key { // A new extension key marks the end of the last extension value. if len(extKey) > 0 && extValueStart <= mark - 1 { - e.pushExtension(extKey, replaceExtensionEscapes(data[extValueStart:mark-1])) - extKey, extValueStart, extValueEnd = "", 0, 0 + e.pushExtension(extKey, replaceEscapes(data[extValueStart:mark-1], extValueStart, escapes)) + extKey, extValueStart, extValueEnd, escapes = "", 0, 0, escapes[:0] } extKey = data[mark:p] } @@ -76,19 +88,19 @@ func (e *Event) unpack(data string) error { action extension_eof { // Reaching the EOF marks the end of the final extension value. if len(extKey) > 0 && extValueStart <= extValueEnd { - e.pushExtension(extKey, replaceExtensionEscapes(data[extValueStart:extValueEnd])) - extKey, extValueStart, extValueEnd = "", 0, 0 + e.pushExtension(extKey, replaceEscapes(data[extValueStart:extValueEnd], extValueStart, escapes)) + extKey, extValueStart, extValueEnd, escapes = "", 0, 0, escapes[:0] } } action extension_err { recoveredErrs = append(recoveredErrs, fmt.Errorf("malformed value for %s at pos %d", extKey, p+1)) - fhold; fgoto gobble_extension; + fhold; fnext gobble_extension; } action recover_next_extension { extKey, extValueStart, extValueEnd = "", 0, 0 // Resume processing at p, the start of the next extension key. p = mark; - fgoto extensions; + fnext extensions; } # Define what header characters are allowed. @@ -96,7 +108,8 @@ func (e *Event) unpack(data string) error { escape = "\\"; escape_pipe = escape pipe; backslash = "\\\\"; - device_chars = backslash | escape_pipe | (any -- pipe -- escape); + header_escapes = (backslash | escape_pipe) >mark_slash %mark_escape; + device_chars = header_escapes | (any -- pipe -- escape); severity_chars = ( alpha | digit | "-" ); # Header fields. @@ -119,12 +132,15 @@ func (e *Event) unpack(data string) error { # Define what extension characters are allowed. equal = "="; escape_equal = escape equal; + escape_newline = escape 'n'; + escape_carriage_return = escape 'r'; + extension_value_escapes = (escape_equal | backslash | escape_newline | escape_carriage_return) >mark_slash %mark_escape; # Only alnum is defined in the CEF spec. The other characters allow # non-conforming extension keys to be parsed. extension_key_start_chars = alnum | '_'; extension_key_chars = extension_key_start_chars | '.' | ',' | '[' | ']'; extension_key_pattern = extension_key_start_chars extension_key_chars*; - extension_value_chars_nospace = backslash | escape_equal | (any -- equal -- escape -- space); + extension_value_chars_nospace = extension_value_escapes | (any -- equal -- escape -- space); # Extension fields. extension_key = extension_key_pattern >mark %extension_key; diff --git a/x-pack/filebeat/processors/decode_cef/cef/cef_test.go b/x-pack/filebeat/processors/decode_cef/cef/cef_test.go index a0dc7c0c46c..7ab286e1f2c 100644 --- a/x-pack/filebeat/processors/decode_cef/cef/cef_test.go +++ b/x-pack/filebeat/processors/decode_cef/cef/cef_test.go @@ -52,6 +52,8 @@ const ( tabMessage = "CEF:0|security|threatmanager|1.0|100|message is padded|10|spt=1232 msg=Tabs\tand\rcontrol\ncharacters are preserved\t src=127.0.0.1" tabNoSepMessage = "CEF:0|security|threatmanager|1.0|100|message has tabs|10|spt=1232 msg=Tab is not a separator\tsrc=127.0.0.1" + + escapedMessage = `CEF:0|security\\compliance|threat\|->manager|1.0|100|message contains escapes|10|spt=1232 msg=Newlines in messages\nare allowed.\r\nAnd so are carriage feeds\\newlines\\\=.` ) var testMessages = []string{ @@ -71,6 +73,7 @@ var testMessages = []string{ paddedMessage, crlfMessage, tabMessage, + escapedMessage, } func TestGenerateFuzzCorpus(t *testing.T) { @@ -374,6 +377,18 @@ func TestEventUnpack(t *testing.T) { "spt": IntegerField(1232), }, e.Extensions) }) + + t.Run("escapes are replaced", func(t *testing.T) { + var e Event + err := e.Unpack(escapedMessage) + assert.NoError(t, err) + assert.Equal(t, `security\compliance`, e.DeviceVendor) + assert.Equal(t, `threat|->manager`, e.DeviceProduct) + assert.Equal(t, map[string]*Field{ + "spt": IntegerField(1232), + "msg": StringField("Newlines in messages\nare allowed.\r\nAnd so are carriage feeds\\newlines\\=."), + }, e.Extensions) + }) } func TestEventUnpackWithFullExtensionNames(t *testing.T) { diff --git a/x-pack/filebeat/processors/decode_cef/cef/parser.go b/x-pack/filebeat/processors/decode_cef/cef/parser.go index cd765873527..b9e19b03e7c 100644 --- a/x-pack/filebeat/processors/decode_cef/cef/parser.go +++ b/x-pack/filebeat/processors/decode_cef/cef/parser.go @@ -18,25 +18,26 @@ var _cef_eof_actions []byte = []byte{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 16, 16, 0, 0, 0, 0, - 19, 22, 22, 22, 19, 22, 22, 22, - 0, + 0, 0, 0, 0, 0, 0, 0, 25, + 25, 0, 0, 0, 0, 28, 32, 32, + 32, 28, 32, 32, 32, 35, 35, 0, } const cef_start int = 1 -const cef_first_final int = 31 +const cef_first_final int = 36 const cef_error int = 0 -const cef_en_gobble_extension int = 28 +const cef_en_gobble_extension int = 33 const cef_en_main int = 1 -const cef_en_main_cef_extensions int = 24 +const cef_en_main_cef_extensions int = 29 //line cef.rl:16 // unpack unpacks a CEF message. func (e *Event) unpack(data string) error { cs, p, pe, eof := 0, 0, len(data), len(data) - mark := 0 + mark, mark_slash := 0, 0 + var escapes []int // Extension key. var extKey string @@ -50,12 +51,12 @@ func (e *Event) unpack(data string) error { e.init(data) -//line parser.go:55 +//line parser.go:56 { cs = cef_start } -//line parser.go:60 +//line parser.go:61 { if (p) == (pe) { goto _test_eof @@ -119,471 +120,545 @@ func (e *Event) unpack(data string) error { case 9: switch data[(p)] { case 92: - goto tr11 + goto tr14 case 124: - goto tr11 + goto tr14 } goto tr1 case 10: switch data[(p)] { case 92: - goto tr15 - case 124: goto tr16 + case 124: + goto tr17 } - goto tr14 + goto tr15 case 11: switch data[(p)] { case 92: - goto tr18 - case 124: goto tr19 + case 124: + goto tr20 } - goto tr17 + goto tr18 case 12: switch data[(p)] { case 92: - goto tr17 + goto tr22 case 124: - goto tr17 + goto tr23 } - goto tr1 + goto tr21 case 13: switch data[(p)] { case 92: - goto tr21 + goto tr24 case 124: - goto tr22 + goto tr24 } - goto tr20 + goto tr1 case 14: switch data[(p)] { case 92: - goto tr24 + goto tr26 case 124: - goto tr25 + goto tr27 } - goto tr23 + goto tr25 case 15: switch data[(p)] { case 92: - goto tr23 + goto tr29 case 124: - goto tr23 + goto tr30 } - goto tr1 + goto tr28 case 16: switch data[(p)] { case 92: - goto tr27 + goto tr32 case 124: - goto tr28 + goto tr33 } - goto tr26 + goto tr31 case 17: switch data[(p)] { case 92: - goto tr30 + goto tr34 case 124: - goto tr31 + goto tr34 } - goto tr29 + goto tr1 case 18: switch data[(p)] { case 92: - goto tr29 + goto tr36 case 124: - goto tr29 + goto tr37 } - goto tr1 + goto tr35 case 19: switch data[(p)] { case 92: - goto tr33 + goto tr39 case 124: - goto tr34 + goto tr40 } - goto tr32 + goto tr38 case 20: switch data[(p)] { case 92: - goto tr36 + goto tr42 case 124: - goto tr37 + goto tr43 } - goto tr35 + goto tr41 case 21: switch data[(p)] { case 92: - goto tr35 + goto tr44 case 124: - goto tr35 + goto tr44 } goto tr1 case 22: + switch data[(p)] { + case 92: + goto tr46 + case 124: + goto tr47 + } + goto tr45 + case 23: + switch data[(p)] { + case 92: + goto tr49 + case 124: + goto tr50 + } + goto tr48 + case 24: + switch data[(p)] { + case 92: + goto tr52 + case 124: + goto tr53 + } + goto tr51 + case 25: + switch data[(p)] { + case 92: + goto tr54 + case 124: + goto tr54 + } + goto tr1 + case 26: + switch data[(p)] { + case 92: + goto tr56 + case 124: + goto tr57 + } + goto tr55 + case 27: switch data[(p)] { case 45: - goto tr38 + goto tr58 case 124: - goto tr39 + goto tr59 } switch { case data[(p)] < 65: if 48 <= data[(p)] && data[(p)] <= 57 { - goto tr38 + goto tr58 } case data[(p)] > 90: if 97 <= data[(p)] && data[(p)] <= 122 { - goto tr38 + goto tr58 } default: - goto tr38 + goto tr58 } goto tr1 - case 23: + case 28: switch data[(p)] { case 45: - goto tr40 + goto tr60 case 124: - goto tr41 + goto tr61 } switch { case data[(p)] < 65: if 48 <= data[(p)] && data[(p)] <= 57 { - goto tr40 + goto tr60 } case data[(p)] > 90: if 97 <= data[(p)] && data[(p)] <= 122 { - goto tr40 + goto tr60 } default: - goto tr40 + goto tr60 } goto tr1 - case 31: + case 36: switch data[(p)] { case 32: - goto tr42 + goto tr62 case 95: - goto tr43 + goto tr63 } switch { case data[(p)] < 65: if 48 <= data[(p)] && data[(p)] <= 57 { - goto tr43 + goto tr63 } case data[(p)] > 90: if 97 <= data[(p)] && data[(p)] <= 122 { - goto tr43 + goto tr63 } default: - goto tr43 + goto tr63 } goto tr1 - case 24: + case 29: switch data[(p)] { case 32: - goto tr42 + goto tr62 case 95: - goto tr43 + goto tr63 } switch { case data[(p)] < 65: if 48 <= data[(p)] && data[(p)] <= 57 { - goto tr43 + goto tr63 } case data[(p)] > 90: if 97 <= data[(p)] && data[(p)] <= 122 { - goto tr43 + goto tr63 } default: - goto tr43 + goto tr63 } goto tr1 - case 25: + case 30: switch data[(p)] { case 44: - goto tr44 + goto tr64 case 46: - goto tr44 + goto tr64 case 61: - goto tr45 + goto tr65 case 93: - goto tr44 + goto tr64 case 95: - goto tr44 + goto tr64 } switch { case data[(p)] < 65: if 48 <= data[(p)] && data[(p)] <= 57 { - goto tr44 + goto tr64 } case data[(p)] > 91: if 97 <= data[(p)] && data[(p)] <= 122 { - goto tr44 + goto tr64 } default: - goto tr44 + goto tr64 } goto tr1 - case 32: + case 37: switch data[(p)] { case 32: - goto tr55 + goto tr75 case 61: - goto tr46 + goto tr66 case 92: - goto tr56 + goto tr76 } if 9 <= data[(p)] && data[(p)] <= 13 { - goto tr54 + goto tr74 } - goto tr53 - case 33: + goto tr73 + case 38: switch data[(p)] { case 32: - goto tr58 + goto tr79 case 61: - goto tr46 + goto tr66 case 92: - goto tr59 + goto tr80 } if 9 <= data[(p)] && data[(p)] <= 13 { - goto tr57 + goto tr78 } - goto tr48 - case 34: + goto tr77 + case 39: switch data[(p)] { case 32: - goto tr58 + goto tr79 case 61: - goto tr46 + goto tr66 case 92: - goto tr59 + goto tr80 case 95: - goto tr60 + goto tr81 } switch { case data[(p)] < 48: if 9 <= data[(p)] && data[(p)] <= 13 { - goto tr57 + goto tr78 } case data[(p)] > 57: switch { case data[(p)] > 90: if 97 <= data[(p)] && data[(p)] <= 122 { - goto tr60 + goto tr81 } case data[(p)] >= 65: - goto tr60 + goto tr81 } default: - goto tr60 + goto tr81 } - goto tr48 - case 35: + goto tr77 + case 40: switch data[(p)] { case 32: - goto tr58 + goto tr79 case 44: - goto tr61 + goto tr82 case 46: - goto tr61 + goto tr82 case 61: - goto tr62 + goto tr83 case 92: - goto tr59 + goto tr80 case 95: - goto tr61 + goto tr82 } switch { case data[(p)] < 48: if 9 <= data[(p)] && data[(p)] <= 13 { - goto tr57 + goto tr78 } case data[(p)] > 57: switch { case data[(p)] > 93: if 97 <= data[(p)] && data[(p)] <= 122 { - goto tr61 + goto tr82 } case data[(p)] >= 65: - goto tr61 + goto tr82 } default: - goto tr61 + goto tr82 } - goto tr48 - case 36: + goto tr77 + case 41: switch data[(p)] { case 32: - goto tr65 + goto tr86 case 61: - goto tr46 - case 92: goto tr66 + case 92: + goto tr87 } if 9 <= data[(p)] && data[(p)] <= 13 { - goto tr64 + goto tr85 } - goto tr63 - case 37: + goto tr84 + case 42: switch data[(p)] { case 32: - goto tr68 + goto tr90 case 61: - goto tr46 + goto tr66 case 92: - goto tr69 + goto tr91 } if 9 <= data[(p)] && data[(p)] <= 13 { - goto tr67 + goto tr89 } - goto tr47 - case 38: + goto tr88 + case 43: switch data[(p)] { case 32: - goto tr68 + goto tr90 case 61: - goto tr46 + goto tr66 case 92: - goto tr69 + goto tr91 case 95: - goto tr70 + goto tr92 } switch { case data[(p)] < 48: if 9 <= data[(p)] && data[(p)] <= 13 { - goto tr67 + goto tr89 } case data[(p)] > 57: switch { case data[(p)] > 90: if 97 <= data[(p)] && data[(p)] <= 122 { - goto tr70 + goto tr92 } case data[(p)] >= 65: - goto tr70 + goto tr92 } default: - goto tr70 + goto tr92 } - goto tr47 - case 39: + goto tr88 + case 44: switch data[(p)] { case 32: - goto tr68 + goto tr90 case 44: - goto tr71 + goto tr93 case 46: - goto tr71 + goto tr93 case 61: - goto tr62 + goto tr83 case 92: - goto tr69 + goto tr91 case 95: - goto tr71 + goto tr93 } switch { case data[(p)] < 48: if 9 <= data[(p)] && data[(p)] <= 13 { - goto tr67 + goto tr89 } case data[(p)] > 57: switch { case data[(p)] > 93: if 97 <= data[(p)] && data[(p)] <= 122 { - goto tr71 + goto tr93 } case data[(p)] >= 65: - goto tr71 + goto tr93 } default: - goto tr71 + goto tr93 } - goto tr47 - case 26: + goto tr88 + case 31: switch data[(p)] { case 61: - goto tr47 + goto tr67 case 92: - goto tr47 + goto tr67 + case 110: + goto tr67 + case 114: + goto tr67 } - goto tr46 - case 27: + goto tr66 + case 45: switch data[(p)] { + case 32: + goto tr96 case 61: - goto tr48 + goto tr66 case 92: - goto tr48 + goto tr97 } - goto tr46 - case 28: + if 9 <= data[(p)] && data[(p)] <= 13 { + goto tr95 + } + goto tr94 + case 32: + switch data[(p)] { + case 61: + goto tr68 + case 92: + goto tr68 + case 110: + goto tr68 + case 114: + goto tr68 + } + goto tr66 + case 46: + switch data[(p)] { + case 32: + goto tr100 + case 61: + goto tr66 + case 92: + goto tr101 + } + if 9 <= data[(p)] && data[(p)] <= 13 { + goto tr99 + } + goto tr98 + case 33: if data[(p)] == 32 { - goto tr50 + goto tr70 } - goto tr49 - case 29: + goto tr69 + case 34: switch data[(p)] { case 32: - goto tr50 + goto tr70 case 95: - goto tr51 + goto tr71 } switch { case data[(p)] < 65: if 48 <= data[(p)] && data[(p)] <= 57 { - goto tr51 + goto tr71 } case data[(p)] > 90: if 97 <= data[(p)] && data[(p)] <= 122 { - goto tr51 + goto tr71 } default: - goto tr51 + goto tr71 } - goto tr49 - case 30: + goto tr69 + case 35: switch data[(p)] { case 32: - goto tr50 + goto tr70 case 44: - goto tr51 + goto tr71 case 46: - goto tr51 + goto tr71 case 61: - goto tr52 + goto tr72 case 93: - goto tr51 + goto tr71 case 95: - goto tr51 + goto tr71 } switch { case data[(p)] < 65: if 48 <= data[(p)] && data[(p)] <= 57 { - goto tr51 + goto tr71 } case data[(p)] > 91: if 97 <= data[(p)] && data[(p)] <= 122 { - goto tr51 + goto tr71 } default: - goto tr51 + goto tr71 } - goto tr49 - case 40: + goto tr69 + case 47: if data[(p)] == 32 { - goto tr50 + goto tr70 } - goto tr49 + goto tr69 } tr1: cs = 0 goto _again - tr46: + tr66: cs = 0 - goto f15 + goto f24 tr0: cs = 2 goto _again @@ -611,364 +686,574 @@ func (e *Event) unpack(data string) error { tr8: cs = 8 goto f0 - tr12: - cs = 9 - goto _again + tr15: + cs = 8 + goto f6 tr9: cs = 9 - goto f0 - tr10: - cs = 10 goto f2 - tr13: + tr12: + cs = 9 + goto f4 + tr16: + cs = 9 + goto f7 + tr14: cs = 10 - goto f3 - tr17: - cs = 11 goto _again - tr14: + tr10: cs = 11 - goto f0 - tr18: + goto f3 + tr13: + cs = 11 + goto f5 + tr17: + cs = 11 + goto f8 + tr21: cs = 12 goto _again - tr15: + tr18: cs = 12 goto f0 - tr16: + tr25: + cs = 12 + goto f6 + tr19: + cs = 13 + goto f2 + tr22: cs = 13 goto f4 - tr19: + tr26: cs = 13 - goto f5 - tr23: + goto f7 + tr24: cs = 14 goto _again tr20: - cs = 14 - goto f0 - tr24: cs = 15 - goto _again - tr21: + goto f9 + tr23: + cs = 15 + goto f10 + tr27: cs = 15 + goto f11 + tr31: + cs = 16 + goto _again + tr28: + cs = 16 goto f0 - tr22: + tr35: cs = 16 goto f6 - tr25: - cs = 16 - goto f7 tr29: cs = 17 - goto _again - tr26: + goto f2 + tr32: cs = 17 - goto f0 - tr30: + goto f4 + tr36: + cs = 17 + goto f7 + tr34: cs = 18 goto _again - tr27: - cs = 18 - goto f0 - tr28: + tr30: cs = 19 - goto f8 - tr31: + goto f12 + tr33: cs = 19 - goto f9 - tr35: + goto f13 + tr37: + cs = 19 + goto f14 + tr41: cs = 20 goto _again - tr32: + tr38: cs = 20 goto f0 - tr36: + tr45: + cs = 20 + goto f6 + tr39: cs = 21 - goto _again - tr33: + goto f2 + tr42: cs = 21 - goto f0 - tr34: - cs = 22 - goto f10 - tr37: + goto f4 + tr46: + cs = 21 + goto f7 + tr44: cs = 22 - goto f11 + goto _again tr40: cs = 23 - goto _again - tr38: + goto f15 + tr43: cs = 23 - goto f0 - tr42: + goto f16 + tr47: + cs = 23 + goto f17 + tr51: cs = 24 goto _again - tr44: + tr48: + cs = 24 + goto f0 + tr55: + cs = 24 + goto f6 + tr49: cs = 25 - goto _again - tr43: + goto f2 + tr52: cs = 25 - goto f0 - tr69: + goto f4 + tr56: + cs = 25 + goto f7 + tr54: cs = 26 goto _again - tr66: - cs = 26 - goto f20 - tr59: + tr50: cs = 27 - goto _again - tr56: + goto f18 + tr53: + cs = 27 + goto f19 + tr57: cs = 27 goto f20 - tr49: + tr60: cs = 28 goto _again - tr50: - cs = 29 + tr58: + cs = 28 goto f0 - tr51: + tr62: + cs = 29 + goto _again + tr64: cs = 30 goto _again - tr39: + tr63: + cs = 30 + goto f0 + tr91: cs = 31 - goto f12 - tr41: + goto f4 + tr97: cs = 31 - goto f13 - tr45: + goto f7 + tr87: + cs = 31 + goto f30 + tr80: cs = 32 - goto f14 - tr57: + goto f4 + tr101: + cs = 32 + goto f7 + tr76: + cs = 32 + goto f30 + tr69: cs = 33 goto _again - tr48: - cs = 33 - goto f16 - tr53: - cs = 33 - goto f19 - tr54: - cs = 33 - goto f20 - tr58: + tr70: cs = 34 + goto f0 + tr71: + cs = 35 goto _again - tr55: - cs = 34 - goto f20 + tr59: + cs = 36 + goto f21 tr61: - cs = 35 - goto f16 - tr60: - cs = 35 - goto f22 - tr62: cs = 36 - goto f14 - tr67: - cs = 37 - goto _again - tr47: - cs = 37 - goto f16 - tr63: - cs = 37 - goto f19 - tr64: + goto f22 + tr65: cs = 37 - goto f20 - tr68: + goto f23 + tr78: cs = 38 goto _again - tr65: + tr99: cs = 38 - goto f20 - tr71: + goto f6 + tr77: + cs = 38 + goto f25 + tr73: + cs = 38 + goto f28 + tr74: + cs = 38 + goto f29 + tr98: + cs = 38 + goto f35 + tr79: cs = 39 - goto f16 - tr70: + goto _again + tr100: cs = 39 - goto f23 - tr52: + goto f6 + tr75: + cs = 39 + goto f29 + tr82: cs = 40 - goto f17 + goto f25 + tr81: + cs = 40 + goto f32 + tr83: + cs = 41 + goto f23 + tr89: + cs = 42 + goto _again + tr95: + cs = 42 + goto f6 + tr88: + cs = 42 + goto f25 + tr84: + cs = 42 + goto f28 + tr85: + cs = 42 + goto f29 + tr94: + cs = 42 + goto f35 + tr90: + cs = 43 + goto _again + tr96: + cs = 43 + goto f6 + tr86: + cs = 43 + goto f29 + tr93: + cs = 44 + goto f25 + tr92: + cs = 44 + goto f33 + tr67: + cs = 45 + goto f25 + tr68: + cs = 46 + goto f25 + tr72: + cs = 47 + goto f26 f0: -//line cef.rl:37 +//line cef.rl:38 mark = p + goto _again + f4: +//line cef.rl:41 + + mark_slash = p + + goto _again + f6: +//line cef.rl:44 + + escapes = append(escapes, mark_slash, p) + goto _again f1: -//line cef.rl:40 +//line cef.rl:47 e.Version, _ = strconv.Atoi(data[mark:p]) goto _again - f3: -//line cef.rl:43 + f5: +//line cef.rl:50 - e.DeviceVendor = replaceHeaderEscapes(data[mark:p]) + e.DeviceVendor = replaceEscapes(data[mark:p], mark, escapes) + escapes = escapes[:0] goto _again - f5: -//line cef.rl:46 + f10: +//line cef.rl:54 - e.DeviceProduct = replaceHeaderEscapes(data[mark:p]) + e.DeviceProduct = replaceEscapes(data[mark:p], mark, escapes) + escapes = escapes[:0] goto _again - f7: -//line cef.rl:49 + f13: +//line cef.rl:58 - e.DeviceVersion = replaceHeaderEscapes(data[mark:p]) + e.DeviceVersion = replaceEscapes(data[mark:p], mark, escapes) + escapes = escapes[:0] goto _again - f9: -//line cef.rl:52 + f16: +//line cef.rl:62 - e.DeviceEventClassID = replaceHeaderEscapes(data[mark:p]) + e.DeviceEventClassID = replaceEscapes(data[mark:p], mark, escapes) + escapes = escapes[:0] goto _again - f11: -//line cef.rl:55 + f19: +//line cef.rl:66 - e.Name = replaceHeaderEscapes(data[mark:p]) + e.Name = replaceEscapes(data[mark:p], mark, escapes) + escapes = escapes[:0] goto _again - f13: -//line cef.rl:58 + f22: +//line cef.rl:70 e.Severity = data[mark:p] goto _again - f14: -//line cef.rl:61 + f23: +//line cef.rl:73 // A new extension key marks the end of the last extension value. if len(extKey) > 0 && extValueStart <= mark-1 { - e.pushExtension(extKey, replaceExtensionEscapes(data[extValueStart:mark-1])) - extKey, extValueStart, extValueEnd = "", 0, 0 + e.pushExtension(extKey, replaceEscapes(data[extValueStart:mark-1], extValueStart, escapes)) + extKey, extValueStart, extValueEnd, escapes = "", 0, 0, escapes[:0] } extKey = data[mark:p] goto _again - f20: -//line cef.rl:69 + f29: +//line cef.rl:81 extValueStart = p extValueEnd = p goto _again - f16: -//line cef.rl:73 + f25: +//line cef.rl:85 extValueEnd = p + 1 goto _again - f15: -//line cef.rl:83 + f24: +//line cef.rl:95 recoveredErrs = append(recoveredErrs, fmt.Errorf("malformed value for %s at pos %d", extKey, p+1)) (p)-- - cs = 28 + cs = 33 + goto _again - f17: -//line cef.rl:87 + f26: +//line cef.rl:99 extKey, extValueStart, extValueEnd = "", 0, 0 // Resume processing at p, the start of the next extension key. p = mark - cs = 24 + cs = 29 + goto _again f2: -//line cef.rl:37 +//line cef.rl:38 mark = p -//line cef.rl:43 +//line cef.rl:41 - e.DeviceVendor = replaceHeaderEscapes(data[mark:p]) + mark_slash = p goto _again - f4: -//line cef.rl:37 + f3: +//line cef.rl:38 mark = p -//line cef.rl:46 +//line cef.rl:50 - e.DeviceProduct = replaceHeaderEscapes(data[mark:p]) + e.DeviceVendor = replaceEscapes(data[mark:p], mark, escapes) + escapes = escapes[:0] goto _again - f6: -//line cef.rl:37 + f9: +//line cef.rl:38 mark = p -//line cef.rl:49 +//line cef.rl:54 - e.DeviceVersion = replaceHeaderEscapes(data[mark:p]) + e.DeviceProduct = replaceEscapes(data[mark:p], mark, escapes) + escapes = escapes[:0] goto _again - f8: -//line cef.rl:37 + f12: +//line cef.rl:38 mark = p -//line cef.rl:52 +//line cef.rl:58 - e.DeviceEventClassID = replaceHeaderEscapes(data[mark:p]) + e.DeviceVersion = replaceEscapes(data[mark:p], mark, escapes) + escapes = escapes[:0] goto _again - f10: -//line cef.rl:37 + f15: +//line cef.rl:38 mark = p -//line cef.rl:55 +//line cef.rl:62 - e.Name = replaceHeaderEscapes(data[mark:p]) + e.DeviceEventClassID = replaceEscapes(data[mark:p], mark, escapes) + escapes = escapes[:0] goto _again - f12: -//line cef.rl:37 + f18: +//line cef.rl:38 mark = p -//line cef.rl:58 +//line cef.rl:66 + + e.Name = replaceEscapes(data[mark:p], mark, escapes) + escapes = escapes[:0] + + goto _again + f21: +//line cef.rl:38 + + mark = p + +//line cef.rl:70 e.Severity = data[mark:p] goto _again - f23: -//line cef.rl:37 + f33: +//line cef.rl:38 mark = p -//line cef.rl:73 +//line cef.rl:85 extValueEnd = p + 1 goto _again - f19: -//line cef.rl:69 + f7: +//line cef.rl:44 + + escapes = append(escapes, mark_slash, p) + +//line cef.rl:41 + + mark_slash = p + + goto _again + f8: +//line cef.rl:44 + + escapes = append(escapes, mark_slash, p) + +//line cef.rl:50 + + e.DeviceVendor = replaceEscapes(data[mark:p], mark, escapes) + escapes = escapes[:0] + + goto _again + f11: +//line cef.rl:44 + + escapes = append(escapes, mark_slash, p) + +//line cef.rl:54 + + e.DeviceProduct = replaceEscapes(data[mark:p], mark, escapes) + escapes = escapes[:0] + + goto _again + f14: +//line cef.rl:44 + + escapes = append(escapes, mark_slash, p) + +//line cef.rl:58 + + e.DeviceVersion = replaceEscapes(data[mark:p], mark, escapes) + escapes = escapes[:0] + + goto _again + f17: +//line cef.rl:44 + + escapes = append(escapes, mark_slash, p) + +//line cef.rl:62 + + e.DeviceEventClassID = replaceEscapes(data[mark:p], mark, escapes) + escapes = escapes[:0] + + goto _again + f20: +//line cef.rl:44 + + escapes = append(escapes, mark_slash, p) + +//line cef.rl:66 + + e.Name = replaceEscapes(data[mark:p], mark, escapes) + escapes = escapes[:0] + + goto _again + f35: +//line cef.rl:44 + + escapes = append(escapes, mark_slash, p) + +//line cef.rl:85 + + extValueEnd = p + 1 + + goto _again + f30: +//line cef.rl:81 extValueStart = p extValueEnd = p -//line cef.rl:73 +//line cef.rl:41 + + mark_slash = p + + goto _again + f28: +//line cef.rl:81 + + extValueStart = p + extValueEnd = p + +//line cef.rl:85 extValueEnd = p + 1 goto _again - f22: -//line cef.rl:73 + f32: +//line cef.rl:85 extValueEnd = p + 1 -//line cef.rl:37 +//line cef.rl:38 mark = p @@ -986,38 +1271,50 @@ func (e *Event) unpack(data string) error { } if (p) == eof { switch _cef_eof_actions[cs] { - case 22: -//line cef.rl:76 + case 32: +//line cef.rl:88 // Reaching the EOF marks the end of the final extension value. if len(extKey) > 0 && extValueStart <= extValueEnd { - e.pushExtension(extKey, replaceExtensionEscapes(data[extValueStart:extValueEnd])) - extKey, extValueStart, extValueEnd = "", 0, 0 + e.pushExtension(extKey, replaceEscapes(data[extValueStart:extValueEnd], extValueStart, escapes)) + extKey, extValueStart, extValueEnd, escapes = "", 0, 0, escapes[:0] } - case 16: -//line cef.rl:83 + case 25: +//line cef.rl:95 recoveredErrs = append(recoveredErrs, fmt.Errorf("malformed value for %s at pos %d", extKey, p+1)) (p)-- - cs = 28 - goto _again + cs = 33 + + case 35: +//line cef.rl:44 + + escapes = append(escapes, mark_slash, p) + +//line cef.rl:88 + + // Reaching the EOF marks the end of the final extension value. + if len(extKey) > 0 && extValueStart <= extValueEnd { + e.pushExtension(extKey, replaceEscapes(data[extValueStart:extValueEnd], extValueStart, escapes)) + extKey, extValueStart, extValueEnd, escapes = "", 0, 0, escapes[:0] + } - case 19: -//line cef.rl:69 + case 28: +//line cef.rl:81 extValueStart = p extValueEnd = p -//line cef.rl:76 +//line cef.rl:88 // Reaching the EOF marks the end of the final extension value. if len(extKey) > 0 && extValueStart <= extValueEnd { - e.pushExtension(extKey, replaceExtensionEscapes(data[extValueStart:extValueEnd])) - extKey, extValueStart, extValueEnd = "", 0, 0 + e.pushExtension(extKey, replaceEscapes(data[extValueStart:extValueEnd], extValueStart, escapes)) + extKey, extValueStart, extValueEnd, escapes = "", 0, 0, escapes[:0] } -//line parser.go:883 +//line parser.go:1116 } } @@ -1026,7 +1323,7 @@ func (e *Event) unpack(data string) error { } } -//line cef.rl:145 +//line cef.rl:161 // Check if state machine completed. if cs < cef_first_final { diff --git a/x-pack/functionbeat/Dockerfile b/x-pack/functionbeat/Dockerfile index 70d7f46a2cd..5a75f945955 100644 --- a/x-pack/functionbeat/Dockerfile +++ b/x-pack/functionbeat/Dockerfile @@ -1,8 +1,8 @@ -FROM golang:1.17.2 +FROM golang:1.17.5 RUN \ apt-get update \ - && apt-get install -y --no-install-recommends \ + && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \ netcat \ rsync \ python3 \ diff --git a/x-pack/functionbeat/Jenkinsfile.yml b/x-pack/functionbeat/Jenkinsfile.yml index 84e95e829ea..f3b4bf10973 100644 --- a/x-pack/functionbeat/Jenkinsfile.yml +++ b/x-pack/functionbeat/Jenkinsfile.yml @@ -39,7 +39,7 @@ stages: macos: mage: "mage build unitTest" platforms: ## override default label in this specific stage. - - "macosx&&x86_64" + - "orka && darwin && poc" when: ## Override the top-level when. comments: - "/test x-pack/functionbeat for macos" diff --git a/x-pack/functionbeat/docs/fields.asciidoc b/x-pack/functionbeat/docs/fields.asciidoc index 6c968ea5a30..0251ede5401 100644 --- a/x-pack/functionbeat/docs/fields.asciidoc +++ b/x-pack/functionbeat/docs/fields.asciidoc @@ -15456,47 +15456,16 @@ type: ip -- - -*`kubernetes.namespace.name`*:: +*`kubernetes.namespace`*:: + -- -Kubernetes namespace name +Kubernetes namespace type: keyword -- -*`kubernetes.namespace.uuid`*:: -+ --- -Kubernetes namespace uuid - - -type: keyword - --- - -*`kubernetes.namespace.labels.*`*:: -+ --- -Kubernetes namespace labels map - - -type: object - --- - -*`kubernetes.namespace.annotations.*`*:: -+ --- -Kubernetes namespace annotations map - - -type: object - --- - *`kubernetes.node.name`*:: + -- diff --git a/x-pack/functionbeat/function/beater/functionbeat.go b/x-pack/functionbeat/function/beater/functionbeat.go index be8d59b9db5..0906a1433e3 100644 --- a/x-pack/functionbeat/function/beater/functionbeat.go +++ b/x-pack/functionbeat/function/beater/functionbeat.go @@ -13,6 +13,7 @@ import ( "github.com/elastic/beats/v7/libbeat/common/fmtstr" "github.com/elastic/beats/v7/libbeat/outputs/elasticsearch" + "github.com/elastic/beats/v7/libbeat/publisher/pipeline" "github.com/elastic/beats/v7/libbeat/beat" "github.com/elastic/beats/v7/libbeat/common" @@ -55,6 +56,7 @@ type Functionbeat struct { // New creates an instance of functionbeat. func New(b *beat.Beat, cfg *common.Config) (beat.Beater, error) { + c := &config.DefaultConfig if err := cfg.Unpack(c); err != nil { return nil, fmt.Errorf("error reading config file: %+v", err) @@ -83,6 +85,8 @@ func New(b *beat.Beat, cfg *common.Config) (beat.Beater, error) { func (bt *Functionbeat) Run(b *beat.Beat) error { defer bt.cancel() + bt.log.Warn("Functionbeat is going to be removed in 8.1") + outputName := b.Config.Output.Name() if !isOutputSupported(outputName) { return fmt.Errorf("unsupported output type: %s; supported ones: %+v", outputName, supportedOutputs) @@ -152,11 +156,11 @@ type fnExtraConfig struct { Index fmtstr.EventFormatString `config:"index"` } -func makeClientFactory(log *logp.Logger, pipeline beat.Pipeline, beatInfo beat.Info) func(*common.Config) (core.Client, error) { +func makeClientFactory(log *logp.Logger, pipe beat.Pipeline, beatInfo beat.Info) func(*common.Config) (pipeline.ISyncClient, error) { // Each function has his own client to the publisher pipeline, // publish operation will block the calling thread, when the method unwrap we have received the // ACK for the batch. - return func(cfg *common.Config) (core.Client, error) { + return func(cfg *common.Config) (pipeline.ISyncClient, error) { c := fnExtraConfig{} if err := cfg.Unpack(&c); err != nil { @@ -168,7 +172,7 @@ func makeClientFactory(log *logp.Logger, pipeline beat.Pipeline, beatInfo beat.I return nil, err } - client, err := core.NewSyncClient(log, pipeline, beat.ClientConfig{ + client, err := pipeline.NewSyncClient(log, pipe, beat.ClientConfig{ PublishMode: beat.GuaranteedSend, Processing: beat.ProcessingConfig{ Processor: funcProcessors, diff --git a/x-pack/functionbeat/function/provider/provider.go b/x-pack/functionbeat/function/provider/provider.go index a2198251a07..c08db30e1d4 100644 --- a/x-pack/functionbeat/function/provider/provider.go +++ b/x-pack/functionbeat/function/provider/provider.go @@ -13,16 +13,17 @@ import ( "github.com/elastic/beats/v7/libbeat/common" "github.com/elastic/beats/v7/libbeat/feature" "github.com/elastic/beats/v7/libbeat/logp" + "github.com/elastic/beats/v7/libbeat/publisher/pipeline" "github.com/elastic/beats/v7/x-pack/functionbeat/function/core" "github.com/elastic/beats/v7/x-pack/functionbeat/function/telemetry" ) // Create a new pipeline client based on the function configuration. -type clientFactory func(*common.Config) (core.Client, error) +type clientFactory func(*common.Config) (pipeline.ISyncClient, error) // Function is temporary type Function interface { - Run(context.Context, core.Client, telemetry.T) error + Run(context.Context, pipeline.ISyncClient, telemetry.T) error Name() string } diff --git a/x-pack/functionbeat/function/provider/provider_test.go b/x-pack/functionbeat/function/provider/provider_test.go index e93d8bd5546..6e940ff302b 100644 --- a/x-pack/functionbeat/function/provider/provider_test.go +++ b/x-pack/functionbeat/function/provider/provider_test.go @@ -14,7 +14,7 @@ import ( "github.com/elastic/beats/v7/libbeat/beat" "github.com/elastic/beats/v7/libbeat/common" - "github.com/elastic/beats/v7/x-pack/functionbeat/function/core" + "github.com/elastic/beats/v7/libbeat/publisher/pipeline" "github.com/elastic/beats/v7/x-pack/functionbeat/function/telemetry" ) @@ -22,7 +22,7 @@ type simpleFunction struct { err error } -func (s *simpleFunction) Run(ctx context.Context, client core.Client, _ telemetry.T) error { +func (s *simpleFunction) Run(ctx context.Context, client pipeline.ISyncClient, _ telemetry.T) error { return s.err } @@ -42,7 +42,7 @@ func TestRunnable(t *testing.T) { err := errors.New("oops") runnable := Runnable{ config: common.NewConfig(), - makeClient: func(cfg *common.Config) (core.Client, error) { return nil, err }, + makeClient: func(cfg *common.Config) (pipeline.ISyncClient, error) { return nil, err }, function: &simpleFunction{err: nil}, } @@ -54,7 +54,7 @@ func TestRunnable(t *testing.T) { err := errors.New("function error") runnable := Runnable{ config: common.NewConfig(), - makeClient: func(cfg *common.Config) (core.Client, error) { return &mockClient{}, nil }, + makeClient: func(cfg *common.Config) (pipeline.ISyncClient, error) { return &mockClient{}, nil }, function: &simpleFunction{err: err}, } @@ -65,7 +65,7 @@ func TestRunnable(t *testing.T) { t.Run("when there is no error run and exit normaly", func(t *testing.T) { runnable := Runnable{ config: common.NewConfig(), - makeClient: func(cfg *common.Config) (core.Client, error) { return &mockClient{}, nil }, + makeClient: func(cfg *common.Config) (pipeline.ISyncClient, error) { return &mockClient{}, nil }, function: &simpleFunction{err: nil}, } diff --git a/x-pack/functionbeat/function/provider/registry_test.go b/x-pack/functionbeat/function/provider/registry_test.go index 3e05e43db69..cb24e0f0ca4 100644 --- a/x-pack/functionbeat/function/provider/registry_test.go +++ b/x-pack/functionbeat/function/provider/registry_test.go @@ -15,6 +15,7 @@ import ( "github.com/elastic/beats/v7/libbeat/common" "github.com/elastic/beats/v7/libbeat/feature" "github.com/elastic/beats/v7/libbeat/logp" + "github.com/elastic/beats/v7/libbeat/publisher/pipeline" "github.com/elastic/beats/v7/x-pack/functionbeat/function/core" "github.com/elastic/beats/v7/x-pack/functionbeat/function/telemetry" ) @@ -49,8 +50,10 @@ type mockFunction struct { name string } -func (mf *mockFunction) Run(ctx context.Context, client core.Client, t telemetry.T) error { return nil } -func (mf *mockFunction) Name() string { return mf.name } +func (mf *mockFunction) Run(ctx context.Context, client pipeline.ISyncClient, t telemetry.T) error { + return nil +} +func (mf *mockFunction) Name() string { return mf.name } func testProviderLookup(t *testing.T) { name := "myprovider" diff --git a/x-pack/functionbeat/functionbeat.reference.yml b/x-pack/functionbeat/functionbeat.reference.yml index 4b6dab7943f..090ab1cc877 100644 --- a/x-pack/functionbeat/functionbeat.reference.yml +++ b/x-pack/functionbeat/functionbeat.reference.yml @@ -375,66 +375,6 @@ functionbeat.provider.aws.functions: # length of its retry interval each time, up to this maximum. #max_retry_interval: 30s - # The spool queue will store events in a local spool file, before - # forwarding the events to the outputs. - # Note: the spool queue is deprecated and will be removed in the future. - # Use the disk queue instead. - # - # The spool file is a circular buffer, which blocks once the file/buffer is full. - # Events are put into a write buffer and flushed once the write buffer - # is full or the flush_timeout is triggered. - # Once ACKed by the output, events are removed immediately from the queue, - # making space for new events to be persisted. - #spool: - # The file namespace configures the file path and the file creation settings. - # Once the file exists, the `size`, `page_size` and `prealloc` settings - # will have no more effect. - #file: - # Location of spool file. The default value is ${path.data}/spool.dat. - #path: "${path.data}/spool.dat" - - # Configure file permissions if file is created. The default value is 0600. - #permissions: 0600 - - # File size hint. The spool blocks, once this limit is reached. The default value is 100 MiB. - #size: 100MiB - - # The files page size. A file is split into multiple pages of the same size. The default value is 4KiB. - #page_size: 4KiB - - # If prealloc is set, the required space for the file is reserved using - # truncate. The default value is true. - #prealloc: true - - # Spool writer settings - # Events are serialized into a write buffer. The write buffer is flushed if: - # - The buffer limit has been reached. - # - The configured limit of buffered events is reached. - # - The flush timeout is triggered. - #write: - # Sets the write buffer size. - #buffer_size: 1MiB - - # Maximum duration after which events are flushed if the write buffer - # is not full yet. The default value is 1s. - #flush.timeout: 1s - - # Number of maximum buffered events. The write buffer is flushed once the - # limit is reached. - #flush.events: 16384 - - # Configure the on-disk event encoding. The encoding can be changed - # between restarts. - # Valid encodings are: json, ubjson, and cbor. - #codec: cbor - #read: - # Reader flush timeout, waiting for more events to become available, so - # to fill a complete batch as required by the outputs. - # If flush_timeout is 0, all available events are forwarded to the - # outputs immediately. - # The default value is 0s. - #flush.timeout: 0s - # Sets the maximum number of CPUs that can be executing simultaneously. The # default is the number of logical CPUs available in the system. #max_procs: @@ -751,6 +691,13 @@ output.elasticsearch: # The pin is a base64 encoded string of the SHA-256 fingerprint. #ssl.ca_sha256: "" + # A root CA HEX encoded fingerprint. During the SSL handshake if the + # fingerprint matches the root CA certificate, it will be added to + # the provided list of root CAs (`certificate_authorities`), if the + # list is empty or not defined, the matching certificate will be the + # only one in the list. Then the normal SSL validation happens. + #ssl.ca_trusted_fingerprint: "" + # Enable Kerberos support. Kerberos is automatically enabled if any Kerberos setting is set. #kerberos.enabled: true @@ -883,6 +830,13 @@ output.elasticsearch: # The pin is a base64 encoded string of the SHA-256 fingerprint. #ssl.ca_sha256: "" + # A root CA HEX encoded fingerprint. During the SSL handshake if the + # fingerprint matches the root CA certificate, it will be added to + # the provided list of root CAs (`certificate_authorities`), if the + # list is empty or not defined, the matching certificate will be the + # only one in the list. Then the normal SSL validation happens. + #ssl.ca_trusted_fingerprint: "" + # The number of times to retry publishing an event after a publishing failure. # After the specified number of retries, the events are typically dropped. # Some Beats, such as Filebeat and Winlogbeat, ignore the max_retries setting @@ -999,19 +953,13 @@ output.elasticsearch: # Set to false to disable template loading. #setup.template.enabled: true -# Select the kind of index template. From Elasticsearch 7.8, it is possible to -# use component templates. Available options: legacy, component, index. -# By default functionbeat uses the legacy index templates. -#setup.template.type: legacy - # Template name. By default the template name is "functionbeat-%{[agent.version]}" # The template name and pattern has to be set in case the Elasticsearch index pattern is modified. #setup.template.name: "functionbeat-%{[agent.version]}" -# Template pattern. By default the template pattern is "-%{[agent.version]}-*" to apply to the default index settings. -# The first part is the version of the beat and then -* is used to match all daily indices. +# Template pattern. By default the template pattern is "functionbeat-%{[agent.version]}" to apply to the default index settings. # The template name and pattern has to be set in case the Elasticsearch index pattern is modified. -#setup.template.pattern: "functionbeat-%{[agent.version]}-*" +#setup.template.pattern: "functionbeat-%{[agent.version]}" # Path to fields.yml file to generate the template #setup.template.fields: "${path.config}/fields.yml" @@ -1058,17 +1006,8 @@ setup.template.settings: # output.elasticsearch.index is ignored, and the write alias is used to set the # index name. -# Enable ILM support. Valid values are true, false, and auto. When set to auto -# (the default), the Beat uses index lifecycle management when it connects to a -# cluster that supports ILM; otherwise, it creates daily indices. -#setup.ilm.enabled: auto - -# Set the prefix used in the index lifecycle write alias name. The default alias -# name is 'functionbeat-%{[agent.version]}'. -#setup.ilm.rollover_alias: 'functionbeat' - -# Set the rollover index pattern. The default is "%{now/d}-000001". -#setup.ilm.pattern: "{now/d}-000001" +# Enable ILM support. Valid values are true, false. +#setup.ilm.enabled: true # Set the lifecycle policy name. The default policy name is # 'beatname'. @@ -1166,6 +1105,13 @@ setup.kibana: # The pin is a base64 encoded string of the SHA-256 fingerprint. #ssl.ca_sha256: "" + # A root CA HEX encoded fingerprint. During the SSL handshake if the + # fingerprint matches the root CA certificate, it will be added to + # the provided list of root CAs (`certificate_authorities`), if the + # list is empty or not defined, the matching certificate will be the + # only one in the list. Then the normal SSL validation happens. + #ssl.ca_trusted_fingerprint: "" + # ================================== Logging =================================== @@ -1237,11 +1183,6 @@ logging.files: # file. Defaults to true. # rotateonstartup: true - # Rotated files are either suffixed with a number e.g. functionbeat.1 when - # renamed during rotation. Or when set to date, the date is added to - # the end of the file. On rotation a new file is created, older files are untouched. - #suffix: count - # ============================= X-Pack Monitoring ============================== # Functionbeat can export internal metrics to a central Elasticsearch monitoring # cluster. This requires xpack monitoring to be enabled in Elasticsearch. The @@ -1369,6 +1310,13 @@ logging.files: # The pin is a base64 encoded string of the SHA-256 fingerprint. #ssl.ca_sha256: "" + # A root CA HEX encoded fingerprint. During the SSL handshake if the + # fingerprint matches the root CA certificate, it will be added to + # the provided list of root CAs (`certificate_authorities`), if the + # list is empty or not defined, the matching certificate will be the + # only one in the list. Then the normal SSL validation happens. + #ssl.ca_trusted_fingerprint: "" + # Enable Kerberos support. Kerberos is automatically enabled if any Kerberos setting is set. #kerberos.enabled: true diff --git a/x-pack/functionbeat/include/fields.go b/x-pack/functionbeat/include/fields.go index 080d4f2c5c4..84ea17cc41a 100644 --- a/x-pack/functionbeat/include/fields.go +++ b/x-pack/functionbeat/include/fields.go @@ -19,5 +19,5 @@ func init() { // AssetFieldsYml returns asset data. // This is the base64 encoded zlib format compressed contents of fields.yml. func AssetFieldsYml() string { - return "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" + return "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" } diff --git a/x-pack/functionbeat/manager/beater/functionbeat.go b/x-pack/functionbeat/manager/beater/functionbeat.go index 855cf16c02a..2178228c577 100644 --- a/x-pack/functionbeat/manager/beater/functionbeat.go +++ b/x-pack/functionbeat/manager/beater/functionbeat.go @@ -51,6 +51,8 @@ func (bt *Functionbeat) Run(b *beat.Beat) error { bt.log.Info("Functionbeat is running") defer bt.log.Info("Functionbeat stopped running") + bt.log.Warn("Functionbeat is going to be removed in 8.1") + return nil } diff --git a/x-pack/functionbeat/manager/cmd/root.go b/x-pack/functionbeat/manager/cmd/root.go index ca9e8bda81a..0d63eb391a0 100644 --- a/x-pack/functionbeat/manager/cmd/root.go +++ b/x-pack/functionbeat/manager/cmd/root.go @@ -5,6 +5,7 @@ package cmd import ( + "fmt" "os" "github.com/spf13/cobra" @@ -31,6 +32,8 @@ func init() { RootCmd.RemoveCommand(RootCmd.RunCmd) RootCmd.Run = func(_ *cobra.Command, _ []string) { + fmt.Println("Functionbeat is going to be removed in 8.1") + RootCmd.Usage() os.Exit(1) } diff --git a/x-pack/functionbeat/provider/aws/aws/api_gateway_proxy.go b/x-pack/functionbeat/provider/aws/aws/api_gateway_proxy.go index 6d897b9c893..c8ecfe8786c 100644 --- a/x-pack/functionbeat/provider/aws/aws/api_gateway_proxy.go +++ b/x-pack/functionbeat/provider/aws/aws/api_gateway_proxy.go @@ -16,7 +16,7 @@ import ( "github.com/elastic/beats/v7/libbeat/common/cfgwarn" "github.com/elastic/beats/v7/libbeat/feature" "github.com/elastic/beats/v7/libbeat/logp" - "github.com/elastic/beats/v7/x-pack/functionbeat/function/core" + "github.com/elastic/beats/v7/libbeat/publisher/pipeline" "github.com/elastic/beats/v7/x-pack/functionbeat/function/provider" "github.com/elastic/beats/v7/x-pack/functionbeat/function/telemetry" "github.com/elastic/beats/v7/x-pack/functionbeat/provider/aws/aws/transformer" @@ -45,7 +45,7 @@ func APIGatewayProxyDetails() feature.Details { } // Run starts the lambda function and wait for web triggers. -func (a *APIGatewayProxy) Run(_ context.Context, client core.Client, telemetry telemetry.T) error { +func (a *APIGatewayProxy) Run(_ context.Context, client pipeline.ISyncClient, telemetry telemetry.T) error { telemetry.AddTriggeredFunction() lambda.Start(a.createHandler(client)) @@ -53,7 +53,7 @@ func (a *APIGatewayProxy) Run(_ context.Context, client core.Client, telemetry t } func (a *APIGatewayProxy) createHandler( - client core.Client, + client pipeline.ISyncClient, ) func(request events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error) { return func(request events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error) { a.log.Debugf("The handler receives a new event from the gateway (requestID: %s)", request.RequestContext.RequestID) diff --git a/x-pack/functionbeat/provider/aws/aws/cloudwatch_kinesis.go b/x-pack/functionbeat/provider/aws/aws/cloudwatch_kinesis.go index cb976702ea5..247e239dd49 100644 --- a/x-pack/functionbeat/provider/aws/aws/cloudwatch_kinesis.go +++ b/x-pack/functionbeat/provider/aws/aws/cloudwatch_kinesis.go @@ -15,7 +15,7 @@ import ( "github.com/elastic/beats/v7/libbeat/common" "github.com/elastic/beats/v7/libbeat/feature" "github.com/elastic/beats/v7/libbeat/logp" - "github.com/elastic/beats/v7/x-pack/functionbeat/function/core" + "github.com/elastic/beats/v7/libbeat/publisher/pipeline" "github.com/elastic/beats/v7/x-pack/functionbeat/function/provider" "github.com/elastic/beats/v7/x-pack/functionbeat/function/telemetry" "github.com/elastic/beats/v7/x-pack/functionbeat/provider/aws/aws/transformer" @@ -70,14 +70,14 @@ func CloudwatchKinesisDetails() feature.Details { } // Run starts the lambda function and wait for web triggers. -func (c *CloudwatchKinesis) Run(_ context.Context, client core.Client, t telemetry.T) error { +func (c *CloudwatchKinesis) Run(_ context.Context, client pipeline.ISyncClient, t telemetry.T) error { t.AddTriggeredFunction() lambdarunner.Start(c.createHandler(client)) return nil } -func (c *CloudwatchKinesis) createHandler(client core.Client) func(request events.KinesisEvent) error { +func (c *CloudwatchKinesis) createHandler(client pipeline.ISyncClient) func(request events.KinesisEvent) error { return func(request events.KinesisEvent) error { c.log.Debugf("The handler receives %d events", len(request.Records)) diff --git a/x-pack/functionbeat/provider/aws/aws/cloudwatch_logs.go b/x-pack/functionbeat/provider/aws/aws/cloudwatch_logs.go index ebe379dfe49..7cfaab4fcaf 100644 --- a/x-pack/functionbeat/provider/aws/aws/cloudwatch_logs.go +++ b/x-pack/functionbeat/provider/aws/aws/cloudwatch_logs.go @@ -22,7 +22,7 @@ import ( "github.com/elastic/beats/v7/libbeat/common" "github.com/elastic/beats/v7/libbeat/feature" "github.com/elastic/beats/v7/libbeat/logp" - "github.com/elastic/beats/v7/x-pack/functionbeat/function/core" + "github.com/elastic/beats/v7/libbeat/publisher/pipeline" "github.com/elastic/beats/v7/x-pack/functionbeat/function/provider" "github.com/elastic/beats/v7/x-pack/functionbeat/function/telemetry" "github.com/elastic/beats/v7/x-pack/functionbeat/provider/aws/aws/transformer" @@ -106,7 +106,7 @@ func CloudwatchLogsDetails() feature.Details { } // Run start the AWS lambda handles and will transform any events received to the pipeline. -func (c *CloudwatchLogs) Run(_ context.Context, client core.Client, t telemetry.T) error { +func (c *CloudwatchLogs) Run(_ context.Context, client pipeline.ISyncClient, t telemetry.T) error { t.AddTriggeredFunction() lambdarunner.Start(c.createHandler(client)) @@ -114,7 +114,7 @@ func (c *CloudwatchLogs) Run(_ context.Context, client core.Client, t telemetry. } func (c *CloudwatchLogs) createHandler( - client core.Client, + client pipeline.ISyncClient, ) func(request events.CloudwatchLogsEvent) error { return func(request events.CloudwatchLogsEvent) error { parsedEvent, err := request.AWSLogs.Parse() diff --git a/x-pack/functionbeat/provider/aws/aws/kinesis.go b/x-pack/functionbeat/provider/aws/aws/kinesis.go index 2cdc02d075e..3ff7a6513cf 100644 --- a/x-pack/functionbeat/provider/aws/aws/kinesis.go +++ b/x-pack/functionbeat/provider/aws/aws/kinesis.go @@ -20,7 +20,7 @@ import ( "github.com/elastic/beats/v7/libbeat/common" "github.com/elastic/beats/v7/libbeat/feature" "github.com/elastic/beats/v7/libbeat/logp" - "github.com/elastic/beats/v7/x-pack/functionbeat/function/core" + "github.com/elastic/beats/v7/libbeat/publisher/pipeline" "github.com/elastic/beats/v7/x-pack/functionbeat/function/provider" "github.com/elastic/beats/v7/x-pack/functionbeat/function/telemetry" "github.com/elastic/beats/v7/x-pack/functionbeat/provider/aws/aws/transformer" @@ -135,14 +135,14 @@ func KinesisDetails() feature.Details { } // Run starts the lambda function and wait for web triggers. -func (k *Kinesis) Run(_ context.Context, client core.Client, t telemetry.T) error { +func (k *Kinesis) Run(_ context.Context, client pipeline.ISyncClient, t telemetry.T) error { t.AddTriggeredFunction() lambdarunner.Start(k.createHandler(client)) return nil } -func (k *Kinesis) createHandler(client core.Client) func(request events.KinesisEvent) error { +func (k *Kinesis) createHandler(client pipeline.ISyncClient) func(request events.KinesisEvent) error { return func(request events.KinesisEvent) error { k.log.Debugf("The handler receives %d events", len(request.Records)) diff --git a/x-pack/functionbeat/provider/aws/aws/sqs.go b/x-pack/functionbeat/provider/aws/aws/sqs.go index 4bc1b9593e6..859c726884b 100644 --- a/x-pack/functionbeat/provider/aws/aws/sqs.go +++ b/x-pack/functionbeat/provider/aws/aws/sqs.go @@ -18,7 +18,7 @@ import ( "github.com/elastic/beats/v7/libbeat/common" "github.com/elastic/beats/v7/libbeat/feature" "github.com/elastic/beats/v7/libbeat/logp" - "github.com/elastic/beats/v7/x-pack/functionbeat/function/core" + "github.com/elastic/beats/v7/libbeat/publisher/pipeline" "github.com/elastic/beats/v7/x-pack/functionbeat/function/provider" "github.com/elastic/beats/v7/x-pack/functionbeat/function/telemetry" "github.com/elastic/beats/v7/x-pack/functionbeat/provider/aws/aws/transformer" @@ -68,14 +68,14 @@ func SQSDetails() feature.Details { } // Run starts the lambda function and wait for web triggers. -func (s *SQS) Run(_ context.Context, client core.Client, t telemetry.T) error { +func (s *SQS) Run(_ context.Context, client pipeline.ISyncClient, t telemetry.T) error { t.AddTriggeredFunction() lambdarunner.Start(s.createHandler(client)) return nil } -func (s *SQS) createHandler(client core.Client) func(request events.SQSEvent) error { +func (s *SQS) createHandler(client pipeline.ISyncClient) func(request events.SQSEvent) error { return func(request events.SQSEvent) error { s.log.Debugf("The handler receives %d events", len(request.Records)) diff --git a/x-pack/functionbeat/provider/local/local/local.go b/x-pack/functionbeat/provider/local/local/local.go index d7b76824a94..d0d849688d0 100644 --- a/x-pack/functionbeat/provider/local/local/local.go +++ b/x-pack/functionbeat/provider/local/local/local.go @@ -13,7 +13,7 @@ import ( "github.com/elastic/beats/v7/libbeat/beat" "github.com/elastic/beats/v7/libbeat/common" "github.com/elastic/beats/v7/libbeat/feature" - "github.com/elastic/beats/v7/x-pack/functionbeat/function/core" + "github.com/elastic/beats/v7/libbeat/publisher/pipeline" "github.com/elastic/beats/v7/x-pack/functionbeat/function/provider" "github.com/elastic/beats/v7/x-pack/functionbeat/function/telemetry" ) @@ -44,7 +44,7 @@ func NewStdinFunction( // Run reads events from the STDIN and send them to the publisher pipeline, will stop reading by // either by an external signal to stop or by reaching EOF. When EOF is reached functionbeat will shutdown. -func (s *StdinFunction) Run(ctx context.Context, client core.Client, _ telemetry.T) error { +func (s *StdinFunction) Run(ctx context.Context, client pipeline.ISyncClient, _ telemetry.T) error { errChan := make(chan error) defer close(errChan) lineChan := make(chan string) diff --git a/x-pack/heartbeat/Jenkinsfile.yml b/x-pack/heartbeat/Jenkinsfile.yml index ca184f785f4..96a48489c62 100644 --- a/x-pack/heartbeat/Jenkinsfile.yml +++ b/x-pack/heartbeat/Jenkinsfile.yml @@ -30,7 +30,7 @@ stages: macos: mage: "mage build unitTest" platforms: ## override default label in this specific stage. - - "macosx&&x86_64" + - "orka && darwin && poc" when: ## Override the top-level when. comments: - "/test x-pack/heartbeat for macos" diff --git a/x-pack/heartbeat/heartbeat.reference.yml b/x-pack/heartbeat/heartbeat.reference.yml index 1eb37188303..aca74cd9e63 100644 --- a/x-pack/heartbeat/heartbeat.reference.yml +++ b/x-pack/heartbeat/heartbeat.reference.yml @@ -343,66 +343,6 @@ heartbeat.jobs: # length of its retry interval each time, up to this maximum. #max_retry_interval: 30s - # The spool queue will store events in a local spool file, before - # forwarding the events to the outputs. - # Note: the spool queue is deprecated and will be removed in the future. - # Use the disk queue instead. - # - # The spool file is a circular buffer, which blocks once the file/buffer is full. - # Events are put into a write buffer and flushed once the write buffer - # is full or the flush_timeout is triggered. - # Once ACKed by the output, events are removed immediately from the queue, - # making space for new events to be persisted. - #spool: - # The file namespace configures the file path and the file creation settings. - # Once the file exists, the `size`, `page_size` and `prealloc` settings - # will have no more effect. - #file: - # Location of spool file. The default value is ${path.data}/spool.dat. - #path: "${path.data}/spool.dat" - - # Configure file permissions if file is created. The default value is 0600. - #permissions: 0600 - - # File size hint. The spool blocks, once this limit is reached. The default value is 100 MiB. - #size: 100MiB - - # The files page size. A file is split into multiple pages of the same size. The default value is 4KiB. - #page_size: 4KiB - - # If prealloc is set, the required space for the file is reserved using - # truncate. The default value is true. - #prealloc: true - - # Spool writer settings - # Events are serialized into a write buffer. The write buffer is flushed if: - # - The buffer limit has been reached. - # - The configured limit of buffered events is reached. - # - The flush timeout is triggered. - #write: - # Sets the write buffer size. - #buffer_size: 1MiB - - # Maximum duration after which events are flushed if the write buffer - # is not full yet. The default value is 1s. - #flush.timeout: 1s - - # Number of maximum buffered events. The write buffer is flushed once the - # limit is reached. - #flush.events: 16384 - - # Configure the on-disk event encoding. The encoding can be changed - # between restarts. - # Valid encodings are: json, ubjson, and cbor. - #codec: cbor - #read: - # Reader flush timeout, waiting for more events to become available, so - # to fill a complete batch as required by the outputs. - # If flush_timeout is 0, all available events are forwarded to the - # outputs immediately. - # The default value is 0s. - #flush.timeout: 0s - # Sets the maximum number of CPUs that can be executing simultaneously. The # default is the number of logical CPUs available in the system. #max_procs: @@ -719,6 +659,13 @@ output.elasticsearch: # The pin is a base64 encoded string of the SHA-256 fingerprint. #ssl.ca_sha256: "" + # A root CA HEX encoded fingerprint. During the SSL handshake if the + # fingerprint matches the root CA certificate, it will be added to + # the provided list of root CAs (`certificate_authorities`), if the + # list is empty or not defined, the matching certificate will be the + # only one in the list. Then the normal SSL validation happens. + #ssl.ca_trusted_fingerprint: "" + # Enable Kerberos support. Kerberos is automatically enabled if any Kerberos setting is set. #kerberos.enabled: true @@ -851,6 +798,13 @@ output.elasticsearch: # The pin is a base64 encoded string of the SHA-256 fingerprint. #ssl.ca_sha256: "" + # A root CA HEX encoded fingerprint. During the SSL handshake if the + # fingerprint matches the root CA certificate, it will be added to + # the provided list of root CAs (`certificate_authorities`), if the + # list is empty or not defined, the matching certificate will be the + # only one in the list. Then the normal SSL validation happens. + #ssl.ca_trusted_fingerprint: "" + # The number of times to retry publishing an event after a publishing failure. # After the specified number of retries, the events are typically dropped. # Some Beats, such as Filebeat and Winlogbeat, ignore the max_retries setting @@ -1052,6 +1006,13 @@ output.elasticsearch: # The pin is a base64 encoded string of the SHA-256 fingerprint. #ssl.ca_sha256: "" + # A root CA HEX encoded fingerprint. During the SSL handshake if the + # fingerprint matches the root CA certificate, it will be added to + # the provided list of root CAs (`certificate_authorities`), if the + # list is empty or not defined, the matching certificate will be the + # only one in the list. Then the normal SSL validation happens. + #ssl.ca_trusted_fingerprint: "" + # Enable Kerberos support. Kerberos is automatically enabled if any Kerberos setting is set. #kerberos.enabled: true @@ -1216,6 +1177,13 @@ output.elasticsearch: # The pin is a base64 encoded string of the SHA-256 fingerprint. #ssl.ca_sha256: "" + # A root CA HEX encoded fingerprint. During the SSL handshake if the + # fingerprint matches the root CA certificate, it will be added to + # the provided list of root CAs (`certificate_authorities`), if the + # list is empty or not defined, the matching certificate will be the + # only one in the list. Then the normal SSL validation happens. + #ssl.ca_trusted_fingerprint: "" + # -------------------------------- File Output --------------------------------- #output.file: @@ -1235,7 +1203,7 @@ output.elasticsearch: #path: "/tmp/heartbeat" # Name of the generated files. The default is `heartbeat` and it generates - # files: `heartbeat`, `heartbeat.1`, `heartbeat.2`, etc. + # files: `heartbeat-{datetime}.ndjson`, `heartbeat-{datetime}-1.ndjson`, etc. #filename: heartbeat # Maximum size in kilobytes of each file. When this size is reached, and on @@ -1253,6 +1221,7 @@ output.elasticsearch: # Configure automatic file rotation on every startup. The default is true. #rotate_on_startup: true + # ------------------------------- Console Output ------------------------------- #output.console: # Boolean flag to enable or disable the output module. @@ -1351,19 +1320,13 @@ output.elasticsearch: # Set to false to disable template loading. #setup.template.enabled: true -# Select the kind of index template. From Elasticsearch 7.8, it is possible to -# use component templates. Available options: legacy, component, index. -# By default heartbeat uses the legacy index templates. -#setup.template.type: legacy - # Template name. By default the template name is "heartbeat-%{[agent.version]}" # The template name and pattern has to be set in case the Elasticsearch index pattern is modified. #setup.template.name: "heartbeat-%{[agent.version]}" -# Template pattern. By default the template pattern is "-%{[agent.version]}-*" to apply to the default index settings. -# The first part is the version of the beat and then -* is used to match all daily indices. +# Template pattern. By default the template pattern is "heartbeat-%{[agent.version]}" to apply to the default index settings. # The template name and pattern has to be set in case the Elasticsearch index pattern is modified. -#setup.template.pattern: "heartbeat-%{[agent.version]}-*" +#setup.template.pattern: "heartbeat-%{[agent.version]}" # Path to fields.yml file to generate the template #setup.template.fields: "${path.config}/fields.yml" @@ -1410,17 +1373,8 @@ setup.template.settings: # output.elasticsearch.index is ignored, and the write alias is used to set the # index name. -# Enable ILM support. Valid values are true, false, and auto. When set to auto -# (the default), the Beat uses index lifecycle management when it connects to a -# cluster that supports ILM; otherwise, it creates daily indices. -#setup.ilm.enabled: auto - -# Set the prefix used in the index lifecycle write alias name. The default alias -# name is 'heartbeat-%{[agent.version]}'. -#setup.ilm.rollover_alias: 'heartbeat' - -# Set the rollover index pattern. The default is "%{now/d}-000001". -#setup.ilm.pattern: "{now/d}-000001" +# Enable ILM support. Valid values are true, false. +#setup.ilm.enabled: true # Set the lifecycle policy name. The default policy name is # 'beatname'. @@ -1518,6 +1472,13 @@ setup.kibana: # The pin is a base64 encoded string of the SHA-256 fingerprint. #ssl.ca_sha256: "" + # A root CA HEX encoded fingerprint. During the SSL handshake if the + # fingerprint matches the root CA certificate, it will be added to + # the provided list of root CAs (`certificate_authorities`), if the + # list is empty or not defined, the matching certificate will be the + # only one in the list. Then the normal SSL validation happens. + #ssl.ca_trusted_fingerprint: "" + # ================================== Logging =================================== @@ -1589,11 +1550,6 @@ logging.files: # file. Defaults to true. # rotateonstartup: true - # Rotated files are either suffixed with a number e.g. heartbeat.1 when - # renamed during rotation. Or when set to date, the date is added to - # the end of the file. On rotation a new file is created, older files are untouched. - #suffix: count - # ============================= X-Pack Monitoring ============================== # Heartbeat can export internal metrics to a central Elasticsearch monitoring # cluster. This requires xpack monitoring to be enabled in Elasticsearch. The @@ -1721,6 +1677,13 @@ logging.files: # The pin is a base64 encoded string of the SHA-256 fingerprint. #ssl.ca_sha256: "" + # A root CA HEX encoded fingerprint. During the SSL handshake if the + # fingerprint matches the root CA certificate, it will be added to + # the provided list of root CAs (`certificate_authorities`), if the + # list is empty or not defined, the matching certificate will be the + # only one in the list. Then the normal SSL validation happens. + #ssl.ca_trusted_fingerprint: "" + # Enable Kerberos support. Kerberos is automatically enabled if any Kerberos setting is set. #kerberos.enabled: true diff --git a/x-pack/heartbeat/include/fields.go b/x-pack/heartbeat/include/fields.go index 205ce7d0046..efcd48a2e5e 100644 --- a/x-pack/heartbeat/include/fields.go +++ b/x-pack/heartbeat/include/fields.go @@ -19,5 +19,5 @@ func init() { // AssetFieldsYml returns asset data. // This is the base64 encoded zlib format compressed contents of fields.yml. func AssetFieldsYml() string { - return "eJzsvft7GzeyKPh7/gqsZr+VlUO2SL0sa+/sXkWSE33Hr7HkyZzE84lgN0hi1AQ6AFo0c/b87/uhCkCjH5IpWXTsjO/N8VBkN1BVKBSqCvX4C/n5+O2r81c//h/kVBIhDWEZN8TMuCYTnjOSccVSky97hBuyoJpMmWCKGpaR8ZKYGSNnJxekUPJfLDW97/5CxlSzjEgB398wpbkU5DAZJIN+xm6S7/5C3uSMakZuuOaGzIwp9NH29pSbWTlOUjnfZjnVhqfbLNXESKLL6ZRpQ9IZFVMGX9mhJ5zlmU6++65PrtnyiLBUf0eI4SZnR/aB7wjJmE4VLwyXAr4iz907xL199B0hfSLonB2Rzf9t+JxpQ+fF5neEEJKzG5YfkVQqBn8r9lvJFcuOiFElfmWWBTsiGTX4Z22+zVNq2LYdkyxmTACp2A0ThkjFp1xYEibfwXuEXFp6cw0PZeE99sEomlpST5ScVyP07MQ8pXm+JIoVimkmDBdTmMiNWE3XuWhaliplYf7zSfQC/kZmVBMhPbQ5CeTpIXvc0LxkAHQAppBFmdtp3LBusglX2sD7DbAUSxm/qaAqeMFyLiq43jqa43qRiVSE5jmOoBNcJ/aBzgu76Js7g+FBf7Df39m9HBweDfaPdveSw/3dXzajZc7pmOW6c4FxNeXYcjJ8gR+v8PtrtlxIlXUs9EmpjZzbB7aRJgXlSgccTqggY0ZKuy2MJDTLyJwZSriYSDWndhD7vcOJXMxkmWewFVMpDOWCCKbt0iE4wL72/x3nOa6BJlQxoo20hKLaQxoAOPMEGmUyvWZqRKjIyOj6UI8cOVqU/O8NWhQ5TwG6jSOyMZGyP6Zqo0c2mLix3xRKZmUKv/9PTOA505pO2R0UnlOTzq6kyJdXhn0wHRR9LhXJ5dTRBFjDDesYwVEGf7JPup97RBaGz/nvgQUty9xwtrDbgwtC4Wn7BVOBQHY6bVSZmtKSMJdTTRbczGRpCBXVDqjB0CPSzJhykoSkuMqpFCk1TESbwEgLxJxQMivnVPQVoxkd54zocj6naklktPniHTkvc8OLPOCuCfvAtd39M7asJpyPuWAZ4cJIIkV4urmmP7E8l+RnqfIsWi1Dp3dthpjp+VRIxa7oWN6wIzIc7Oy1V+4F18bi497TgesNnRJG05nHss5uv8bchCy2s/HPmKvolAnkFCfhj8MXUyXL4ojsdPDR5Yzhm2GV3I5ycpYSOraLjBJxYhZ2I1lZaux5N3FLQcXS0pzaDZnndgv2SMYMfpCKyLFm6sYuD7KrtGw2k3alpCKGXjNN5ozqUrG5fcANGx5rblRNuEjzMmPkB0atSABcNZnTJaG5lkSVwr7t5lU6gcMNEE2+d6i6IfXMyssxq0QzcLaFn/Jce95DIqlSCLtPJBLIwhbhp9yQixlTsSCf0aJglgMtsrBTA6og5C0BhOPGiZRGSGPX3CN7RM5xutQqBXKCSMO+tRuxV8GXWFYgTjEZM2qSaP8ev3kJKoo7ROsIuRWnRbFtUeEpS0jFG7EgziTzpAMJDDoH4RPkFq6JPWqJmSlZTmfkt5KVdny91IbNNcn5NSP/SSfXtEfesowjfxRKpkxrLqZ+UdzjukxnVmC/kFNtqJ4RxINcALkdyXAjApM7Dp/QMjdXsMyRLlJpNNWuGZc8zxIvv9zszZ3etddv3e3NHXb2wTCR2RPcTlUj5cTxA66d53Gn66AYt0qPcAMYGXYnFcuO8WAHUlwIVFHCkHZnFEre8Iz1rM6iC5byCU8Jvg26EddBg3OUjSTQnBnFU8tTQWV9mhwkA/KEzrODva0eyfkYfsavfz2gO7vscHI42R1M9geD4Zju7u2xPba/lx1mz9Lx4U46Hg6epgFEi48hO4OdQX+w0x/sk53do+HgaDgg/zEYDAbk3eXJPwOFays8oblmtWVlxYzNmaL5Fc/qi8rccjzCwvo5CM+sRJxwplBacO32zRM+gQMHTiW91VxibpUYNQfF0OvuNFVS24XQhiorPselISPkEJ6NYPvZjddeoUO6Zwk9qRGiif7j8PQ7wX+zmu398Q6alpVIKMfgvQWodGNGQGrxDgZ06GU19Oy/60DQKawgTuMDoLWCmlB8Ck8/1Dim/IaBxkqFew2fdj/PWF5MytzKTCsBHIZhYLOQ5LmT34QLbahInQbbOH60nRjOIMskTnsilfbECqpAMoSxuSaCsQzNz8WMp7P2VEGQp3JuJ7OWVYT3+cTKD3/QAKp4Avmv5MQwQXI2MYTNC7NsL+VEytoq2oVaxypeLos7ls8fbnYCQvMFXWqijf030NZaAXrmWROX1Rli+K5V3pKKNCIc0YGq1bPI4m6iMaseAY2FT2oLX61YkwFqiz+n6cxag20Sx+N4OjvBvQZS/90dCXViN2A6ABeHSndirVXXVNbSSCHnstTkAjSAj6ivx4LQ6hVUGsiT44st3JhOGXWApVIIBr6Cc2GYEsyQN0oamUp/7j85f7NFlCzhNCwUm/APTJNSZAzPaXv6Kpnbwax0k4rMpWJEMLOQ6prIgilqpLL6rTfv2YzmE/sCJVa9yRmh2ZwLro3dmTdel7ZjZXKOijc1xHksEIn5XIoeSXNGVb6sTkCwaQK0MufpEuyIGQOVwSKYfLJ+JMr5OOi1dx2huQzKW22J3FGB4xCa5zIFHdtB2lo+p3aGr8NGcKvrBnpyfPFqi5QweL6sTiKNNlRYEtwr5zV6RCw53B8ePKshLNWUCv47iM2kfbx8ivoA1upVTOVIBHozn9zpBOhYvkr5aVD+dYQJzNLC/kcpLUe+eHES7cg05w1D8qT65g5L8ti9abee506qHTtyw+3OwI3gF8dtSKcJe+DQQlRsSlUGloM1DKTQveh5tBrGHF2vXAqak0kuF0Sx1BrVNb/F5ckbNyqeUxWYLdjsF/bxCDLYjpqJYC/aZy7+6xUpaHrNzBO9lcAs6OoonEBpTYXuRavo1Sb1hq4CzZtpC4czxTyVjKJCUwAmIRdyzoJxVGo0Mg1Tc7LhfaZSbVRuFcUmXnY5UEQDQY0bzv3snAC4smMWjGBwAkQEcJvRgiWmfpmrKWL40Z3hmMhPYM+yUpeWIG7UyvrmwoL3r1LgAoAxjua192h3DFbRV0jTGtKqWbhefdjH3pUYHJA43rafJ7iMYfOg4kazjGg2p8LwFE4C9sE4HY99QO29hyqVlwM6aHpGkhtu0eW/s8qzYhFlCuw5zU1J3XKcT8hSlirMMaF57pnPnw9Whk6lWvbso15F0YbnOWFCl8rpo85PbdWYjGlj2cOS1BJswvM8iDFaFEoWilPD8uUjWNU0yxTTel2WF+wCdK04nnMTOi0piJ/5mE9LWep8iVwO7wRBurDk0nLOwG9Pcq7BmXn+pmeNaDyNpSLUHjMfiJaWfxJC/quieNAaKx0K94eiCw+T3w+jxH0xQpLVdVFBuIlUzaxE3zIelKOEFyMLyihBsEY9krGCicwZA6jJS1EBAX4et5KVrpX82x3nVCf/tid65OVaGqY/ovZHK44+ofprNUB+sD+goy/cu7md6BgBBWl7gQ73aoAhO6/BIHESHcdPanNOmUxSbpZXa3IenFh9vnN1Xlr7gTk3Yw0cKQwXTJirVGbrgOlyIfs5M4bZYyVj9TvRMPum7ob71fF3H2HUbmTWROBXkVcmTNYGWiozI8dzpnhKO4AshVHLK67lumh+glOQ84vXQPQWhCfHt4K1LtZ0IHWu8gkVNGtTCiT8x70GUyavCsnD8Vq/9JJiyk2ZoSqSUwN/tCDY/G+ykcNtav/pbnIw3DvcHfTIRk7NxhHZ20/2B/vPhofkfzZbQD6uWG84OzVTfa9SRD+hMePJ0yPO2YMKppyQqaKizKniZhnrBkuSWh0FNOpIBzjxR39wpSGHc4XKYsrsoefsikkupXJnZw9cRzNeae3VIYvg5aSYLTW3H/zNXepllI5AeCVNFKkA95IcHSxzOOOnTHps2w6nsdRGin6WttamkNrQfF27bPMNDI9ijWotU17d4eHdtwO5QvTvLiag0nrdVUy4dgkXiWNGroVcCGvjUGJRgYmkIr+cvyERTgRYG1TKG6qWZMEzq8nA8eh2NV7gwMc2/Z7tDfYG9xGzik25FOsUYG9hhrvkV/9vJ7fBtSYJ5mDqFGB/K9mYtfnPave/V7rxox6r1vrmc0Z+B3/gpMZwvXB7eX786jh6rhN4d1BtH6spHMt0+4eSCamvjrmKlLCPMAYvPoJleKCGx/mbYK34cxX1pyfnb272LLefv7k52KrrUXOarmM/vzw+6Qam4bwX0oRb1Dl1iujb5yfk6WBvB+6hMSqOZUfkzBoRMjXMkCdgGHPdI4f9Ma90cKvrbuEVqFONXNDVQpJfy6JgKqWa/ZPM2AeasZTPaU4yPuUG7kCsGmUhhWijMKYDHye2AkSQUmg+dcEobMpUQi7KFO6+b9yDLlYJ724QBhpGnC2LGeuQvoNBfzDo75/Bv7v9nd3aSglqkiZndJ6P3dyxeamo0OhJOX9jsXJ+BQxkfHV8GZx05AlLponzP1upXLkOCXqkvGu6dhkaDp3IL0WMonBhIaYklzQjY5pTkcIZOOGKLWieox9QydIejQ1r1yJdSGXuZ+x600cbxbst4JgadvyvhR7o/7qHFVjD+g2+/SCbb6cOR2tNVjFFb1+PN24NYkERz2fPI22YYtlVl7X5eHqiFUozPp0xbaJJPY1w7h4gUhQs8yDrcuyN1LD+z6tbYdT3ouGcX8rqKxsTKRP3XJLK+YYVXxvxF83ragy+dNfQGTNMzUGrLRRLubb6CqhNFH1hEKsDQaflOOcp0eVkwj+EEeGZJzNjiqPtbXwEn0ikmm4l5FItQSxKVLQ+cKtFopI1XhLN50W+JIZeV+uKvrOcagNiFyMvUacS0hBwAS1YngP2ly9Oq/igjVQm5fVGWzBG1KhxRSD7OrkhTAJMH0yGSWm39m8lzfmEV0uK9+cY1xap8HnuWQX0dcI+pKwwVfgZvFbdUbbYPYF7aUoKqgyPHO6kBQEID45z2f9zv6M2U9k1YICUdk3szCkVlced1PmqF1EgxKO2EBqzXC662bx7T9T3TUzbjcVikTCqTTJfuhGQMXBnUG02ott6BMKNMqO6CicFXEH9CNNU2tyGLsc7iS7Hw9rm69WYuAIPDQrn2vXxW9UYGz3cc0JaAc9zuMxlisuOEBiLwKqaoJHFFaDxGaQem0zsIXXD7KyOURz2T9jli9OtHhpTwZKq6B6IhqKj56/lQAhYlvW8Em2SpC0gm/OGYaMAG7tKwAdft2QEqXibUKxWYjXxCN/X+KbUTCXrZZnYf4c3uFLhvaidHEM35gzuBeTktmORCvLi9PgNBIQixqdhqJhXNtvYsTnl+ZqQe2cxgAm8EZO0AbDSs8NA/opuIiyam7o6BsAJRW8oz+k47zBu8zFThpxxoQ1zjFWjCFwz/mFsB7Ovn+8QybUFpLaDMn18MeLn48bg4m27yKmxynUHeyKca3SpxiuBk7WBmFE9WxcnOEqBtLHzoGNOKWatulaENnViSRAqpFjGqTNon0Ss8k4zF9k5Aix4hve28IfFbhRUgFSKCa4VzWtzUpF1aFUQadjBVGsJ8L0lvhdJ1trdF/1hf7+/M+zvDHb2dvaeDXeeHj7t7xw829nbebY32Ovv7O4Pn+0fPD086A8Hg0EbicdzFn5mOXgxs9YnuushG4OLO0lFE3arDFQyb17SPhrLHytFIY0KWBlm8vcV4JesJ1g1gN78deOaj6mgVxC7uNEjG4qB1i2mV3ZATES6g25VbJksEfAQWua/uD2yDFNSCe7OEGkAQ4HBIiaKhty0Cg30o2EMs3cmQCQzuTXLZkJeVlkOXMfh1lSQs5MdtLjsBp0wk86YhruZaHTCjXaJTRWQdnPX8/FqiVVchzDeOghuXFUKlzGl2FyaEPRLZGk0z1g0UxMyhIkSl9LjEfKsI6pX3b1SPXUQB60GgtwlN7l3+Nhhua5AdQSL8nY9cC5aa06XVp5plk/6Lm0TrVd4yqXiJN+jGISvDFVTZpLvCTGyxtxj5jIPMYvMPuVh2tzUEfW9aPUYu8gqObFEqLGIVJasU2mxcCF5ukcU0wXq1fkyIT/JBbthKiKZZkaTDgTcoA005qU126Vx2ZATuGkL91VKSuNAD4MT57SGU8ALA1lRoeKACDWIx0lNSfOwUI7SmK6Gt2J2gTwD+9kaiNgVsyIy5Og6MsaTeTIGolX09Cmq0icgoVPchStiiGdYs/aiYQSRh+0Wiq4AYWtZK9huoWibozqge4RguRQuBdenGG5We9DNBWweBxPxLOShukN/STI+mTAVu6vh9phD9qVVle1R2zdMUGEIEzdcSTGv39NUsvX454swOc96PlAJ5D95/fZHcp5hpiiE0ZZN/aNtuR4cHDx9+vTw8PDZs2ed5FxnSECboF4FoDmn+g5aBhoGGn0aLdH4alEz47rI6TI2RWI/EpaP6GfsZlV3krPteM7N8qp9m/p4iko0D96Wch/eCCclnq2K4Y0LsEx1ChEXjdjSYErdZ1Sb/rB+O+xza9a39c59TtX5qRfJoEL4A78JKO8Pd3b3rKr8bEDHacYmg26I18jdAeY4+60NdXQNDF+2k7geDaKXXueI8rnuJKPZSeYs42Xd5+8OtG/y9lHk7QpCo0HwbxL5MSWyJ+6fSTCvjvbXI7ofgNMfL9xXB/rLF/+r4+JqdH2Wk8HNFcvcLslSkyNvwjs9cvx7qVj0TUfFhmXfTfJAMnweee0JgVFxq5IApWydCN2idb4kDyaDtVZXyZb55Ch2TwmYMPHIx8Wr6EL3CLX49sg0LarbZqkwDo3mMmVUtF2Oi5WjBx3iGMG5JrRdAOejHh73xM8XuPk8/O0R8eUR4nIuGdeGi2nJ9cw/pxtOOqiCVCkr/toGy2+BpuLZpkfYFDSRs5MdcqPJCzofZ7RHfjx5Q348OSM3lYZzXBTkTEy5CHvo7y/tK/Z7V1qnayfSoiDMvWY/O5B7DlNVih6ZUDWlhvVIDtO39yN+v+qS/buL5H93WfwnE8JxUOLXJ2JD8Nw3AfrVCFDnI//m9PhcTo8Gwb85PR7T6eGJ+2/m9HBo/6mcHk2cvgqnhwP6T+H0cLj8u2vYDTL8uyraFRn+TPr26oh/nRr56vh909m/dJ09BMnJjF1pPhXUlL7UuIuWkxkjF7Vfbg+bu5wxzZpVvWtxphB/NuaCqiWmz4dJ9acXDsz4lGlzRfOpVNzM5uvkuRnVM6hD5icLmq/FCBM1sML07WkfNa4MdMDGFBQbfXBNXPJuSBSCylFhSN85wjI9PKmgMKvLHKn4GWlTgdvmFz2jO/sHq25xLLNbp3ArgHYsZc6o6CLiD/gThEHTAsIoOVasdHSwqLus6HZ0qGWDj8R/Rq4DPrX7fI1lmS1DRIHLq3IC7zCXXEV03+WBzKkoJ9T1QBgvLYV8SfwbJjKpkmhMVlXwVixnNxQTZY8Lyzffv76AgLWujJx5YudkyYcitcfxh+XKtDXUlGsrunacZdyVWmxLETjPmTKYLsgcKN00npS5r10/hfJDalkYOVW0mPGUMKWk0lU4ZDzqDc15FpdTkcoKIW38fOQFozeMlCKqJjjxifnwavWK10Kq8cOwC2s7i3TG0uuuUuhnb9++fnv17tXl23cXl2enV29fv75ceY1K7JiypvIYFzh8zdAJoj1odVVBKp4qaXmYnEhVyFqx6I8rFozO17yP7RSPuZlhPKncbnVlef0Wdg02onjTyjlyvz189ref/vHL4cvD47+vTEvfOWgFamYVq9Yodmq3CBUZqXdUqp/sjV5HUOAazrS2XN8Z7Az7A/vf5XDnaDg42h38srKchz3GVmGOO86lzQsj7SEMSxft8469S9JZPV/473bDY3hx9fpt7/mg9FTOfd3FHpJyxqvjvZbJ68ONK0ljT38pc+3aMLhwcQJiBPUCFFItdrnfCQqS7BPp2n3gY2IcWFX1o/+GKcwTp1PKhY6SaGasUiCtih97CjtlMa0R/yOCdhXCVFozaLhOxgWFOf7yjuLF4cF6gVpXOrbVjCrqieP6aDggAxQhYt+EVmIYJl9FjkcZEpWiPmN5EeWiQe4FlhUJQ2uX1SGW1viwm/0RgtDXmUZWEYVn9dhRPqfTtZqksb8BJgv5HwiQZUDsOyJFF2iGTtcEWcVxDi46baQKR33Y7p4+6sd2R0e2pk8UZnXNzWrzrnE5KqSrGljhShR5eV0eGBzdqvB0iocC1xUjtE4/7AMXyRe7E6+0UYzOYwlzajfoRfX1R1ptRaP4HW/oNcNKB1xg5WJ/Zgm2cL18qvGJBQdyZtIZi3yH56LrlfrDVYWqkAYdPRo8BdAtzRNcNusR+pSi+FWXbTOReS6hjdycCsHUERn9d4QweMv/p1/7yn7WzDS+hbogBU3Z/4ySICQ5tAhzCXRRSzk4iENS7YxCP0jlT2HlVH9CtS8nUdGRgSYRYaIT8lKqRtlzxypYGmIiS+HSi7gOrTmh7AjeZiWp3B7ncrpNRZ8LE5q29Y3smxnrh0svamgfZ+3jKvVxlX61bzsYC6nNP8MaHwtyhm9rRlU6q61BKoXmkNVUb04xpuk1NvjKeMo0qjXBE1VnFSiDONe1uhuN913RSHJaMmQO3EU3VsmWotceV2O6G9T/QAaxQ7EPnjUV00ZxX4q+lmrfyftMu+To0AJu9H7UI6Nt+8/39p//1/6zYf/5X/af/8f+8//Zf8iIPAG2qthky0M86o3AAzv6yyjx7Vc1wy1TJzqU1GcixZqRtLKKb2GGackzts2Eb9qKw2yHYbbTUikmzLajcD9VjBrWByolMzPP/9L4hRa8X1Az6xdU0bn+NSbhPx9BF3CbcgVJbJnOUGGu7jhoNipXiN1DUQczM0NJRw2ZQwtAzYRm3r5zNtv7oE++j/QoL7yS96LVEnAkplx8SCiU1bPrXig5Z2bGSviLiQzq1I7ikZlJkflqnAugQbDAgoOKZrAdF3yfYTPgmVVyHcWIZiYedcFCjwYUu+83wPTi6fuNUJzBvwtPJGSEOdju25EzN+JRYcbgZ8SBqSajDrk6St6LH9hSgiXTYOR4yI4jI1XcMMWpRdJq/vZ4xYzXUYAN555RHW2DeNiYMY/eC0K+Jy997qvng1F/hL+8klD3DVVnQYaDQSTNN5rnc7zGq1pO4Vh5LM4+xnR6Xxs4jJ+A3gkfgyXh2kBQkICwL7mYxsRyJ1HyXry0qr0dWROaK0azpY+jYa4isBfG2DqNLr2xitxU2zJdeoCQC3+B4sYYM21IYYnNU4a1bh05E2LBiYdEyKAAkTft4tK54LkbubdHiesXFlohW6MK2lBCW4t4XHvSQLeD8O7tzFs/Q+q8Go/p2HYUliZmWtBmKvl9B7fGQ34i41ZtXFd2pawWZLAKx24eCyJvmLIkBNm7LFhNEDl+ietS4+mUL5F1WRbfz27kcqo3gPk2sEGk3kjIz4ywDwVLsT2KPfhplpENo+x+2Agjw1t6KcyM2XXdqBrHUEUmpSlVx8W2nXA1h0DU8KSmsDe+vkNhjx6tFE70ljQVROYbdddbHAXosT/MNtbgTOomP/geq1Y1WLGh1j2n54p3Wg3Fm3kQwuZ6oCBH2gWNmtbSzg5CfmE7cIt68nysGw+ew5PQK564G49b+s1EE4CamkGJP9QuNbQzjzvtYVMVN+rYd6oB55GoY6xvm9CToU5Mv13ihkq1tu7Aq2Fs73d2lz/1wsgAb9zzF2qqwAEpup/zVAhYYnXxQOmvqu1OrZvQSr13wrZ3ve0fqfdOGBZ68OBO/NZ751vvnX+v3jvxdvTFmEEy/nENeOID5lsXHvOtC8+3LjzfuvB868LzrQtPQPRbF55vXXi+deG5swtPrNd9Ga14Ioi+9eP5Avrx8AIcxxGffKQJDat1nykUv7GC9/TlL1td/Weq0pRfVAse6PkSRdY4TCHepqKNkXaxLCVOGeQ+PD6G62iqcw9j7vN11qnte/IFtdfJWnbmtx4733rsfOux863HzrceO9967HzrsfOtx86jAfGtx863Hjvfeux867HzrcfOtx47HXB+IT12shzPXR/v9OIF/Hl3YsIqlQLA5Z7zsaKKM02ypaBzdKJ4gkqaoSdN+sRMuNlwP0NYoyyYck0/QEZqjKe20mFDzyg0zK3Ns4FKYZU8DwaNNwTGPjzfWQDM4HjaxVoGW8qnJhx5aL4np4hAP+fi2s23JE9GSZbnoy2SyvkcUgvAQSQF+ZmLTC509f4FgvsaM26fjBItu957J/iHPiizLdxbsNTAWOZ83DXgnKavLz49WKheZiL5Vq/h89VraJD+Kyrf0ID8WzWH9VVzaJL6W3GHL764Q3PJ/jy1HhqYfSv98HilH5qk/bNVgmji960wxJoKQzQI/a1OxC10stpnMs/21yS9Xp7u4xT3gkfP6HBNAF38dDx8GESVSrsGmHb2Dx4G1b679l4LVPvDnYdApTPGVpHYD4Lq4vTs7M39oFqTylHz7zpbtXkA45GS50syp4XuqiAAxhkUeNTX7c18zZRg+e5O4h0ZK6BbULMuR+bzMs8RYjtJC/cG8CdH752f4P0F2Pi7O+8fhBBLIEfPsDSUelxDOY4370g8je946n3aFu0Wih8O9u6BhT04qViuCQFMRoG4U5imxWY9n+eaEWrgKZ6zPtTMeVT9uGBJBNi6sW2EPz8A2Tc0jhH/OHJ2+KsbpvRnwM5N80DMDpLd5NnBYJAMn+4N9++BIp8X67wPOcZbkFCLqJDKuB4Hb85wp5FjQRwUpN+HQBF4jERwEfuLu0L3ds6EiylTheLClXOF3K0bJgidGKaIYkgxl8fo+x9YfbEPeFZ6mqJCB/NfY6kBmUKFiqznUt0WGGUBGa1YY8QoWlXBsNBjinBdx1MCH6amViljwhVjSxAUWDfFzBSjpq+YK5SxMxjubQ+G20ZhJZL+nObWaOsjcfrOmQiVMjoCMdODw8Fuusee7ewM7YcspfvPDnYpzXYPsmxyDwZxHavzK9gMa7y6CzvhU6TZxZvj81eXydk/zu6BorOD142Xm+ZT8NsI4vr9h+Mz75yHz6+Dmx2P4I27CRDuTQQadP7e5NUF/HnHvclzvDFxCR92wtNXF+S3ksEGhDo7Qi+YqjaC/d21Q3fWIuOwF0OQM7htxTRnYawlKRSXcEMyZQbwcsO6QZ+MMqGhuNIRPD/aInh+L/0k8egQTuAT0vEe1N34mJCki9OGHHeNsS+0FlfmYECbdsHQiYJrF7I4YJw2lPjqaOsxMp5rlFi5SFqrKAKFu7sokZ4K9waG/NB05uYimmEmvGKmVCK6pva3Cc1S4pczRiBm4ZotHb2qZGO/MEh/zdys9Vzq8ZKcnVxU7ui3LJUqc2OBjAbJGntu5xU6+KOfXJCFfevs5MIN38w9smtseQ/LQUDgMYTUM/ilXvjAPud5nBwbMueCz8t5z30ZxvVIQSmoiN+wlszIAgep+C00uK4iXnrWoAhDQihhCgcqB8+cxYhqUkit+RijSDIoPGH1wqjMhy+7JiM2bgFKNUlLbaQvi9bM5nY4pzldW7o9FtOnmHoRFsRXrKtqkPkGAnDMq7b37vxVJ+h2tHXpOr7SXSwaMfbUB7LXNwejsOekz6DDVwsmMu0jaqBSCUgrT5J4QI976/gfDhL/XycV1pmxeFmPqLQcF3V/aIBOCqYgdjeizTm4wcANKSfk5NXxyzMCtXpc3TSZ31itLBJOm5saa92MIhFjouILUjCUGhCKowtpSRyuY6JBYF8m5DzIKiGNj5psjun0IjL6rWQ6ZPqP7LHDosoW0bJACPEtUeN+aYxZJX7wttSKkBMGWS83cK9lRTcgDBToXAXv7qXpLJbsbAKCqVYlguuUqoxlCfmFKemr4szBXTpzcR8oQysCjiuq4RQd+fndjLrGTkOXs6rL0ANlDPBmDe4ZoxlTV5OcTtd3aekDbnaIy6q3YhJnJjBzraFHwVJTK190RI6Pe+TypEfenvbI2+MeOT7tkZPTHjl93eFk/nXj7elGj2y8PfaxOLcVz33UpbE4YZpRfB1GtQttcFpHoeRU0TmyXrjVqQw7SDVgCmuxxANB/caCV2VEUCzoDst6Zzis94GURUfS66Mj78JmpMALLFSgsOyyuwK65gJyfVBvramyhMyZ1nTKkjiAhGsIFXK0cwLM+GtBHAZVY6AMRDTFY95Ko7+9O3v7XzUaBZn42XQF5bRDPCfQHPmoWlAT3es8EeEobIAWn3jBWexKRvqUFiFFH1wcVhWM67w+wdyW3R2oF2QhIMOdg604VUTq2huVEI9zS6kmTKe0sHuKakaGA58TqsmT96enp1uVAv4DTa+JzqmeOUPvt1JCVZYwshsqIZd0rHskpUpxOmXOanBlWHMeVQ2aMJbFI0BVVeXyGN+bHnmv8K33AviPuXvE+52uYZ3/8Ly9b7l6X1KuXuCLz5y0x2tOBYfhXZl2LWHxFeWWLRaLbqJ/SyRDEfgtkex+iWQVA30e88BZSXdrFsfHx/WSSt5UvfqUmgfHLQ9dnpPzN1aRY9BZcRR7NkYNF4P/ceQ9fY53+GTC0zIHB1KpWY+MWUpLHbzSN1RxZpbeNIo5dU6NtiZhVNQ6IWcfDBTRDfBF1RE9oGbGFMNCt0InEXFGlc4K5bC5Cd4sCGeDkrdmxuZQzSQaGvUCfAl+Z1RzCKoPI95wXdKc/86cumI13InsaHm9+etG5DSx9k7157Bp+Hg9+HOYAX6u7io4r15D4GYNujVuis14VwSvvg+SynqOwlYjBcarH1tLWaqomHl0KwDBY1N+w7R9KL5P6MEXcYwZVoMP42ZCh1EmCFvzYmBVKCoAvJff3QHUgGjML4UvDlow5fB/Igv0uuZLO4SWMpwozlbDbbGVkGOREeo8NGHMVn1bu6luv53wfnxrxTlh0OLv4PANzRPT2r3P2cnH7n1eMkP7sZPa9wByXuhP753ZedEeBfAo9lvJFYuH+SRmPju5CLfucLAFumM/CCMTMmKpTtxDI8zj9GBUUhFUJZBFpTbYlhKuuPPcsVbEgT/PmMC1hIVNldSRBucrnPf7zmnqLjQsQBAGnPPpzORRS/vK01NhA+9H+UE5M9iLdqrcDTfN/mVB9XVW0hmb0wb9SS1zq4OlhskgGcQclU9qHPXiOfkJnFIfYazOPKwXXJQfyNkHlpZo+r7g4ho+PMc6S0/OXjzfghZVUD7+k5nvM8Qd+d7mtdgjR2RLre64o8OD/uqhR+OlYVdSra+T9Q9Lw4hmv5XQCkRObgf8BTcmZ+RMZJyuHnBflFdrPL9O3ryrdZa/FfhzYdjKUWtwInAprqLA9IfErzstimUYux6UoFAiyYK6qSumJ+dWXFDjEsDCxuUm7vClfEhBBhcbVnHz1QUn9Bp9qS64BFGRSq8ccck+QETPClhPcmoMq26O6zU6OUaj43AsIyxn85D2iKHny4KtDhe6wxM65muO3/p7PWzLctRxlG31A4Z/QwzIhKaMPDn+4Xzrvmis04mKMrp+wdjcF6vCucbbVeg4hkdBBKSb955gMmHUMq4X+2gl2hwxqwk+laKur916eXhzY/BhiK15wq2mB7g6+FcGWV/RMV8TqB/fW57iqEG8vrgvxdd4/DjuuOsEWhXKzy7U7rnTXKTnY50LONwjnAsujGkVwASLMrYeFDrlY6Zaax1OamtPf0p8lC7HfdRmw5DgRRaMmhkZsXySeIyT70erb+XwUjrjq6SddAjJWt+HuhY24339W+kyEMd0zHNulpDarvi4jEnm4Lj38oKIl8UqAfj3Av1iRoWQgrjhSUrztHQRxkFNezDQ6wwbsMx34fgRdpWLFLgvjGu8KG2BGNcqXh1CX2/8Sk4mq/XzexRgcbZPAFfz31eh7H2aZrSADLXY7WT3h3WNZ2MLVDvU/SG84cqUNL9avSfQvfS7FpRuvnpFtocA/PDVfwC091z9qT1yP9eRCZP90UcmYnzPI9O9dA8V46EbxVHNEysw071hXfOGbsB5vy0NdYauQkWkNYHpNUxXhakq9ARpRhAqxXWEzMrwG5ZP1phZ5YcnejkfS5eAZLfRihZFcOAo5brreb9t+GLl2llURLkWrtgJXEYsIUYtbN532BV2jtsdn3PB/EXBoKdYzsiEGWzT6K91oEBeSjW6uVQchosee240yydRHWCBoz9CpsWaulsAkTGwrxEsjoDXbalsDRDcXtKxAwIXTPgRMLor3nXg7WMT6/vd0PT6CrplrrBlFjzPUhpw/sy1+S6xekUKTSZ9a2aukXSWW4scUj3YB1NH8jMFLIRl7MXBJVjrA/x8cQoaVv2ODJbgBf8XvaFJTsU0eVXm+RsJQeVn/vFYiNz4mygvRMIXdwsRt4FrrThdKhVUzPhgbinMVDWLB34yiqc1YVB1j7ePEmhQ5Do06lZDzUYLUejPWDXpRuFURXy8kEE0wX2fb8AdKh5SEzIeIGJGTKsxSOjbLScREm48PxT1ZX4sl0ExRGKxh6rsvajFqQuQxsCU0E7BjenTmCCGJ24Y0MMWk36QVArhlMQxMwsGleSiPp603vETJ+OCG+x1ZJcql9riduxX4uPkxl79fvdKBf0doQlNTuaM6lKBn0eHDs9tykaPwXWHodcs8HBM5pg9KhrP2VxCliHTdhg/XFZR2vVXveFBIhk2h6jsUrGEXLg++a51uT3pRog2xyQud6vsvUD1vvlhC8eJZQ5SKEpkqGncvX7S9WbaztB/nNoY0GwTMfRxID7C3NX8jFT3uFEYZoTHWW8ieoucG8tGwBpVpMGMCk/vlBo2lRDe4ccPi24FyQgI1adZ5prh2/3Uh/3E4CurJPUxmiMbYYKAD5MPIwoLXJ4vYwPCJbKjI5J1xBKVmql+QbW2xOxjyml9MaZMmCueXa25ut0Ud5DdXB4PF06E94pS+XJNXvsYAWgJz6qgLAwhcG36XfCp66SKzZ8jVY1Dq2h/SXNTLzlVb0qE/XoktHibWR0k9UxQL5FsqqbCrslwCGvAaLbKinN1ARSb5NCFe8aILE0q/VFHTQBJ3tb/wdV5AjJsbupYOHIdw+rb58wvX1x4IRVGdACnTEVNm+2456chkXjKsLRaJdDgcSvJuNYldoqu7nTrq+M5VXjKu8g+VyvKV6JqVveyC1gb0advWX0I6et2V4NFj0KRKwyCybIqcwZ7dYdhocrCglsDvGpLhqUXGq3UK9sdKlDXorSwd75bKyjkyZRlDEcWdx0ehSiPGZFzbgxrdDnu6N9+VD0wqtDqu4jJQOKI8ZFA0CElTqcicuwyxqJjlwCXRJEp1WRzrmGgj0yWSaYhbjYsS2Peitbx/HfOq7mYumldDTwh2/PHEtgur1uC2P0ysrNc+Vmubhu6BguYcMja7vl4m1d0C9odbo7z07Zs9eu1qhXuT4n1nHxYeNHx+USWCqKwTnBO3zUZ6yVgsCoPARuxuMDwPxcc7tbADuSBJzPOFFXpLK461TwGKxMcRc3GmE/JuIRWWxsQqVONyJmuB6hH0j43TDmFszHFkTtER2Tp9PUQ4EagwL0LGHePVeuaGn7DzdLlooWKsqA2wpkUGpe5Ge2ijHzhFV/aksatRXU59mA1FYwwvg+MdPNCODpIAwthwVSgxu+h1b0Ovd51JCepsZwFSxMi9SJKtoMta0faR/wJj3fenztbPo3SBkNRCpTS9nyDiFWovRxRLmpy74sflJoFvT1julZa1FnwmpQi6njfI4pNqcryePVBAYeniTUlS/tBKmLRAx8wRCKiri9vmAJFH2oC+SPZG9dc144uV/sETc1OWbF3sHdYJz4qex+RBbeFZ2263YCD1M91+852veyoa/hPLUOqqCikYhTrLgsUc2CNjZcYl1zwguVcsFt5Gut/p65v3v8OZVNRbFATf1W103Ww1ugH0LIQchZuL0MESFN7Pxdkbq0izU2JYaQ952k3C0nCtG6jjVlHsCpq2f7PNE4Lr5V28teqaGBlLIf8dLRN4/htl/Hr7hIaikjNcoRlgVfxbIE1CeX6M8KNkxINSOZScCOrShnVEFY7lNWK2T/9TbaR5JqxgpQF6ojwUry56lRNqXbegzodreKOOy6leS9e2Ybm1M5m2BkMD/qD/f7O7uXg8Giwf7S7lxzuP/2lnsdgz+bWDenjV0x00zRKPIgaRTBLCRJLsbaWtfSgbINzaeVyasntjhts7UnT2jmTy2nPueByOd3qxZPHBZLRnFy64wVrQ1SiLq6UbzdFDDYsOtQVm4PMhrr5VlPzMeEwvDUxa3ODty2Um5jLrMwr1sceR9ipwVdkz6TpVXpuPEzHYVPQdMaSiBZheUu1SvP0jivFxptcFKW5CtERVEhXUsK74EoTP0D1S57nvPMZzFUDHhl2Ms6pm7oWfU4gqy5MW+cklFNIdbvn8W8mMthAmM9nqvy5WoWQLlnkBQ3MLjLvjbFrylvdl5hYpQjCbUdKBWrrNGkeJMhv9uD033u1KgBuzxpIv5Nj8Nhldd/zGi+jfqJ6Rp4UTM1ooe3m0wauo6oKfRCWp+jCnWQGwo8ppnhF7ve5FNooiz54bSFlwWqOTaYf7uzu7R88PXw26Pp0/MPJaQ31dd6gnJ9abLxXK/Z7NWA+pHuT/cEgq0MmpqxdGHx1neQynAnYAsRLVaoUv2HBokuZMIrmrjKLkaqlYYBu4Tt/gDIwqg6cWBdv8KVXF/JlqJiYOElZncS5lq3Ra9pUPMGcuaLzvvY22vr2vLYARee7O8s1XXS6G8+F83vZ3YV+V2uGaV3OrcYgJLG4gbXTC5qCO3t9stdMSSFzOa11/LFHjbz2GbZcH9VoRf5XE7nqG7/co5XO7P1kOBiuXnL+mjeF0Rdm5/p6CA8ydNG/jjl6dqC+H6V5PQSF3rzaEP8cg1K7kNCYzG5fdlcpUWobthCA6u263syq24J2fiZvtaC8i9v20Jwp4xUZ2Au1C4qG+8o5miZtx2fV8AHTw2bY6lZjYRiAoFZ0MTrgyIyKDBJCLmdsCUlmC2sqQ9Mfv00VszjDfVH1JaoZQBAl8wprbmAU2OkzlhcYU6ONZYbFjIH7L5SGSuUcfUCEGkiom5Y5VaFmVWU6Kqtcdag8loI11q/pVGtTZHGWqFobVBECXJqaosszdeYDGCgoq8oCS+A6toKGy9ZEhqHRosjLKWgCbU9KlehKYScIrz2jPnwMqiCcv1s9v29w5FGjlEPNFKxug+HGxT5/m55Zo7qX/feie528b63sZh9M8BFYrhWGq7DJ3jkuv1U5iNklxIdgwU/7nB/4iStnpoucYz1RbqyFFjt1CqqM3rKcHG8Wr9z3CFB5IhVRDNLSbzXTrU0AT7gWI5lMryoHtBUHVvcJCVlYJI1g6V+WVdvK2hcu2R4AMYqzG2+tj65w9UdwL1NqBj2GsOekvGFK8cwxK42Si30+vQe3R4qcWQtUM0ZGz1FcQbLNsmB65MX06MyqljxFGMlb5tTmjpPsghVk+IwMDo92Do6GA7xLPTl7fjT4v/4y3Nn7vy9YWtqFw78IVj6eU0GnTOF3w8Q9Ohy4D5WSa0WdLkEMYbdzbWRRsMy/gP+rVfrX4SCx/39IMm3+upMMk51kRxfmr8Od3Z3vImI0Aj3CUnWdse5C6Ys+Zq0h+dBT1uE38hU+Miakyy8MMhzPzsjdTP2CQGBBZT1Tnlv9LbiWCqZ8AadwkgoDHhN7ZmN9ZLzhaSlzr6RxRdBcrztXLxhqd9NwQ+f18Ky2r1FuYs3IhgpgTy3fgiU656pTvEGYnj0Cne8StQNeeYciBCPQj+2hKAL8XiWnWG8DjsNClt5yJU8Cbu4eBgtXoqYSBq2K/qBy6nAEr0fVGLKKjg1dZoIfAjULO3ok7HSo5oBHlJUjNM/jBV5pWW/i1HS3sHE5iOelAn6qyCJcEV53xoETEYr8Wj1fa5m6cBNch1uUL1OTwlVPDjt4RYJJI2bIcoafFWKAwyXEkdWtRr34iKFiGZQ3OHE41CENV83R7d11tTqaCd1xqDqy1kSMKyi9rgzuzYtQ+6Jrn6E7HXYVKiq+Ps/FUjsfXNv7/kJOI2/zHNXGmopRFdzwJmpIRnZGcxySFjqU3VHX0W0WOJIvlnpu9dSZMUW2BR517HRWjl2ogr+HbvQiDSM+wXYlvaofRt+h2PfHVf+4tEakmG7d1r2ltoyKUb2+jM23MDpZzJZx6QofZtYWUm3Hc0cwjh0N6Gb1IJ6CUu5Eq6WoY/AQ5VOL1wnj/gwqmA8jgLdHdZnihgzyw11NuVeQbqMKtOrony2rXmIW+RD01eijThZsTKDrpKuIJRrwREPa3Zsxwd2xY3U9KwSDMRPOhgZ4QYzW1hmBRKYcjXMJwRiaGzbqYJpLKODl2tCRUoRL/rra/1G7X7G6C3MNzOYmIO/eviA5F9e+NNjd/TM9Xza5zo+C7Yoh1I2ncehciKdFQXEcWcy9oPTUStBHToIjMA/tQa0Ynq5zKeA2E47ccCMK9Gyviu/SgQIirpW3DXNs/2UwAF/jysvD9fWVjnTE27TGSS5pZ9T0W66vCYwA9qHiUnGsztUUhNrJKqJlDomUOirf+U4zd3sGqMH9lbvrQ13A7tzkFtivhFSrdEe+FYnNV+CL47+zDIb9CEI9jMPUKYUr4IDEwPLMcDDo8F/OKXcNo12j/KUsYd3rN0ruREBJAvWEdQSQrl8g2iEWzh9pDSTqXIqABlLN1fABLQkbXDfuCHy5lBWod6/0rs0LX4cFE1ZvO9IhWr3xKFQyQvj9zRtmR7XiAHpwDUqv69XP2QeaGgKVZlwNe6cTRQEBcTiAh626www3QS1q3bDIrL/HrdUdlIISvBhgHCao75/agXnXhe3Pocp5MBbCiHE19KjWHj7l75V8fEVslHvppBN3yVgW/uCOQk3DSkDAspuVO59CKoXm2sR6t+PM2NVoQuPvrpYETscL+IyZJTP0axrlcppo+D3xvyepzNgo8cLXf10dr7E3v8oQwhxpN0VLUandCqNUm3DFFjSP3I3npxdbIRq19kZQvx1bE240kQsRZsRibvZ8r6q0hXFTWWCA7+3oRmFKAeH2KfK0ztOGqlUSke++J8RLyI/eFLoQ5/iuMOIIvDOs4lJuuSy0+/R3KdZYSPBuI7WGkt0QleCwKxwQQkebS8BwMNd1kVwxmnmdzB3WntGrC5/omMQN6JmjimeNLfo0ZQUWowmT+tqYUGGf2u0vBZh+56du8o2zUsmCbR/PtWEqo/ONqFw3HY8Vu0Eb1z9+cbmxhSYn+emno/m8Eiac5v6p/mD/aDDY2GqI0Xam0RfmpTIzrh4Y8wjhgXUHVCOUb0OX4z4GP27ASd9DlsJAwujsIJUi3wqojGJydY8wYddbRxGSTq5mEGAgI8cXIgV1cwtllxSUTufU8SVJm1HonzF20fmVoHBKnWtKtUr3kQcxTtN0EDA2NEbzGpkE4cYFRLbfMG341GNX9/CsYFUIDDl3Q+O9ABf9jBVm1hodjyR36Vc5e/A+W8QJfq7eqQDDkxQ5Tdmt9sktdkm15T/JPpkvOywUmGJ7f+fpMGPZuD/ZHw/6ezvDw/7h08mgv0fTvcOnA7p7OGF3Wy+eHyaU1sqEPqf0Y3VCrR5RaqZ8Ul+IjOhO5JuUAq15ql2mWZRuBe7Seif6hsfh03J782zVk/mOduG+W7hPyYDVhxs/mMHFDoFfxSN7j/J6LC3bMVyPmjQa5oiyU5DxTbU64aFWWAudPMv2Kd3r04PD/f5euj/p052dcX9vb29yOBjvpunO4aroGsWn05U8n7dXmjitZdTVWMwNv3oKv3veOYWu1trwpiK+mzb4onr+DrPnTWNm0ttDou6L3RpzkjcuI3RCe+U2T70XXX2K3ov3QVa+J+R7EH3vhf1UlGNdjvEzhEeC8o9/W41M4Uc4Aza6JOiK4o+7oAIv/vzfd2Q1H2Pb7EYKLDTeacWjQHaxJmNrFtaD012Wrv0VYvV9XiqU5EO574+/59BX3BU7cVZndGEC+g1cwfoDyif++r+pyLalqpAltSjbnuskE27nxkuc8txfwJOXVZTDr8/PX/7TdzrVVYqvE+x6K8GX3eHg7joaabDgJIYuASxDajbwCedDFYXmLnQeJVUWY8I/wV7bfEFdtJoLXssxMcoP3Xmv6S/AqiXWGEYOLYDhAME7uI4wVGqwdNrayqRUXcdwPcJ8sVUUvnTl+UBrvaFqaXmmyKmxvJ+Qn5jCcHnobsQ+zGip4fIwd7VYUAbUlVirLAUHOY/zQF3t5hvWg5tU6A2Q9UjGFUuNVEuruqdqWZg4sAJlD+uRGc8yJnqQloH/SpEve05x7JGF4qbj4m7z1w3/7EaPbODTvk/AKnlpMmNXmk8FJpNnfGoPGJpbld7MVnG0PrwrEXaOJmGyKjCeT9EQcxcQtzcgiePZAhbaX817Aeh6tQW7A8ztMKRvHAveKPukgnAX18Ok8pshbSpwO25RZ3Rn/+CBpMdUqI+Yyiuof1HAKoe7Rz8DZK+ipdo6tDetJHoo09hPXEzXp5ZsNprmrconUa5FyBgDmR4Vb51TUU5oGuoF0OrS94aJTKqk5pkMhnFsCxwXlqu+f30BnSG6OsfMEzsnSz4UaQIXgg8l9XoT9e++RqulcBMEpZvkkxJb7ORyOrVbHMSenCpazHjqKy4Fh0c8KmT6NoLpjCq18fORF4zeMFKKyknHfbMYfLV6xRsR1fiVt4VqUgqXpt5eMehmcvXu1eXbdxeXZ6dXb1+/vnzokpVYOrldsPJRHGEXOHwtbAEyLlGUNRELYQXkRKpC1tJr7ouZYXS+5k1vp3jMnQ/jSeW2tgvO8PvdaYtJtdHDoPfc8Gd/++kfvxy+PDz++0NJ6x3Cn6D8ndr9BMmHtXzQwBx4KNiNEAJbMMcITsv2EbEz2Bn2B/a/y+HO0XBwtDtYPSegiZ/dnyuptneceJsXRvpYjlhGdOx77OMcccnf6zVBbpMXrv+z70ss53hwQGQLpHVGycC1WwRoEVS7SrBqhpS5rkJHbli+xEoZqICggGureJ9yNoNQ/EQyd2sWePU45QbqeEY6hi+N4It/RPozI2Osle4SGaIF6RTrtLYWH5HZ96RTVw72/YwrMCB90w20hla1pyD1CZmt9n7dmkqjPKPHMv8qi8kZq1gZA6sDdRuE+Fvo2Q/DuAVE06os4P5vNLdTjdxVAbd7hWkyAiyiUCeXlY0J95ZNTKV/20d7RHORhuH8LYSH2+9SqC3ZyCOOa2Q9euMHGDz4guvBhAGglkmQ0TqI3hpcF5R+/DgFwZlBuQTRFbeVj2vGZYrfRMHb0NLbXVdFV0gtDLdncs62ae4pHzC1w13hMJ+KbCdznyqw1bH1+B3Y1i+0QDD7s7zSMoWPJO1Me4ry3IuCqZRqhgdA7doXDtc8BJLEDdpXlUosnyR/jg5QFpOvvQuUxeGr7AQFgP87d4PKJ8mX2hHKwvYn6QoVofLFd4aKYP3Su0NFoH4NHaIicL+mLlEx2F9pp6gIhS+8W1QE6ZfeMcqC+qV2jYr7KK0A3L9z56jai19Z96ga7F9TB6ka4F9wF6kanF9sJ6kalF9HN6lukL/cjlI1eL/YrlI1KL+WzlKdQH+53aXifkuf6Wj9WjtM1V78CrpM1eD9gjtNAZxfebcpi8MX3nEqjmo2TKzTUoUbojBLj7APaV5m/tIxZxQ+Z/KOAiPBpQ0X/DOqo/QJP7AmT3zwvaEqmf6+1QM/dxgTZoOKjCJ2ZocM+icb0983euDN3sARNjryxAsnf0NUqlTXHWENjxiPAlO4Qv8+MgWuq5pxpXFAamDZgP5rgbZ1D4p8uVsbP3QIKYArueZErdHDoG4W4uJsab6gSw0LRI1dWkdtmMaHHMOQ1hYEboCmNs1GLHDiXWu4coaQsDoery6fX/R8HWpCBc3lVJYu1YQc55DJYhg6oi6MYnROnhyfXmz1Qh1ity3CqK4WIzwKvWHCFcq/SijDkucsI//n6fHlcUJ+kYIl51VABlYem0uX8FzLhfe1OYx0oaOhfF0mFyKXNIvrPYNTRDADNbePTy/gks3X8qio7u7apJofkdHJ0fuCmtl7I99bmEG7DrviSMs5uwpMOkIKjBrfhpHdnV5VjcZvlKryQvVWgm1b6hOOmgXuojetWIqhaL3UfLh6AOJRKu4o85xYpF3nmMR+HvXwWjW+igLG6y7VGy9iZB1+RFpO1xbq80bxOVVLjJOGPMUfz0+37rxX3RwOBsP67W8VZb1uCONYq07o2reh9pBK5tn+muB7ebqPU7Qn1TM6XNOsFz8dD++YtoqFXcPEO/sHd0y9P1zF3/PAqfeHO7dOrTPG1sWEFxenZ2dvoqlX2LRcrK/Rw7kdu0p/9WoNnh6V5uLTRJo7eGf/YPdwt76H53zO1nnd+vL85Rl6sn0ARBwdiLZmvLOJVP5olJOaN4KQEhrI+DTIxWKRcCpoItV0G8t5gMGxPWcZp33w88afkw8zM89/PT9+dRwdbhOecpqjV/ifPRfV4K9cE/Kz1Qg76tJbVQCvGcY569XSm7FVQqgjG6Ee+h2tyErz9XHSS8tIMdm5IDI1NK+4i3Ym/W0ODvYGDRb6xKCpjpipEOxEoSwpRLfVN/8ateBXjcPGHfKhT2tlXfjawRiZ5+KAWiTzlkJTm5cLsbY4DUwNsxNsgsKtYj/oHaem1W0eD6TP3Jz1udfU4sC5XmP5gmnXEZVVM9+yKNrpflFZ27eteME+R6zRyZt39TgjQ9WUmSoNszPWaPVAowIyzgsq1hVSh4YJVG+HaVrqX8+nD0Isowtr6WM8aAOvTwq/L1gSAbZubKNvH4jsG1rFLayCnB1+zbEDAbub+j3xPTE7SHaTZweDQTJ8ujfcvweKfF6s0TO2eYzOMIeUu8WG+ubkzRnuNGtdOyhIvw8d8eCxuC0Hsb80irtHPTQwiJszLENB6MRAkjhSzJWyUK7VYiozhhXyK2mmqNAhu0hjcVXfs8H3X1i4tgdUTH3dNEWDawagx+zMegi5cuoRNTXFbMIVY0ssTTHO5XQbaz33rWphZdP2zmC4tz0YboOfgotp34We9ZE4fZermFidrW1PD9KDw8Fuusee7ewM7YcspfvPDnYpzXYPsmxyDwbxES1XsBnWqFaEnfAp0uzizfH5q8vk7B9n90DRpdmsGy83zafgtxHE9fsPx2fenwWfX4cCrheYcrsqAe5/A9bhUraD2G0NBknNQRgFN6OSgE4irFTENdmwf260WXh4sHu4VwMUj+mrr1oFu0RVA5QwKH20nENlns/WDB9WC4yuJ8h7GVdQUMFBstXiuVD9IJRCWmu1D6iQc35KnrwDj5uqKndGWXdPLhruONTlV3HKfdgfPEuoc0vzGxRpa7/VcjmR0bwu5OrJxfGrrQRtKjCyQ1mAriRRWpoZVgSlIqulIsGSjktTOb/dZS85f+NvypnukdNXFyTGmJAn0ImE51lKVaadW57NKc+r99qE/T5h2PYgSeXK97RAe+jhrBKEc50Hiie+qyMFYvfJySvgGwsE5AFHJAzEbWHr2qeDl4/8xKczcqx1qahIGblg6oYpcnL8MCKUwqwt9aYiAMxCnpxsYcfSJn7vLh4CfFTqgGXrXMjTeCK3jqcPWceTv7676JHXf/XreS7SHnn97q9WI4uKhfXIyau/3rHmYet80trnMqV5q5zroy++n8bLmxdbLaXJsoeVFH/nbPEQTKSaUuHq7a0Zm3gqTZ68/oTNfC7ST0WW5lel4OtSHLtwpjmxM1rU3z0A9wajPwR/bSjkUF2B0rq+2urh6LTzYTFsnC8cnJc9cgGqy5sWS5/QnE+kEpzeC0UhzRUYjyvgdJu39pLPwdpDq7GZvQ0dkECXBlNUaJ4xhcW9eDvDfWewM+gPnvaHB2SwezTcP9p99h+DwdFgcG+ssMXTOtHCmrkroDR81h8cAkrDo73B0c7+A1CCEsbp1TVbrr0y0HGrGJAvToDlHgASO3IL1bcX9zsXIqTSUt2sa2NdYhXDGxaFVjHC8tw+kLqfKrSi8kKQuBoOP66jQkn+PqdFBMG1KfZ3hg+lBPtQSMHum23UyBfEIcICZgxc143lC3U6VsDqYH9/96mn+qqdsh6A/Sfa5lDf3lrmzlKKVlUXNEWLnZu2er8z2Fu5NCXArJniNL+qRfc/NuO6trI4VVWuX5cVF3efgtAEJVSBT5dRc8ZJ3AAZ1r6YUVcPv0d4HOSKDkIf4CXB1MqtFmLtpZCFHYZOZxSyVFWbuvv7z3/44dnJ09OzH54Pnh0Onp0Od05Oju8nLUKFi7VLwCi4amIJGZdcCmU2IinxM6s6geOddCAKHt0T6OnFBflRkhdUTMkJVGNyQZ/LhFwwFrylU25m5RgcpVOZUzHdnsrtcS7H21M5TIZ721ql21jOadsSBv5JpvIvL3Z3n/Zf7O7vtuiPwRr9+8pnZ8T/MZarDqarB6OJFUbOJtNcjmketDzBVr7waCD5R1imn2iYeuC/BMu0VZ3MuYCwr98tpunF5V8r1bVHXvz1ggry3BqdXKcyMl171nxJwFB93HX/YqzSGuYPQuWPNktv26i1JfxkzL4AG7SB6P1w+TPbk+5Od71qUZRgbCd1ekqL63bvhjzErDLcbK6u84/uzzvKOv/IpC9anEJ3H6WWLiYeyjTSKtgLKuBYWBXDiloQJO4hrbUuAGV8ymR4Ja7/6DsIMWzljxHbLJ2Bglg1ZrSQnb/x2p5U7vZY9XVZFDkPJbs+qVQ+N8t1VVI88QKyfc8phVGM1vsqYosIJsxV2gqMexR4Lhey76obpa1AyzD7pu6G+dXK2laFyJoI+6pWmtJN1gZYKjMjx2AL0AaAoLZccS3XResTpxmdX7wGYrcVhuNOkNbFig6czpU9oYI2qor5bfsRUKZMXsXFROoSW4opN2WGNSNzauCP9lXUf5ONXIqNI9J/upscDPcOdwc9spFTs3FE9vaT/cH+s+Eh+Z/6NeA6s4TeWRnj0x4bUUs0kKbn68xhUxw5IVNFRZnTWut2M2NLK1MZStPoav3EG6aNHrFcofRNoTOa7uEdaS6lcjZzL5i97U6iCF5eJS+jutoDOYcnZT0zrMqIQfcKF9bwlnMQ75H8bl/wj6U2UvSztLYuhdSG5uvaVZtvYHgUX82ULVgLD26tMCf0XWg0LYoaKoeWqGNGroVcuJYtFhWYSCryy/mb2MDBFopVFfgFz1i+xIPM20TQ9Ac+tmn3bG+wt7LHVLGpVULWKKzewgx3yar+3066YFqTtHLwdAqrv5VszOo8193S7XGOTNfZkfzu2oLFTNYLmsr58avj6LlOwN1BtH2spnDk0u0fSiakvjrmin2kJW47I8nrd+GLu/sWYZqRU/OsNOroXgjP6KopQaOm4eO2KMrknPK1pcnGCkIIXIe/kBDQJHTOXG/RuHt7rd2yIC9Oj9/Y/X+MTeCrYpgIf5wOFxJk1hVd4/ynvO7Oq5CSmCGD2THboSvF5zo2Y5oDQMl39VymmG9/8n/fYZj4lg6ebStOjVqPcrPg2j0XfJhxC1I8URuhndDEL3gzlXfU2VGY6w5DXp7u9yAhbYtgSR7mVIKEHGeZB2oSGsFgeKobYrwkuVyAS9kH5tdBxBOfeg8r1lHAxsGaFVRBeUI3Mq2fXk+0oNfYU61HsDnyjO5e7Q93tgKCVc53dc5pZkJ6chtpeDgqS11CZ56bYPZSoiB01uo5TEC/WQwWJGegYvSDlegG9LLxX3TXBQUjBYJUhh5zWZXYhSBCdm+4pVw6U5M8MTl66gvWI4rZybDe9dYjGIGfO43y82dQ/jHJk39M3uQXkjIZRJ90Fcu96PN/39lqC/paNVtt4c117vanFRtcaENF1O747OQC3k2+9xKqswut1ZfbralgUimq7ed1GGhFNaNFwQTLwMcGqm4VTDBnVJcKa9EtqIYmkiIBXF1YZD0FaUZVtqCK9UJtnTlWENY9cirTa4yuMJQLMIHsxv/Pcgzp/NAFOQuFGT9l39+erPQoymMV0u3qSMTzdVVDvjqoR0ynRZmUmk5XObKhn3x2dXuX+jdMWZMS0qfgDMDVg4iW0Pjd3cNWbdft09A9vmb5cIOngeu9ja3rIzXqIqW5xXtCrbZkKVTrax9pWUfwByVmIWEe4MFefKtb8S902rlhik69olGZ2e513QvdyAcA6TAYXxphuophWtUEy7i+ThSjWRJn7D70St9IU12A+yxg8mRKyynbgk5d9vBMmdaT0hrmT+h0qtg06i5AkO40zwE0veUq3IeyLNgzjqQyz+9ZcQ9Qxd5g68fVzmOY+CPR/Xx2CFoMchKJTS/lvTFymyVSVZPHnZHGW8IOsrmpb7NRwohSkVfM/HD++qJmvcBMWCm2PXYFdDRTGBGsI5f8ojqK1L9+dfn64vWqSzFlMvmC3PEAzp/FJV9H5gt1yyOQX5xrPgbrC3HPW5C+eBe9BfKbm/7LdNPbtfnmqn90V70l65foro/g+jJc9hagP7/bvu4EWBPlN39yY8daWrSpzo0z8KqcQk0WMycVRx6yEfgD7V5RzJRKaO9PBh3VWecfcXU/Dj7Oz426cdxA7FgHOqLZanyRxBJe6VnZ6Push2uMOaOCi+mkzK3UXMpSESZuuJJQTika/swvuYuwVxhz7qzN0ZhRgxX3mlQoPkIFXnThCb4RXjSTNINPkqbrYhby8vgknjZQwCIupHE127F2FQjKt89PyNPB3g70Pi6nU6hVfETOaDojMjXMkCeujVmPHPbHvEqstvbeFna7dJqt8zIsJPk1RF3/k8zYB5qxlM9pjk0ANZnyG+87hzWtDBnkc5yYQjO3UriWzFwYNmUqIRdoUvIb9yBeeznfuuvMG0acLYsZ6zg8N3/dGAz6g0F//wz+3e3v7G70SOvLPd8g+/Z7lsdZvld37nOI33Jpw7DDo90d7ep3gn9wLimvt4Dh/VtJcyhFFcaM7ETw+lHUgJyrv/IXldqSHNIVrHKniF3KDPo1WVO3vnxG2ucbm8i17k/YFGqCP4br4TanA1whyRI8nTTP/dTAOtBEpdXJG0TRo7kcGqgWNL1mK5UIXw1ZN94Xhy4X61taxVIGoYQe6S8E13WvbcD7D8JX6mRC5zxfV7j56wuC45MnXmdTLJtR0yMZG3MqemSiGBvrrEcW6CBrF8DAJ1twl3n+eFB/5jIkrZsFlND1SnChIpXzLXW7vmhqqfxS/ovetNb2minBHpFKd+OAswWwwbBTdOEaNbQg30v2kkF/ONzpu/voJvSP63v4MlY4rsjoCHXbkv6jSQ8fEfK51tPP5/ZuyoSRukfKcSlMedd+pWrBW/t1jTV1Nt9plIYjN8/IeRugP7VhU6n47/iEbCLJhZGVYloZm2MlaQYmFVNQgRXkGG8UV/KPa0YmMs/lwo7sDJh6UVXyxMeTsK0jkmPx+TlNgaKCf6hyIhettrPnCNLrC2v9bG5CTw+8nwNnjDOlXBxGzvH+jdXbj9snxpUOF66SE/ImZ1RDIUlSanDK2LNGFsz3KYEUT5zq7OSiZ6laKFlIzQg3kU/MFa5va+GA5j2OpPVW/Gvx+aoCazhIhnvJsAZtm6sfx064dL31GjbCc6nISS7LLNza+AslzMiAq3zXyhcqEuX8mpGR2UnmLOPlfJRYZrqZV9zWvjIK9/Y9bE0T7rB8Bb84E6QyzsOIXUZ63VYoixUr8t6mVF2wVIpMVwrRjGoyZkwQjFqrL9vuzn4czmFMLQLzp8vLN/D37eEcz338WkiasS9hx37Ibw7yp1S5lz2amdBEwiNlLS2VexGj2G8l048Qi+kHGsts+RD1/KO9tS7i6nIN8AnM2iT64eHT20F01ZNXANKXxfpjzvBLZ1njct+J708szyVZSOWaPbTwXsOqXMLVvL5rbZ5YYMGBjj0vO07r4d5u91KtLQ5289j5+5qhsNAFq0ZrcOwrF0KYy6n20SFhLdOcQwMRi6OGclBQ3hRKilLfFio8bVeUZ1WYJEo6vI4hQoq+NlRkVGUIBhKt8jeP/tF/i5D1z0+rRiFS2V9OHKBcCvtrR0XFnV22t3/wtM8On437w51st0/39g/6ezsHB8O94dO9ewS0+EWaMzOTa1uo2lrgVHd1w1cMPFfc2PMIomJDL5fQlxfDz+vREaMfzy5H1ZE0mjLju6L8yC5H4Piz1nGzuI3XtOp3TG3Cv3l9cdlNvTU3F9h8yV1ZwaBW2v3YlP8RRUPU1LyEUL58WQ/8G1ON3gJ/UkcN42IBVVHTKn7u+dEJvtC/BB3ZtcElJ3JeUOWtznkMMg2DWvUvUhrCbJubmsTDulG9QjJjeeE89xkzLHU9IRSjRpMQek3InOtUigmfQvcpt6nbK8nndMq2p3zlArqexopNmFJrywF+64avWDHeOi2Z62trjHM5jeuBbTdg14UUmn32cx2nXfVgj4H8Wk/2uzC+/Wj3mH/us91B+7DD3QH9R4s+B8bjyb5oCR9R+LlRO6Qf/vIQ8VeTdWFUp7w8isxzxNWGmlJ3RDF8eovV+r7BibqDGfYG9Zjo9Rr3ANdtjrUhGO9VIyTnY4+twfPal3fn5IUB4rw8X+NMsVQqq1jCRQLW9MWP9XlJzZyGAt2Kuebw4yW2iUXWcGlNE67YguZ5jyhZQuuPXFK7OXIqUqa2wqjVNvkQtkkYa0ZFBh4kGu4cUimEuz4g5Ny9TrXdCm5MSqxSl0fDVCRA4PxYmgktFdxqEF1QAS0Ot3BPx3D4i5YOUnSkPXy6pUxzTtdVazqwDs6Cdx3VSlapfb2OYDC/qpUXxbLs3Lc5Qh0XSMxBB+4RWRr3QZFs/ru1jiASrVoSQeddbiz34qrSZG1mYEWv89MmsWpsX1Hr4tXLN639Q8j5acfJt7IptcYQx/N4LdjtHNFuyWRmH4G/KvQwjeXXC/fnHblJp620IbDJ7EmWy+kUTiiWzqjgem6Zy38JJrWFPqoRA0Z5lapkBWC1Wh9NV2pN58b1MjS1ZgKEtm5btdrPH6Ux1+1IvdS5nIaJxiw60iA/k4wsuPhY8v2ohoh/q+qMJp0fE5KnXI/YOoZWvbBIsCwe//tgy45LQxR1TlMyQpi/H0E6pXDe1LOTC0e+R0iICv0/16XVtVpYWYJDAwCwepBWqWV2a/o3bjTDhr2rx9VKva2qrT+puIEsqBabmwYzcDDjJMDXI5mE9QpdVe/yGGzfULWdy+n2pBTQCUQnfqOtIFHi7jaPeivw2ntRLFYhHtovQ72AU6CN41wZU8rdHmhHIDeUAlMLGuWzG6YgoNk0Ss7C6S1cbvJUQmIgsj0MghcMsG/cvJlkuCq4sZb27UpBX8oSvHFFaeLdFva6lUoeGAK9D1HRuMCt7n/ainPX5Jz5lUSRNFpQJUY9MmJK2f/h8E+la9C8w1vHlHL+iUjUTpsehEeLdo0DQHEid9Lbs9C1ckTdzJfJLXUJQijeWPEoaU61D+DighvuUgSrGUB3cJYKJWmpjZx3RxlINfX9JrA/UjKW0mijaJH84D/ViIUOP+jgleS8GSR87xAaO0QUR1NrxEi58Pab4zkIl0DMneMxzkVr7JcGqns7t+KxzmSIJg88Fnbh+66KAv7qOBQTcf3fa5Id4wLBDZ8afK+arPsVOy7IhKofdXuDBb5J/kVvaCfRS5GusXhki+RuOrsr0NndovJHeIf7QpAhlR3E1ArwY+/426B00m7ODIWclViWuzSV6AxE6TnnJmaLG07dMOHGXzNG3j4/0WR/b2fPIr07PNhLOuBPJjTlOTfLZB2uhM0IQ1f5mfgJW8cbYEtvKM/pOI8VgePU2tuwU2SElbW7LVq3ZCRT4QOOq7TjMKR9d2e3zbg7u3fSaI1SIqKUPan76BFbmVgNPCCF6WkXLoXiUq1WhPZ+S91YZj9Pm6EfuMSsGpJrcki+r4jzH0FZSMKIcJSGQub2fQV9Ggj7ULDU3fX7gGzquKeRn/5s2HHTt7vfRdYAwP230Ud3TFCSVt4xNdXZHS1QoB4aG0YCI9YWq8o9zYkrSQNUajqrzk8vtnqxYmg1uxbwbmdOpSW8s5f8j6PkTtCtngmHmdczLbDacJGaSJ21+qbVeGSBil9ewZ3KAm3yhm7ZCUpryTtlQljwdWsOfzQzhAnrmQIrMQH4J2/hgMiu+AMXP4Kite5nzkxoRJDHPplX0VcfKZcV4r9rhWPQkTufl8IZAWiByxumnIZCqyo1EI7gx4kLv+iau8NHuj+kzIwf3QdAuWGbSaJUODXpEQq9VAbQurYRdNKPaiVHU2IXRHXDU9BsQ9SKczLES4685B3pgXZPkE+3M6YNOX+je+AQ1724Qr0Gc2zBlW91sdWI0kOV3enbyBURkHYrVXBuhpIDYYyaq6wdk1GhpWuLHGEzZj6mo9KRKoIt2LiikiXlCK65Rx0j9Vxc4oSmbCzl9SgOBRiZhVVd1agRaoLoRzeEYxZXvjEyVGzDrOPfSqaWXEzbe5byeY27Oi5wW3b9fS5vN/H2Fm9tsbkxUwod/WNptxSU+GjEJp1PyAjZBG+URxgBY1nGGh/W9vffK5c83SMjv4/dT6jF8Iqaupx3HFYHhzUCOOFillfrDPrynai9K1VA1r9Hzm4LLBCHO4NqsmB57uRfwKdQ0shU5lUafV00Rm2EiJEy79OpkNrYQ9GHdhnpeb2S/5O8HnLd3Tk66oViGSTn05nZDsTr8wyK6HXog0ez1/+hX+399B8vf9x/+V/bh7Nz9Y83v6V7v/zt98Ffa0sRWGMNfqaNUz+4Vwz81jSKTiY8Td6Lt75zDAvhVVSxo/eCvA/EeU++9xeb7wUh37ubTfzMxViWIsM/ZGmiv7jrxOxe+uD/ikcm35NSAHO/F+8FCOU5LQoreEBMae/YtQeeM4DmUnAjlS+5wj6YXjxkh8e3CkyDkjiaQIUNS5UbzhY9V9MxZK5q8n7DI7wRDy0Veb/hsN9I7oTXk1oqUjDF58ww1YI/Htujcjf8NcCbyxomqtGjEzlcpo0eeb8RFg3+Cou24bD1yxYRInkvKvdS7RXnYEqV1DBrgIjAFNA0HkP9uEY3VAwp9ArD2hsNBcgbYWYhYQk1qBzu0jtMkqDXi+Za1oZFMCtMwuS1Gd2m6JjL56bHg/rR/MVIBMRlFWMfRdS7zJBJmcO35xdv7AEeD/n3N6/CiRri/ZONttcJaFkTIxOpFlRlLLv6lOz2qnUx3sFETsjoJ3crUCj5oR09NXy2kwyTYVL3qnIq6Hq7ckBpiDf+sHiFNv4TL8gXi0ViYUikmm5TrfkU8hT0tj9e+ghc+4vkw8zM863KHLlwxwooIblrcuLf0m7xac6nwh1ooBu/YuZ5LhcYtgyfXHZBGBeinVG7L116QRdO7dZ4dUILsRKJb/c/vgopsYKp+KKXZpk7gV3ij+V8r47c5FS4h2NncbW3IH5GMDW3fPb3F8evkMN+63PR/w2/MBSvh7kmrvRAQo5zq+RFdeUQHn93aKdNeAZkhc/ukhFgj2Bq3ONaXSIMCXBoJjJ36Q0yABYNghTtzj0c7CTD3wgTKS10mbsQDSMjMY8RMA1L+BfGrnvkZ66YnlF1nWwFgn8sCMMikDjs1rRjgObtUIxauE5rd68cZRFhsEZnyGtn2SMytwVd3IrOPUNj1ogI1ImY8hsmXDIeFpSGjCJnOlR1rPyma6LzI0Ru/8wnvAZ2Z1L7XQZPl3HjM9kfYt64dzsMnOqXDhPH/xiG9MZOt5GzU4879CJ5DXr1pouWe31xTl7KjOWoqS3irLrjyJ3wgi6ZCgAl3RY6WM+jHhllQo/ANTDSerY+ozjkxYWwa38Hvw6KXbitGQouVApBD8JmuNCG0SxSVv8T54l3XSglU8UG5UDbJ2VW9IhJix7hxc1Bn6fzokeYSZOtddHPpA3yrSkzdAVec0c28lliKbCHdIgarxaapT1S8DmQZV1EsVPXqPI1H2F/hsMr3LC7UeBp56d+HX93V3HzKDizWeEcvIE0FDLp2dOqRO+7VB1u3IyBdVN1hjYsNT0/PgaoYBTgR0fs1zVoZ33bIwbro+h6b7uQ8xwiX3xNcxyUipRhySSHKhh9IdG4FcFvJFGlWJ0ARMuJsdMlvnBZs8a6vzfRPfCtWvsKrGUujCq1cy/jQbtdKMAXxvWFobwqWrkX3MCom7phY5D+f/bev6mNnNkX//++ChXn1iXZr21sfiVQ9dS9DpAN9RBCMNnds8spI8/Itg5jyavRAN5b971/S92SRuMxxNieLMl6z3N2wYyl7pam1d3q/nQwI+QZJDIF27s0tJFq++KjL1r4H7ny8PszuFmgSfLExYLV4S45mvcJFb6GA6SOfKZ+X6QuJxT3Rprb3U/IG7iwo2KGh+JRg3xkKUDE/ZmxDAcmJ1dnANEPXctTH2kcKwmIZHloxw/jO30ohvGOvFLRyQMS5U6OOiu4DWFhzvxiXp171y2IFRlKdKPy/HuI0AfJ5OhBG/EAkok/MIxWxA0BGIzhEFpiEhrvT1zxgws0EtLBUgKqRoUImB/X1dxOu1RTRQXu3gpKC4yjPF1aQAJ8jxAMxBIyr/K3YF9eII11KcGz/aWSDH/42oISx99nsUGJoe/ZjAtZ+M6tuRJTZTje1UUkrBZ2iLzulsCHyJ7g7jEdDGUX+Q0gVQxyG4tnhe2RdWovFWrkxEba8zPo+OPvNfLhskbO2MA8YRy9aYFeZL2ER10cZv7m7OumBuumBuumBuumBuumBuumBuumBuumBuumBvPhMEz1NCjaufml4AojGc7frzyU4QML32ssw6Fbr4MZy+AilIT4w0czyix/7+EMx9H3HM8o8PDDBDQcV98wosFFJEdh0s9iEY0cKYLiqFOnhdVWpWgGRDH8oF+JZhx//H1uSS6WAJgn+OXQY7NP8Yo63RSa3JQp8JJaN72Z2hsrbHqzOr/4KEcXeHItXe4+PAjLYwEKMBlKy/DEc6m1RbC1IMc2Nxv6efaev+X0N49mrhEkU3gIL+PLCiLVgAr+17RLeNonQoaACZDnzFjM4hB63dKVsL4mbDTWMxy5VhfSZjs/FxZi3ZbD/uFlNG1Yt+VYt+VYt+VYt+VYt+X4XtpyjJWMs2geHOJFA3l2hkcMmikS022L7O7xAZjiNKm2AsYFxuxkNuxVNN0ra18yLGL/5m7TkOENBWTgjVw9cdGcV7Y9KBkr5q5SXGVNPtJkzNLGLLQvV/ukQkx5Z/QB9Fecwn/G8B8wwOAHmSQMAMIwOmd+ypPcZtT+F4JTOb6tiGUVKGG/wMDzbbjOZESFngpvz3x/V0Ka32rB2ZljOUVDlmqoX4DvumzT6c+/2n/FpgIGFUSKobPtCqV865rCrE7HjaiAXrCK0EiTbOzO+OWACXi3Wr3Yvjj1qhAL8D08JlVqQpzZQsOqYb8R7lo9pmlrXi0fJVmqmaoyjFS4j7fTPZe8TFVlPX+5PHPEGcE7UdutswzN1e6Sq9AxWUy4cME7zqPFVSw8jE+gu615X/N9C7U89BZKhBMalR2q26zH6mgZzG2yBM57VWdsMAWh/T6CRtlYIcJqvOpLhV5OXTNBhS5rRAI52Tobz7DaLerivDw7jfit3mA3n1VNFPjPVWtYH8NSXR/LuB7F0f3cZqfnp0I/xfVam58XW5Q9LxMV0h6eou6NR8sLK07Na6MEA3QZIUc0hrBFIrO4LzMRq0l5x+VfeZq/R18zf8BPff4V7KNwHFc6wIQyegIsRnSqgjvZHJAokqMxFS5aJpXNXClYm1PZHiEYUuoR/IcsGQNMFFWKCjQW+jwxQoVxoJubCw5yEbMHcMoEPOgCjJ6MnJ9VYDtXdj31ZWYzLj21JI3SYbE6cr51ECjcaS58lzu6hU3svdJOfvY83Rbik8Pz9siBszftdMxjeWP0u4wZrwPGXwkYf8fR4u9bS6w4VPwdx4nXQeJ1kHiuCumXHiEOITDogIUn/UXw0ZMHfG4tPn6+g3WYapokLPaFvm5WR9+pdiOkBLQnZKmVhnJfyzNEUREFx0rK/wpHhVxkP7QlBMe0Nbf5WJBoCl1eosDMWyokpqIh1yzSmapKadi1KkxVWvWHt/vd/SL6QC/jSVxxvG6zbd+lmasJ6slQMR2t8dslf83dbvGfBPggHhPKaDmuSedDGysMBBbCMwCWc0PMAIDs7/bfsLcHcbzf6jUP3r7ttbYZazabvYO3B/v7b/ffvGk1o3jeFz8asug2zao6247s8CVhOQ7BY7ljCqFUZx3J+297O9sHMT14e7DDdnabBwfRm/gtjfei3kF0sFu8ngkmr4ij42JlCOCnFbWDp/zTmAkPyazkQNER3JskVAwyiEpKu6VSSI7dUizhtJewLdbv84jnVe8kxxwoepYozm4aycrO+VMRw9KIARnK+5BhaFngV9RW+2UpU3UoR6mRQSJ7NCnJBT+exQibx1OOqZ5p9l0ZhQgYYDPpK0ou4RETaWW20RkOb5tL5THTkDL3sgd6wphU1BgPStuzAmSKFgaOGDr7So5I5+L4N+KmO+OpNiJQoc2RpryXsBxCLx3HDwCfZ4dMt16X9Ux7TKMh8wNvN5oV+gczj4hginznyKJhXl2/rAuqhyjJwrrx0oYKe09lqdqCrb91xJKEqq2B3Go1WtuNg+n+wIC+XlnA/oMcGZIxCuYnC69IvGUD9itPc1PFdyslTzSg8LC60ugys5nmPW+MwTMH189qTuF2TKHpbvkc2d7eaX0z58iFpsu2ACQ+Wv/A2aHhFsOebJMxq7kOdHpIi4/gpVZ+BQFxCQ9Gc0jUeFQj8fh2UCM9xe5rRJgPBmxUIyKDj/+bqvI7r8Zz39BUa4m5BS3OEnaD3W4chE5B0R84IR+gl+8iHsGv6AeSC6m02frk5IFFGf746uLktW/l812Y20cXXwrTEE3VgGkfJoYuTyXze393buuxEL6vpJBEQNEnTFPIoMDWgBZcNyZUw1M8YdD1rxzY4ZGSRuuRI6nGUhWhrL7CZvVWpWc1LpuXz+T0gobV2V/hzIxdsVvlWZvym57J1n5jp3Gw32w2Wm92W3vz8sdH4yFNK2uqmUPjg3MzAgR8xLa/OLE92NrCUUHqdWggCo+RgC5i/mJzzl3iQp+LAVNjxYUmPS4Abxsupgnta6agTbURl+9zgU1JIxmzetjGkligT+fOpmRIoUghypQyVjsapwhDGA3h7gzQ87Wi3h0G6jHC9lWo/fv7+0afK8YmDPD2e4kcbOmhYlTXFcMmhFvbzdbuVrO1pRWNbrkY1Ec0MfZIHYVTNxNyMWgM9SgpH1TNaP9tcyfaZQfb2y3zQxzRvYP9HUrjnf04nrvfuuuj0YXXoOqSOCPIZTRY56J9en7VOPntZF7+qk2m9EzNyqh8JnMbXj9fP7RP3CkMP09f5G08zX3Ae+QqlJ1hEHz09JX2XJFCN8XsC2nzOvtLaejBCJ0ALOpcsXc89NxxwxEebwVbMeiGO0LAuwZWTt246cc8viGyr5kgqaaT1MWkcSrCdcqSPqHCr67hasxRzZgH0R93/QngsgvJzePKy9k5g6oqlDfbStGJxW0H4VE1yAAQvmaEobSP10PGUi+VSaaZ64Ocq8ghI8wbeoGK+0gnRiljJgFKbKyksaagEJxrflcoN59Z0wV+YY+LrTQdbtTIRj0x/85Spsx/W82G+b/W/nRRl5FbF4AknucwTUUimBhof0S5PWPGhlSJybRnUiiACrocOKhY2wbDcGx+62XRLdOECppMUp4SKchQ3vshR8Zs82tC7o0/7ZWClrhGwatEPsJp4r8wQvlT4UfkNhyFhkSapWMecZmlvqdVeQmeYc7GrJvygaAQl475gKW6S5OBVFwPq4qRQg6NPfCIn8wbAoaewtpNLRii/ZoFw8Zpg4ynQ+K5sA0gqG/vaisXfVEdNMn2Q7oKbaPK4UkFoM5WReV941A2ObllqadDur23v6Do2QNPvwp03pMyYVTMkuk7/FPY5pb3Cc3FEvYmKL2yRp1tLki5+YmLQYX9mMx2CaKA8+4TnvpHXROl6U5k5nXN+hRcRSxZzQNFmB0fduBkeStixRJ2Z7uwtMdmV/30qQNoGOV9EclRw8zJGg/jqAE5/IuKWlOdVXe0fO02KOgAR5CU2SJ3GjSR2BUjUpOxlgNFx0MeYbfyND+jwlHvaMLjEFfKuO0qS7Wbz5jgd4xkIgfotT2F3Vfzr7jk4nx8P+w9TUkm4CqIzeipf3J5+emy++X86vJL5+rkuHv56dPVokuWARxMVbBBHRy+YIlC5g6qspUGBaY404yOKn7pzRSrfPNhPLh+g/oUuIXMr7zRqG/kL3p+BD/vhT/5/OG3399+fNv+ZVHRmhNK09F4DuE+djl0bN4nKmK8Nvc9kfzmwEPBvAh4oW9eJWjxA6dl+YjYbm636k3zv6vW9mGrebjT/H3RIwPez7muvp448TY7WrrmkqGOmPHeGzefTwGl8Rh9rPzrj33P2WTGn4ODg8UIvaSHPLcjCmkwAItUgBE3ZoaUiWvIZUw3lkzwNhoNEFRwZXN6mbMZlOKSYp5tWUC+Mh9wTZOijYFX22YzDSgXqS64HBDXmWC/uELL/5lqnRbW4is6+7lyGo2oiLsJnwuz5Z4ncUS9CltJel9Ryu+zJHFUEUMVbhRwF2wzf6vspnM2nY/nJ7W+3pSPh1uWJknubATyh9rEkheyhBcYuoCkDj0wFfGe37zLxJJ+4xvcGnyk0dCIvHBzYNXBydn7R24N3u7X5784MJz0Jpp1pYorq6N9NzGWGfszg9tP2X+c+DOudcLIiYg5ndsAMDxE46xb4TXi0cWXQjXuowycCu0jvvMRrhhs1W5wYC5yrp48aIX1Nph54bINfJtLQ+5mml+buXwS65jmRoUGldbLeKIx4RrChXEDsu2o8DidfXqLB4gNGWMrCZn3spiLf/YAsfo5OO8nVGsmWDyL/TNb3IzDsZgwxLjDmjw8FqHc+Tm0DeH2skF7VVeo/lK8kTG7K+x29Q6PpxzP7VX73enrRVgBBMaKmMC7XgR5fOw9eQ6tZpdWROox1ZTgXXJAqJ13AVKZ0GoSojGvLKXCCjWfYBWSRSjQqrM4N5oPrQ1wuH2bdEd0bk8+i+y0S3u8InK//r45yZ9xkT2QT51FJF/hEWV3ylOn1HMo/eYKb4G3z97zrurswOFWdHa4HpNzECdY4HWWGoXB5YC7/rI1CfgCI0wbjYauoWV53YP4AzMLZf28vDjDhl7tVRUA5pqhEQfEIYf0JiTNevWpZrSQUimYsepvQo4bP9087/X2X4yGfHsxBVqAgZlKfOb19M/MRlJ6tMcTricQole8l4Vis3QstMxwBMjxPBk4zyK/M6RCSEHs8CSiSWTb5eam3VKE9xNa2bWg2YgduzfhLYPJFqOzwqyAEplhfeHzqHTI/13Z76esqhv/EsE425IkL54SComecxHqOyOEBTfPo7fCM7RErhlqMSrvuNIZTboWf3XVdmGJUjufw3tdjugqkoMfpXiBnTCAcNA3Olphsr/7aEWOFzha7RefYY4s+uJYyTmB+U21EL0Vv+RTtD7/NR9SxeJuwnsKEgIrItVZpjgd8dPhNRKkCPA0YOhZPGiW9CvMyXTDk3Qy6kmbumheq+d7JWKpaiTXMySIVRP4+qzLpNZ+vblX3965ar49bO4d7uw23u7tzH+hhKgpFV4/Po40MuvOkU01e0AthjeR0GYXbkR6AcwLVslhA/E0BAb0o8o+uQdQ6UJ9NxToQJ8lR0g9v7/78uX0uEY6k3QkhUv+Iz9/OT1O87pv6BPsknhh5gxYTSb+rhR7p/mmsnBNWub6SIpUqyyCWzRqc+qSiR0ulBygZEdyZKgaKxppHkEp4IhrPgiv5S9Oj4liWQpw/fcsSaDsN7jEpU6akd9hEhAW+YjVCI2UTNNpcBvi2pwY6clUz7hji7aj3b29+KB/cLDzZm/uUtL8cmV1u/AbI0e0pxIEiy9vkCA4JbHwemdKJnxWs7/npfBdwc0V13hbXczky9uCwbbSTI1cU0ZAMWvMahCfGwu0h7YCjOnRO/PJ3FtuEdGgGjHMrDX/wKXcjBLC1s6bebeOeQEbo3ivIvX18XgPpyhPmg49xuKqZ+18aLeemDZPjqtg4u29/Sem3mvNE+9YcOq91vajU6cxY/NkcSw0def45OQimHqOffddw9xsuiMNwwb++x05YpAyQyJbao+15zYrSpGUj3gyqwBwWnuNqTIqZJ3A/bwE7nkqM3LJrlO8v2WKtxX8OtP7b8v0nr0C31HC92wG1nnf1eV9PyLxdfr3i0//fmTlfpws8NkMrpPBV5cM/oiEf7Sc8EfYXKeGV5QaPlve6wzxr4lrnSj+HSSK29X6cfLFA4a+97TxgJXvMns8pP8fnEQeiOGl5pIHJP4gKeVljl58ZnmZ5JeeYF6m+HvIMy9T/T2lm8+g/jvNOi9z8sKTz8sEv/Qc9IDil5qKHpC4zkhfVGLfW2L6LBa+p/z0WfS/4DT1WeS+2Gz1WcR+H0nrT1L+cnPXZ5H9YlPYZxH7vWSyP0X7y01oL1C9zmtfTGLfQ3r7LLJfcJZ7SO53nuwesPLd5Lw7mr+f1HdP8ToDfp0B/zdnwLu9+FIT4avJdX+OYNbZ8PNL65smxT+TrG+XNv98wr5hYv3zifuGqffPJe6lJedb4l5gjv43SsOfX0Zj9i3u+avuJpMz8w/pK5Mz/ON2mMl5/NF7zeScrrvOrLvOzLNPfvj+M57Tf2InmrIcBnOFJ54VDT7NvWrLLzRpCSrqbOKv8+x6zIxvvOjnGmLjaepLyfrP69ro292U1mB3e3f7mcSB2zWHcJ8Vs7JZpNVFrUBBxY3Vb4srGJicHq9CtpbKCvWTJTe8UfQE4+z15nOJ5vplx1+83wCUTkUmzA6Ez2sYkkNHwtfr0dTvUZAZOQpyG33p3qEfsh/0H6ekp+R9yhRJmQZtxrUlwkWB7lkP28fCaS10MiFyzESQRT7vKmRjQ/nzdnfRcWSRFHFRhQ2pUWNMkGxc2i2tne3nGmz3UhljoBtzxSIt1QrdjtXvGrM5LMHEEzxd+jstlK2hHLEtmvCIzS2bH8Oj/Oe4kj+0D/kPcB7XXiNZe41Pb5Af3l38x/uJL9FB9MR9e/fPTf2SnDtvvv2NrtsUDS/BMfMkvUC364k378fxyZxU/j6Py1Hw0v2p+bfDCpwtR51iA55qKwvbj/oy/OzxhtTvgV2CDaTB3rKHjR/A7AR0Fyw5yP5i7ZqhwDLMTl65JfrJFUrBLOReca2ZbYPdoynb3yVMRDI2RlX+Cr6XyjOuyozXSJpFQ/MWdpj+xZh/Jw9QuHLJBp8zpib2s1oRjABaXadj3PEyT8eCYjRM0bpJxl3z2U3DI2jIsTU2e5l2JkOArMS0s3rvmHIVFoAckWez+rp9owcuT37uvjs9b1/+J3LOYmfBluzJ3z+/y9pHzfYvn99dtdvtNvyO//xrXjsDlhhPoK9BLk1V8BcX8ghhCbBq1yyjeVFwXFcv5IVy4RmmKaEuWXjWN0H+di3cQjdg+VMuBkEal33ebwaYkrwywuz8XgOhnvx20T4/7nZ+f43rHib7eBq4zp0bKZgd105p68Ah681OCBvVjP7xy9nVKcwFY7vhkoT0cirvqOJQkZkATBsOK7IRUzwCXvOda8Y8/vXT5TFu3JOfu5/NbwXSg10WbCKPHxSziI9oQhSz+dLoc71ijQG52Wht3MxITdr8Y+Po8Fppeq1Y3NV6fN3j4no0oeNxgz2wZ8DawcYqZxevBtVHUxFTFRfXG49Rqy0cTkY6zSFuiXm5GPK7Khho93qK3XFYL3A8XJTLzFc6Rj78++zjvATfskkF9H7gd6wOpw6/s1mCsg+p+SViO5/eX/3avjy5zp0ip6rPr66P0GKxhY/XpyNjxrznCSMnkGZoNugnmDS9vufCEGr23dxeE9XDCtgHZBEzdggcYpaqZoaDNxR09KyFu15aIP41nyGY62PWywaDoDLuKxIK6VyliM4D9xnBCe1ZXtog81GcG0ug1Yq2Uv7R46bSZoBvmTJtjuoRs8hUfRqZg5hqRsb8TmKWspKZiAklY84A68PRZ/SYO7sA4wUegEMgRIOzcbDUmMYAfyQmZJxQ8yQX5oQ5OerYzFNyFZJgh8YIk6HE6oJRjaQaglTudJJ9AJ+BKdAmsGcjV4HxkvuSFptPkBsrxcaN56RtFGSkmPbZ5UZCpxeu5omlLsTmAnwiZgqSpGtE9lKm7piquVT1fEdom2RbI1HCmdA14h41b4lg2hjRjb5U91TFLO7ycYOc9slEZoSOx8zi65xeOL2tZU49H9/U4ElDkjbmAgoNJEbJgN8xYVjQit9xmiSTGhHSWP7GBLsfMr/NuYbJKAQSe5Mc7TSY6rB1sN1oNrYbrT1XGbSMKV1hOLedJHh20HTIUtweUhhBKbfhrMWFeEfutaiBDL12yVJ0NgE5LperHdWIfMiSsdlOKdeZDcqCVM1Um8pskRRQ0oa0iFwFYdgc45Sn5BUigTHF+hK+YTaaUaVwGHoC5kcDgeT9CuVrxscCeB+yNh8FlQyzBX+C75YXR/g8HiWMvP98fJ7WSCxHlAsss6+Br5lai81+ZDZ5wmn6jNp7Pk8Sr3+oxLXV56cXM5krxhrSykCY3P4G/KupRYDPZi2Cz83/iqz8OZPZVXKHjPv9iRPGPGNfdii7cXcgDuoN4kG2JgVLZcTE604inbzowDhOhgBb6OiKdghNmNIBt0IioAswlntUdpPBFEEBkR0Nr0icf4CuVEC43YWHTjc7ouIRT+HqyxjSSibmMNPmuEtr7lFDGLwFp8edrdOLTv6HPlfsniaJ2cis54YMkEaCBzKVWJS0tEaYiBH7JWbaFrYaVYFHW8rIq5Pjy9ckhVi6L1xiOlqBhqaZHsqq9rAxj8wbPKCC/2UPSKnIOGVZLMVk5F41JAJedfjJaFiJiFQsLihVWEO34/yOAe1e2Peha9fRVNXPpIqf4cdFVLPBSiN3xZfbTWDFYo1HO1RQeMlsZxt7TjkReJmYsyrfNK7GbrYo2lqz0dg4X6eBBXfG6O3c3m3lF+xX4MGX7tZh2e1yOznMZvJdIqNbotifGUs1WIrjrJfwiByfd7Ay7sPV1UWHbJGrsw5gE8pIJuncR0tV5ZVt5PH0GNUXT13V4D3XQ6z4JmkkEebH2MYDMDO9TZrHb5zanLlxnrVhWs3WvHJJeMREWtUlTOhm2ZmsZY421NOawYsGq9aMS0RjRugd5cnMAr/2mEZDRrYbc6fcVXoBxQq3tMAnhAIdhOp878XZp6N/d4/PO13zEnSvzjrz8qYYXNxEVTG4eekmIF8uz8zq0a8hj4dr7Vd35mng/2rEaIY3Fj2etTbAinDPm5spiWWU5fXKxdnAXTNv5uZmvp+E1PkuqhknIkRYpCTh4hb4wbQLJDDBSywUQc/5JvkhZ5G8wAgqRypd3gYTjXt+y8cs5rQh1WDL/La10PIaC6wy7JnzqZ2bMl0jY5nwaFJDiwUtAkhE9KeucbfgzX7W2Y8lryM26uVQYnmAzgZPuxdW5Xffo/U1r5yy7IXofojrSOWzGLyM4EhI8zMBnafgMEBMh68fB0WFWT4WWs0m/v+8sqs2be0K3mLMWNsiit3xdNp06DHDNewdiJrYTi5l1hpf4cknZICEQ9epk3/yhPPUts+ZRXaQLTS1Nz0QyDJ/E4R6pyKSQtjl6XtDHV0hotiAKgjLpgzclrQWPI/r3+N4cYv6tJ/Ie7iXU3HuSb2XilwdXdhRaxY6zJGJtEWM3+UZNFxwzWlCOv95TsY0umX6VeoQE+2gZsCcFrz0wb3oja7pmayCTCYlefyPXAs4uUCiHLWDQ4TS+keERjpD3IWUWWR/NSIbfrwNoz/gVAuGdVSIKcJThPy3f7beo1XeRotrypM0PyzsiEgKYLeLgVvgfIqQDxsy6RQmQL8auLAjBjDn4Jz+dyZwU8DFF0Yd7bdnDZaLVkhdGrIPKtgsI2YjTrvaRzj8lmOheLeGYTIaxyRlIyo0j/Aa6gHOWCoIe8BUxVpBqfMUQmv9LDGP3XHDLv+L5TfQhlGmNC3E3lzcVPk5+sahdmMKVKHuIMHAqb3yTDVPEsIwXIfYShAxAF87COKCwPo8SbxuouOxkmPFqWa+pcNSTvfciF4LGVTwNuCRaBfMh7cLWFF01OODTGZpMsFdDt/x2h/ucVNfxJ3wVJvVPL2oEeridhCCzgR/IKk0+6dByH/mEqfJPZ2kGNAvHuX03tHk3oebhv3gBkVWtN2Esa7yq+s4c+0VIFTe4OMbQ8pNA8m6qZGYjRncChBpbQkiRRCRNMfsVOIQTRsFvMVFcocsSA6OQ2iSSE+lDXRIIUcyS62KQLnnH3sCrQaxA71qd85fl2BpIMmYRsM8MoWixCxPNuPk3mvtH0zzHIZnXiLWwPzZSp8CTmZn7P0s5SBh5OzsqCCFGck+8+R2Popg+A7SegBKJcDihDfRbgRU2OUFertbDLjAdv4KZQvlEiA1OH4xpj1gshFxPamqOdER15PZq/NRCq0YTcrkSKG5YGIWds5KaLq6l/UEk5YA58YfcC6nAmbfTGfTfd6e1xAuMlORgM8LXZ/sZGWipdJD0oYsHDqDyExoNenyVFYl8yOcgpx2PoHQSxQetR8lq6qtaUmaucpHVNC4LCnQ8CXnpkTOgMluCCBfROCTYsB1FqMpklANv5Rj2f+XbCRSbByS+pudxn5r9+1Os0Y2Eqo3DsnuXmOvuXfQekv+32aJyArjU5tfUqbqzqSYit1S4sRTIxSjKWhgyj4ZKCqyhKqwv5sesgmJAMzNWNQFbDV79OtiPIwrNBYjJvAuBSoZEokpZj2mckQsZ7XnhyySl+QAsxgzrZHI6agwge9cApSjeRCdC7DFzdk9gjN+wKTjthy46clUS1GPo9LajGWqaVLVW7Z5AcOjWqNpKiNezJfzJBdaXmXGVMytXpud4VNLRnTi41y3Qt4LyGkkhhUEJVPk99MLEvBEYGuDSXlH1YTc89hYMnA82rcaLhHxx7L8Dnabu3OHY41YFRtwKapUYJcww1P6q/756DG6KtJglqaZCuxzxnqsvP+Mdf+XnO5mtZpj1ZWdmPF9AN9rBJf1edo+bwfPzSTeHlRbbTWAY5luvcuYkGm3zRWb//pm/BUuZ2cF5AlCOTI82E+vTi/uds1uP724239dtKNGNKriff7YPppNzFSwW0gbyEZrFd+0y/dH5E1zdxtQOLPBANCMD8mJcSJkpJkmr2wIskbe1ns8t8GNrfsaex1a08heUd5L8kc2HjMV0ZT9FxmyB+pScKHbW0oG/M7FHMM8POLIx4kxKToTtmcvF5oNmGqQThZFLE35nX0QXdiUjaly3fKoH3E4GQ/ZDO3bbNabzfreCfx7p769U1gpQXVjiZyRzStFRWqDM1BXFgYTetQcFOftKx+js7iJ3Hpp+eEnyVjxO6Nujz/+/jpYzuKhA6o7kTQmPZpQEcGxF6QWSEWUzMxpOOXgGj7Hcq5CsmcVbIUCgGrZlysCjHI9w9crluzhtxfy7IqFa+VlWLKY0Io9VAeETFffMMXi7iyfcsUNvvlgyFIdTOpkhHPXgJHxmMWe5KznXFG/5O/z8rBaUAoBw9nok7FKNvpSNuxzjUiONoyS2gg/eLyLOEZwASMV4AlZxFNjldgW4BDxSvitLZvEPII06/f5gx8Rnnk11Hp8uLWFj+ATDakGrxvkClMstURz6oGP/KVVb0JSPhonE6Lpbb6uGCFLaKpBuSa0x5IULSchNaTIIRKw4f7q7Dj15+hGJBvZ7UZZ/QXSKOwKL/Yqd4OfBDa9dwz6mXmb/8xoglDQQSKgy84KDPU8LQ9T4dhDxMboUEAuFnwNUwKKW8Vu9wYhp8JYqFRpHoTVSYkCUB62Xan5f/t3m8HlvRdwM7LEVohHVORxdVLcV7VAArY1QFpmqMcSeT97m89+J4rvTSjbjfv7+wajqW6MJnYE3Bj4ZtBUb+TdzE9tY1YcZUhzsGjkFct+3DS5zbaRZr3tRpr1WoWXr1bYxDl5BaBhK4VgjI0avnNCEq0oT8wrM2aKyxltWw0D89p7Wo67wMY30Hqs32fQq9fMajeK5f4Vuzo7fl1Dl8n7S7ncvdBQddTctRsoAbNl3V4JXpJGWUFOz+uHDSptzSrBPvi+NSNoxceUYr4S86lH+Lywb7KUqUa1WyaM0uWltT7jN8hlILL/2LFIBTk7bl8YldVGjo/9UOFe2Sxzx0aUJxUx98VwABMUm8kUCDDac8UYHt/4vsGwuZnmxwCEmp5IK0t6TGlywkWqmd1YBYnAZeLftu0wn6TyfYdMVpZL83iXCpsvY9Np4Hpty2V3z9ieSGeFgdNwJXCyMhFVwiFZSYG2gVoVCL8prAUqJN5hoRGqJUGokGIy4n8FmdkoQv/rl5T1s8S8DDfABY/xdhZ+MdzdeBMgkqKPazWd7CfiGVaVcf5mbaqvIrOsZivZ1YIpp9/uTr1V36tvt+rbze3d7d2D1vabt2/q2/sH27vbB7vN3fr2zl7rYG//zdv9eqvZbJaZWF1I8Bvrwc7QeJ/CoroncsDFk6KiDfaoDlQyqQx3oe3qCWErw0zuVgKij5bmRwsJbnmPCtql8YiLjRrZUAysbjHomgG/Wl0Q5o45IMIgecx99GRxJ3PfLqUi6fBvWEwBEYo8Qzpou3xPUxLJJGERAADZT6+gq5gdGMreJjIjfS5ifB29ckjkILVawXefcXNDWTBm49k3tS+lFlKzQzKD/hGdYAFp0q9jczXrxtnnLOZX4yeEj7AfIkpi4yeSJwB7QeAXDP8WS9F+yWeauMQhKGWN5AiSRBSRmR5IhFPA4oEagRw0NCWTidsRH+Q9g9JO7RqopBgTmofeUWacVakNz0b3GYXm1sSY1ugBSqmn5MR0nhtqM2ALK485b4WtZbu+2XRQvOPJm76kuWByks1iGDXgoe2KErPDhnLzhRZS+azEadosahsiXFiuXHImfr2Rb8Aydflaf4U8M2hpER3N6jHq7CZ5krIXnOvVtlcBWJIKV6EuGZH7TVl830EvTLt+ASwI+XJ5mhe1ubuGV3x8t3uI4V1F/uDju/3/gl9fYxKYYphN54cFvIRXmBaWzuoH9Ga7sb3faDa2D/d2d+aGZGbijispRmyuXuwLyfQ0T6/CCiw/oxVzqGt5SlQmRBGqx0ZVABbLPagyASrII2GFA6fklYXkw5sxTQdcDGrkc7sWHMd3LJHjERT+MB01XtdK9Bnf3fcGw3Rbc9RSB+DiqMojDvYty8G60E72StOosaCGMQ3i3oa7YPLyEucszb264yEbMUWTChvZnbg5SqZd8Ma84n2AwmEPPDXbd+p14TERxlZNkonF4UxdszXFAFgvxU52N07AxgiOJUuN9i9L6i3d7e81m/2CMCqxamf08fOZ8rCN8y1x2p/e6ZEcjRVPA9Nf9hH0QciY2eyLAsu5XvFbBgwHCNzELJ0hWPuVUhO+kBiLRDWit+Zc12Qs05T3ECzO2yl5KMrYK2Yjj5hWPELbBYCOpqyXInSCMZwgYBxlCVVArx+SjbiGxM7cYPR/O5faJhhzxHgQDI/slLH8C/ZNKpABsWxZEHv+/gepzFg5jM4s1eTGfM96VsbRgl+N9MHMpjOCqPHOG7bHen3WpGw/2j14sx332EG/2XqzS1v7O296vbfbu2/6+4X9WFHOQiEm4TYbZoA/eWoV6+KCXerfTLDzASDD7heaJPIel9/3ew82s1d6IFWVQU29j4cD2kLRS0ZLweXlOz0L9535GyJ8mD88IazpQlPg4CShqeaRRaAovEXOYQ4j53jRmKXaJyuTICj8jlGdzhoEQ6tWCUMHyrFH8/OPmoW8yV17RFPpmxcD72aC/p0zgvMhH3X7uhU3kYxZpflobjdRvyVgyik9E+wEfS9RF4UHZHhsC5tG7v8Gr2lQehjiW0J6FRjaCPNRCxbBse7VYp5O1nNdR/2g9jjxlDmoFzfafHtpSiUHJJR31BQB5llc86AOrbhR7R5sGBLM9OkMA8kcemJzMw8rAKS1tdvhFg+Y87PVpm71pHJEWiCMEHw7j2RIeKO5GGQ8HfpVy19KeKXNeUGyceGot+ecTA2pJAw4WVxDKxcBVjDkLXiVULatZu6aXMG43fOa1FEreBlbpkZUYPFSymaYCW6+etP+0ypqaOvJrX2O1focVqxr1+NHdj3cIq89kOeIa+2jrH2Ul+CjzL9j117M2otZ2It5xjZb+zlrP2ft56zWz5n/9UsDkNmVlggicjGB8aekMTdApaWxIpxwuCZ2OELPPo3gi1PtrdAun3EHXLBXvKVQuIREToJJTtwin/ZxEKn8GFSxKeqm3/JHFPy9s+BuCrr75iu6/ZkLNhPHZjVr9kux5ZpbMndvP4c3bTW9liSR8pZQczQiLibTeG06dWMfdHnzZ0hZXjuN7cbc7Qb/vrfOp7fgbfE6ArLaCIgV6zoC8iNHQNwiryMgzxHXOgKyjoB8JxEQu2PXEZB1BKTKCIjbZusIyDoCso6AfPMIiH39XnQExNK4joB8LxEQu2DrCMjX5LTe0S9hRz+JPP0P2a8+KJdHiFy5Uf7JE9VG+JQr1HHtfUqQxyRlWGfSD1CrHeTvFgKuBAUeaaF5UIBBbDYGLcIi1yxeSwhkDrC21kwIwVCQqgIRIUR03ssuZCrAWf4KwnKIZ2NhlnOeHgMSDmaJpEh5DKgORmbGtUi4YGFTXETLtaP2HAQx1BSLIt/pYxM6MRSF6fZ6iJh9GtS6YejJj+1iDhbywiFJIga0q2ryDguU0WFTtdnPOSl4LhE2zov7+8JTtnJf4ymv8ZTXeMp/K54yvomuZXmuBP9GUGUkaQ2qvAZVXoMqr0GV16DKa1DlNajyGlR5Dao8L6gy2k8vBFQZiFmDKr8YUGW7O74CJmy0MkQg8uNPepzhmYDCQa8vohWFGJsYvHiA5UfF0VhSHi8QYHl+V+8boixb/UBeEspy6ICuUZbXKMtrlOU1yvIaZXmNsrxGWV6jLK+MiDXK8hpleY2yvEZZXqMsr1GWZ9D5QlCW9VAxilK2WU9X+SePZz1tvMdsFfOaJjRNeX/iCkGgGCthyvwYRRIb7xvDys5FNH2QQo4m15bCa28UGYY/nl5dnpD21dX/Ovr39UP7hPQVHTFjUzWuRSkxymgDw2+BknxgSwfm+XgvhysbAnAxsdPjTo2c//z+V1uz5vK7KYnkaGS0tCW5kQ8N8WVgqKFppHnU+CkkbMSogMbuLiFM21iENYpd63Ui+/mY2o9pCbve4KMxjfT1xutGYUYWDUEhPD1pPjKmotxyAVEOsHFpNPQ4yb2Ju6bSmIeH89Rg3aJIjsYJT+HOJh9yIGniyWQihhtGEjNhtKfx0zDxzpC+8T/IkqlLTCgeDaEKcY73ERGyZ7516AkYGeT3UVzExqWWKiWy998s0qmdz4WObZYdFXHB+A8AlSFy7YbkUmzlBM+d7B3w2PAkzcEt0jyL20/wlyAN8BGuZ3C7HNWNf1JS0zJCeulZUMslOi0sGWeJRVXZuxt5/fR116i17h0TsVR1wTKt4M7aUXDdVQDKft3NUvhPoAWNHjyXgm2dyfutjyzm2WjrAx8Mr7tpRJM85ZEL0h5DZuADabujvXN1+hvZbrTCEy4Y9xckyGc15xQRGNw3BaBxzGJzfEZZquXI5d1ei5OHMWjzcNQ7e7+u2OG1IOQnyCzouAo395Fg+NOZvMcfkDf82TC4Mb3y+MByqx6sUEXLfuzSMPCotYUCmOxrBBxnkbtbzA/baVZPL8hDA/4PktexcQDknyT8jimnRttikDBFTv69pCqF0EXFSA0BmoA30zwF9nq0EEIhr7jKuz74/SX71o/nUrwuCW485Onw/0zH/xcWTJ8nrEHhhpbN48HHeaFX0fk8g+sNY3RDIJ0niEnhhp5ZDC2kBovSPI3nS0puGRsTrWh0i7vKfB3GbXzFGJ+PU20LeKuD63AuCYggny8QQNt/aK8K8qya3oT4CAb5wBTb3EyhjFHU2cOQZimEZpz5hXooMKeM/aQYYVZnYX62S/o5JFRFQ37Hali1D+tSy2NGNcJEpCZjzeI86M8eWJRpViNDHsdM1IhiNMZ/m2OuZu2CGrlXXM8oENn8Y8M9axwsfPqrjtVcaxnJmHVTPhDUmOmNmA9Yqrs0GUjF9XBU1QLDfShNwdLzk/lSJ0MPhtCVjCBM6kU5FZAPC0s9F1Dqanwm2D08JTabwl/hQD5/HkCZBKXF5kkFIBQ2pp8DkKBscnLL65QO6fbe3GWf868K4ml8JQjSkzJhVMwS9zv8U+gEcqhIcjMYIdmElrKHb9yhCraa+YmLQYWYJWaTBWGqeXdX0LKngJER4LpALXCfRoYRTL4hqezre6M30HxrBGMyV8yfEsUSdmdd4/bY7MWfPnWgdGzW/cuoYeZkjYdx1Bgr+TCpYBU01VmVsEvc/DgdxfSlaBFTtnKJESRl9mr0M7zDSuRgANnoRsXKgaLjIY8IU8o4jz6bMxz1jiY8DrNrpTIOfqrdfOSM0TtGMhHUk/VdnhZ8Nf+KyyfPx/fDmnM6E9GQRbez8BlOLi8/XXa/nF9dfulcnRx3Lz99uqpgNTPws6vKq+zg8AX4D8h0RbVZssR5pKR5L8iRVGOp6LMay8zNtGZ0VLEWMVOsUpXAeFJZXWHLQ50CsThQQe8vP+gzNcjJ5w+//f7249v2LxVI3Zyhmo7myRh8zN49Ni8oFTGavPe+ItFtKTybzJs1YIJhpiPUKcJ5Xj6ptpvbrXrT/O+qtX3Yah7uNH+v4OQCXTCXof/EmbzZ0VI59y/QRzN0DImGxXyXX4xiwv5s+dcf+55zzjF2CoGrGgp9yHMjqJCJ4nq25RrR2EhSJharg9oOewTUHVpPqEzLpmtF1gPo5iVXYLZZhFfAA65pUjSQjEcNGVF0QLlIg7DVkJEeF8b1gEBsAbVq5ulCC8v0laNjdSI03vRyDup7Y1HDOOYcB49yXp8UimBxixa+vxLOzEgrdrxzr9OCI1AssYEy+dmuuAO1s3FhGMbuCHRPs7GhgNyMzFQ3FhuLm/eSpeQGuAjgFMw3IKr236Bv3KUcOCrm0RpJuYj8cJCkIHK6fT6ekdAqpByzAFJi9QExi8aATTODNOKQjZLHFdNVMOa896p481kgOQaT803tXUKDnPr6bpvniZpIhVEtrM6sWf82r0wqyWVrKEdsiyb5ei0lH0NEFydfVkQzX79jBREZZhECH5XRVV58xVM8ppw9lNv3gvzKRSzv06laEIwa5DX0vl4Dj0Ojs0LJRzKZVcK25H0CyJMl/QaEkTQDF7KibfeRRkOArAimcm/Tydn72W/Uw9v9+v7c6DlfYbI30awrVbz8tnmExXcT4ziyPzO4jZD9x/k641onjJyImNNVOCGGvWicdcv4QStj7ujiSwFC6FHeToVmyap4sodzNy6hkT3rSD150IpC/BSUlUcS9UUiZsbN1B+sDXKKxNjwXe7zaDCQehlPNCLOjcY8sRozcji8PUb69BYt1RFNwJECVqRKl7z28KJhD2Op5rr27ydUayZm3/yf2cAzDsdiwhIGcMQYxwbTfDJmKyN7yGjMVIP2eHcmutLK9usUwJLZru0gZvYOTWS4x+7TiJFX7Xenr1fMJWTeVMTfB5gCk3seeydXxEbQ+n3lxoixYjU172LAg513tVwwodUkrPdfWYGdXYp8gorXAzNbKn5/NjeaD60NRFHGFuyJ5yddiQUfcpR2aY9XxMnXX3u3XmdcZA/kU2fF61XhqWy33lMH84qY+ObaerVKgI9WelzicNUfl6mtLZ6D7sez+zbbglC4xA5T3oTNkMNyHBoNiZ2svJEKnsstm9jIW+692Os6ix6WMp8wGAKc9SYkzXp1zMPxQ0JBoGBUD8lNyHHjp5uVaRk/ZjTk24tp/0LaXtEwHvJ6+mdmg+U92uMJ15McWbyA8hiFhccrY8ucPHI8T8DgWZx1hlQIKYgdnkQ0ibLE1hv48uqKeOondFCV7WR2dsdudnijYbKVs1BhYUqJgzDvcGUMOBCeruz3U1ZV05YSLzhbddyk/K951uU5GHMlHjx+kZls5axUaFGUOEGw3hUzcMeVzmjSnT9/71kWeYkJO1+x1LECfhbfWgsws9qtNVi+jGB+QwMm+7sNDeR4tYaGHfMZdtuiL6kVqpOl34qrZqViXTPFxkq1zZAqFncT3lNU8coSRJ1PgNMRP12xhijndVXsaZb0Kyw+dcOTdDLqyQTrT80rvFIH01BbZRQD7oj9LDXCHqIki12yQsIo/BzL2b2dfBYIXP5AplEBfsMPnJJXLoFbU9UY/PW6BjdCfkyPigB4+F6f2av+mLzaGPy1UYN7nw0cYWNG/71xcEIsLvS+VLcrruqfOgbMPrmFK+A85w77HE7BHdLgVt6/Hl5onwSGZGpBr0I/tE97gqv86YlKo/tB7SykbW/WERXbLCvVZkPYNYJpXF06DGnhW/CCLp/PD2y+gdUnkCJb5OP86n2nhpoAbsZpIgcyg9t5Kkg7AbQtzTAg2tGK0RF51T7uvHbpMcwtuR8Vwf7xUSz/dleU/52l2nhrCYvJ/zxuX7Ub5HcpWOM0TxrDRm8juLUsNMjpTdyNJWQOQNq+TRtISSzvRSJp7BD3C6VgpC1I+7gDF+YODyyXur03l2p0SG6ODq/HVA+vtbw2NIPz4t+lw1SOWNdv0huUwM3Up35kez+PF6qhueCSXMhN/q0GuSlP6Nos+SGDb5r3JaSi9KXph/MHIGcu3x1ZkkB/zZp90Px8U8PEivCqFzZegMwQvP7hIgYu++KaYFBZpuKF4iOqJhbR4fSYvPr59Pj1k+kTm61ms7UKSyyvpa2arzD3dCZPq0p6MIdvYxTvVcTVx+M9ON9XcaTDOOmQtiqitfOh3Vo5sXmlRAXkbu/tr5zgvdY8gcwFCd5rba+Y4DRmrKpXstM5Pjm5WBnBXJSwiVdXUChKUPZ5alFuadrC7ZKC3N7b33m7swoVOeIjVmW2yMfTjyd4K+XSyMKMc4t/GyhOIpUzZWS/EGYjBOqLyVDrcXq4tXV/f9/gVNCGVIMtmqZ8gF2Yt0Ys5rQOty/hz42HoR4lf5y2fUsAY4z0ecRpgnc1/1WzWV4uLaRBfjV2/whTRKkAexCY4akrvOlZQDc/5kimOu+1FLLuMHFWsWzVbc2PABLeL+xHGWma5Nt1NmrqZnN/t7mSPblk3uyMtFmf72qcNhlju9IVkPqNIKfsOoQea+DKGhfHlS75pNHS8ji3dDWuo7wXlaXPgasOE2yCd6dmYimsyqIy5vfqGFk9qsR75y+ECdy1qd3gwxIzMnYLoYc4yGl9Xsbu1mo30Jh9i2TTo4svxURTbEDp/fnZyaYryTQdQwn/mIqq8rdPPTI3TlNyQmquIS0k6dsMxTqWR0yxXFVR3Jh9A9QKL4ipDicLyOGChm1gluLb/Lfi1CzP+F0xa+aZTO83dhoH+81mo/Vmt7W3Gu75aFwlHmIbo9CWX5vTA4CH5OIE32rSFsRSQep1AIqGx0hAFzF/mepo2udiwNRYcaGxfgqgj+6MouxrpohiKEzb1tB1lIxkzOrAZ65vFRWpry9OsY+1jKJMKRbXLOYYtifFGh1raSrqQ5hAPWJBFKu3lDVLqS4YxH2uGJuA5tnqJXKwhWAldWO3GT24td1s7W41W1sQz+NiULdpyXUUTt3CHzSMrTyjV0O0/7a5E+2yg+3tlvkhjujewf4OpfHOfhz3V7N3XJphF16hCk0s//4sozk7F+3T86vGyW8nq+HeFtpWzbKdZhnWN/ypAUCENloMP38aM0SFIh2EBVmBbJ5/pT7jBsgMYvQEeJaFyHxQtYN2EUZnzaBQxLZhfp0BSN3a33m7CnsBLZPuSzdHr9CAAoPUWFHpZJRwcbuS6+YK4xCw+OCMv8JdHnMF3QMs/WU0JvPYCnjKKousXzn48dNj8uoLBNUVSVmUKa4nIS7Aq85UxB2dq+ri7g97zYMGtVdZ/A51eOW37hYGIpjXJuO+6rTPXzfQoYZAjwdkmgWZQTM9lCBCgDUOKqJh+/QynV+YOWTkvAkVS2vk+LxDQo4JeWUbrMURVXFqr/IKgGF5pnC+HD81bEfyRiRXtiw8TTOmGshClYerWxcLEQvnzKujc9iIhggATAmk6+VeEoRtCw8RdEDXI+00zRQVESMdbA59NHebz7nlA83uKpcNdtd7dfQaDMh0mvUvnRXzFUBTsbjK5T8OJ7Krf7zI6h/960unRj79y+2CUxHVyKcv/4LGKTlWXo0cnf/riZ3i38Wqdgy0q8whfaraMm4ap9vOXpcsUrOpjFb6hbP7FTMZ4rFWzGg4VUpefVpCcZyKqEI50KSbCV6VwT5LHDQhZkYjlS8LiGXqzVmxaFJNoby6C35EdRC1/tw38xnTx83nT/2rGumAjXdRekeOaML7Ugm+CqAG4F5I3YUAwRzsPnZxccVH4NFjZGAaN4enREhwbyDcIFIeQ+MpAJ0pLfJ2c7tZb76pt/ZJc+ewtXe4c/D/NZuHzbkbtc7DcI/15Vyx24U57nOV6nm4bR3Um2+B29bhbvNwe2+13GJPpO4tm1QOQ9kuIU86nKmwgdMtK7/Yl52VHWoBv1Gm7qp6iY0PA+MHObKMsCQxD0T2TznHAcwloG74Q52nAWCnu3wtyUfwVI/3tlsVCIk9jKVgzy0pnsImwCH8sscMLmumFt1juM3B8P7e3s4btyAiZg9TjUFk1MXg4nTDkNUJZsmoDTQl5H/5EFWwF9IxjTCWw3XZe9pu7r5dFTspU5wm3bkR+5doYINTOSx+OFL9azH7dIdmT6AgU81ENMkBfl1zdcyIhB0zHlKRQbvmGuFhPQWGqV06rgQnNzGGl/FUPSaNHzoaUsDRUGXB7+29f/fu4OjN8cm7982Dt82D49b20VF7ZZrJo59VrohPi32pCqigHoIt0Ei/MrwcGDEjszTshYcmSV9mApCbf5bkjIoBOQLAUFspMGmQDmM+nD/gepj1IJI/kAkVg62B3Oolsrc1kK1Ga3crVdEWIo5uGcHAvxoD+R9nOztv6mc7ezvltkeQglZf4TFhgy5/Tzgh9fEER8Y0w1iJ0RgkskcTb/MKtoorvin+/45wQXXRAsfXSwgXlBB5baDPvJyPxgs6V//KbfwaOftXhwryXlER8TSSQTyhZrzDBkQPvtlueTGhgoJQVs3l3x0reEwpFBa+SqZfQGBgSgYrY/Mf6uTbPItqLcEAAsVMak2z0jbeWZYplepuytg87+aj7juWRE3DJXOhjQs3wGY8tloLHHnswscALHmoi92CjVfjyZvmdhPiGa1Wvbl31XpzuL13uPum0WwujaQ8YLIRcT2pCpz8yOnfcuKAFFoxuiRCHtAvhebGc+xGpbTglTBxdS/rFgYzKuWt+9k309mMni9pbRZZrGidzgvg8XayMitS6SFpgwO1pFJBrsCe6/JUVrV0R9ZkPO18grUrm0srWR3ko6p3yPIwc3cdUUGXhds1PACaa8lSKdE/YLIbYscVTyspBlxnMerDhGr4pazL/i/ZSKTYOCT1NzuN/dbu251mjWwkVG8ckt29xl5z76D1lvy/Fai2Kot7v6RM1R3UwlTqJSVOnjUHEI19PWWfDBQVWUJV2P5CD9mERNT40z2ZhSWzRy5CYcYIkpW4wrrXiAnNVIpN9fuJlMoGT2o+/hG7rmZ+UCQvycFZ0Jeokciby8Uy8LyQFaNzXEAjxREUMA+YdNyW04N6MtVS1OMlb6DMYo5lqmlSlabYvIDhUcNPl2fDAjoeC5D/0C0vzyC3mdUeEHlEJx4K9VbIewHd0ohhBSaSivx+ehF6s4TYZAnbN+uexyyZYJmxc4Ch+zX8WBb4wW5zd8mwvxG2YgNj6VWomi9hhqc0c/3zkrjOASMV6WbLxEzV/DljPbaCfW8My7+kqMSyce2kzfju/M9Vl2u8fNo+bwfPzeTWWgVbbTUAy4huvcuYkGm3zVWAFbWQFPg8JZP+oWe3LszTl4p9C4ns+5fyib6FrcZ2Y6exZA5kQr+pOwIQHC/OGxlRdcvFoKGTqmpkN64U7fd5RM4My+RCSS0jmUCk1FjzloK0QS5dKBsvXfOuqGG7VPIT+fXD6dUJdj79+fLk5Bx/bH98d3KJP16eHJfaof465HrJ2yZXxtel80RYVrVl3Kxh5zAvD3/2ffudYzbyHGJ47Jrt61oCUE98j+gFtMTu7pIRC5uXXlXY5apoX+bsb6YuJb68nIn6q5upZEizJTW8YtDPsbJA2qUbn3y5PCMJF7dQOihDvJxZzfCe3MzuqsqWqQc5RVv+S1vNZrO1vbPk6WCMmNSYewDKH5aFr9yt+eRArmEWaH6qmUAzuEdTtr9LmIhkbPR0bgm/l8rD5ThiicQqCCnS3JToMA1W88kDqJxLNvicMTWxn9WK/a8iCe+ZFLFv32MRiIyCgovhm2TcNZ/d5IkBcmwXtJdpt3WDxqIYyFEskndMOZRaaGCWo+v5tlBGpV2e/Nx9d3revvxP5NwfCDOAaT6/y9pHzfYvn99dtdvtNvyO//xrlTsAQRK/1nzUZVzPXOcjVxJu9L1ZZfNC4LgOutnL7MLLAw0mxDac9U1YHrtUnmTYHSkXgyR3cuzzfq9gYvorI+vO7zWQ+clvF+3z427n99cWMCpfoJwGrvNiNoAUg3HtlLYFSYohdJgQ9rEZ/eOXs6tTmAvGdsNBdyc/4h1VHED5EyYGeojD2gwC4DXf2GbM418/XR7jvj75ufvZ/FYgPdiEwR7zHmbMIj4qAQ2QV6wxIDcbrY2bGUhom39sHB1eK02vFYu7Wo+ve1xcjyZ0PG6wB7Z0P+LivitXqKymhaWmIqYqLm4HxMm0usZjb00LAHfMipgc8ulUr5Xw1+71FLvDeAKcsa7+2sxXOlY+/Pvs44r4uWWTCtj5wO9YXbEEi0ygFEr2Aaa0nHLx6f3Vr+3Lk+u8Vs4dE+dX10eZUkxoe+NzfTqiA4alSifQnNvs/k8waXp9z4Uh1GzqFQmnXGq2Eum8zwHOcpACbE4OKXzCHh+zlv16aXl5FTNDbtfHrJcNBssipnkBhmxUdRmByVvWCiltr9UwlEZUCKa6qaZzAf8+5kVAoN4Q3v5l6+T40jaSddi9GTT872dJMiEx09jGfkQTHnGZpWG9HbRD/nJ5VvYhluTTuvnL8HiOHpBZHT6CTqmhiQwAM7KXMnXHYqOy4yyy6E7gU0GP0llZK9tLhiwrLJ3cuLJNRQoOoT+j0Qw9mhipfALOwWDggnSuTn8j241mI4wYlMMKhxgmoJmWQo5kltbRn7AfK837NNL4m4e3KYUhYjmiXNSNjPBRKK+r0zhW+LvZX/gTH9/tBn/g47t9++vUmCMaBc+NMs0e8EfjC9ufsMUy/uKaJeNvmUquBQmH/AnqNes0guA1PnWP2q3ulEr9lk3wLw97zYN6kPhUCqJ4PpbbOplKGii9qlyqYxjdabRMJbnVuAHFKL7McSMwuk8FSeWIkYimEJYwjuuITgi4yhYv9fTCnCdbUmF4ArdHMskxkSgpsEYcSI7AFxcbLQJ6aR4DRUiGgXR2/A0OcYNXGiGFyJAhzFaCGjoTrpmiCTm9uNv3YzIRJdKmuN/8cYMYov91Q16dnly9J5fvj/yg2292tl8jTeGDecatcwPctYqHDrbAcY7cPCwFZJcs56Lkl99DlUM4+87jubR9RbOfPMej9d2qlHGDgs7IsAHnwX++Ko/uGnymTBPeJ1wjxm9aM5tZSE3YHVMTMwUiCU99f2pwN+2YKS5jMspS7FLcc2hfLEaXi7mctdwkgId7jGyMxWAjT/oG4OiG+eyfAWRtdl5fUQCNr2rjXSDgc6DALBYMvG7/cROoMy3HG1OLfPMfN1i7pcmYqhzt0BK9bM8BEECWJHMwPxUPWT04xGkf4Y2/XJ5hJwZElaFCG106kZkyJ2CudSfBxgH47jxCwAW5cazdAFIZwOzoQq9dxSIpUq0ysCUhPTBsCwGwPTkbGMd/NIpZ1IeHu7s7Wwia87///Jf9HH//Dy3Hy6+ZU08vYd02vwh/seHVJmzzlKQM7kNyeXo5zlAvXBDB9L1Ut2QkBddScTFAreWtYneO95hRj3a7WOhNmoYbgILHQBI5sPkd5qtGA/c1EwhuHpqheE1B9bDwAob7ZcTsVvRf88PS1PV0dYTWAP0mYZh4KqQua6+Fto4Z7ZE/L7+rxjRNAwW3ctRrO7xTYvZoXTK/GAmfC/fmqZDuhQ3EBIQFmtmKfGMVtD77su3rzX3MGfMo8bu75WKepe/TDCd/ZqyyqhWw12AC+wL6PCxgEv9io9KzGPfvsFm9qReldMb+bzhj0agLmxKEszTM+USL5rqQ5rugXVQefsBS64D2hrX1FdbRwXy9TPunasFkyCyahX5EbEMhCBuNdU4PkI5P3thvT6HRxbwPF3cakqt6TN+zoAu1mVTfS3SRVmFIoBfKFIu71bqEVxD8HQwZ6HA3KZw5OHENhDQeM69r0qyHf5q6divYxsFY+DCEmjf6UobXkxsA6BV+MH1koI1tFyNmmqkR5DmOFYt4ypKJayyS8FSThN8W6nTTrN/nD35EeOaVOSwOt7bwEXyiIdXgdYNcqYm7jR2PlXzgIyz25im0sOKjcTIhmt4WM1Ss+W3WP6E9lqR4e2PsTDiA71mSAPdXZ8dprgcj2chuZ+CYrQwRwuyjNBqy6jJPOzD646oejuVp/wdv+G8OZxrjSO8jB/wKxOG2bpWvk5/ENajBRFwMuP6Z0QTtO/sMuH7WyQwSY5PEiQQLbNhDxMZoJQ2lbS+JHdSmXjerLxoQt6EgXF5o/DJNARTtcJwLlSf83fZn9tnC4CoZIxFmjqgQMjdwC+9mLZBAHo6ZZqjHEnk/W1XM1itF3RPKFmNXNNWN0cSOgC8Xaheaam9s+FiRHaXgcwOvqS3X8trPbeY0622bDdQqKLBaQRHk5OHhY70qB0+Wj7GBkTFzbmlFeZIHH2YoBJouWflotr6W4y4w+A0OFNbv25QkY2bjFrJyecWuzo5f1zBo5hOR8xXJnURQzDXXTQhUbKgpgtdnRmhmet48Bpc/adYPdsj3fe7AmfPYkZOvxHyHD3y+/GZzYPEVbbIvdvjVej9rtMSXhpa4BkqcUzQ/BEbiGh6xAnjEHx0ZcQ2KuMZD/KpU/lEoCf8kFMR/DADiPwj7cA17+Dz5rBEPyzL5fsEO1ziHLwPncA1x+DIgDv/B6IY/ILDhGtOwyj3yYvz7FcIZ/tOQDH98EMN/Ln7hjwFdCGmMLG5QLUc8qtoewts/nCsofEETE1IdLT0eS4qJO66kGIUZp0zEUKoNCYQ2LxJyKEsi6dG47u+QFwpBOfnAw99GPHjZbI+zkqxmSSmQjJfWM6QESJzQ3z8d0u29/WXkVFlftikhdXlcgpQwfmhmeTeU+abes7nuH+xQxvbqb/dpq75L91v1XpPt15tRHO20duJmq7dQ11YvCeMnfythmLmWlQdPWI9RXX/baDaa9e3mdqvR3Gts79SbzWaztVCcw8miwjq6KVFoW1UHM+PLElEMhPhMaw0FPkhnkBvvC+YH/A6Ss60YpwXl/9DFHHCVzd/SsK/oiJlXsSJphDWutjjST5n34s0UNtelmhkf9C/E6YkSmqa8X6xF0TTSPEIcHxYNMczgL+ot0BPO1DBWop3KjsWjIpSPzcDwvVB7rmYVsB6gPjGtEWbOA8SF0ISLAUs1lIXCga6YVtKB5ISFM3QwQPZgkcuRhY+nV5cnpH119b+O/l1Yk4GS2bhBE06rSg/YuDKa3EzwiqXeU4F5IUBAofBJ9glUv0PNmVYZnPmutDUseIRdTbGncXSLYqSFi25bWODbVpq/Getv0rgWvw6hRknqcEjF/sw49E+eyAyWKUsZoQWhQQtaJNrz0iiVT27+QTY+0gGLqNLkZ3h6f4PMjxeBq1HZMQJLkZ8dz1oDEHwoteXXIBd8OO5ca8DjsvB/bjZ9nHZOSVfoqW9Mgz99xzseMtNK8n5/ej63tYTirhqRCmSuCrBUzxB+YXOHu35x4edDztj088m+wE55EVzck2pNo9vGiGvFjLO9Bd9Ot+Cl2Jp3mXIHj6aNud26x+4ebFzeBuRpAiCYeEyBde+r8+3ph8UL+cdeePhnjxTX7py/Nv78nxlLgq7EKWE0GnpzX+K6YHdyVjb5Wnut/YOFBBNGFlasQlZfh/cpIHY2yujPUg4SRs7O5kaGzaURSdE3C1DdK52buNddPWTXXUQAqQuWaQXYwo6C6y72h7/uwi0CPh680+dSsK0zeb/1kcU8G2194IPhdTeNaMKIw5zmgrTHYyZi/kDaTnlY0IlWbk0W4Cd+QYLc/WFAEYHBU1+aGMdYUhhlqZYj9HXTxrU4eRgDdEk4agEfk5CfADK6g3Ow2H0kLDDEmbzHH5A3/NkwWFIY+MDzVzpYlYqW+rhQy+V8GQrYjw73JL/Rs2b3NHunF+ShAf9XxE2JWcLvmHJeYFsMEqbIyb/njgDmkoC00YZNG63esXsUYreQvlrEz/T7SPafws8cD3k6/D8L5ClNNTLBolo2j9n6WNLK5hm1jk4OJWAW0A09szTYHKc0SeBp60CRW8bGeFjj7oFyXzPu/LVs09xprXgvqxAfsg1AebKPbOfzBUy3/Yc2zJujmfcmZJxQ3Zdq1CAfmGKbm2bXCCnq7GFIsxQysRMbNka9Eri51r5hVgehPeMqnA8JVRECbUVyNIZE6biWY+bUCBNwm8ri/PKcAXAWq5Ehj2MmakQxGuO/zVFVs+d5DSCoZlRIbf6x4Z7dqJENfPoZqHtT6xfJmHX91XMj5sanrvwaHMsRaQqBJ1rKQTL0YEIGov08XrQR3C3mF+gpom5YLBCewl9YnBcAAZKUH9LqzNTYq/CkgjR6W/fhC0IJyia4nS+tzfOCpE+vRKGe9TGws56UCaNilojf4Z8Auh8hQgjvGwPfpxnw1ME3lJP7tcrYiraU+YmLQbcyx30THXefWDHvLuKpf9R+GzcCHY8TVxY3oiLr0wgRVsC7cZhTFmytEYzJQqCMhN1Z7IP22Oy5nz51AM9lVi3OqGHmZI2HcdQYK/kwWZHkNdVZdXr5aSDjqft2IGX2CvQzrGFK5GAAScSQgDJQdDzkEWFKSZXmIdhwVEjNDNuaSEWMv6rdfOSM0TtGMpGDn3IP8wdfzb9SzhLww5qzNhPRkBknt7yAJ5eXny67X86vLr90rk6Ou5efPl2taAXx+rSqZhIdmwUhCs2YYqcGS9axg4gkR1KNpQojuEsyqhkdVawhzBSrVBMwnlRWD2Dtr1cOYyWNRd7ItYIf9Jna4eTzh99+f/vxbfuXFUnanH2ajuZpePCYPXpcBvAvbB08X8xb47KJYwS8hnN4JkZ/q940/7tqbR+2moc7z8Dn/wq75t2ey/h+4izd7GipnOsV6JdZmUXRsFjZ/ItRNFQ73+oxXYPfc84wAOHA5zFW4xVQygs1x1DpV4B3NvaMlImFAaX2OoSA+kJLB5Vj2bRc4akP+nVJqc82YaAomA+4pknRmDEeLNS70wHlIsCfM9/ocWHcAQvqHKzPzBOCFpbmK+p/ObEZ73U55xDweGEcc/6CNzevPwgYYLgVC99fmBvz7RU7urnHZ7TtiGmKfciGVAwecX3xbx7CH4aJHPy8cQ2zMfQguRmZqTySv3nnWEpugIscztFitBMa/zfoEtdgDRwGvH1MIcXIDgcZ0SKn26MqGAktKtmY3fHK4ojHMLhFFEM1Z3uwhKSXvJ352wBOM+M85Kr4ceMjyFm+CXhKbJy9QU59mrpF5UDNosIIETbhrFl/Mu+6VpLF1lCO2BZN8jV6tkzMxF2ccFmxzHy1jqHUw7YVfUIuRQQ3OF6cvZLb2cI135jChULPPE//9xn+eIwZHRRKG2oByhp1gVg7yJAl/QaEZDQDl62i7fWRRkMuGAmncm/Kydn72W/Lw9v9+v7ceNozGOtNIIOyuoY87ybGUbMtLAw/j/JyxrVOGDkRMaeLOgCGpWicdStMADq6+OIj5U+uzanQbO6+wLP4sIdnNzjXFjn+Th40VL/EqHDGMk15L2E5upqZcTP1h2CDnCIxNuSV+xiIrNjLeAJZfsae5InVepE5nCyWcZ/aa9sRTcBxAVZkXn6ziDjYw1iquYDt+wnVmgn/6cxcXhyOxYQlDHLWMMYLZjH2jVmc1CGjMVMN2uNdm7Bb0V4MMnXdVmwHcaZ3aJ7CfWyfRoy8ar87fb0CziDdqiKePsAUmNH12Du2BOlmh1dlIEDXIMDND+i28y5PORNaTcKuxStDrbQizyeoQO4SY07Vvg+bG82H1gbE/TwAruPhGciKT3CRdmmPV0T9119dty5nXGQP5FNnBetS4Ulpt9VTh+UShH9zzbr8i4w42is7wnC4ao6wFC+w56FVsCAWNhXNdw3OLGgUXMwJgroAIcZoNCR2svImKXgBt2zimtDkLe4KSOEps0MjbLnLMOlNSJr16pj74YcE+EPBqB6Sm5Djxk83S2kKP0405NuLaepCGljR+BzyevpnZoPBPdf3L+YphgUCKVo6VrEJ4OiR43kc62dx0xlSIaQgdngS0STKElSA3jpdJR/9hM7VNmgRjWF2bcduZHhDYbKVkF1hzmyJ6jBfbSmiXVf+ruz3U1ZV6WGJfpxttRw8HxDC7f2wx+nTdLvJADpiJeRXeLKXqDdDrYToO650RpPu/Llez7J0S4Tb+VxO10p5WHzbLMDA8tsG+ph8qwMfJvu7D3zkePkD347zDJtp0ZfOCtLJz2+5VZBfsb6YIn1pjQGQCF1EJOHVI63CdMRPF0A+8TTgbxmWNEv6Q5rO00BjEVbc8CSdjHoSOlsN4ZVc2imrumXY+0L3rfm6fv0QzbKmBN2X6rZKqJPNttkPt3DVmOdhwcUoTVMZ8bzRMw1ufP3W94L6JDBEUSOUKGZv/dzQPkUGromnJyqN7ge1s5C2vcFN7ukkxf5s2mwCuy4wjetMbPusA9g7Xhbl8/mBzTewYgDSI4t8nF+979ju13ADSxM5kFlqOxe2LfAyw+BfRytGR+RV+7jz2qVYMLfMflQgKsVHsT7KXZdBM6SIJgmLyf88bl+1G+R3KVgjAHjiaQ7FnKVBOXFv4lvXa2nTsV23aRLLe5FIWmiq4st0SFuQ9nEHLmknY2OEBnve3dVKNTokN0eH12Oqh9daXhuawVnw789hKkes6zfpDUrgZupTP7K9Ew7AGOwr5ZImyE3+rQa5KU94M92QPPimeV9CKkpfmn44fwDyq/LdkTdCxgfNzzc1vMAPrx1h4wGB5Yb6wSLO3+Z36u0fVJbJdqH4iKqJLX87PSavfj49fv3kNf1mq9lsLWo1wTzfhJcwB3EmH8tcrgOExSjeq4iTj8d7cEYveiw7hI1WRfR1PrRbKyEwz26vgMTtvf2VELnXmieYtyCRe63tFRCZxoxV9Vp1OscnJxdLEclFjgm38uItM3beD9CZhniu5tafLXotKbPtvf2dtzuLqrMRH7EqMw4+nn48wVsUl1oUZgxjzCBUckQqZ17IfiEERRDtsdDxkFNBoXyZpikfAJZPujViMad1uEUIf248DPUo+eO0fd4ODIQ+jzhN8M7hv2wLSJ9m0CC/Gvt7hCmBVICNBswYcwpvvHq28YofcyRT7dFhC6zbpmqL7sFRdVvwo9mB4SpwQWSkoXOx3ZY0DGTnu6+5v9tceO8tmRs5IzXS5zQaJ8n2E11U3hU6K+dTR7u1xTzoUO4uOoxYzPG1SXylZXCu3+LumbwXlaVRgQsME2yCB6Vm1pUvY83M2brzb6uqf+/s8DABtza16t7Fn5GJWXDj4yBv8XmZmFvLb5Qx+xYJhUcXX4rJhJqqAdPeN56dULhwNuEYypnHVFSVf4v+KuAPwDQl476WAz1R7bLT6pi6PsXmKouOxuwbVOp75oNPF+T9guYpRAvwav5bcRqPZ/aumIXxTEb3GzuNg/1ms9F6s9uaG1uvzDEfjSsMy262MRLr0PQwRwQaZ5OLE3xLSVsQSwWp16HlIjxGArqI+ctU39k+FwOmxooLjbUqANlyZ5QddL4HFPAxt1fuUhGJQG0yZnXgM9eZiorU12OmZEjvGJFRlCnA1cHGF/fYrxDqJKzFp6gP7wH1WAtfrJRR1jykumCY9rlibAJaZauXyMEWgjLUjS1l9NrWdrO1u9VsbUGsi4tB3aab1lE4dVsK3jA2azkm04z23zZ3ol12sL3dMj/EEd072N+hNN7Zj+P+4vvFpZ514VWp0ATy78kymrBz0T49v2qc/HayOMe2MLFqNu00y7C74TU/AD7ZiCn8/GnMEM2GdBD+YEF5LNk+Am87oIEEF+i9FSLSQeUE2i0YlTSDQpHQhvl1RnPG1v7O20XPdrQcui/dRLxCAweMRGPlpJNRwsXtwtejFfr0sMjg2L7CHRxzBXiTluYycox5bEE+ssoix1dDOGwUBI2/QNBY5bhsQV30q85URBmdmdXGldc9OIn4u3pwzlqKf3rzzSdl8p113XyCl5fQiuM7a7f5hDRfTB+OhfpsPsHY391/o/IGm3Py/gJ6cXyTzppPiOMHbdwxi+MfrpfmY0z+OE00Z3H4o3XP/AqP/9y2mV8RzD+rX+ZXhPE9NMqcxcK6Q+Y37JA5cwHWrTG/XWvMmQvwg/fEfJrn76sZ5lO8vATX+/vpgvmUJF+M271Q+8unOPu7/e6V9r2cl9EX4GQ/t+HlU6z9gxzm77LFZciISnU3ZWyed+1RVxhLV6bhULnQxk0aYKMLW1UDTrFvjZbywVCHVgtWrnjypjnchHhAq1Vv7l213hxu7x3uvmk0mwshpQ6YbERcT6oCFj5yerN8iS2FVowugLYFNEuhufHIulEpPXQlhF/dy7qFyItKecp+9s10NnPnC1h6RbYqWo/zAsCznaxMvlR6SNrgpCygGJATsKW6PJVVLdGRNddOO59gjcpmy8KrgLRX9U5YumfunCMq6CJwmoZuQG4sWQwlmgdMdkNMquJpIsWA6yxGPZZQDb+UddD/JRuJFBuHpP5mp7Hf2n2706yRjYTqjUOyu9fYa+4dtN6S/7egSqqyYPJLylTdlZ1PpeZhs1xbeahtqeodS8zfBoqKLKEqhJnXQzYhETX+aE9mYRnikfPqdbHBHVdYSxgxYVz3Gl6uJ1IqG3Co+ZhB7Dr9+EFdx2MPPIH2eo1E3jwtltPmxYEYueICGoeNoCh0wKTjtpx60pOplqIeL3CTYhZwLFNNk6re/M0LGB4183SZKyya46sAvw2dovKMYZtV60FOR3Ti4RBvhbwX0EGIGFZgIqnI76cXoWdIiL2stz1m7nnMkgmWazpnUkv3Y1nIB7vN3QVC3EbAig2MxVWher2EGZ7SrvXPC+CzBsRXpF8t4TPV6+eM9diCe9oYdX9JUYm1MUQAaWLGd+dzrorSLBqazXjaPm8Hz83k0J7aW201AGuFbr3LmJBpt81VgGszN+d8nvI0/9Cz23Pl6TDF3lxE9v1L9kRvrlZju7HTWCBHLqHf1OQHCIIXYfGPqLrlYtDQSVV1hxtXivb7PCJnhk1yoaSWkUwgQmisZ0tB2rgWly5uizeDeSu/sMcf+Yn8+uH06gTb9f18eXJyjj+2P747ucQfL0+OSz384EsLCMjWT3XpPKGIVe0NN2vYQsfLwB9U32aLmF06B+uP3RF9/bUHeAffqHSB1353dwE33yYcVxWfmO5k7CfeTF2uc3nZEvVXN1PJkGYLqOaqGwVfFnoEJ1zcQs2WDAFAZnV8enKjunsWW9cbJKls+S9tNZvN1vbOAmrdWBapsbUAFTuso125H/HJodXCLNClTzOBNmiPpmx/lzARydgo29wMfS+Vx/xwxBKJaexSpPlZ32EaTNaTB1Ahl2zwOWNqYj+rFRvBRBLeISli3+vCwqgYhQO3lzfJuGs+u8lvqeXYLmIv026LBt3wMPqhWCTvmHKwldC9J4f28r1SjIq6PPm5++70vH35n8i5V+oz0DU+v8vaR832L5/fXbXb7Tb8jv/8a9lVRyS2r3XMcym2M9f2yNXTGp1tVtZsfBzX4bR6OV14GaBFg2Bqs74JS2KXx5MMOyLlYpDkXoV93u8PzER+ZeTb+b0Gcj757aJ9ftzt/P7aIt3ki5LTwHVeaQT4RzCundLi+6cYO4YJYe+a0T9+Obs6hblgbDcctD/xI95RxQE5O2FioIc4rL3aBl7zzWzGPP710+Ux7uWTn7ufzW8F0oONF+wr79LFLOKjUmU2ecUaA3Kz0dq4mQHbtPnHxtHhtdL0WrG4q/X4usfF9WhCx+MGe2ALNcss7rVyucFq+rFpKmKq4uIWQDA+q1M8UNA007hLlmBsyKfziFbCU7vXU+wOHXU4J11Rq5mvdEx8+PfZxyV4uGWTClj4wO9YHTriG1MFalZkHzAPy3f+n95f/dq+PLnOi5ec2j+/uj7KlGJC2yuN69MRHTCsLzmBrrBmZ3+CSdPrey4MoWbDLiGQch3QSiTyPkdayqu6sRMu5IEJewTMWt7rpWXkVcYMWV0fs142GCwC3eSFFpJeVRQeM4Os9VDaRoszkUZUCKa6qaZzIYQ+Zs1DtNoQ2/5l6+T40nY5dCCfGXSO7mdJMiEx09gbeUQTHnGZpWEBFPTk/HJ5VrblF+DN+s/L8HWO3odZBT6Cln6h2Vpsi27bqiNiAfgz0ExvVqrE9gLxvApr1jauLJJ/wQHzZyiahkcTI4lPwC0c6Fy4bv7NRuiLl91123WfZloKOZJZWke73n6sNO/TSONvHsej5N7HckS5qBu54KNQ71Sncazwd7OP8Cc+vtsN/sDHd/v216kxRzQKnhtlmj3gj8b3tD9hn0/8xXXsxN8ylVwLEg75ExTN1WkE0Vx86h61Vd0pjPotm+BfHvaaB/Ugw6YUnPB8PH+7ZCppoMSqcm2OYXSnoTKV5JbcBlQW+FqzjcAQPhUklSNGIpqC62+cxhGdEHBTLfji6YU5E7akwhAAbolkkgO+UFJgjThkENtuHTuIARRiHjjEGvaBdLb1DQ5xg3H9kEJkyBBmy/EMnQnXTNGEnF7c7fsxmYgSaXOdb/64QUDC/7ohr05Prt6Ty/dHftDtNzvbr5Gm8ME8PdOZ5u5uwWOPWpQrR24e7gGyS9ZsUfL/P3vfutxGjjX2f58CpamKrS9Ui6TuTk22ZEn+Rln5Ekve+ZLJlgR2gyRGTaANoCVzKj/yGnm9PEkKB5dGXyg1KdGiZLu2dkSyG8C54OCcg3NZjG+WXve1aH7tMezTR/3kRUFL3/JFaHMkaNUJTNemaOxFfXTXrU4ShegQUWWKhMqOZmDGFSI3REz1FKYUaeX9yuBu2owIyhM0yaVpoTlw5YtIYkwf4oKjimMdHh4QtJax0VoRFQzVZiP93cutfqu5bSgwVI5eFrN9MlViA0Fli2TAtvrlKhBbimdrFcJe/XJlEnEUyrAoyrHZRS9SYByAztO0BcAV/8PjZ9afDk0d1C+fz0ypdVNiw3abnvIcOl8XEnUaMAjU+S0scsrQlQPtCkovQc0RVWoQKUjMmVQiBx0Q4tDCuu9Qw6QAw/i+Z3oHy7Luzfb21qapIPL3r7/a783nXxTPFqOTEz2rQKtXX5i/APAiEdhZIkng3qDAocddg+igDDGibrm4RhPOqOKCspGRSF6bdefygGjRZ1nE1gDEMiQ6Bu0epXxkAxX0q1q6DhVhpvJxqEoa1z5W42rndM8jE2LZz7/mh8XSNSt0C+2Y7tfERDUyruqSaSF20aPN+HkxTsqwlIHwevTyuHZ4J6DsUblAkKpZbKuCIHe5Rz9Zx0ewmEDSWtSuLbq+uS+f7u/Aoc+JmQve3q5nbCx0v6RX/zUnS0tTAN0KJrAbygcIAWDmF+vJbQLW70lNpQrj187Gv8PZaBSwsAJ5OEukzxhcVqcZ1++CtBCF6W/yXYO1R1YXNw3bMcw3yJV/qhNMZoA1Kpwf0dScZ4hMMlWsB5Zunryyb1fKayV0CJdaCiKABkTdkqBdKjTmv+XGhFlUATDWIBEkuVyumXYBztPRmIAcdpPCuWEm7gBisox42SHzgfmpciVV0l2DsczD4KpdG3IeXtetQeWi8Iuq2Dc6sCVAQhQREwi6ywSJqSTp1HUOSKlUKKXXpYRKmQ+H9JsfEZ55rQX+m81N84h5IuJitB6hCzF1t5NZJvg3OjHZt1RCbxk6ydIpUvi6HHZh1WNN8xQPSCrNLYfWCeEQvSVpCtBfnB3LQsbFPMqvGwo2PSjlXvOOjMdkeaGP5zD6bNENx2nVJjE321dvGpVls94ZB/OCKHAsusxt4ydxnSZM9KdxZH7NcWp0MfsMmGDW2AuiMdPUocFkWpBvMcmMRjPmti+baWFU2VZWLkTgM8GAUFrq4FBdAWRvUDOXEYzwu2086kNUwXzRCh3MHGPGeKGMlvZgJ8BA4QqpAjQgKb9tFgnN8qMsY0LcGr8RliqaTO0IZhMZKYKl8gqD99PYUUq2L8Aqba6Ol3KOgWU+6GsG6pUEVae04YvlmYPFWj2uPlMxxprxSukzSQlM08IJ0LDxsVwgpU2zu+LZJQD1HQ4LMhzaMButBhu2sbh4TS7Ojtc7xknlo18LKhSGGwjdjmsFAuIzlAjBlmlwi1TnLXxexZOaZsAVz/tMgfNk1nFSUKLdwQLfL8ZgrvL0khjrix3+4dbJz1Jwq1AK7mcVuDvQ8WwLwP2s/fZItd9eYtm3H7Ti289ib02YePFp6y+9xNuLru72wgu7/azpdj9OftRybs+7ktvPIm5PV8TtZ/22p6vf9oOVbnshVdt+Fmx7bF5YGVv5gbXafoQybS+zQtuPVZzt+dZlc4H4EU4pXpb7f02rvzDBayK9hHVT2xb/kgDtIOELwrWVyAFUl/0R5gdA+B02/dPia6Ns4pJf28bw+VY7+jfN3NPof7HfxxDqy1U4pCBfcwq92qY8hzuvXBKE0fvTi88n6PDi4j8d/QPaYAUlcDwIAbhRLfvg1R9o7T82DkeEqTXUPgvSk2ZpzYmALjSpEaQwUeHeEXJwoLIOJOagARnjG8pFiD1/3TLhCUmJVS1ryAuR34zxcNAG5Ps10qSO6PPuzk5/bvQuUcdYq5YpeFYohlvlGpIPk3eUJXNjOUux0sJqqTLGT/J98R1mav0zzNQ6/P28lip1+Ffu8p7gT3R4bGutHH0yf5xRltv0qQmOP56bPz+YSGP4EA75cTikMUFbuzvmuXOM7Ruudx+7lyMcG4TjNnGEx2+zkLMTLiTkll1eA/hDlGpszMcjIW4cuzx8T5YYbvaZ49dYgqBOBWeXY6VwfB1NqBIEete7ATZBRm7OTZ6lZk2O7b29Vt3m3LCeAiEi59qwxlFodsx70x/VfLjgPC3tXoZabqNGymkI6wTTk7QlhtKaUPx91AGYqokIEfofdwJc0tJglE4p3Ai9Jt+i2XxqXpGbF4fdbre/idbrGINfmhCzzIM8TCJ3vNoaSSFOagzycCTVcVTO2a+g6TtL2lykq4SscPg64tqOUsYricfgB/8+W9PN9uDd6QaaD53uLbl50evuHDRwH3w/A0OPu0cfJTfsDsl7pzo/Nx1maFdLo8MRn0wwS+Ay5NxAwUamWXQmiLuOr9PoiQREa3zeY78sDZ/t352BWJkPvpesgMB0IzDCWR8qf8OxHobebrc3S3RE3W7rm+sZyF1BMTNbksxJoLtNtSUT6BO/JeJ8TNL2WmszhZ5GyLRGdYjeWZr9klE93/t3k8MTIzX+F0UVbLczc103EjzP3iCjVVfasGum915ZxRHWb2k7jJl6oZAHKG0dComGPM4l4sb76sZHKHN1aamSJB3CmUShpBrcO6RThG84TSSibCMhGaQb4nQqqSxC3c0SvkU73QM7anhJN6SpC9C2lfc1UH9rQIoSts5UuKMdhmKajZfmvT83+aL24sCV2jBTGnZMcuG/NiW5QlTXxOXZ+eXJ0fFvJ5efzw8vfz+9+O3y8OT8stffvzx6e3RprtLbbtQ4pYSpqB5v/+gp1ifvN1zJSqkwSzZwyln5ypVD4mgRRGLWVouFymUOzDPJFfyxATm00tS2RVd1kC7jMRSrkXAtVASa+EEhJccktZo7BKwgc6XeUuX0NIpa34zNWsmSUHwINST5sITrYHJbUWyCrwnKs+qFt0cGLPEuWixEg6L2jqMCVjbcpwjtMRVZIOIxDIM0cgXWVU/G+GPNEGWtg9xf7T2Rdp1jLMfRJNlZEmGOShKLjbQqTiE2zm3798c7KKEjYq4yj08+e/rZC0aPPT5ss2UqgVYmY4tDSRENq/V/hVl7PviqKdDKlF31sVUwRo0S3Xd7u0d77/pHOztv3x3vHe+f7L/df7f99t3bd92jg5PWjQxCmsgx7j0ZUc5/O+w9e6ocnGwdbB0fbPW29vf394/7+/v93d2j/vFBb6ff2z7uHfeOjk7e9lvHXVWoUxw1T0Kf/s5uM4U8Dm+Ku/OHU6gY1VDqcfbN7v7eu93d3cPuzvbJu97eYXf/pP+u39vtnxy+3T56e9Q97u/unPSO9/b3dt6e7G2/fbd1tNfrHx0e9I8P37UO8bYwmiSEJRGtIb4qyAB0ZdthBe4TqHaNB1GpgmJApZrLo0hJ+sy5QkeHkLp0yoYCm2pJuSDoguBJBx0f/eqzZY+Pfp0jl8NO/ifeWtbxbYSAKTJUFPg380ooeJ5oHXtsEsanKCNCs5pmsfPzs81C70ZojFkix/i6Xv4p2SY7g95+sjvY2Yn3ev29/v7BVr/fiw92B7jfvleORcdjZHkcY0U2IRMi0JGhQpuZpE3SR7gzG/IjXvW7/d5GV//vAvIi3nS78/VuCOB9cNbHvABXk0DuA7Z3sNd9DGChSJRYZjzmoVa8Y5ymWlgydP7h1MpURdJU2mAeyCQ0GTJjLhVIFcXNN8FZ6eQDhI8rRSbG9WnuD7UxhRSP0O+m8l8p1vwG0xQPtEjwgeZ+3BHRmM+osYOvEqIFnOl8ZYtKNieLzV1F0uHcyMqnlM81iVxIYo+WeyXyZGp+A1F8zON84gvKP5Iklnlmmv1cGlt6WUEm3qyy0zTrDiUj3nwzJmnKmwyWGRZ8f2f38t+P3msLfmt/W9szxYMnR8d3PerpsraQ/fOzLsDT1QUISfCjFwVoxMUzqwjQAMMqpDc8s3IADVhcmfyGhWoBNAD01LkNSy8EcA/MK5Dr8F2qADSg4YUmR4SQvrj8/ypwLyf5P4TspWX+z4Dtx037n4GQHyvnfwYSnkPCf7j0n9n+3zHbv4T4n6n+3y/Vv4T4F57n3wzr80ryb4JhFUzg55Ph34TBlTF/F0rvb4Loqe3fR83tvw/AFTB2503sbwLpBzBcn2VK/zLtmRkBjIWF49rMjugNYfaapGMuNHGWpTTGg7R+Ey1JnPV3dkVry4VIhQcpCPYWkA44TwlmTQC9NT+hYYpLYNny7xdn54iREVfU3FfdYhm04dSKp1eplMBMQqN2GyfLEGGgD+nPOWMkbb3dGPmmLl3I7HclpY/THRD4CtZNkgh9snX1jY2FaLmNx+nhh8OiffLrsFMQxQxD2DKWWkudEKbkpkrlhm+spmHYMOPO/CH6NlaT9BecZmzDrXGDJnK9EiJlO7IURkPKb4mAFiON7a82e1FrphNE5pOlMhyVleBqYDg7L7SF8dBq9vpmFJwql7ZmM3OfvpoRv3Zt80b81kF6qojfWStZEoqXGfEb0mIhGqxmxK9d54uJ+HVkes4RvyFNXkbE71NS5bEjfivUeSERvy0pVIz6DCN+LYxLjfg9nyu2txbTW5wRZq01U+67xPbayf/EW0sLImsO7jUTP1pw79bB9vZ2Dw92d/Z2tkm/390b9EhvsL2zN9ja3e61L+Bk8PFYV7hS4UlWi3W1gZ2rENwbwPsot7rzAPzdg3stsMsNND1vHVJaEcgNAqAWdLQ0AfAzDvLp4iBDEvzocZCNuHhmcZANMKzCJdAzi4NswOLKXAQtFAfZANBT3wMtPQ7yHphX4Grou8RBNqDhhV4nhZC+uDjIKnAvJw4yhOylxUHOgO3HjYOcgZAfKw5yBhKeQxxkuPSfcZDfMQ6yhPifcZDfLw6yhPgXHgfZDOvzioNsgmEVTODnEwfZhMGVMX8XioNsguip7d9HjYO8D8AVMHbnjYNsAukHMFyfZRxk+Zr+sVf7wahmKMPCX2246+YMC2njteB7LuiIauYz0WkNFzlRv7Vz3NFiyeGBHzT2U/oXSUwIHVxh++hAOERCMO8D0RUenQmgZ7sMM1cbuQmmOkQz4ClB88qq7LRQHV33jwwz0KNdw6iYm+r+WkwogWMS/c2u/NA8LIi9sIL7fZ5p8xxC9cwg2ESCYojf6yCZx2MIBYCWEUQqExsKYQV2XL3TaExg52KUYIUHGtlfcyKmkeGLgvuHwwO8f7DfG+zFcbKD/9YCpQaK74jTKtrgs6nHKk0x5SwliNwADlN6TUKU2UC1AdEmJVJ8RDSqjOnkrvTsyFib1cIjdoxZkhoTzE9CmSJiwwZUksThWlbxuj0YHvSHWzt7e4Ot7QTv4q2YHPQPki7pku29rd0yOt1avzNS3bSt+TV8h5oaSmM6GmtkwZL1e7dcXKMJwTIX1qIEJvZMaRnYozxkY3dIVJDZ7Q67u3sYdwf4oNsf7AXIy4URWLYA8ZfPZ/BxdgHiL5/PXGlhOO8SraRCtR9j/HE9pT0PsVDaIP/y+Uya60n7pFu8hn8gCL6mbIQSfss0e3Ak4zGZkA4yRZw6KMNqbN/nyIXTPqSmsBl4SYL61TGM7tgkF2khdNbK9afWPGsgdMqQ5BMCkdFaOmk8T/DUlMy28eunnzQWNjVqNb4TKkis0mnH+x1wGTRjT0d6bHBm6LE7Jj7cXy6jW3BjjLieQ/90ZWtnGcyFKzQA6YXZO2q9zpQqInCKTj/d7PoxCYtTbh2LV39cAe2u/nWFXp+eXLxDn98d+UH7e1v9dbOm8MHCR+L8LBAVPND4yRTsDLvf3HL9iGbZr6oHXkPlL5+84OLbl8UR0ABAL6tAnAmu1VLXTd6gntit7UEDXoLY3sSF3aUEJ2b3qIBUF/XRqUQQXiCJQlRLJxti3dF8ybjS4l9MoS77GI7H8vuVwd20GRGUJ2iSSwWDDLSE1+sjSfmEKHIVzMMDgtYyNgrKY+nX1yL9XTDXB65sdPKtKQ5n4QJ9R6+zOL3cSiV67cxZhUU0+mu9A5D7MQFtWOvuLAwU9Iz1em3011rHrMeMsLZe56fMeq0cEw0FHk3aOacX4qFPXCirjVuxguDqymyCX64CIaN4tlah19UvV+YuSpUUZLdoC56HJU/bqLEu+MR++Z2bv5wOTVMNfbpA61E60VIRMzgKpzyHCu6FzJsGtJaKh+FclKGrXKSRHu8KsqMgyBRkptm3VILLkpmwJpIYcw+0TieIQH3yQ0qei7g5xcUl4hTS6M329tamJFjE479//dV+bz7/onhWoo0TDitPn1df2IQnWmVKCokGbCuRJISV8Obx1bDzKUPM9FpEE86o4tqgMQKFD0DhSfxpOSBaclm2AEoKgmVIaAzJYijlI9nx5xl0NVCEoT+1bPIGhQ0aBgWktKFCvpgQy3L+NT8sllrO3mLpF9opKUiMq7pgWYhF9Ggzfi5xT4alDGTPo+cV2eGLHhFwgEWVNajx/NxbmUeNK3ME8s8iYq0yLRdz3hwah8cba0I3roMXsrS2ju3t+s3C9vZWaVFgUy5T7YAJLLOaXwfEaB/mF5uf1wSD53eN0wpT1c6Xv8P5YnST0NUSzhJpmY3LCiTj+l3YiaK4IjNhE8HaI6t9CnMXB/MNcuWf6gSTGWCNduNHhNwBzBCZZKpYDyzdPHll344x01LE3w9TyE1gimJF0ICoW0LKqZbqlhulvXKImuxLIkhyuVx74yKwIotJQdQ6C0rDm2Wk6CydD8xPARlr2lowlnkYDLy1IedhhNGaJsha+EVVUhqtz+I1IYqICWUk0ednTCVJbWIHhiQ/634obqZlPhzSb35EeAbyWd9sbppHzBMRF6P1CF2Iqa0sjLNM8G90YmI1qNS2iKSTLJ0iBRZnXSHUpEzxgKRSS58U1CU4d25JmgL0F2fHshA0MY/y67W6CK8GYHlfGhi2y+KDcxh9tliEg6WqXJuIgKs3jeqhWe+MI6oMmWOoZTK5nwRkuVWGzXE/RV9znBplwz7DTNd5EEiFHMBp6qAzXnryLSaZObLHXFsx+rWcJVazru3iCEx17JwbgV1RXQH4D23eupFO8HtsvJPe36NcdziYOcaM8ULZKu2YToCBwgKvAjQgqUlUqW/g5t1elgghbo27AksVTaZ2BMPyZs9jqdaiqnvAjlKyzQBWae93vExyfCnzQT+S+aBXEiud0vYslmeku1XlXax8McaacYbog0EJTNPCSG3Ypli2vu5UPLsEML6DMCfDIYkh10BrdoZRLPSvycXZ8XrHeEOuGb9lGoUF3gv7A4Rix3kZQbyFWzvYJA2GenXewrkSdFWL+QT44HnLfJD3s8R9QYl2gh++L/FNLolYYijBFzt8g8IdrsB4TK2L132e7eMFLgRXvvX0Os0RUWaUYi0g8IDnRnDCo8ZWg9Z05AZ7U9h6FcHK81xiu9hp/hjjGwKeGAKhHVwELh2mBCXSqo0wCYgVLsAyZPAaTZykcO5ozBCG5HtrPZoTIBCUE0u4B7WlG2M2IjJarjQIu1wbby8X0wLloApPCIS78eEsXQ4zdHZ8+Emj9tAw87EfKhQD7cuiW9gh2WiJjF3OZmpfG8kuTx+qjxzG8/iNRzWcr2ShAHS0xuC7XtTsx8N0QIRCJ5RJRSibFyXA60/GszD7UzOtQcHSmv3Wrwt9BSaA3jbilFOpyGQzS7HSAnVu3jZQLPFgCaloJpt3iUGK/qPz2BffMNYWa4BOMsK0JC0dUkO4wzfSkiHMOJtO6F+B79eg33/8IskwT/UmvNIvRTS50jxoPmgAr7zSGXM2NHTGaflgZEmDHp9LkszPrlVGjYt8jsdkUnerIBvSfM83ehs7G/3eRr/b3+5vH/T6e/t7G/3dg/52/2C7u73R39rpHezs7u3vbvS6c5S2tiDWuXhRIB9fPJ+PubA2IRco5aPgYrcJVzgiC4pmwdOlpTP7WkQmPEPPhLBR3RQt9rnV0Sogvfpj7ZoOMMOXOJlQttZBa4KAkchGl3rAOSr8vDhtyV8hO0Phh1QIC+hXVCUsFvhTKWxAyg+sFlaR8FwVwyocK6kaFov8qRw+RDks8PiC1cMCyB9bQSzw8EOoiE+hQYRxT6uoHLQPunkEzcGt7qUqBWX4VvK8Ly/x+x/lbv6fp/TMU9qh6LkewL6y+Wqdre0l3QMPXh+l8yOcqQqLEVE/pGvCgr6ifgm7ulXVO57AKWEx8lKVj3kxsJLqybxArKQvwq7wp4rzEEeEReJzVYLaQ7hiatJ3dkFYJLxgXSkMlrrEI5fJE4RMoeLbFoFTZgwXPsUgdx9q+06IiY3HaCD4bZAt7Xf3xZhMbTaKHPNbpE8ihm7JwKUAQ+6KHoqyURFob5P/c79UF+T+8FinhOhpv5cYt7NVaUw/jTkj99guS1lQgdK61MFDLGhpUXPkZz2dKscCbrkscUsVwvf8L5qmeHMn6qLXhgb/BR19+mLpgT6eo17/smdCON/jWH/xH+voMMtS8jsZ/IOqzd3uTtSLejt+na//8dvF+7OOeeffSXzN112xkc1eP+qi93xAU7LZ2znpbe9bJG/udrdtayiPahkN8YSmy0qg+XiOzPjotYv8FCQZY9VBCRlQzDpoKAgZyKSDbilL+K1cryHQPFlbd7sMy9U0vT+aEhtsZNVDZw6wMDHZt/oQUKrLKME17jIM857/iW9IFUfXRDCyLKOtBoOZzS/bVAjBt7P2xXa0HXU3er3+BhQEpXF19Stozj2Ywq7MQEDfWST9jyo+nAnxvejp5rN7NyZMcdlB+SBnKr9rv2JxS2v7VS9saWaCNMHvV3YeW3kBrAWsyIgL+pd5gleBpExxT1wtju2RNRAcJ1AWkIhYK/4gxyiRgQ3x0T8uCRryNOW3emTbT7DIlYZMuNe+5tD6G5RSln/roAmOAaOMfiuSNSxe62UjPp6jKc9fvRL6hMeQlwEpADbtyCYDp1Sqjk3zD/I8TGkBP2TGs1zbUEmEPqUES4JSolAuISMCDaYaUUzPgJkpA2qmOjk672isZoJnXBJEg/xAnCTQK7Ie0w9gttWUuYyWW+aqxudtBVavG/WqB+hylxrUD7tHjdKHfqCE36T2wLTq9z/PDj+0Ubz1c07lxqLI4bQm5BTtd/tR7ytSePRarpvksQzH10T5AkbS5H5giSgbQSkT6Kph/oTxsZQ8prZKnx6CueRusN3BuNdQ+42JfelgO5k5El1HSb9TPpgc90hD3wSFIDEXiR6OslFqoVV4BGlmIB1yKAcBbSwd8camAIJe6NcNyja+IsJinMncrFJ2rOuhaWWolLeuphmNg3w3m20BJV6wT9CXhEku0GsSjSL0Pwm57qDfqSByjMX1OmSf0xuSTpE3z8DRJPAQKitXMEEZI2ImVc0QyDxkgSsILNFrl0diR7W/leFfnwHk3eAZ+Oy480J5B3hG2v3NifN06uUvZV5CadhZA69oRjddjYhDh8KjEcgCO+THgWs7FjC3494o5HJ7CjTwn3vcDul5O3QtQa0WvytsXTHnkEqojAUBB1h1h9kxYQXBeLPoMqSC3OI0lR0kgPllx3hAcIIGOMUsJkI+gv27NCcsAHp6bAwLzSpFvWpPlbocb3sWLdE8/pjZ6p0AAbie5oGB50rS5J5K6P40yFNGBB5QX1nWHQu1H2afD/p4KA3UIrMNN0yNamlurrV04Zh6UFqZUfiWWhICWk7xoVMgtPwX8ZgqYvp1AYCqhi8MYUiyyPe9AMXRFl1x2vaGlwevh+EtyTFYwXqu8y/nJ+v6D9NIIYUH/aDFC67qIhfond3n66VM1aKr9dccp1M5yrFIIvM3VAP/eksGY5Jmm0N+CZWB0k2tH6YkGRE99GYJwEunaxMZjdXkj/8OA/mFlZFRPPuv9ca6MK7GlctFrKuVr/5Yc3DNcZMbp/pwcUnkS+ISaA5RmsgXVC1hQcZcFJpoiTiFrycsZwPNQqD3eHwj5Wa9KO4/z1tX8A5WvGJmdg2XwRfNiIQtZ0826Q96nMKZGU7b9PaMTRHfkGhClSCm17uWaJtD/BWYO/0lviGXkHB7GSxOXsaCaLPqjyMoKO+nDSUtJebEPvmWcanlxdE/T0II/1Wj6inTNtTHc2S60aB+1OtHu52wnEsZHdYW/PzpaI723gR6Myx7WzjZGdxKgX5kLk+pvIM09S3RRKKGPXHSFgVL01M05A5iKxBenx6vu+ICtuFGqShH09GJTI53hE7DtGyUly/67AR2UHcrXcdr9cxoy/q3Y6wuqbzUW4Am65bXqzxeOAaqvH56/K8GGm2YDkfdbrd1lxuo7EmWV5/8EAliyqrNFjAlLdtKG1NqdUIVHRkjyePCEcNzf1KhSxUxzRSJR3RjQJn+FrzC8Yj+Xf/xq8fjbq83Bxo1410ulfmtrckFkjFmzaza2POq1+3tR/MwhR6fERHdEJbwZVV2v7DFYmYd67AEZJZQA+uCMDxI27cxirkg0aBogHMXMMOU48Zj9NW5HsZUjBCYjewtajfqav271426tu6L/hMNiLuFmHCpkCQ3RIS1Bd9qxVLaEbm2UbWeJiWRcgLXtiC1s5RT5ZAyIUrQWKLXWCkcX6MbCPEp/J6mrN83qqYdlAl6Q1MyIrbqsY3rUESY0s/rHUQnGY5VMWoYpaHH8OPq10YChtVD2XgrWJNt+QoFp2coAQ1Kl1PQgXU3Eh7nGuT1mn66E+3MR2LCbqjgTI/W6vbzO9H6JFzWfUTHbIp80UrgEkuhDlqEQnC3TwXR48sVIJEik4yLVaLOhV3RfYSBK8QJVrlBtEZpQoNCWp3See1oFT/evmiJ4eV61MF8/+A6p5T8H4XB/PrDP4/Xi8Meqo4paF3tcQRkAP7E7JqyETiy18747VoHrb0nCc0na4ab136jo/EakEAbZ+imr4nqxacfEThBVt2UEEFYzKVgqmKsrahrq1dNwdOYkCFl5bK8eoTi4RKNAi6CJ6hE/JaRxGgvmOGR8US9O/18fhF9FCPTLAe9hi+08ERfzjdMd3/G2UYm+JAGplbQpqaDbsdcCwMqXS1txdGYpBnIffC7SxIDc2rNFuSE1r4yzoLGb4rgiUQ4FlwaxfmWizSZwaLsJokYlSoa8RvwVGxYUQTsWhcG5gqlHatakixRu/BUb9QwoO6Txh4ICncIYuj5Bo3WU4+zTFAuqLKEQIKMsIAYg0AELIbBmhKvp4n91Pd4Jb/tdA9CZyR0yDmqtH6/876KSq0FpOZwMDc1xhLRG8u5J/Vm+Vbpzy9LPThDvyU13TvSKUr5aGS7R6CLs3Okham570noiMJJ6DrzFe32PEZInCut46EBZVhQrcecb74/fX9Sno3ZqPcBT+AZOEBxOpVQThkKtbtVcvD7X/s9+7ur5h42OzOBsdJ0stBvd6CCt78NhojAK/0DdEG6imAYO+IYyzGRjt+OTz5vEKZPjXK7fS1mfMy6bTug37yCNi9QHL90CTMgxWWzvx00t1tmIfrlSI5xf2f3at2Dd3JjiYpVEYgbNs6tOZvdDVNx/SY75aU4VJheTAYfYZ1K647W1LYOLHSlUhkFfaOubPsIOyL8HKeUMGUR+vC7EpzCBtbHDWQ0LCte1Dffsg3ygnltHczX54cf1iMTyafnkegGi6k+EeLKNgW1wfUENQpEQCtw+QygqafenhDFaShaNNHQ3H/84RyFECP0Wg/lylhLq66XEkVIvQXoq38Lqn631j5sz+4naTnpO04u1qy9oSf//L34PfxP0YZSVkFr34fSrnsVWk/ORz3TedJ3ltSqVQd9/PJrpf889Jq8g9J+ryxK8ZVpOfleM4WWCv+k5HZOIJ66y+RiG/eUxQ+AcwWaTc4HdoWz5wT9hTalZFxdQhuaFuAkxXlbthfohCDo8EPjcU0pNK0AUs5GxLbqTqCi9Q1OadLgc+13N7p7G71d1N1609t5s3Xwn7vdN+3zfTRA5p5qmRCB76ENNL2Dje4+QNN7s91909+ZD5qgb/yym4Af+k75LmDIXPCrWnP9KpRztNkO4IlzcbOsTQQX4Hp8A4sNZyFpqh+I7U9B5/ygt3lgmSHTNt6hxTkvavBrGzXb6be+IgiQQL5lnLVrOhX0NSnBemKHKDpeEAGlx8tEM8EN7QDa3dnZ2vPmaUK+VSLNeXxp4suqEejtAZf0rzbEnwU0uCjoX/4CJKClzHCsDTQ0oKqunfe72/vt3SyC4nS5PXptkqSZyt2ZwpHj2bb5dAOXCQggqQiLQ3/20N5kQwl3oHg2xsy01+0gqoLYcGPFKutp4GAkpVqxgGuPLDMh437ooqtfDbE7O+/evj042js+efuue7DfPTju9Y+ODts34HfujKULutNyynSpW7tbRCgRficQOjmZELgKCovQmyPZuV/Qv3N0htkIHYlppjhK6UBgMY3QOSH+JnVE1TgfQHzTiKeYjTZHfHOQ8sHmiPei3vamFPFmDANsapse/i8a8V/Otrb2Ns62duo9ibRavrO7MYcYLrr+P4G5Kb29Oas5+sN723v4nsKcXNyadOteBXOyKnqco0Zvnpn25PnFr4UO2kFnv5Ya+Qf2pvHlg3X5aNReGVOyBPS8UDy1LTlrU5YI9xCgVsBwrMDYGowXagS6DvhL1XSCbCLjAQfVo8ZmW3ctekPP/AYNCFxtYxaPuTAfN2IX8Wjvc96aZ0pL+K8w9pHrvGTPJP26v59wVwtwE5qmtrkluJ/1Uhs95pASNeZSBYLa4Amn1DevzLAau4eDBxsWqP8dk0yQGG4tNuDmoHgRrmngEy1nR2Hm0rNK69PwRYpOyF8u/3728kwUfOXhCR2ZuEx7dVAa3WCkNCyHzWK/Mh8um/hmBuiePhB2A6EAo1wAUcxkTfC1QL2mUPjcnWDBoIvS9M6RNXK1uk9kRJlUgRP1XhyBW8K8i9y7iCZuW8Qpz5NiBxzpjy6OQKAJUTjBCjdvivf2VxMMEpdehYDDwh7BSXIJD1y6IfWTMZHSBJuFe6QEObwU0QkeBXVvZ91NhfVOJnQDD+Kk199qlCwF65zqsdHpsQ90NIA4XFnG+QUdahrCQzxNQhZ2S9WQRWa9Dgv3rncWezQOcyeLBLO7pV+2QNjdC/BI8CPNvYaS2HrgKtpul2AdExyPKSOXQS73osuwQ4Vp4W1XEcaHXQZSctGlzBqv7XoywUHCPphB7EDz84cgo0JXXXT20iCNMzsxl/D4GvaRlXPH7nODUDC/gR6lz/s0JdD8G4Sc+U1LLDnmQl2ak6bQj5x6Yebb8DJuhhrgl9UGC8XdfHmwkrg05yBUB/M/NqExQGXzK43onDGVlqDzzwYyPdjSc85aebPdpItPZ1vEol/Qxcfjj2/Qb/xWK1ITnJlqCn+vraWk0qC71Ro0+3xC/owyS4gcT2tN42+z2Mby+W/umdrQp2zIQ+62hx+0Q3WSLmBo/X0jO9vT8eToPMzXdj07ZURiGU0naWSfMwmEWBhfM+Nso3izUoeYz2rU2WpnzCZlqcaeG2LAeUowa0mOYYErSGUq2KQ+L5fRIKdpfco6B3jtZa23f9zrHqy1W87HcwQzhBFGzQuJeUIa981da5FKEBWP2y/GzWKKhbKp59jrfEAEIwqCJyyH/iP8rmHc4nevjZZVy2JQFPLn3fK5eOleGV1a9KLcWKVFxpNmATaXWAhwk3HjiquTXU+VN5wGi870iSfoy+lx80Q0q81T+qr9FKef6jOAIyPDcR1tIc6b8F4dpfTDbIzcs+TKsv3y6lP4UoNlSixj7toUbm57fPxb4/y1wwrdf2BVHrmc4CyjbGSfX/u3tUeAxh67E5w1wgSlTI0v8pkBFqwcoKszO09q6tHDdi5zJdlmTFZxXTx8QjdgU50IPeP/+z//V9oabPUlNbDrYnpVW0q2gylgyNqSZ3HjKqz7Xn6TJIX0ttVbul9Z88IFyVIaY1mu2IsezL3FuDM2TUKylE8nFUfewycuxp0xMbj4h3n66CAHA8+Y+h77a9GJ/bD2PjGhQ8iTVqbnt3K5q77yrciZohOy7lRLq8UVeuUn/0XDCuyPhUbp3XlNGmAxNnok9Y98a2u62rmjIj/jDvO1Og2/ZUTcqyuV8OMwA6+WDYrijbu0q7n0m5m3QI1ra1UcvLyaOXW9e9fTVCukOmepeEd51safGBeTSlRUI/gtS367f4UrHJoy/M3tlD95yq8p3sC54gmVkHxZbJv/Zn5Fx/aXKQqfQ4FH+t4LgYahQrvNrsMPOeuqzD4XmRuTcq7lfXux1d2Ru2S0gVR86JcWFC5sXk1r/2mrhZzgeGzLeI9xqUiGDSqNMUMDgghV44IWCUpyU5FHYaHyzPGEGYhCn4GJqc/h78UgBynDAk+I0iALm7MLtCYKXEIROh3aL/THji0CAUuDTD+c6iGUNJF1p5/ME1ZgIZp0ID0LknhLS4KUPyUBM83ItdlLmeBJHrd1ArVCMQR5+rPGToDoEHmo71rQEpivtKBX0lf2fB2saf2eRQVFIx5tTWZUH9PjURZwltSHMFRcpax5hbmYkVi5+Lq+fD5DY35rohXNQuyugDXeRcI4F6Ttfi27A2es5/cxgY1Y4OQWS7/JrFMV52qszytXU0sgxpX3iFUjENZsYZoxwUJBkMGEM6q4WKtI3BnC0j49UyGZeX0Os9q3y1fms7WY4CJsFiXvmNNR1E1qxEHdMn2wmhlMUqJO9S5g5tF+x8E+81iHnNi/iHiDJCT81gF7qEuuBBY0aPqTD2xhSRfB7tkoekJAk7xUoQu1U0QvuMKpAxDqSRCpmsa6C5BcNoIRRIg3zn3sjkjK0ITGgksSc5bIBkssHpPW11C5SKPaC7N0+Dtpf2gySfWIdgnldPgrFWdXHcj11f8ZK6U/6oMX/pZXDRstuG9pA0ipTdfCgPzmPER86DudGFXEUl7rIUdGwEMhBjaCWwX3LC0T2L+kmf/0UwOUD3BQn366c5Wn4arKK3F+sE5pPMhDp5mr/B67ECaT2S15ekMSRDOXNlzEp+QCLGOITWp2DpT43tajSWp0WeQi0hQb5kITwUnuGDIDIJvJZf44TCgOBTGLhnF1h8KYxNeXVVGwwNIOkeLXhDmlGeoJSKqFHWaE5zKdIspu+DVJXLezoZlcmsrfRd3sW6hR6CpJo9NP5k4THnanuivIffzh3Ba4q4MGUVsZrgs+jaZLqJ7SUtTTCbF1d0DvyUwtDOtQBb0ftHdTwtWEy5i/Yc2glsBTWo0nLAkehq+dmsfINwXyJMlTkpiXI284ynwywRAY75SV95YB7C8tdZRiHHS/jrL2SRBpDRnoFYClsgGWZEIhC8WaP9iuF8yWgjcNhT0xCUsyTpmSHaC6DKhO1RhdTXgCYi+9itbuUX8aGBbKQpVcLvcc4IXN6RdmCkjIPI4JSYKb6iJm5LbOUY838RDTlCSe6FYQBUTXIhulnF/nWUuCF2O0IHix1GCiUoDAbIqs7BH22OdQcSTkrIjdGNEbwmYdC0LVUXOnAuaVIHd+mHrwQEqEoRAGuHnc4dbWQfjoOpkTT1OmxkTROHACr537L008dlsRFY7VjK8ZBAomNJVtkpa828qY8h5pHF/jEbksOyTufw8SMx8mPE71EKaLmOE8KB8MCjpo7FwkRq74SPgyvUGOUwlncVzxLBfgTVOO6/ZR7RrKVKVMqs5TH5Cd8kFtEChvNJ0FrPnVFAaqLiMc9nJC57dL9Tu+mrAeBdng6vL4UpG6dHiUCIcG++0uj3YQBNPoLr8L8NlMh+5gvDvU2HaTNRiIs3GIWsk8U+XTKbaKZFVP+33Iq4FxNwbuWldV+FWn+pPngpHpd+KeBe58vLjDoypWyuY/HslCxsDytYyx8LXjC3/bJgS//xrs0UKGimhnKcuBsS1QKRWOr+9/pfA/CEKYHHN1Kcjw/gN+yvCExvXLpruAv6WJGrfevxU6/q5fdvYFeKmKJWtuzug3iGltmnhM6Gjc7IhqMfNv8Pa9UzfOPEh5fN3MZPfKkEOlBB3kNoLAWC/GSZ7QG5rkuLQOM1OEPrJ0avpFw9lozlgJ6XtUvTJmCtQh44ygW/IqQV9zIvTHeaVR0Py6Dt1sOV/GLTS21uaCsba1be1uZaU93yFkeWAKpxGmInTEhamOafoWAeTI1VxFRSWUgAymW+6Dti75lhFBCYubN+K95KyHcx0OJE9zRVy/JKvrQOZZMZuvcGkN1zos5p/pHXZDXOlUhm9sCXZrmxtjd5bgn42AEAnDuArj3RioYcEdqxrYd66OjSbrME9RhilzZa0bBpq1OHTfEYnuPSZ9rNhjwneGxYisGoRJnD4ehMdu01kQoXsWSRBhiWG3J6JiWed/IJBnHD8cohnq5HxwxemDFcA4T/OJkRMpnvJcITmmQ2UKMrvqwloKDUWpGiUquWGMpLlUAj+eNITBrJACF5qiE3PcFdVO4aTAgiBBcGqFXW0gq9rZ9+UDJV6DxobmPeVY0C0hAHPmnBUTvjxnY+hPlcquxI7t6jrB4hpxgSYEQyeSILF85iLg0HjYLppwxhVntvkeZdrCl2DhAxLMsQQN+u+mEXocsdHgGWq1QReUGxVqV2GsqluPBOR9MqRceb3t2xUwb0ElJokVGxbYkkAxHO5TzJTKQtfvxcWnOQMS7AjN9Jjl+NXTzOc9KyJNUAvHb9CIHS3q9j23rt5cpP663aKmrsjWqsIvoskOeDJtLbW/hxVQPwz0P7ANQqvLAQ8A+NtcXzAQ7uLcM9L2h05MyExqK3w324eCJFSQWLX3Et0LgCui4oe2TbLNWrGAKnlQ+sN3atOmzRmWClForFi0tHa3S18+n4ETA2L4ajNqpHg9jEI72Fs2yx7GCRFzJbrMcJC2wgWEpmFmDgI3uaNscb9td6uhXwPrz3vvULld0aOneEoEEnDZoQTNzM1q2wsHdzG9mMbzv2t48c64AVG3hDBb2HMwVSBSLT6+5gS6QULPc0GVIgxhVt9Txe6AR234pJEnduVcRMGk0LuCM4RTQXBNIqCgHE29vHxwL+T+feBKHyDDYjLXnV0Pr5cEHMqFcT9glAkypN86YOXPONLs5WLCiRlJi4Fp4Q0xRyzcFoAWwcoXnRUycViIsaG1AJlT0N3hfG1ULOYOBUINrHY5l6xuy288JFL5Vg6bDiilGIyGQ8f8M2j8yQloiZygtzy5tGJgIU64kw+kjeKwHUTM/UQoeRokRl1SGAlyj8RYYSQ7Dr80h9PjoNkE27jd5WR8iHAfMxN+qZHfINzNMaD3ZnBKwL156dy00l/To6BcfeNWZP/zpZzTnBYMBijTCASDEpTckMSHq4emG/K2W+NiQAA9urQOl+eSIhyjaAOTSdMYMELnmp+M5lt3r0BAF1UUp+ji6FNAX4SVIpNMReiEJVZvhqrshfyujZZQG9VVOiBW+SxYFS62BrGKQ3tYEwR005bGsIrntoX1FG5vWzV4LsM442KekKjK4w+yjKF7qmuT+th2gUf9wmaB3UmL7fu6tdS474lUeJBSOUa4unvn0OOLgK9V2Q1LsLPuwGih95pbMZIV2CPfTDXiCnpXBVEuNo3H13InjEv7ePSP8x19LnxrHTbrxmhG6qx4tGCiiuh4c4/oeOgOPTtfrR1aUxrC3RnszBuKHdr0QzY89g5lzG/UYBDFS6hfFX7051gaRklqUhEGBeShueo8R1o6d4hkwBhzHWVBYfFLxtUlyIRy3xZUCrEv8akrjfsG7UX7vm1mHXNFDV3K0BDfmCTIalO9qGgZcxWhEyxSqvV8Ve8B41nilSz1c4T7sFIHmPsgDVvu3AfTDCQsCCjMfBWhM6weEconly9jzBI5xtePdmLVJMyQMi1e9FL9ZC2suNrAq3ewVecxLDMfPY+JgmSDWrPTsO7wXYB6zaOpFnl5IY9Rf+LuauTuX1CV3ElbGk9Cs+H06P2nluLVvtmM0FkFjT+ZBKF2UtW6KGSNdHNFhX+wTWiGSAOHTuIx/2wHBi/JYxgAfmT0OXCrfCaZtiLLIqAl3zx2KsL/DwAA//94FXl9" + return "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" } diff --git a/x-pack/heartbeat/monitors/browser/synthexec/enrich.go b/x-pack/heartbeat/monitors/browser/synthexec/enrich.go index c3ab6c76faa..bec551a7947 100644 --- a/x-pack/heartbeat/monitors/browser/synthexec/enrich.go +++ b/x-pack/heartbeat/monitors/browser/synthexec/enrich.go @@ -112,6 +112,14 @@ func (je *journeyEnricher) enrichSynthEvent(event *beat.Event, se *SynthEvent) e } switch se.Type { + case "cmd/status": + // If a command failed _after_ the journey was complete, as it happens + // when an `afterAll` hook fails, for example, we don't wan't to include + // a summary in the cmd/status event. + if !je.journeyComplete { + je.end = event.Timestamp + return je.createSummary(event) + } case "journey/end": je.journeyComplete = true return je.createSummary(event) @@ -155,23 +163,24 @@ func (je *journeyEnricher) createSummary(event *beat.Event) error { down = 0 } - if je.journeyComplete { - eventext.MergeEventFields(event, common.MapStr{ - "url": je.urlFields, - "synthetics": common.MapStr{ - "type": "heartbeat/summary", - "journey": je.journey, - }, - "monitor": common.MapStr{ - "duration": common.MapStr{ - "us": int64(je.end.Sub(je.start) / time.Microsecond), - }, - }, - "summary": common.MapStr{ - "up": up, - "down": down, + eventext.MergeEventFields(event, common.MapStr{ + "url": je.urlFields, + "synthetics": common.MapStr{ + "type": "heartbeat/summary", + "journey": je.journey, + }, + "monitor": common.MapStr{ + "duration": common.MapStr{ + "us": int64(je.end.Sub(je.start) / time.Microsecond), }, - }) + }, + "summary": common.MapStr{ + "up": up, + "down": down, + }, + }) + + if je.journeyComplete { return je.firstError } diff --git a/x-pack/heartbeat/monitors/browser/synthexec/enrich_test.go b/x-pack/heartbeat/monitors/browser/synthexec/enrich_test.go index 629454f34c0..f2c8ba25dca 100644 --- a/x-pack/heartbeat/monitors/browser/synthexec/enrich_test.go +++ b/x-pack/heartbeat/monitors/browser/synthexec/enrich_test.go @@ -21,6 +21,18 @@ import ( "github.com/elastic/go-lookslike/testslike" ) +func makeStepEvent(typ string, ts float64, name string, index int, status string, urlstr string, err *SynthError) *SynthEvent { + return &SynthEvent{ + Type: typ, + TimestampEpochMicros: 1000 + ts, + PackageVersion: "1.0.0", + Step: &Step{Name: name, Index: index, Status: status}, + Error: err, + Payload: common.MapStr{}, + URL: urlstr, + } +} + func TestJourneyEnricher(t *testing.T) { journey := &Journey{ Name: "A Journey Name", @@ -50,17 +62,6 @@ func TestJourneyEnricher(t *testing.T) { Journey: journey, Payload: common.MapStr{}, } - makeStepEvent := func(typ string, ts float64, name string, index int, status string, urlstr string, err *SynthError) *SynthEvent { - return &SynthEvent{ - Type: typ, - TimestampEpochMicros: 1000 + ts, - PackageVersion: "1.0.0", - Step: &Step{Name: name, Index: index, Status: status}, - Error: err, - Payload: common.MapStr{}, - URL: urlstr, - } - } url1 := "http://example.net/url1" url2 := "http://example.net/url2" url3 := "http://example.net/url3" @@ -121,6 +122,24 @@ func TestEnrichSynthEvent(t *testing.T) { wantErr bool check func(t *testing.T, e *beat.Event, je *journeyEnricher) }{ + { + "cmd/status", + &journeyEnricher{}, + &SynthEvent{ + Type: "cmd/status", + Error: &SynthError{Name: "cmdexit", Message: "cmd err msg"}, + }, + true, + func(t *testing.T, e *beat.Event, je *journeyEnricher) { + v := lookslike.MustCompile(map[string]interface{}{ + "summary": map[string]int{ + "up": 0, + "down": 1, + }, + }) + testslike.Test(t, v, e.Fields) + }, + }, { "journey/end", &journeyEnricher{}, @@ -195,3 +214,75 @@ func TestEnrichSynthEvent(t *testing.T) { }) } } + +func TestNoSummaryOnAfterHook(t *testing.T) { + journey := &Journey{ + Name: "A journey that fails after completing", + Id: "my-bad-after-all-hook", + } + journeyStart := &SynthEvent{ + Type: "journey/start", + TimestampEpochMicros: 1000, + PackageVersion: "1.0.0", + Journey: journey, + Payload: common.MapStr{}, + } + syntherr := &SynthError{ + Message: "my-errmsg", + Name: "my-errname", + Stack: "my\nerr\nstack", + } + journeyEnd := &SynthEvent{ + Type: "journey/end", + TimestampEpochMicros: 2000, + PackageVersion: "1.0.0", + Journey: journey, + Payload: common.MapStr{}, + } + cmdStatus := &SynthEvent{ + Type: "cmd/status", + Error: &SynthError{Name: "cmdexit", Message: "cmd err msg"}, + TimestampEpochMicros: 3000, + } + + badStepUrl := "https://example.com/bad-step" + synthEvents := []*SynthEvent{ + journeyStart, + makeStepEvent("step/start", 10, "Step1", 1, "", "", nil), + makeStepEvent("step/end", 20, "Step1", 1, "failed", badStepUrl, syntherr), + journeyEnd, + cmdStatus, + } + + je := &journeyEnricher{} + + for idx, se := range synthEvents { + e := &beat.Event{} + t.Run(fmt.Sprintf("event %d", idx), func(t *testing.T) { + enrichErr := je.enrich(e, se) + + if se != nil && se.Type == "cmd/status" { + t.Run("no summary in cmd/status", func(t *testing.T) { + require.NotContains(t, e.Fields, "summary") + }) + } + + // Only the journey/end event should get a summary when + // it's emitted before the cmd/status (when an afterX hook fails). + if se != nil && se.Type == "journey/end" { + require.Equal(t, stepError(syntherr), enrichErr) + + u, _ := url.Parse(badStepUrl) + t.Run("summary in journey/end", func(t *testing.T) { + v := lookslike.MustCompile(common.MapStr{ + "synthetics.type": "heartbeat/summary", + "url": wrappers.URLFields(u), + "monitor.duration.us": int64(journeyEnd.Timestamp().Sub(journeyStart.Timestamp()) / time.Microsecond), + }) + + testslike.Test(t, v, e.Fields) + }) + } + }) + } +} diff --git a/x-pack/heartbeat/monitors/browser/synthexec/execmultiplexer.go b/x-pack/heartbeat/monitors/browser/synthexec/execmultiplexer.go index 57b423626d1..07de0143c38 100644 --- a/x-pack/heartbeat/monitors/browser/synthexec/execmultiplexer.go +++ b/x-pack/heartbeat/monitors/browser/synthexec/execmultiplexer.go @@ -29,7 +29,7 @@ func (e ExecMultiplexer) writeSynthEvent(se *SynthEvent) { e.eventCounter.Store(-1) } hasCurrentJourney := e.currentJourney.Load() - if se.Type == "journey/end" { + if se.Type == "journey/end" || se.Type == "cmd/status" { e.currentJourney.Store(false) } diff --git a/x-pack/heartbeat/monitors/browser/synthexec/execmultiplexer_test.go b/x-pack/heartbeat/monitors/browser/synthexec/execmultiplexer_test.go index 56af4c94d9d..ec85a6b5222 100644 --- a/x-pack/heartbeat/monitors/browser/synthexec/execmultiplexer_test.go +++ b/x-pack/heartbeat/monitors/browser/synthexec/execmultiplexer_test.go @@ -18,7 +18,7 @@ func TestExecMultiplexer(t *testing.T) { var testJourneys []*Journey var testEvents []*SynthEvent time := float64(0) - for jIdx := 0; jIdx < 3; jIdx++ { + for jIdx := 0; jIdx < 4; jIdx++ { time++ // fake time to make events seem spaced out journey := &Journey{ Name: fmt.Sprintf("J%d", jIdx), @@ -45,11 +45,20 @@ func TestExecMultiplexer(t *testing.T) { }) } - testEvents = append(testEvents, &SynthEvent{ - Journey: journey, - Type: "journey/end", - TimestampEpochMicros: time, - }) + // We want one of the test journeys to end with a cmd/status indicating it failed + if jIdx != 4 { + testEvents = append(testEvents, &SynthEvent{ + Journey: journey, + Type: "journey/end", + TimestampEpochMicros: time, + }) + } else { + testEvents = append(testEvents, &SynthEvent{ + Journey: journey, + Type: "cmd/status", + TimestampEpochMicros: time, + }) + } } // Write the test events in another go routine since writes block @@ -77,7 +86,7 @@ Loop: i := 0 // counter for index, resets on journey change for _, se := range results { require.Equal(t, i, se.index) - if se.Type == "journey/end" { + if se.Type == "journey/end" || se.Type == "cmd/status" { i = 0 } else { i++ diff --git a/x-pack/heartbeat/monitors/browser/synthexec/synthexec.go b/x-pack/heartbeat/monitors/browser/synthexec/synthexec.go index e5bcd1332f5..039a3480c80 100644 --- a/x-pack/heartbeat/monitors/browser/synthexec/synthexec.go +++ b/x-pack/heartbeat/monitors/browser/synthexec/synthexec.go @@ -196,8 +196,9 @@ func runCmd( if err != nil { str := fmt.Sprintf("command exited with status %d: %s", cmd.ProcessState.ExitCode(), err) mpx.writeSynthEvent(&SynthEvent{ - Type: "cmd/status", - Error: &SynthError{Name: "cmdexit", Message: str}, + Type: "cmd/status", + Error: &SynthError{Name: "cmdexit", Message: str}, + TimestampEpochMicros: float64(time.Now().UnixMicro()), }) logp.Warn("Error executing command '%s' (%d): %s", loggableCmd.String(), cmd.ProcessState.ExitCode(), err) } @@ -243,7 +244,7 @@ func lineToSynthEventFactory(typ string) func(bytes []byte, text string) (res *S logp.Info("%s: %s", typ, text) return &SynthEvent{ Type: typ, - TimestampEpochMicros: float64(time.Now().UnixNano() / int64(time.Millisecond)), + TimestampEpochMicros: float64(time.Now().UnixMicro()), Payload: map[string]interface{}{ "message": text, }, diff --git a/x-pack/journalbeat/cmd/root.go b/x-pack/journalbeat/cmd/root.go deleted file mode 100644 index d549011f73a..00000000000 --- a/x-pack/journalbeat/cmd/root.go +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one -// or more contributor license agreements. Licensed under the Elastic License; -// you may not use this file except in compliance with the Elastic License. - -package cmd - -import ( - journalbeatCmd "github.com/elastic/beats/v7/journalbeat/cmd" - "github.com/elastic/beats/v7/libbeat/cmd" - - _ "github.com/elastic/beats/v7/x-pack/libbeat/include" -) - -// RootCmd to handle beats cli -var RootCmd *cmd.BeatsRootCmd - -func init() { - settings := journalbeatCmd.JournalbeatSettings() - settings.ElasticLicensed = true - RootCmd = journalbeatCmd.Initialize(settings) -} diff --git a/x-pack/journalbeat/main_test.go b/x-pack/journalbeat/main_test.go deleted file mode 100644 index fcac188a31c..00000000000 --- a/x-pack/journalbeat/main_test.go +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one -// or more contributor license agreements. Licensed under the Elastic License; -// you may not use this file except in compliance with the Elastic License. -package main - -// This file is mandatory as otherwise the journalbeat.test binary is not generated correctly. -import ( - "flag" - "testing" - - "github.com/elastic/beats/v7/journalbeat/cmd" - "github.com/elastic/beats/v7/libbeat/tests/system/template" -) - -var systemTest *bool - -func init() { - testing.Init() - systemTest = flag.Bool("systemTest", false, "Set to true when running system tests") - cmd.RootCmd.PersistentFlags().AddGoFlag(flag.CommandLine.Lookup("systemTest")) - cmd.RootCmd.PersistentFlags().AddGoFlag(flag.CommandLine.Lookup("test.coverprofile")) -} - -// Test started when the test binary is started. Only calls main. -func TestSystem(t *testing.T) { - if *systemTest { - main() - } -} - -func TestTemplate(t *testing.T) { - template.TestTemplate(t, cmd.Name, true) -} diff --git a/x-pack/libbeat/Dockerfile b/x-pack/libbeat/Dockerfile index 2c51fb632b2..78c387b04d9 100644 --- a/x-pack/libbeat/Dockerfile +++ b/x-pack/libbeat/Dockerfile @@ -1,8 +1,8 @@ -FROM golang:1.17.2 +FROM golang:1.17.5 RUN \ apt-get update \ - && apt-get install -y --no-install-recommends \ + && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \ netcat \ rsync \ python3 \ diff --git a/x-pack/libbeat/autodiscover/providers/aws/ec2/provider.go b/x-pack/libbeat/autodiscover/providers/aws/ec2/provider.go index 19d8c8a9784..3cab8c3ca28 100644 --- a/x-pack/libbeat/autodiscover/providers/aws/ec2/provider.go +++ b/x-pack/libbeat/autodiscover/providers/aws/ec2/provider.go @@ -64,8 +64,9 @@ func AutodiscoverBuilder( if config.Regions == nil { // set default region to make initial aws api call awsCfg.Region = "us-west-1" + ec2ServiceName := awscommon.CreateServiceName("ec2", config.AWSConfig.FIPSEnabled, awsCfg.Region) svcEC2 := ec2.New(awscommon.EnrichAWSConfigWithEndpoint( - config.AWSConfig.Endpoint, "ec2", awsCfg.Region, awsCfg)) + config.AWSConfig.Endpoint, ec2ServiceName, awsCfg.Region, awsCfg)) completeRegionsList, err := awsauto.GetRegions(svcEC2) if err != nil { @@ -81,8 +82,9 @@ func AutodiscoverBuilder( logp.Error(errors.Wrap(err, "error loading AWS config for aws_ec2 autodiscover provider")) } awsCfg.Region = region + ec2ServiceName := awscommon.CreateServiceName("ec2", config.AWSConfig.FIPSEnabled, region) clients = append(clients, ec2.New(awscommon.EnrichAWSConfigWithEndpoint( - config.AWSConfig.Endpoint, "ec2", region, awsCfg))) + config.AWSConfig.Endpoint, ec2ServiceName, region, awsCfg))) } return internalBuilder(uuid, bus, config, newAPIFetcher(clients), keystore) diff --git a/x-pack/libbeat/autodiscover/providers/aws/elb/provider.go b/x-pack/libbeat/autodiscover/providers/aws/elb/provider.go index 39313f36871..8f39ea10ce4 100644 --- a/x-pack/libbeat/autodiscover/providers/aws/elb/provider.go +++ b/x-pack/libbeat/autodiscover/providers/aws/elb/provider.go @@ -63,8 +63,9 @@ func AutodiscoverBuilder( // Construct MetricSet with a full regions list if there is no region specified. if config.Regions == nil { + ec2ServiceName := awscommon.CreateServiceName("ec2", config.AWSConfig.FIPSEnabled, awsCfg.Region) svcEC2 := ec2.New(awscommon.EnrichAWSConfigWithEndpoint( - config.AWSConfig.Endpoint, "ec2", awsCfg.Region, awsCfg)) + config.AWSConfig.Endpoint, ec2ServiceName, awsCfg.Region, awsCfg)) completeRegionsList, err := awsauto.GetRegions(svcEC2) if err != nil { @@ -86,8 +87,9 @@ func AutodiscoverBuilder( logp.Err("error loading AWS config for aws_elb autodiscover provider: %s", err) } awsCfg.Region = region + elbServiceName := awscommon.CreateServiceName("elasticloadbalancing", config.AWSConfig.FIPSEnabled, region) clients = append(clients, elasticloadbalancingv2.New(awscommon.EnrichAWSConfigWithEndpoint( - config.AWSConfig.Endpoint, "elasticloadbalancing", region, awsCfg))) + config.AWSConfig.Endpoint, elbServiceName, region, awsCfg))) } return internalBuilder(uuid, bus, config, newAPIFetcher(clients), keystore) diff --git a/x-pack/libbeat/common/aws/credentials.go b/x-pack/libbeat/common/aws/credentials.go index 08bcbe56875..0b03155e0f1 100644 --- a/x-pack/libbeat/common/aws/credentials.go +++ b/x-pack/libbeat/common/aws/credentials.go @@ -5,8 +5,10 @@ package aws import ( + "crypto/tls" "net/http" "net/url" + "strings" awssdk "github.com/aws/aws-sdk-go-v2/aws" "github.com/aws/aws-sdk-go-v2/aws/defaults" @@ -16,36 +18,59 @@ import ( "github.com/pkg/errors" "github.com/elastic/beats/v7/libbeat/common/transport/httpcommon" + "github.com/elastic/beats/v7/libbeat/common/transport/tlscommon" "github.com/elastic/beats/v7/libbeat/logp" ) +// OptionalGovCloudFIPS is a list of services on AWS GovCloud that is not FIPS by default. +// These services follow the standard -fips..amazonaws.com format. +var OptionalGovCloudFIPS = map[string]bool{ + "s3": true, +} + // ConfigAWS is a structure defined for AWS credentials type ConfigAWS struct { - AccessKeyID string `config:"access_key_id"` - SecretAccessKey string `config:"secret_access_key"` - SessionToken string `config:"session_token"` - ProfileName string `config:"credential_profile_name"` - SharedCredentialFile string `config:"shared_credential_file"` - Endpoint string `config:"endpoint"` - RoleArn string `config:"role_arn"` - ProxyUrl string `config:"proxy_url"` + AccessKeyID string `config:"access_key_id"` + SecretAccessKey string `config:"secret_access_key"` + SessionToken string `config:"session_token"` + ProfileName string `config:"credential_profile_name"` + SharedCredentialFile string `config:"shared_credential_file"` + Endpoint string `config:"endpoint"` + RoleArn string `config:"role_arn"` + ProxyUrl string `config:"proxy_url"` + FIPSEnabled bool `config:"fips_enabled"` + TLS *tlscommon.Config `config:"ssl" yaml:"ssl,omitempty" json:"ssl,omitempty"` + DefaultRegion string `config:"default_region"` } // InitializeAWSConfig function creates the awssdk.Config object from the provided config func InitializeAWSConfig(config ConfigAWS) (awssdk.Config, error) { AWSConfig, _ := GetAWSCredentials(config) + if AWSConfig.Region == "" { + if config.DefaultRegion != "" { + AWSConfig.Region = config.DefaultRegion + } else { + AWSConfig.Region = "us-east-1" + } + } + var proxy func(*http.Request) (*url.URL, error) if config.ProxyUrl != "" { proxyUrl, err := httpcommon.NewProxyURIFromString(config.ProxyUrl) if err != nil { return AWSConfig, err } - - httpClient := &http.Client{ - Transport: &http.Transport{ - Proxy: http.ProxyURL(proxyUrl.URI()), - }, - } - AWSConfig.HTTPClient = httpClient + proxy = http.ProxyURL(proxyUrl.URI()) + } + var tlsConfig *tls.Config + if config.TLS != nil { + TLSConfig, _ := tlscommon.LoadTLSConfig(config.TLS) + tlsConfig = TLSConfig.ToConfig() + } + AWSConfig.HTTPClient = &http.Client{ + Transport: &http.Transport{ + Proxy: proxy, + TLSClientConfig: tlsConfig, + }, } return AWSConfig, nil } @@ -80,11 +105,6 @@ func getAccessKeys(config ConfigAWS) awssdk.Config { Value: awsCredentials, } - // Set default region if empty to make initial aws api call - if awsConfig.Region == "" { - awsConfig.Region = "us-east-1" - } - // Assume IAM role if iam_role config parameter is given if config.RoleArn != "" { logger.Debug("Using role arn and access keys for AWS credential") @@ -118,11 +138,6 @@ func getSharedCredentialProfile(config ConfigAWS) (awssdk.Config, error) { return awsConfig, errors.Wrap(err, "external.LoadDefaultAWSConfig failed with shared credential profile given") } - // Set default region if empty to make initial aws api call - if awsConfig.Region == "" { - awsConfig.Region = "us-east-1" - } - // Assume IAM role if iam_role config parameter is given if config.RoleArn != "" { logger.Debug("Using role arn and shared credential profile for AWS credential") @@ -143,17 +158,30 @@ func getRoleArn(config ConfigAWS, awsConfig awssdk.Config) awssdk.Config { // EnrichAWSConfigWithEndpoint function enabled endpoint resolver for AWS // service clients when endpoint is given in config. func EnrichAWSConfigWithEndpoint(endpoint string, serviceName string, regionName string, awsConfig awssdk.Config) awssdk.Config { + var eurl string if endpoint != "" { parsedEndpoint, _ := url.Parse(endpoint) if parsedEndpoint.Scheme != "" { awsConfig.EndpointResolver = awssdk.ResolveWithEndpointURL(endpoint) } else { if regionName == "" { - awsConfig.EndpointResolver = awssdk.ResolveWithEndpointURL("https://" + serviceName + "." + endpoint) + eurl = "https://" + serviceName + "." + endpoint } else { - awsConfig.EndpointResolver = awssdk.ResolveWithEndpointURL("https://" + serviceName + "." + regionName + "." + endpoint) + eurl = "https://" + serviceName + "." + regionName + "." + endpoint } + awsConfig.EndpointResolver = awssdk.ResolveWithEndpointURL(eurl) } } return awsConfig } + +//Create AWS service name based on Region and FIPS +func CreateServiceName(serviceName string, fipsEnabled bool, region string) string { + if fipsEnabled { + _, found := OptionalGovCloudFIPS[serviceName] + if !strings.HasPrefix(region, "us-gov-") || found { + return serviceName + "-fips" + } + } + return serviceName +} diff --git a/x-pack/libbeat/common/aws/credentials_test.go b/x-pack/libbeat/common/aws/credentials_test.go index dde6a0665e2..3b5c6233cfc 100644 --- a/x-pack/libbeat/common/aws/credentials_test.go +++ b/x-pack/libbeat/common/aws/credentials_test.go @@ -6,12 +6,36 @@ package aws import ( "context" + "net/http" "testing" awssdk "github.com/aws/aws-sdk-go-v2/aws" "github.com/stretchr/testify/assert" + + "github.com/elastic/beats/v7/libbeat/common/transport/tlscommon" ) +func TestInitializeAWSConfig(t *testing.T) { + inputConfig := ConfigAWS{ + AccessKeyID: "123", + SecretAccessKey: "abc", + TLS: &tlscommon.Config{ + VerificationMode: 1, + }, + ProxyUrl: "http://proxy:3128", + } + awsConfig, err := InitializeAWSConfig(inputConfig) + assert.NoError(t, err) + + retrievedAWSConfig, err := awsConfig.Credentials.Retrieve(context.Background()) + assert.NoError(t, err) + + assert.Equal(t, inputConfig.AccessKeyID, retrievedAWSConfig.AccessKeyID) + assert.Equal(t, inputConfig.SecretAccessKey, retrievedAWSConfig.SecretAccessKey) + assert.Equal(t, true, awsConfig.HTTPClient.(*http.Client).Transport.(*http.Transport).TLSClientConfig.InsecureSkipVerify) + assert.NotNil(t, awsConfig.HTTPClient.(*http.Client).Transport.(*http.Transport).Proxy) +} + func TestGetAWSCredentials(t *testing.T) { inputConfig := ConfigAWS{ AccessKeyID: "123", @@ -86,3 +110,88 @@ func TestEnrichAWSConfigWithEndpoint(t *testing.T) { }) } } + +func TestCreateServiceName(t *testing.T) { + cases := []struct { + title string + serviceName string + fips_enabled bool + region string + expectedServiceName string + }{ + { + "S3 - non-fips - us-east-1", + "s3", + false, + "us-east-1", + "s3", + }, + { + "S3 - non-fips - us-gov-east-1", + "s3", + false, + "us-gov-east-1", + "s3", + }, + { + "S3 - fips - us-gov-east-1", + "s3", + true, + "us-gov-east-1", + "s3-fips", + }, + { + "EC2 - fips - us-gov-east-1", + "ec2", + true, + "us-gov-east-1", + "ec2", + }, + { + "EC2 - fips - us-east-1", + "ec2", + true, + "us-east-1", + "ec2-fips", + }, + } + for _, c := range cases { + t.Run(c.title, func(t *testing.T) { + serviceName := CreateServiceName(c.serviceName, c.fips_enabled, c.region) + assert.Equal(t, c.expectedServiceName, serviceName) + }) + } +} + +func TestDefaultRegion(t *testing.T) { + cases := []struct { + title string + region string + expectedRegion string + }{ + { + "No default region set", + "", + "us-east-1", + }, + { + "us-west-1 region set as default", + "us-west-1", + "us-west-1", + }, + } + for _, c := range cases { + t.Run(c.title, func(t *testing.T) { + inputConfig := ConfigAWS{ + AccessKeyID: "123", + SecretAccessKey: "abc", + } + if c.region != "" { + inputConfig.DefaultRegion = c.region + } + awsConfig, err := InitializeAWSConfig(inputConfig) + assert.NoError(t, err) + assert.Equal(t, c.expectedRegion, awsConfig.Region) + }) + } +} diff --git a/x-pack/libbeat/common/nomad/watcher.go b/x-pack/libbeat/common/nomad/watcher.go index 31cb5590ff9..5293d02e474 100644 --- a/x-pack/libbeat/common/nomad/watcher.go +++ b/x-pack/libbeat/common/nomad/watcher.go @@ -130,7 +130,13 @@ func (w *watcher) sync() error { w.logger.Debugf("Found %d allocations", len(allocations)) for _, alloc := range allocations { // the allocation has not changed since last seen, ignore - if w.waitIndex > alloc.AllocModifyIndex { + if w.waitIndex > alloc.ModifyIndex { + w.logger.Debugf( + "Skip allocation.id=%s ClientStatus=%s because w.waitIndex=%v > alloc.ModifyIndex=%v", + alloc.ID, + alloc.ClientStatus, + fmt.Sprint(w.waitIndex), + fmt.Sprint(alloc.ModifyIndex)) continue } @@ -156,7 +162,7 @@ func (w *watcher) sync() error { case AllocClientStatusRunning: // Handle in-place allocation updates (like adding tags to a service definition) that // don't trigger a new allocation - updated := (w.waitIndex != 0) && (alloc.CreateIndex < w.waitIndex) && (alloc.AllocModifyIndex >= w.waitIndex) + updated := (w.waitIndex != 0) && (alloc.CreateIndex < w.waitIndex) && (alloc.ModifyIndex >= w.waitIndex) w.logger.Debugf("allocation.id=%s waitIndex=%v CreateIndex=%v ModifyIndex=%v AllocModifyIndex=%v updated=%v", alloc.ID, w.waitIndex, alloc.CreateIndex, alloc.ModifyIndex, diff --git a/x-pack/libbeat/common/nomad/watcher_test.go b/x-pack/libbeat/common/nomad/watcher_test.go index 197a929e990..a8cd6555acc 100644 --- a/x-pack/libbeat/common/nomad/watcher_test.go +++ b/x-pack/libbeat/common/nomad/watcher_test.go @@ -242,6 +242,30 @@ func TestAllocationWatcher(t *testing.T) { deleted: nil, }, }, + { + name: "old allocation index new modify index should be detected", + node: api.Node{ID: uuid.Must(uuid.NewV4()).String(), Name: "nomad1"}, + allocs: []api.Allocation{ + { + ModifyIndex: 20, CreateIndex: 11, + AllocModifyIndex: 11, TaskGroup: "group1", + NodeName: "nomad1", ClientStatus: AllocClientStatusRunning, + }, + }, + waitIndex: 24, + initialWaitIndex: 17, + expected: watcherEvents{ + added: nil, + updated: []api.Allocation{ + { + ModifyIndex: 20, CreateIndex: 11, + AllocModifyIndex: 11, TaskGroup: "group1", + NodeName: "nomad1", ClientStatus: AllocClientStatusRunning, + }, + }, + deleted: nil, + }, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { diff --git a/x-pack/libbeat/docs/aws-credentials-config.asciidoc b/x-pack/libbeat/docs/aws-credentials-config.asciidoc index d7223720ad4..3ccfd09a84d 100644 --- a/x-pack/libbeat/docs/aws-credentials-config.asciidoc +++ b/x-pack/libbeat/docs/aws-credentials-config.asciidoc @@ -18,6 +18,9 @@ services do not include a region. In `aws` module, `endpoint` config is to set the `endpoint-code` part, such as `amazonaws.com`, `amazonaws.com.cn`, `c2s.ic.gov`, `sc2s.sgov.gov`. * *proxy_url*: URL of the proxy to use to connect to AWS web services. The syntax is `http(s)://:` +* *fips_enabled*: Enabling this option changes the service names from `s3` to `s3-fips` for connecting to the correct service endpoint. For example: `s3-fips.us-gov-east-1.amazonaws.com`. All services used by Beats are FIPS compatible except for `tagging` but only certain regions are FIPS compatible. See https://aws.amazon.com/compliance/fips/ or the appropriate service page, https://docs.aws.amazon.com/general/latest/gr/aws-service-information.html, for a full list of FIPS endpoints and regions. +* *ssl*: This specifies SSL/TLS configuration. If the ssl section is missing, the host's CAs are used for HTTPS connections. See <> for more information. +* *default_region*: Default region to query if no other region is set. [float] ==== Supported Formats diff --git a/x-pack/metricbeat/Jenkinsfile.yml b/x-pack/metricbeat/Jenkinsfile.yml index a9be741ddae..db7fb380c50 100644 --- a/x-pack/metricbeat/Jenkinsfile.yml +++ b/x-pack/metricbeat/Jenkinsfile.yml @@ -45,10 +45,22 @@ stages: labels: - "aws" stage: extended + cloudAWS: + cloud: "mage build test" + withAWS: true ## Enable the tests to run in AWS + withModule: true ## run the ITs only if the changeset affects a specific module. + dirs: ## run the cloud tests for the given modules. + - "x-pack/metricbeat/module/aws" + when: ## Override the top-level when. + changeset: ## when PR contains any of those entries in the changeset + - "^x-pack/metricbeat/module/aws/.*" + - "^x-pack/metricbeat/Jenkinsfile.yml" + - "^x-pack/libbeat/common/aws/.*" + stage: extended macos: mage: "mage build unitTest" platforms: ## override default label in this specific stage. - - "macosx&&x86_64" + - "orka && darwin && poc" when: ## Override the top-level when. comments: - "/test x-pack/metricbeat for macos" diff --git a/x-pack/metricbeat/metricbeat.reference.yml b/x-pack/metricbeat/metricbeat.reference.yml index bcece50b832..2c3a35d801b 100644 --- a/x-pack/metricbeat/metricbeat.reference.yml +++ b/x-pack/metricbeat/metricbeat.reference.yml @@ -80,7 +80,7 @@ metricbeat.modules: processes: ['.*'] # Configure the mount point of the host’s filesystem for use in monitoring a host from within a container - #system.hostfs: "/hostfs" + #hostfs: "/hostfs" # Configure the metric types that are included by these metricsets. cpu.metrics: ["percentages","normalized_percentages"] # The other available option is ticks. @@ -872,6 +872,16 @@ metricbeat.modules: # If kube_config is not set, KUBECONFIG environment variable will be checked # and if not present it will fall back to InCluster #kube_config: ~/.kube/config + # To configure additionally node and namespace metadata, added to pod, service and container resource types, + # `add_resource_metadata` can be defined. + # By default all labels will be included while annotations are not added by default. + # add_resource_metadata: + # namespace: + # include_labels: ["namespacelabel1"] + # node: + # include_labels: ["nodelabel2"] + # include_annotations: ["nodeannotation1"] + # deployment: false # Kubernetes client QPS and burst can be configured additionally #kube_client_options: # qps: 5 @@ -906,6 +916,38 @@ metricbeat.modules: # If kube_config is not set, KUBECONFIG environment variable will be checked # and if not present it will fall back to InCluster #kube_config: ~/.kube/config + # To configure additionally node and namespace metadata, added to pod, service and container resource types, + # `add_resource_metadata` can be defined. + # By default all labels will be included while annotations are not added by default. + # add_resource_metadata: + # namespace: + # include_labels: ["namespacelabel1"] + # node: + # include_labels: ["nodelabel2"] + # include_annotations: ["nodeannotation1"] + # deployment: false + # Kubernetes client QPS and burst can be configured additionally + #kube_client_options: + # qps: 5 + # burst: 10 + +# Kubernetes Events +- module: kubernetes + enabled: true + metricsets: + - event + period: 10s + # Skip events older than Metricbeat's statup time is enabled by default. + # Setting to false the skip_older setting will stop filtering older events. + # This setting is also useful went Event's timestamps are not populated properly. + #skip_older: false + # If kube_config is not set, KUBECONFIG environment variable will be checked + # and if not present it will fall back to InCluster + #kube_config: ~/.kube/config + # Set the namespace to watch for events + #namespace: staging + # Set the sync period of the watchers + #sync_period: 10m # Kubernetes client QPS and burst can be configured additionally #kube_client_options: # qps: 5 @@ -923,8 +965,6 @@ metricbeat.modules: - /var/run/secrets/kubernetes.io/serviceaccount/ca.crt period: 30s - - # Kubernetes proxy server # (when running metricbeat locally at hosts or as a daemonset + host network) - module: kubernetes @@ -1541,66 +1581,6 @@ metricbeat.modules: # length of its retry interval each time, up to this maximum. #max_retry_interval: 30s - # The spool queue will store events in a local spool file, before - # forwarding the events to the outputs. - # Note: the spool queue is deprecated and will be removed in the future. - # Use the disk queue instead. - # - # The spool file is a circular buffer, which blocks once the file/buffer is full. - # Events are put into a write buffer and flushed once the write buffer - # is full or the flush_timeout is triggered. - # Once ACKed by the output, events are removed immediately from the queue, - # making space for new events to be persisted. - #spool: - # The file namespace configures the file path and the file creation settings. - # Once the file exists, the `size`, `page_size` and `prealloc` settings - # will have no more effect. - #file: - # Location of spool file. The default value is ${path.data}/spool.dat. - #path: "${path.data}/spool.dat" - - # Configure file permissions if file is created. The default value is 0600. - #permissions: 0600 - - # File size hint. The spool blocks, once this limit is reached. The default value is 100 MiB. - #size: 100MiB - - # The files page size. A file is split into multiple pages of the same size. The default value is 4KiB. - #page_size: 4KiB - - # If prealloc is set, the required space for the file is reserved using - # truncate. The default value is true. - #prealloc: true - - # Spool writer settings - # Events are serialized into a write buffer. The write buffer is flushed if: - # - The buffer limit has been reached. - # - The configured limit of buffered events is reached. - # - The flush timeout is triggered. - #write: - # Sets the write buffer size. - #buffer_size: 1MiB - - # Maximum duration after which events are flushed if the write buffer - # is not full yet. The default value is 1s. - #flush.timeout: 1s - - # Number of maximum buffered events. The write buffer is flushed once the - # limit is reached. - #flush.events: 16384 - - # Configure the on-disk event encoding. The encoding can be changed - # between restarts. - # Valid encodings are: json, ubjson, and cbor. - #codec: cbor - #read: - # Reader flush timeout, waiting for more events to become available, so - # to fill a complete batch as required by the outputs. - # If flush_timeout is 0, all available events are forwarded to the - # outputs immediately. - # The default value is 0s. - #flush.timeout: 0s - # Sets the maximum number of CPUs that can be executing simultaneously. The # default is the number of logical CPUs available in the system. #max_procs: @@ -1917,6 +1897,13 @@ output.elasticsearch: # The pin is a base64 encoded string of the SHA-256 fingerprint. #ssl.ca_sha256: "" + # A root CA HEX encoded fingerprint. During the SSL handshake if the + # fingerprint matches the root CA certificate, it will be added to + # the provided list of root CAs (`certificate_authorities`), if the + # list is empty or not defined, the matching certificate will be the + # only one in the list. Then the normal SSL validation happens. + #ssl.ca_trusted_fingerprint: "" + # Enable Kerberos support. Kerberos is automatically enabled if any Kerberos setting is set. #kerberos.enabled: true @@ -2049,6 +2036,13 @@ output.elasticsearch: # The pin is a base64 encoded string of the SHA-256 fingerprint. #ssl.ca_sha256: "" + # A root CA HEX encoded fingerprint. During the SSL handshake if the + # fingerprint matches the root CA certificate, it will be added to + # the provided list of root CAs (`certificate_authorities`), if the + # list is empty or not defined, the matching certificate will be the + # only one in the list. Then the normal SSL validation happens. + #ssl.ca_trusted_fingerprint: "" + # The number of times to retry publishing an event after a publishing failure. # After the specified number of retries, the events are typically dropped. # Some Beats, such as Filebeat and Winlogbeat, ignore the max_retries setting @@ -2250,6 +2244,13 @@ output.elasticsearch: # The pin is a base64 encoded string of the SHA-256 fingerprint. #ssl.ca_sha256: "" + # A root CA HEX encoded fingerprint. During the SSL handshake if the + # fingerprint matches the root CA certificate, it will be added to + # the provided list of root CAs (`certificate_authorities`), if the + # list is empty or not defined, the matching certificate will be the + # only one in the list. Then the normal SSL validation happens. + #ssl.ca_trusted_fingerprint: "" + # Enable Kerberos support. Kerberos is automatically enabled if any Kerberos setting is set. #kerberos.enabled: true @@ -2414,6 +2415,13 @@ output.elasticsearch: # The pin is a base64 encoded string of the SHA-256 fingerprint. #ssl.ca_sha256: "" + # A root CA HEX encoded fingerprint. During the SSL handshake if the + # fingerprint matches the root CA certificate, it will be added to + # the provided list of root CAs (`certificate_authorities`), if the + # list is empty or not defined, the matching certificate will be the + # only one in the list. Then the normal SSL validation happens. + #ssl.ca_trusted_fingerprint: "" + # -------------------------------- File Output --------------------------------- #output.file: @@ -2433,7 +2441,7 @@ output.elasticsearch: #path: "/tmp/metricbeat" # Name of the generated files. The default is `metricbeat` and it generates - # files: `metricbeat`, `metricbeat.1`, `metricbeat.2`, etc. + # files: `metricbeat-{datetime}.ndjson`, `metricbeat-{datetime}-1.ndjson`, etc. #filename: metricbeat # Maximum size in kilobytes of each file. When this size is reached, and on @@ -2451,6 +2459,7 @@ output.elasticsearch: # Configure automatic file rotation on every startup. The default is true. #rotate_on_startup: true + # ------------------------------- Console Output ------------------------------- #output.console: # Boolean flag to enable or disable the output module. @@ -2549,19 +2558,13 @@ output.elasticsearch: # Set to false to disable template loading. #setup.template.enabled: true -# Select the kind of index template. From Elasticsearch 7.8, it is possible to -# use component templates. Available options: legacy, component, index. -# By default metricbeat uses the legacy index templates. -#setup.template.type: legacy - # Template name. By default the template name is "metricbeat-%{[agent.version]}" # The template name and pattern has to be set in case the Elasticsearch index pattern is modified. #setup.template.name: "metricbeat-%{[agent.version]}" -# Template pattern. By default the template pattern is "-%{[agent.version]}-*" to apply to the default index settings. -# The first part is the version of the beat and then -* is used to match all daily indices. +# Template pattern. By default the template pattern is "metricbeat-%{[agent.version]}" to apply to the default index settings. # The template name and pattern has to be set in case the Elasticsearch index pattern is modified. -#setup.template.pattern: "metricbeat-%{[agent.version]}-*" +#setup.template.pattern: "metricbeat-%{[agent.version]}" # Path to fields.yml file to generate the template #setup.template.fields: "${path.config}/fields.yml" @@ -2608,17 +2611,8 @@ setup.template.settings: # output.elasticsearch.index is ignored, and the write alias is used to set the # index name. -# Enable ILM support. Valid values are true, false, and auto. When set to auto -# (the default), the Beat uses index lifecycle management when it connects to a -# cluster that supports ILM; otherwise, it creates daily indices. -#setup.ilm.enabled: auto - -# Set the prefix used in the index lifecycle write alias name. The default alias -# name is 'metricbeat-%{[agent.version]}'. -#setup.ilm.rollover_alias: 'metricbeat' - -# Set the rollover index pattern. The default is "%{now/d}-000001". -#setup.ilm.pattern: "{now/d}-000001" +# Enable ILM support. Valid values are true, false. +#setup.ilm.enabled: true # Set the lifecycle policy name. The default policy name is # 'beatname'. @@ -2716,6 +2710,13 @@ setup.kibana: # The pin is a base64 encoded string of the SHA-256 fingerprint. #ssl.ca_sha256: "" + # A root CA HEX encoded fingerprint. During the SSL handshake if the + # fingerprint matches the root CA certificate, it will be added to + # the provided list of root CAs (`certificate_authorities`), if the + # list is empty or not defined, the matching certificate will be the + # only one in the list. Then the normal SSL validation happens. + #ssl.ca_trusted_fingerprint: "" + # ================================== Logging =================================== @@ -2787,11 +2788,6 @@ logging.files: # file. Defaults to true. # rotateonstartup: true - # Rotated files are either suffixed with a number e.g. metricbeat.1 when - # renamed during rotation. Or when set to date, the date is added to - # the end of the file. On rotation a new file is created, older files are untouched. - #suffix: count - # ============================= X-Pack Monitoring ============================== # Metricbeat can export internal metrics to a central Elasticsearch monitoring # cluster. This requires xpack monitoring to be enabled in Elasticsearch. The @@ -2919,6 +2915,13 @@ logging.files: # The pin is a base64 encoded string of the SHA-256 fingerprint. #ssl.ca_sha256: "" + # A root CA HEX encoded fingerprint. During the SSL handshake if the + # fingerprint matches the root CA certificate, it will be added to + # the provided list of root CAs (`certificate_authorities`), if the + # list is empty or not defined, the matching certificate will be the + # only one in the list. Then the normal SSL validation happens. + #ssl.ca_trusted_fingerprint: "" + # Enable Kerberos support. Kerberos is automatically enabled if any Kerberos setting is set. #kerberos.enabled: true diff --git a/x-pack/metricbeat/module/airflow/statsd/data_test.go b/x-pack/metricbeat/module/airflow/statsd/data_test.go index b8cc1ab4718..c2c07d32f34 100644 --- a/x-pack/metricbeat/module/airflow/statsd/data_test.go +++ b/x-pack/metricbeat/module/airflow/statsd/data_test.go @@ -8,8 +8,10 @@ import ( "fmt" "net" "runtime" + "sync" "testing" - "time" + + "github.com/elastic/beats/v7/x-pack/metricbeat/module/statsd/server" "github.com/stretchr/testify/require" @@ -36,7 +38,7 @@ func getConfig() map[string]interface{} { "host": STATSD_HOST, "port": STATSD_PORT, "period": "100ms", - "ttl": "0s", + "ttl": "1ms", } } @@ -58,12 +60,22 @@ func TestData(t *testing.T) { ms := mbtest.NewPushMetricSetV2(t, getConfig()) var events []mb.Event + var reporter mb.PushReporterV2 done := make(chan interface{}) - go func() { - events = mbtest.RunPushMetricSetV2(30*time.Second, 1, ms) + wg := new(sync.WaitGroup) + wg.Add(1) + go func(wg *sync.WaitGroup) { + reporter = mbtest.GetCapturingPushReporterV2() + ms.(*server.MetricSet).ServerStart() + wg.Done() + + go ms.Run(reporter) + events = reporter.(*mbtest.CapturingPushReporterV2).BlockingCapture(1) + close(done) - }() + }(wg) + wg.Wait() createEvent(t) <-done diff --git a/x-pack/metricbeat/module/aws/_meta/docs.asciidoc b/x-pack/metricbeat/module/aws/_meta/docs.asciidoc index c4ceae59eee..9a9a58887f7 100644 --- a/x-pack/metricbeat/module/aws/_meta/docs.asciidoc +++ b/x-pack/metricbeat/module/aws/_meta/docs.asciidoc @@ -58,6 +58,24 @@ If endpoint is specified, `regions` config becomes required. For example: - ec2 ---- +* *fips_enabled* + +Enforces the use of FIPS service endpoints. See <> for more information. + +[source,yaml] +---- +- module: aws + period: 5m + fips_enabled: true + regions: + - us-east-1 + - us-east-2 + - us-west-1 + - us-west-2 + metricsets: + - ec2 +---- + The aws module comes with a predefined dashboard. For example: image::./images/metricbeat-aws-overview.png[] diff --git a/x-pack/metricbeat/module/aws/aws.go b/x-pack/metricbeat/module/aws/aws.go index 0e04ad6f4fa..e11b5a1126a 100644 --- a/x-pack/metricbeat/module/aws/aws.go +++ b/x-pack/metricbeat/module/aws/aws.go @@ -7,6 +7,7 @@ package aws import ( "context" "fmt" + "strings" "time" awssdk "github.com/aws/aws-sdk-go-v2/aws" @@ -105,9 +106,12 @@ func NewMetricSet(base mb.BaseMetricSet) (*MetricSet, error) { awsConfig.Region = config.Regions[0] } + stsServiceName := awscommon.CreateServiceName("sts", config.AWSConfig.FIPSEnabled, awsConfig.Region) + iamServiceName := awscommon.CreateServiceName("iam", config.AWSConfig.FIPSEnabled, awsConfig.Region) + // Get IAM account id svcSts := sts.New(awscommon.EnrichAWSConfigWithEndpoint( - config.AWSConfig.Endpoint, "sts", "", awsConfig)) + config.AWSConfig.Endpoint, stsServiceName, "", awsConfig)) reqIdentity := svcSts.GetCallerIdentityRequest(&sts.GetCallerIdentityInput{}) outputIdentity, err := reqIdentity.Send(context.TODO()) if err != nil { @@ -116,16 +120,20 @@ func NewMetricSet(base mb.BaseMetricSet) (*MetricSet, error) { metricSet.AccountID = *outputIdentity.Account base.Logger().Debug("AWS Credentials belong to account ID: ", metricSet.AccountID) } - + iamRegion := "" + if strings.HasPrefix(awsConfig.Region, "us-gov-") { + iamRegion = "us-gov" + } // Get account name/alias svcIam := iam.New(awscommon.EnrichAWSConfigWithEndpoint( - config.AWSConfig.Endpoint, "iam", "", awsConfig)) + config.AWSConfig.Endpoint, iamServiceName, iamRegion, awsConfig)) metricSet.AccountName = getAccountName(svcIam, base, metricSet) // Construct MetricSet with a full regions list if config.Regions == nil { + ec2ServiceName := awscommon.CreateServiceName("ec2", config.AWSConfig.FIPSEnabled, awsConfig.Region) svcEC2 := ec2.New(awscommon.EnrichAWSConfigWithEndpoint( - config.AWSConfig.Endpoint, "ec2", "", awsConfig)) + config.AWSConfig.Endpoint, ec2ServiceName, "", awsConfig)) completeRegionsList, err := getRegions(svcEC2) if err != nil { return nil, err diff --git a/x-pack/metricbeat/module/aws/billing/billing.go b/x-pack/metricbeat/module/aws/billing/billing.go index c1c66ac0529..b7da00495a7 100644 --- a/x-pack/metricbeat/module/aws/billing/billing.go +++ b/x-pack/metricbeat/module/aws/billing/billing.go @@ -114,6 +114,12 @@ func (c CostExplorerConfig) Validate() error { // format. It publishes the event which is then forwarded to the output. In case // of an error set the Error field of mb.Event or simply call report.Error(). func (m *MetricSet) Fetch(report mb.ReporterV2) error { + var config aws.Config + err := m.Module().UnpackConfig(&config) + if err != nil { + return nil + } + monitoringServiceName := awscommon.CreateServiceName("monitoring", config.AWSConfig.FIPSEnabled, regionName) // Get startDate and endDate startDate, endDate := getStartDateEndDate(m.Period) @@ -123,11 +129,11 @@ func (m *MetricSet) Fetch(report mb.ReporterV2) error { // get cost metrics from cost explorer awsConfig := m.MetricSet.AwsConfig.Copy() svcCostExplorer := costexplorer.New(awscommon.EnrichAWSConfigWithEndpoint( - m.Endpoint, "monitoring", "", awsConfig)) + m.Endpoint, monitoringServiceName, "", awsConfig)) awsConfig.Region = regionName svcCloudwatch := cloudwatch.New(awscommon.EnrichAWSConfigWithEndpoint( - m.Endpoint, "monitoring", regionName, awsConfig)) + m.Endpoint, monitoringServiceName, regionName, awsConfig)) timePeriod := costexplorer.DateInterval{ Start: awssdk.String(startDate), @@ -212,10 +218,17 @@ func (m *MetricSet) getCostGroupBy(svcCostExplorer costexploreriface.ClientAPI, // get linked account IDs and names accounts := map[string]string{} + var config aws.Config + err := m.Module().UnpackConfig(&config) + if err != nil { + return nil + } if ok, _ := aws.StringInSlice("LINKED_ACCOUNT", groupByDimKeys); ok { awsConfig := m.MetricSet.AwsConfig.Copy() + organizationsServiceName := awscommon.CreateServiceName("organizations", config.AWSConfig.FIPSEnabled, regionName) + svcOrg := organizations.New(awscommon.EnrichAWSConfigWithEndpoint( - m.Endpoint, "organizations", regionName, awsConfig)) + m.Endpoint, organizationsServiceName, regionName, awsConfig)) accounts = m.getAccountName(svcOrg) } diff --git a/x-pack/metricbeat/module/aws/cloudwatch/cloudwatch.go b/x-pack/metricbeat/module/aws/cloudwatch/cloudwatch.go index 1e67fceac70..9c2f24d87ac 100644 --- a/x-pack/metricbeat/module/aws/cloudwatch/cloudwatch.go +++ b/x-pack/metricbeat/module/aws/cloudwatch/cloudwatch.go @@ -140,18 +140,25 @@ func (m *MetricSet) Fetch(report mb.ReporterV2) error { m.logger.Debugf("listMetricDetailTotal = %s", listMetricDetailTotal) m.logger.Debugf("namespaceDetailTotal = %s", namespaceDetailTotal) + var config aws.Config + err = m.Module().UnpackConfig(&config) + if err != nil { + return err + } + // Create events based on listMetricDetailTotal from configuration if len(listMetricDetailTotal.metricsWithStats) != 0 { for _, regionName := range m.MetricSet.RegionsList { m.logger.Debugf("Collecting metrics from AWS region %s", regionName) awsConfig := m.MetricSet.AwsConfig.Copy() awsConfig.Region = regionName + monitoringServiceName := awscommon.CreateServiceName("monitoring", config.AWSConfig.FIPSEnabled, regionName) svcCloudwatch := cloudwatch.New(awscommon.EnrichAWSConfigWithEndpoint( - m.Endpoint, "monitoring", regionName, awsConfig)) + m.Endpoint, monitoringServiceName, regionName, awsConfig)) svcResourceAPI := resourcegroupstaggingapi.New(awscommon.EnrichAWSConfigWithEndpoint( - m.Endpoint, "tagging", regionName, awsConfig)) + m.Endpoint, "tagging", regionName, awsConfig)) //Does not support FIPS eventsWithIdentifier, err := m.createEvents(svcCloudwatch, svcResourceAPI, listMetricDetailTotal.metricsWithStats, listMetricDetailTotal.resourceTypeFilters, regionName, startTime, endTime) if err != nil { @@ -173,11 +180,12 @@ func (m *MetricSet) Fetch(report mb.ReporterV2) error { awsConfig := m.MetricSet.AwsConfig.Copy() awsConfig.Region = regionName + monitoringServiceName := awscommon.CreateServiceName("monitoring", config.AWSConfig.FIPSEnabled, regionName) svcCloudwatch := cloudwatch.New(awscommon.EnrichAWSConfigWithEndpoint( - m.Endpoint, "monitoring", regionName, awsConfig)) + m.Endpoint, monitoringServiceName, regionName, awsConfig)) svcResourceAPI := resourcegroupstaggingapi.New(awscommon.EnrichAWSConfigWithEndpoint( - m.Endpoint, "tagging", regionName, awsConfig)) + m.Endpoint, "tagging", regionName, awsConfig)) //Does not support FIPS for namespace, namespaceDetails := range namespaceDetailTotal { m.logger.Debugf("Collected metrics from namespace %s", namespace) @@ -204,7 +212,7 @@ func (m *MetricSet) Fetch(report mb.ReporterV2) error { m.logger.Debugf("Collected number of metrics = %d", len(eventsWithIdentifier)) - err = reportEvents(addMetadata(namespace, m.Endpoint, regionName, awsConfig, eventsWithIdentifier), report) + err = reportEvents(addMetadata(namespace, m.Endpoint, regionName, awsConfig, config.AWSConfig.FIPSEnabled, eventsWithIdentifier), report) if err != nil { return errors.Wrap(err, "reportEvents failed") } diff --git a/x-pack/metricbeat/module/aws/cloudwatch/metadata.go b/x-pack/metricbeat/module/aws/cloudwatch/metadata.go index 7c0a82aafdf..be4b637cca7 100644 --- a/x-pack/metricbeat/module/aws/cloudwatch/metadata.go +++ b/x-pack/metricbeat/module/aws/cloudwatch/metadata.go @@ -21,14 +21,14 @@ const ( ) // addMetadata adds metadata to the given events map based on namespace -func addMetadata(namespace string, endpoint string, regionName string, awsConfig awssdk.Config, events map[string]mb.Event) map[string]mb.Event { +func addMetadata(namespace string, endpoint string, regionName string, awsConfig awssdk.Config, fips_enabled bool, events map[string]mb.Event) map[string]mb.Event { switch namespace { case namespaceEC2: - return ec2.AddMetadata(endpoint, regionName, awsConfig, events) + return ec2.AddMetadata(endpoint, regionName, awsConfig, fips_enabled, events) case namespaceRDS: - return rds.AddMetadata(endpoint, regionName, awsConfig, events) + return rds.AddMetadata(endpoint, regionName, awsConfig, fips_enabled, events) case namespaceSQS: - return sqs.AddMetadata(endpoint, regionName, awsConfig, events) + return sqs.AddMetadata(endpoint, regionName, awsConfig, fips_enabled, events) default: return events } diff --git a/x-pack/metricbeat/module/aws/cloudwatch/metadata/ec2/ec2.go b/x-pack/metricbeat/module/aws/cloudwatch/metadata/ec2/ec2.go index 8637afd8979..0a60351e907 100644 --- a/x-pack/metricbeat/module/aws/cloudwatch/metadata/ec2/ec2.go +++ b/x-pack/metricbeat/module/aws/cloudwatch/metadata/ec2/ec2.go @@ -22,9 +22,10 @@ import ( const metadataPrefix = "aws.ec2.instance." // AddMetadata adds metadata for EC2 instances from a specific region -func AddMetadata(endpoint string, regionName string, awsConfig awssdk.Config, events map[string]mb.Event) map[string]mb.Event { +func AddMetadata(endpoint string, regionName string, awsConfig awssdk.Config, fips_enabled bool, events map[string]mb.Event) map[string]mb.Event { + ec2ServiceName := awscommon.CreateServiceName("ec2", fips_enabled, regionName) svcEC2 := ec2.New(awscommon.EnrichAWSConfigWithEndpoint( - endpoint, "ec2", regionName, awsConfig)) + endpoint, ec2ServiceName, regionName, awsConfig)) instancesOutputs, err := getInstancesPerRegion(svcEC2) if err != nil { diff --git a/x-pack/metricbeat/module/aws/cloudwatch/metadata/rds/rds.go b/x-pack/metricbeat/module/aws/cloudwatch/metadata/rds/rds.go index c74234af7ce..3e64d3079cb 100644 --- a/x-pack/metricbeat/module/aws/cloudwatch/metadata/rds/rds.go +++ b/x-pack/metricbeat/module/aws/cloudwatch/metadata/rds/rds.go @@ -21,9 +21,10 @@ import ( const metadataPrefix = "aws.rds.db_instance." // AddMetadata adds metadata for RDS instances from a specific region -func AddMetadata(endpoint string, regionName string, awsConfig awssdk.Config, events map[string]mb.Event) map[string]mb.Event { +func AddMetadata(endpoint string, regionName string, awsConfig awssdk.Config, fips_enabled bool, events map[string]mb.Event) map[string]mb.Event { + rdsServiceName := awscommon.CreateServiceName("rds", fips_enabled, regionName) svc := rds.New(awscommon.EnrichAWSConfigWithEndpoint( - endpoint, "rds", regionName, awsConfig)) + endpoint, rdsServiceName, regionName, awsConfig)) // Get DBInstance IDs per region dbDetailsMap, err := getDBInstancesPerRegion(svc) @@ -87,7 +88,8 @@ func getDBInstancesPerRegion(svc rdsiface.ClientAPI) (map[string]*rds.DBInstance instancesOutputs := map[string]*rds.DBInstance{} for _, dbInstance := range output.DBInstances { - instancesOutputs[*dbInstance.DBInstanceIdentifier] = &dbInstance + instance := dbInstance + instancesOutputs[*instance.DBInstanceIdentifier] = &instance } return instancesOutputs, nil } diff --git a/x-pack/metricbeat/module/aws/cloudwatch/metadata/sqs/sqs.go b/x-pack/metricbeat/module/aws/cloudwatch/metadata/sqs/sqs.go index 674731f4d4b..812b7d3a5c7 100644 --- a/x-pack/metricbeat/module/aws/cloudwatch/metadata/sqs/sqs.go +++ b/x-pack/metricbeat/module/aws/cloudwatch/metadata/sqs/sqs.go @@ -22,9 +22,10 @@ import ( const metadataPrefix = "aws.sqs.queue" // AddMetadata adds metadata for SQS queues from a specific region -func AddMetadata(endpoint string, regionName string, awsConfig awssdk.Config, events map[string]mb.Event) map[string]mb.Event { +func AddMetadata(endpoint string, regionName string, awsConfig awssdk.Config, fips_enabled bool, events map[string]mb.Event) map[string]mb.Event { + sqsServiceName := awscommon.CreateServiceName("sqs", fips_enabled, regionName) svc := sqs.New(awscommon.EnrichAWSConfigWithEndpoint( - endpoint, "sqs", regionName, awsConfig)) + endpoint, sqsServiceName, regionName, awsConfig)) // Get queueUrls for each region queueURLs, err := getQueueUrls(svc) diff --git a/x-pack/metricbeat/module/gcp/metrics/metrics_requester.go b/x-pack/metricbeat/module/gcp/metrics/metrics_requester.go index e5cf8c8b05d..d518acc0014 100644 --- a/x-pack/metricbeat/module/gcp/metrics/metrics_requester.go +++ b/x-pack/metricbeat/module/gcp/metrics/metrics_requester.go @@ -69,22 +69,21 @@ func (r *metricsRequester) Metric(ctx context.Context, serviceName, metricType s return } -func (r *metricsRequester) Metrics(ctx context.Context, sdc metricsConfig, metricsMeta map[string]metricMeta) ([]timeSeriesWithAligner, error) { +func (r *metricsRequester) Metrics(ctx context.Context, serviceName string, aligner string, metricsToCollect map[string]metricMeta) ([]timeSeriesWithAligner, error) { var lock sync.Mutex var wg sync.WaitGroup results := make([]timeSeriesWithAligner, 0) - aligner := sdc.Aligner - for mt, meta := range metricsMeta { + for mt, meta := range metricsToCollect { wg.Add(1) metricMeta := meta go func(mt string) { defer wg.Done() - r.logger.Debugf("For metricType %s, metricMeta = %d", mt, metricMeta) + r.logger.Debugf("For metricType %s, metricMeta = %d, aligner = %s", mt, metricMeta, aligner) interval, aligner := getTimeIntervalAligner(metricMeta.ingestDelay, metricMeta.samplePeriod, r.config.period, aligner) - ts := r.Metric(ctx, sdc.ServiceName, mt, interval, aligner) + ts := r.Metric(ctx, serviceName, mt, interval, aligner) lock.Lock() defer lock.Unlock() results = append(results, ts) diff --git a/x-pack/metricbeat/module/gcp/metrics/metricset.go b/x-pack/metricbeat/module/gcp/metrics/metricset.go index d284d80ca5d..e121d6a3a02 100644 --- a/x-pack/metricbeat/module/gcp/metrics/metricset.go +++ b/x-pack/metricbeat/module/gcp/metrics/metricset.go @@ -165,7 +165,15 @@ func New(base mb.BaseMetricSet) (mb.MetricSet, error) { func (m *MetricSet) Fetch(ctx context.Context, reporter mb.ReporterV2) (err error) { for _, sdc := range m.MetricsConfig { m.Logger().Debugf("metrics config: %v", sdc) - responses, err := m.requester.Metrics(ctx, sdc, m.metricsMeta) + // m.metricsMeta contains all metrics to be collected, not just the one in the current MetricsConfig. + // this loop filters the metrics in metricsMeta so requester.Metrics can collect only the appropriate + // ones. + // See https://github.com/elastic/beats/pull/29514 + metricsToCollect := map[string]metricMeta{} + for _, v := range sdc.MetricTypes { + metricsToCollect[sdc.AddPrefixTo(v)] = m.metricsMeta[sdc.AddPrefixTo(v)] + } + responses, err := m.requester.Metrics(ctx, sdc.ServiceName, sdc.Aligner, metricsToCollect) if err != nil { err = errors.Wrapf(err, "error trying to get metrics for project '%s' and zone '%s' or region '%s'", m.config.ProjectID, m.config.Zone, m.config.Region) m.Logger().Error(err) diff --git a/x-pack/metricbeat/module/prometheus/collector/_meta/data.json b/x-pack/metricbeat/module/prometheus/collector/_meta/data.json index b1fd95460ad..d35cd24a921 100644 --- a/x-pack/metricbeat/module/prometheus/collector/_meta/data.json +++ b/x-pack/metricbeat/module/prometheus/collector/_meta/data.json @@ -11,10 +11,11 @@ }, "prometheus": { "labels": { + "device": "br-33d819d5f834", "job": "prometheus" }, - "up": { - "value": 1 + "node_network_carrier": { + "value": 0 } }, "service": { diff --git a/x-pack/metricbeat/module/statsd/server/server.go b/x-pack/metricbeat/module/statsd/server/server.go index 3e9f35d8436..a32129910fe 100644 --- a/x-pack/metricbeat/module/statsd/server/server.go +++ b/x-pack/metricbeat/module/statsd/server/server.go @@ -71,9 +71,10 @@ func defaultConfig() Config { // multiple fetch calls. type MetricSet struct { mb.BaseMetricSet - server serverhelper.Server - processor *metricProcessor - mappings map[string]StatsdMapping + server serverhelper.Server + serverStarted bool + processor *metricProcessor + mappings map[string]StatsdMapping } // New create a new instance of the MetricSet @@ -104,6 +105,12 @@ func New(base mb.BaseMetricSet) (mb.MetricSet, error) { }, nil } +// Host returns the hostname or other module specific value that identifies a +// specific host or service instance from which to collect metrics. +func (b *MetricSet) Host() string { + return b.server.(*udp.UdpServer).GetHost() +} + func buildMappings(config []StatsdMapping) (map[string]StatsdMapping, error) { mappings := make(map[string]StatsdMapping, len(config)) replacer := strings.NewReplacer(".", `\.`, "<", "(?P<", ">", ">[^.]+)") @@ -185,13 +192,32 @@ func (m *MetricSet) getEvents() []*mb.Event { return events } +// ServerStart starts the underlying m.server +func (m *MetricSet) ServerStart() { + if m.serverStarted { + return + } + m.server.Start() + m.serverStarted = true +} + +// ServerStop stops the underlying m.server +func (m *MetricSet) ServerStop() { + if !m.serverStarted { + return + } + + m.server.Stop() + m.serverStarted = false +} + // Run method provides the module with a reporter with which events can be reported. func (m *MetricSet) Run(reporter mb.PushReporterV2) { period := m.Module().Config().Period // Start event watcher - m.server.Start() - defer m.server.Stop() + m.ServerStart() + defer m.ServerStop() reportPeriod := time.NewTicker(period) for { diff --git a/x-pack/osquerybeat/Jenkinsfile.yml b/x-pack/osquerybeat/Jenkinsfile.yml index fd55f11b63d..6ebd028027b 100644 --- a/x-pack/osquerybeat/Jenkinsfile.yml +++ b/x-pack/osquerybeat/Jenkinsfile.yml @@ -28,7 +28,7 @@ stages: macos: mage: "mage build unitTest" platforms: ## override default label in this specific stage. - - "macosx&&x86_64" + - "orka && darwin && poc" when: ## Override the top-level when. comments: - "/test x-pack/osquerybeat for macos" diff --git a/x-pack/osquerybeat/docs/fields.asciidoc b/x-pack/osquerybeat/docs/fields.asciidoc index 0ad49632287..96ab2d13685 100644 --- a/x-pack/osquerybeat/docs/fields.asciidoc +++ b/x-pack/osquerybeat/docs/fields.asciidoc @@ -15451,47 +15451,16 @@ type: ip -- - -*`kubernetes.namespace.name`*:: +*`kubernetes.namespace`*:: + -- -Kubernetes namespace name +Kubernetes namespace type: keyword -- -*`kubernetes.namespace.uuid`*:: -+ --- -Kubernetes namespace uuid - - -type: keyword - --- - -*`kubernetes.namespace.labels.*`*:: -+ --- -Kubernetes namespace labels map - - -type: object - --- - -*`kubernetes.namespace.annotations.*`*:: -+ --- -Kubernetes namespace annotations map - - -type: object - --- - *`kubernetes.node.name`*:: + -- diff --git a/x-pack/osquerybeat/include/fields.go b/x-pack/osquerybeat/include/fields.go index b8a323811b6..9d6bce231f9 100644 --- a/x-pack/osquerybeat/include/fields.go +++ b/x-pack/osquerybeat/include/fields.go @@ -19,5 +19,5 @@ func init() { // AssetFieldsYml returns asset data. // This is the base64 encoded zlib format compressed contents of fields.yml. func AssetFieldsYml() string { - return "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" + return "eJzsvft7GzeyKPh7/gqsZr+VlUO2SL0sa+/sXkWSE33Hr7HkyZzE84lgN0hi1AQ6AFo0c/b87/uhCkCjH5IpWXTsjO/N8VBkN1BVKBSqCvX4C/n5+O2r81c//h/kVBIhDWEZN8TMuCYTnjOSccVSky97hBuyoJpMmWCKGpaR8ZKYGSNnJxekUPJfLDW97/5CxlSzjEgB398wpbkU5DAZJIN+xm6S7/5C3uSMakZuuOaGzIwp9NH29pSbWTlOUjnfZjnVhqfbLNXESKLL6ZRpQ9IZFVMGX9mhJ5zlmU6++65PrtnyiLBUf0eI4SZnR/aB7wjJmE4VLwyXAr4iz907xL199B0hfSLonB2Rzf9t+JxpQ+fF5neEEJKzG5YfkVQqBn8r9lvJFcuOiFElfmWWBTsiGTX4Z22+zVNq2LYdkyxmTACp2A0ThkjFp1xYEibfwXuEXFp6cw0PZeE99sEomlpST5ScVyP07MQ8pXm+JIoVimkmDBdTmMiNWE3XuWhaliplYf7zSfQC/kZmVBMhPbQ5CeTpIXvc0LxkAHQAppBFmdtp3LBusglX2sD7DbAUSxm/qaAqeMFyLiq43jqa43qRiVSE5jmOoBNcJ/aBzgu76Js7g+FBf7Df39m9HBweDfaPdveSw/3dXzajZc7pmOW6c4FxNeXYcjJ8gR+v8PtrtlxIlXUs9EmpjZzbB7aRJgXlSgccTqggY0ZKuy2MJDTLyJwZSriYSDWndhD7vcOJXMxkmWewFVMpDOWCCKbt0iE4wL72/x3nOa6BJlQxoo20hKLaQxoAOPMEGmUyvWZqRKjIyOj6UI8cOVqU/O8NWhQ5TwG6jSOyMZGyP6Zqo0c2mLix3xRKZmUKv/9PTOA505pO2R0UnlOTzq6kyJdXhn0wHRR9LhXJ5dTRBFjDDesYwVEGf7JPup97RBaGz/nvgQUty9xwtrDbgwtC4Wn7BVOBQHY6bVSZmtKSMJdTTRbczGRpCBXVDqjB0CPSzJhykoSkuMqpFCk1TESbwEgLxJxQMivnVPQVoxkd54zocj6naklktPniHTkvc8OLPOCuCfvAtd39M7asJpyPuWAZ4cJIIkV4urmmP7E8l+RnqfIsWi1Dp3dthpjp+VRIxa7oWN6wIzIc7Oy1V+4F18bi497TgesNnRJG05nHss5uv8bchCy2s/HPmKvolAnkFCfhj8MXUyXL4ojsdPDR5Yzhm2GV3I5ycpYSOraLjBJxYhZ2I1lZaux5N3FLQcXS0pzaDZnndgv2SMYMfpCKyLFm6sYuD7KrtGw2k3alpCKGXjNN5ozqUrG5fcANGx5rblRNuEjzMmPkB0atSABcNZnTJaG5lkSVwr7t5lU6gcMNEE2+d6i6IfXMyssxq0QzcLaFn/Jce95DIqlSCLtPJBLIwhbhp9yQixlTsSCf0aJglgMtsrBTA6og5C0BhOPGiZRGSGPX3CN7RM5xutQqBXKCSMO+tRuxV8GXWFYgTjEZM2qSaP8ev3kJKoo7ROsIuRWnRbFtUeEpS0jFG7EgziTzpAMJDDoH4RPkFq6JPWqJmSlZTmfkt5KVdny91IbNNcn5NSP/SSfXtEfesowjfxRKpkxrLqZ+UdzjukxnVmC/kFNtqJ4RxINcALkdyXAjApM7Dp/QMjdXsMyRLlJpNNWuGZc8zxIvv9zszZ3etddv3e3NHXb2wTCR2RPcTlUj5cTxA66d53Gn66AYt0qPcAMYGXYnFcuO8WAHUlwIVFHCkHZnFEre8Iz1rM6iC5byCU8Jvg26EddBg3OUjSTQnBnFU8tTQWV9mhwkA/KEzrODva0eyfkYfsavfz2gO7vscHI42R1M9geD4Zju7u2xPba/lx1mz9Lx4U46Hg6epgFEi48hO4OdQX+w0x/sk53do+HgaDgg/zEYDAbk3eXJPwOFays8oblmtWVlxYzNmaL5Fc/qi8rccjzCwvo5CM+sRJxwplBacO32zRM+gQMHTiW91VxibpUYNQfF0OvuNFVS24XQhiorPselISPkEJ6NYPvZjddeoUO6Zwk9qRGiif7j8PQ7wX+zmu398Q6alpVIKMfgvQWodGNGQGrxDgZ06GU19Oy/60DQKawgTuMDoLWCmlB8Ck8/1Dim/IaBxkqFew2fdj/PWF5MytzKTCsBHIZhYLOQ5LmT34QLbahInQbbOH60nRjOIMskTnsilfbECqpAMoSxuSaCsQzNz8WMp7P2VEGQp3JuJ7OWVYT3+cTKD3/QAKp4Avmv5MQwQXI2MYTNC7NsL+VEytoq2oVaxypeLos7ls8fbnYCQvMFXWqijf030NZaAXrmWROX1Rli+K5V3pKKNCIc0YGq1bPI4m6iMaseAY2FT2oLX61YkwFqiz+n6cxag20Sx+N4OjvBvQZS/90dCXViN2A6ABeHSndirVXXVNbSSCHnstTkAjSAj6ivx4LQ6hVUGsiT44st3JhOGXWApVIIBr6Cc2GYEsyQN0oamUp/7j85f7NFlCzhNCwUm/APTJNSZAzPaXv6Kpnbwax0k4rMpWJEMLOQ6prIgilqpLL6rTfv2YzmE/sCJVa9yRmh2ZwLro3dmTdel7ZjZXKOijc1xHksEIn5XIoeSXNGVb6sTkCwaQK0MufpEuyIGQOVwSKYfLJ+JMr5OOi1dx2huQzKW22J3FGB4xCa5zIFHdtB2lo+p3aGr8NGcKvrBnpyfPFqi5QweL6sTiKNNlRYEtwr5zV6RCw53B8ePKshLNWUCv47iM2kfbx8ivoA1upVTOVIBHozn9zpBOhYvkr5aVD+dYQJzNLC/kcpLUe+eHES7cg05w1D8qT65g5L8ti9abee506qHTtyw+3OwI3gF8dtSKcJe+DQQlRsSlUGloM1DKTQveh5tBrGHF2vXAqak0kuF0Sx1BrVNb/F5ckbNyqeUxWYLdjsF/bxCDLYjpqJYC/aZy7+6xUpaHrNzBO9lcAs6OoonEBpTYXuRavo1Sb1hq4CzZtpC4czxTyVjKJCUwAmIRdyzoJxVGo0Mg1Tc7LhfaZSbVRuFcUmXnY5UEQDQY0bzv3snAC4smMWjGBwAkQEcJvRgiWmfpmrKWL40Z3hmMhPYM+yUpeWIG7UyvrmwoL3r1LgAoAxjua192h3DFbRV0jTGtKqWbhefdjH3pUYHJA43rafJ7iMYfOg4kazjGg2p8LwFE4C9sE4HY99QO29hyqVlwM6aHpGkhtu0eW/s8qzYhFlCuw5zU1J3XKcT8hSlirMMaF57pnPnw9Whk6lWvbso15F0YbnOWFCl8rpo85PbdWYjGlj2cOS1BJswvM8iDFaFEoWilPD8uUjWNU0yxTTel2WF+wCdK04nnMTOi0piJ/5mE9LWep8iVwO7wRBurDk0nLOwG9Pcq7BmXn+pmeNaDyNpSLUHjMfiJaWfxJC/quieNAaKx0K94eiCw+T3w+jxH0xQpLVdVFBuIlUzaxE3zIelKOEFyMLyihBsEY9krGCicwZA6jJS1EBAX4et5KVrpX82x3nVCf/tid65OVaGqY/ovZHK44+ofprNUB+sD+goy/cu7md6BgBBWl7gQ73aoAhO6/BIHESHcdPanNOmUxSbpZXa3IenFh9vnN1Xlr7gTk3Yw0cKQwXTJirVGbrgOlyIfs5M4bZYyVj9TvRMPum7ob71fF3H2HUbmTWROBXkVcmTNYGWiozI8dzpnhKO4AshVHLK67lumh+glOQ84vXQPQWhCfHt4K1LtZ0IHWu8gkVNGtTCiT8x70GUyavCsnD8Vq/9JJiyk2ZoSqSUwN/tCDY/G+ykcNtav/pbnIw3DvcHfTIRk7NxhHZ20/2B/vPhofkfzZbQD6uWG84OzVTfa9SRD+hMePJ0yPO2YMKppyQqaKizKniZhnrBkuSWh0FNOpIBzjxR39wpSGHc4XKYsrsoefsikkupXJnZw9cRzNeae3VIYvg5aSYLTW3H/zNXepllI5AeCVNFKkA95IcHSxzOOOnTHps2w6nsdRGin6WttamkNrQfF27bPMNDI9ijWotU17d4eHdtwO5QvTvLiag0nrdVUy4dgkXiWNGroVcCGvjUGJRgYmkIr+cvyERTgRYG1TKG6qWZMEzq8nA8eh2NV7gwMc2/Z7tDfYG9xGzik25FOsUYG9hhrvkV/9vJ7fBtSYJ5mDqFGB/K9mYtfnPave/V7rxox6r1vrmc0Z+B3/gpMZwvXB7eX786jh6rhN4d1BtH6spHMt0+4eSCamvjrmKlLCPMAYvPoJleKCGx/mbYK34cxX1pyfnb272LLefv7k52KrrUXOarmM/vzw+6Qam4bwX0oRb1Dl1iujb5yfk6WBvB+6hMSqOZUfkzBoRMjXMkCdgGHPdI4f9Ma90cKvrbuEVqFONXNDVQpJfy6JgKqWa/ZPM2AeasZTPaU4yPuUG7kCsGmUhhWijMKYDHye2AkSQUmg+dcEobMpUQi7KFO6+b9yDLlYJ724QBhpGnC2LGeuQvoNBfzDo75/Bv7v9nd3aSglqkiZndJ6P3dyxeamo0OhJOX9jsXJ+BQxkfHV8GZx05AlLponzP1upXLkOCXqkvGu6dhkaDp3IL0WMonBhIaYklzQjY5pTkcIZOOGKLWieox9QydIejQ1r1yJdSGXuZ+x600cbxbst4JgadvyvhR7o/7qHFVjD+g2+/SCbb6cOR2tNVjFFb1+PN24NYkERz2fPI22YYtlVl7X5eHqiFUozPp0xbaJJPY1w7h4gUhQs8yDrcuyN1LD+z6tbYdT3ouGcX8rqKxsTKRP3XJLK+YYVXxvxF83ragy+dNfQGTNMzUGrLRRLubb6CqhNFH1hEKsDQaflOOcp0eVkwj+EEeGZJzNjiqPtbXwEn0ikmm4l5FItQSxKVLQ+cKtFopI1XhLN50W+JIZeV+uKvrOcagNiFyMvUacS0hBwAS1YngP2ly9Oq/igjVQm5fVGWzBG1KhxRSD7OrkhTAJMH0yGSWm39m8lzfmEV0uK9+cY1xap8HnuWQX0dcI+pKwwVfgZvFbdUbbYPYF7aUoKqgyPHO6kBQEID45z2f9zv6M2U9k1YICUdk3szCkVlced1PmqF1EgxKO2EBqzXC662bx7T9T3TUzbjcVikTCqTTJfuhGQMXBnUG02ott6BMKNMqO6CicFXEH9CNNU2tyGLsc7iS7Hw9rm69WYuAIPDQrn2vXxW9UYGz3cc0JaAc9zuMxlisuOEBiLwKqaoJHFFaDxGaQem0zsIXXD7KyOURz2T9jli9OtHhpTwZKq6B6IhqKj56/lQAhYlvW8Em2SpC0gm/OGYaMAG7tKwAdft2QEqXibUKxWYjXxCN/X+KbUTCXrZZnYf4c3uFLhvaidHEM35gzuBeTktmORCvLi9PgNBIQixqdhqJhXNtvYsTnl+ZqQe2cxgAm8EZO0AbDSs8NA/opuIiyam7o6BsAJRW8oz+k47zBu8zFThpxxoQ1zjFWjCFwz/mFsB7Ovn+8QybUFpLaDMn18MeLn48bg4m27yKmxynUHeyKca3SpxiuBk7WBmFE9WxcnOEqBtLHzoGNOKWatulaENnViSRAqpFjGqTNon0Ss8k4zF9k5Aix4hve28IfFbhRUgFSKCa4VzWtzUpF1aFUQadjBVGsJ8L0lvhdJ1trdF/1hf7+/M+zvDHb2dvaeDXeeHj7t7xw829nbebY32Ovv7O4Pn+0fPD086A8Hg0EbicdzFn5mOXgxs9YnuushG4OLO0lFE3arDFQyb17SPhrLHytFIY0KWBlm8vcV4JesJ1g1gN78deOaj6mgVxC7uNEjG4qB1i2mV3ZATES6g25VbJksEfAQWua/uD2yDFNSCe7OEGkAQ4HBIiaKhty0Cg30o2EMs3cmQCQzuTXLZkJeVlkOXMfh1lSQs5MdtLjsBp0wk86YhruZaHTCjXaJTRWQdnPX8/FqiVVchzDeOghuXFUKlzGl2FyaEPRLZGk0z1g0UxMyhIkSl9LjEfKsI6pX3b1SPXUQB60GgtwlN7l3+Nhhua5AdQSL8nY9cC5aa06XVp5plk/6Lm0TrVd4yqXiJN+jGISvDFVTZpLvCTGyxtxj5jIPMYvMPuVh2tzUEfW9aPUYu8gqObFEqLGIVJasU2mxcCF5ukcU0wXq1fkyIT/JBbthKiKZZkaTDgTcoA005qU126Vx2ZATuGkL91VKSuNAD4MT57SGU8ALA1lRoeKACDWIx0lNSfOwUI7SmK6Gt2J2gTwD+9kaiNgVsyIy5Og6MsaTeTIGolX09Cmq0icgoVPchStiiGdYs/aiYQSRh+0Wiq4AYWtZK9huoWibozqge4RguRQuBdenGG5We9DNBWweBxPxLOShukN/STI+mTAVu6vh9phD9qVVle1R2zdMUGEIEzdcSTGv39NUsvX454swOc96PlAJ5D95/fZHcp5hpiiE0ZZN/aNtuR4cHDx9+vTw8PDZs2ed5FxnSECboF4FoDmn+g5aBhoGGn0aLdH4alEz47rI6TI2RWI/EpaP6GfsZlV3krPteM7N8qp9m/p4iko0D96Wch/eCCclnq2K4Y0LsEx1ChEXjdjSYErdZ1Sb/rB+O+xza9a39c59TtX5qRfJoEL4A78JKO8Pd3b3rKr8bEDHacYmg26I18jdAeY4+60NdXQNDF+2k7geDaKXXueI8rnuJKPZSeYs42Xd5+8OtG/y9lHk7QpCo0HwbxL5MSWyJ+6fSTCvjvbXI7ofgNMfL9xXB/rLF/+r4+JqdH2Wk8HNFcvcLslSkyNvwjs9cvx7qVj0TUfFhmXfTfJAMnweee0JgVFxq5IApWydCN2idb4kDyaDtVZXyZb55Ch2TwmYMPHIx8Wr6EL3CLX49sg0LarbZqkwDo3mMmVUtF2Oi5WjBx3iGMG5JrRdAOejHh73xM8XuPk8/O0R8eUR4nIuGdeGi2nJ9cw/pxtOOqiCVCkr/toGy2+BpuLZpkfYFDSRs5MdcqPJCzofZ7RHfjx5Q348OSM3lYZzXBTkTEy5CHvo7y/tK/Z7V1qnayfSoiDMvWY/O5B7DlNVih6ZUDWlhvVIDtO39yN+v+qS/buL5H93WfwnE8JxUOLXJ2JD8Nw3AfrVCFDnI//m9PhcTo8Gwb85PR7T6eGJ+2/m9HBo/6mcHk2cvgqnhwP6T+H0cLj8u2vYDTL8uyraFRn+TPr26oh/nRr56vh909m/dJ09BMnJjF1pPhXUlL7UuIuWkxkjF7Vfbg+bu5wxzZpVvWtxphB/NuaCqiWmz4dJ9acXDsz4lGlzRfOpVNzM5uvkuRnVM6hD5icLmq/FCBM1sML07WkfNa4MdMDGFBQbfXBNXPJuSBSCylFhSN85wjI9PKmgMKvLHKn4GWlTgdvmFz2jO/sHq25xLLNbp3ArgHYsZc6o6CLiD/gThEHTAsIoOVasdHSwqLus6HZ0qGWDj8R/Rq4DPrX7fI1lmS1DRIHLq3IC7zCXXEV03+WBzKkoJ9T1QBgvLYV8SfwbJjKpkmhMVlXwVixnNxQTZY8Lyzffv76AgLWujJx5YudkyYcitcfxh+XKtDXUlGsrunacZdyVWmxLETjPmTKYLsgcKN00npS5r10/hfJDalkYOVW0mPGUMKWk0lU4ZDzqDc15FpdTkcoKIW38fOQFozeMlCKqJjjxifnwavWK10Kq8cOwC2s7i3TG0uuuUuhnb9++fnv17tXl23cXl2enV29fv75ceY1K7JiypvIYFzh8zdAJoj1odVVBKp4qaXmYnEhVyFqx6I8rFozO17yP7RSPuZlhPKncbnVlef0Wdg02onjTyjlyvz189ref/vHL4cvD47+vTEvfOWgFamYVq9Yodmq3CBUZqXdUqp/sjV5HUOAazrS2XN8Z7Az7A/vf5XDnaDg42h38srKchz3GVmGOO86lzQsj7SEMSxft8469S9JZPV/473bDY3hx9fpt7/mg9FTOfd3FHpJyxqvjvZbJ68ONK0ljT38pc+3aMLhwcQJiBPUCFFItdrnfCQqS7BPp2n3gY2IcWFX1o/+GKcwTp1PKhY6SaGasUiCtih97CjtlMa0R/yOCdhXCVFozaLhOxgWFOf7yjuLF4cF6gVpXOrbVjCrqieP6aDggAxQhYt+EVmIYJl9FjkcZEpWiPmN5EeWiQe4FlhUJQ2uX1SGW1viwm/0RgtDXmUZWEYVn9dhRPqfTtZqksb8BJgv5HwiQZUDsOyJFF2iGTtcEWcVxDi46baQKR33Y7p4+6sd2R0e2pk8UZnXNzWrzrnE5KqSrGljhShR5eV0eGBzdqvB0iocC1xUjtE4/7AMXyRe7E6+0UYzOYwlzajfoRfX1R1ptRaP4HW/oNcNKB1xg5WJ/Zgm2cL18qvGJBQdyZtIZi3yH56LrlfrDVYWqkAYdPRo8BdAtzRNcNusR+pSi+FWXbTOReS6hjdycCsHUERn9d4QweMv/p1/7yn7WzDS+hbogBU3Z/4ySICQ5tAhzCXRRSzk4iENS7YxCP0jlT2HlVH9CtS8nUdGRgSYRYaIT8lKqRtlzxypYGmIiS+HSi7gOrTmh7AjeZiWp3B7ncrpNRZ8LE5q29Y3smxnrh0svamgfZ+3jKvVxlX61bzsYC6nNP8MaHwtyhm9rRlU6q61BKoXmkNVUb04xpuk1NvjKeMo0qjXBE1VnFSiDONe1uhuN913RSHJaMmQO3EU3VsmWotceV2O6G9T/QAaxQ7EPnjUV00ZxX4q+lmrfyftMu+To0AJu9H7UI6Nt+8/39p//1/6zYf/5X/af/8f+8//Zf8iIPAG2qthky0M86o3AAzv6yyjx7Vc1wy1TJzqU1GcixZqRtLKKb2GGackzts2Eb9qKw2yHYbbTUikmzLajcD9VjBrWByolMzPP/9L4hRa8X1Az6xdU0bn+NSbhPx9BF3CbcgVJbJnOUGGu7jhoNipXiN1DUQczM0NJRw2ZQwtAzYRm3r5zNtv7oE++j/QoL7yS96LVEnAkplx8SCiU1bPrXig5Z2bGSviLiQzq1I7ikZlJkflqnAugQbDAgoOKZrAdF3yfYTPgmVVyHcWIZiYedcFCjwYUu+83wPTi6fuNUJzBvwtPJGSEOdju25EzN+JRYcbgZ8SBqSajDrk6St6LH9hSgiXTYOR4yI4jI1XcMMWpRdJq/vZ4xYzXUYAN555RHW2DeNiYMY/eC0K+Jy997qvng1F/hL+8klD3DVVnQYaDQSTNN5rnc7zGq1pO4Vh5LM4+xnR6Xxs4jJ+A3gkfgyXh2kBQkICwL7mYxsRyJ1HyXry0qr0dWROaK0azpY+jYa4isBfG2DqNLr2xitxU2zJdeoCQC3+B4sYYM21IYYnNU4a1bh05E2LBiYdEyKAAkTft4tK54LkbubdHiesXFlohW6MK2lBCW4t4XHvSQLeD8O7tzFs/Q+q8Go/p2HYUliZmWtBmKvl9B7fGQ34i41ZtXFd2pawWZLAKx24eCyJvmLIkBNm7LFhNEDl+ietS4+mUL5F1WRbfz27kcqo3gPk2sEGk3kjIz4ywDwVLsT2KPfhplpENo+x+2Agjw1t6KcyM2XXdqBrHUEUmpSlVx8W2nXA1h0DU8KSmsDe+vkNhjx6tFE70ljQVROYbdddbHAXosT/MNtbgTOomP/geq1Y1WLGh1j2n54p3Wg3Fm3kQwuZ6oCBH2gWNmtbSzg5CfmE7cIt68nysGw+ew5PQK564G49b+s1EE4CamkGJP9QuNbQzjzvtYVMVN+rYd6oB55GoY6xvm9CToU5Mv13ihkq1tu7Aq2Fs73d2lz/1wsgAb9zzF2qqwAEpup/zVAhYYnXxQOmvqu1OrZvQSr13wrZ3ve0fqfdOGBZ68OBO/NZ751vvnX+v3jvxdvTFmEEy/nENeOID5lsXHvOtC8+3LjzfuvB868LzrQtPQPRbF55vXXi+deG5swtPrNd9Ga14Ioi+9eP5Avrx8AIcxxGffKQJDat1nykUv7GC9/TlL1td/Weq0pRfVAse6PkSRdY4TCHepqKNkXaxLCVOGeQ+PD6G62iqcw9j7vN11qnte/IFtdfJWnbmtx4733rsfOux863HzrceO9967HzrsfOtx86jAfGtx863Hjvfeux867HzrcfOtx47HXB+IT12shzPXR/v9OIF/Hl3YsIqlQLA5Z7zsaKKM02ypaBzdKJ4gkqaoSdN+sRMuNlwP0NYoyyYck0/QEZqjKe20mFDzyg0zK3Ns4FKYZU8DwaNNwTGPjzfWQDM4HjaxVoGW8qnJhx5aL4np4hAP+fi2s23JE9GSZbnoy2SyvkcUgvAQSQF+ZmLTC509f4FgvsaM26fjBItu957J/iHPiizLdxbsNTAWOZ83DXgnKavLz49WKheZiL5Vq/h89VraJD+Kyrf0ID8WzWH9VVzaJL6W3GHL764Q3PJ/jy1HhqYfSv98HilH5qk/bNVgmji960wxJoKQzQI/a1OxC10stpnMs/21yS9Xp7u4xT3gkfP6HBNAF38dDx8GESVSrsGmHb2Dx4G1b679l4LVPvDnYdApTPGVpHYD4Lq4vTs7M39oFqTylHz7zpbtXkA45GS50syp4XuqiAAxhkUeNTX7c18zZRg+e5O4h0ZK6BbULMuR+bzMs8RYjtJC/cG8CdH752f4P0F2Pi7O+8fhBBLIEfPsDSUelxDOY4370g8je946n3aFu0Wih8O9u6BhT04qViuCQFMRoG4U5imxWY9n+eaEWrgKZ6zPtTMeVT9uGBJBNi6sW2EPz8A2Tc0jhH/OHJ2+KsbpvRnwM5N80DMDpLd5NnBYJAMn+4N9++BIp8X67wPOcZbkFCLqJDKuB4Hb85wp5FjQRwUpN+HQBF4jERwEfuLu0L3ds6EiylTheLClXOF3K0bJgidGKaIYkgxl8fo+x9YfbEPeFZ6mqJCB/NfY6kBmUKFiqznUt0WGGUBGa1YY8QoWlXBsNBjinBdx1MCH6amViljwhVjSxAUWDfFzBSjpq+YK5SxMxjubQ+G20ZhJZL+nObWaOsjcfrOmQiVMjoCMdODw8Fuusee7ewM7YcspfvPDnYpzXYPsmxyDwZxHavzK9gMa7y6CzvhU6TZxZvj81eXydk/zu6BorOD142Xm+ZT8NsI4vr9h+Mz75yHz6+Dmx2P4I27CRDuTQQadP7e5NUF/HnHvclzvDFxCR92wtNXF+S3ksEGhDo7Qi+YqjaC/d21Q3fWIuOwF0OQM7htxTRnYawlKRSXcEMyZQbwcsO6QZ+MMqGhuNIRPD/aInh+L/0k8egQTuAT0vEe1N34mJCki9OGHHeNsS+0FlfmYECbdsHQiYJrF7I4YJw2lPjqaOsxMp5rlFi5SFqrKAKFu7sokZ4K9waG/NB05uYimmEmvGKmVCK6pva3Cc1S4pczRiBm4ZotHb2qZGO/MEh/zdys9Vzq8ZKcnVxU7ui3LJUqc2OBjAbJGntu5xU6+KOfXJCFfevs5MIN38w9smtseQ/LQUDgMYTUM/ilXvjAPud5nBwbMueCz8t5z30ZxvVIQSmoiN+wlszIAgep+C00uK4iXnrWoAhDQihhCgcqB8+cxYhqUkit+RijSDIoPGH1wqjMhy+7JiM2bgFKNUlLbaQvi9bM5nY4pzldW7o9FtOnmHoRFsRXrKtqkPkGAnDMq7b37vxVJ+h2tHXpOr7SXSwaMfbUB7LXNwejsOekz6DDVwsmMu0jaqBSCUgrT5J4QI976/gfDhL/XycV1pmxeFmPqLQcF3V/aIBOCqYgdjeizTm4wcANKSfk5NXxyzMCtXpc3TSZ31itLBJOm5saa92MIhFjouILUjCUGhCKowtpSRyuY6JBYF8m5DzIKiGNj5psjun0IjL6rWQ6ZPqP7LHDosoW0bJACPEtUeN+aYxZJX7wttSKkBMGWS83cK9lRTcgDBToXAXv7qXpLJbsbAKCqVYlguuUqoxlCfmFKemr4szBXTpzcR8oQysCjiuq4RQd+fndjLrGTkOXs6rL0ANlDPBmDe4ZoxlTV5OcTtd3aekDbnaIy6q3YhJnJjBzraFHwVJTK190RI6Pe+TypEfenvbI2+MeOT7tkZPTHjl93eFk/nXj7elGj2y8PfaxOLcVz33UpbE4YZpRfB1GtQttcFpHoeRU0TmyXrjVqQw7SDVgCmuxxANB/caCV2VEUCzoDst6Zzis94GURUfS66Mj78JmpMALLFSgsOyyuwK65gJyfVBvramyhMyZ1nTKkjiAhGsIFXK0cwLM+GtBHAZVY6AMRDTFY95Ko7+9O3v7XzUaBZn42XQF5bRDPCfQHPmoWlAT3es8EeEobIAWn3jBWexKRvqUFiFFH1wcVhWM67w+wdyW3R2oF2QhIMOdg604VUTq2huVEI9zS6kmTKe0sHuKakaGA58TqsmT96enp1uVAv4DTa+JzqmeOUPvt1JCVZYwshsqIZd0rHskpUpxOmXOanBlWHMeVQ2aMJbFI0BVVeXyGN+bHnmv8K33AviPuXvE+52uYZ3/8Ly9b7l6X1KuXuCLz5y0x2tOBYfhXZl2LWHxFeWWLRaLbqJ/SyRDEfgtkex+iWQVA30e88BZSXdrFsfHx/WSSt5UvfqUmgfHLQ9dnpPzN1aRY9BZcRR7NkYNF4P/ceQ9fY53+GTC0zIHB1KpWY+MWUpLHbzSN1RxZpbeNIo5dU6NtiZhVNQ6IWcfDBTRDfBF1RE9oGbGFMNCt0InEXFGlc4K5bC5Cd4sCGeDkrdmxuZQzSQaGvUCfAl+Z1RzCKoPI95wXdKc/86cumI13InsaHm9+etG5DSx9k7157Bp+Hg9+HOYAX6u7io4r15D4GYNujVuis14VwSvvg+SynqOwlYjBcarH1tLWaqomHl0KwDBY1N+w7R9KL5P6MEXcYwZVoMP42ZCh1EmCFvzYmBVKCoAvJff3QHUgGjML4UvDlow5fB/Igv0uuZLO4SWMpwozlbDbbGVkGOREeo8NGHMVn1bu6luv53wfnxrxTlh0OLv4PANzRPT2r3P2cnH7n1eMkP7sZPa9wByXuhP753ZedEeBfAo9lvJFYuH+SRmPju5CLfucLAFumM/CCMTMmKpTtxDI8zj9GBUUhFUJZBFpTbYlhKuuPPcsVbEgT/PmMC1hIVNldSRBucrnPf7zmnqLjQsQBAGnPPpzORRS/vK01NhA+9H+UE5M9iLdqrcDTfN/mVB9XVW0hmb0wb9SS1zq4OlhskgGcQclU9qHPXiOfkJnFIfYazOPKwXXJQfyNkHlpZo+r7g4ho+PMc6S0/OXjzfghZVUD7+k5nvM8Qd+d7mtdgjR2RLre64o8OD/uqhR+OlYVdSra+T9Q9Lw4hmv5XQCkRObgf8BTcmZ+RMZJyuHnBflFdrPL9O3ryrdZa/FfhzYdjKUWtwInAprqLA9IfErzstimUYux6UoFAiyYK6qSumJ+dWXFDjEsDCxuUm7vClfEhBBhcbVnHz1QUn9Bp9qS64BFGRSq8ccck+QETPClhPcmoMq26O6zU6OUaj43AsIyxn85D2iKHny4KtDhe6wxM65muO3/p7PWzLctRxlG31A4Z/QwzIhKaMPDn+4Xzrvmis04mKMrp+wdjcF6vCucbbVeg4hkdBBKSb955gMmHUMq4X+2gl2hwxqwk+laKur916eXhzY/BhiK15wq2mB7g6+FcGWV/RMV8TqB/fW57iqEG8vrgvxdd4/DjuuOsEWhXKzy7U7rnTXKTnY50LONwjnAsujGkVwASLMrYeFDrlY6Zaax1OamtPf0p8lC7HfdRmw5DgRRaMmhkZsXySeIyT70erb+XwUjrjq6SddAjJWt+HuhY24339W+kyEMd0zHNulpDarvi4jEnm4Lj38oKIl8UqAfj3Av1iRoWQgrjhSUrztHQRxkFNezDQ6wwbsMx34fgRdpWLFLgvjGu8KG2BGNcqXh1CX2/8Sk4mq/XzexRgcbZPAFfz31eh7H2aZrSADLXY7WT3h3WNZ2MLVDvU/SG84cqUNL9avSfQvfS7FpRuvnpFtocA/PDVfwC091z9qT1yP9eRCZP90UcmYnzPI9O9dA8V46EbxVHNEysw071hXfOGbsB5vy0NdYauQkWkNYHpNUxXhakq9ARpRhAqxXWEzMrwG5ZP1phZ5YcnejkfS5eAZLfRihZFcOAo5brreb9t+GLl2llURLkWrtgJXEYsIUYtbN532BV2jtsdn3PB/EXBoKdYzsiEGWzT6K91oEBeSjW6uVQchosee240yydRHWCBoz9CpsWaulsAkTGwrxEsjoDXbalsDRDcXtKxAwIXTPgRMLor3nXg7WMT6/vd0PT6CrplrrBlFjzPUhpw/sy1+S6xekUKTSZ9a2aukXSWW4scUj3YB1NH8jMFLIRl7MXBJVjrA/x8cQoaVv2ODJbgBf8XvaFJTsU0eVXm+RsJQeVn/vFYiNz4mygvRMIXdwsRt4FrrThdKhVUzPhgbinMVDWLB34yiqc1YVB1j7ePEmhQ5Do06lZDzUYLUejPWDXpRuFURXy8kEE0wX2fb8AdKh5SEzIeIGJGTKsxSOjbLScREm48PxT1ZX4sl0ExRGKxh6rsvajFqQuQxsCU0E7BjenTmCCGJ24Y0MMWk36QVArhlMQxMwsGleSiPp603vETJ+OCG+x1ZJcql9riduxX4uPkxl79fvdKBf0doQlNTuaM6lKBn0eHDs9tykaPwXWHodcs8HBM5pg9KhrP2VxCliHTdhg/XFZR2vVXveFBIhk2h6jsUrGEXLg++a51uT3pRog2xyQud6vsvUD1vvlhC8eJZQ5SKEpkqGncvX7S9WbaztB/nNoY0GwTMfRxID7C3NX8jFT3uFEYZoTHWW8ieoucG8tGwBpVpMGMCk/vlBo2lRDe4ccPi24FyQgI1adZ5prh2/3Uh/3E4CurJPUxmiMbYYKAD5MPIwoLXJ4vYwPCJbKjI5J1xBKVmql+QbW2xOxjyml9MaZMmCueXa25ut0Ud5DdXB4PF06E94pS+XJNXvsYAWgJz6qgLAwhcG36XfCp66SKzZ8jVY1Dq2h/SXNTLzlVb0qE/XoktHibWR0k9UxQL5FsqqbCrslwCGvAaLbKinN1ARSb5NCFe8aILE0q/VFHTQBJ3tb/wdV5AjJsbupYOHIdw+rb58wvX1x4IRVGdACnTEVNm+2456chkXjKsLRaJdDgcSvJuNYldoqu7nTrq+M5VXjKu8g+VyvKV6JqVveyC1gb0advWX0I6et2V4NFj0KRKwyCybIqcwZ7dYdhocrCglsDvGpLhqUXGq3UK9sdKlDXorSwd75bKyjkyZRlDEcWdx0ehSiPGZFzbgxrdDnu6N9+VD0wqtDqu4jJQOKI8ZFA0CElTqcicuwyxqJjlwCXRJEp1WRzrmGgj0yWSaYhbjYsS2Peitbx/HfOq7mYumldDTwh2/PHEtgur1uC2P0ysrNc+Vmubhu6BguYcMja7vl4m1d0C9odbo7z07Zs9eu1qhXuT4n1nHxYeNHx+USWCqKwTnBO3zUZ6yVgsCoPARuxuMDwPxcc7tbADuSBJzPOFFXpLK461TwGKxMcRc3GmE/JuIRWWxsQqVONyJmuB6hH0j43TDmFszHFkTtER2Tp9PUQ4EagwL0LGHePVeuaGn7DzdLlooWKsqA2wpkUGpe5Ge2ijHzhFV/aksatRXU59mA1FYwwvg+MdPNCODpIAwthwVSgxu+h1b0Ovd51JCepsZwFSxMi9SJKtoMta0faR/wJj3fenztbPo3SBkNRCpTS9nyDiFWovRxRLmpy74sflJoFvT1julZa1FnwmpQi6njfI4pNqcryePVBAYeniTUlS/tBKmLRAx8wRCKiri9vmAJFH2oC+SPZG9dc144uV/sETc1OWbF3sHdYJz4qex+RBbeFZ2263YCD1M91+852veyoa/hPLUOqqCikYhTrLgsUc2CNjZcYl1zwguVcsFt5Gut/p65v3v8OZVNRbFATf1W103Ww1ugH0LIQchZuL0MESFN7Pxdkbq0izU2JYaQ952k3C0nCtG6jjVlHsCpq2f7PNE4Lr5V28teqaGBlLIf8dLRN4/htl/Hr7hIaikjNcoRlgVfxbIE1CeX6M8KNkxINSOZScCOrShnVEFY7lNWK2T/9TbaR5JqxgpQF6ojwUry56lRNqXbegzodreKOOy6leS9e2Ybm1M5m2BkMD/qD/f7O7uXg8Giwf7S7lxzuP/2lnsdgz+bWDenjV0x00zRKPIgaRTBLCRJLsbaWtfSgbINzaeVyasntjhts7UnT2jmTy2nPueByOd3qxZPHBZLRnFy64wVrQ1SiLq6UbzdFDDYsOtQVm4PMhrr5VlPzMeEwvDUxa3ODty2Um5jLrMwr1sceR9ipwVdkz6TpVXpuPEzHYVPQdMaSiBZheUu1SvP0jivFxptcFKW5CtERVEhXUsK74EoTP0D1S57nvPMZzFUDHhl2Ms6pm7oWfU4gqy5MW+cklFNIdbvn8W8mMthAmM9nqvy5WoWQLlnkBQ3MLjLvjbFrylvdl5hYpQjCbUdKBWrrNGkeJMhv9uD033u1KgBuzxpIv5Nj8Nhldd/zGi+jfqJ6Rp4UTM1ooe3m0wauo6oKfRCWp+jCnWQGwo8ppnhF7ve5FNooiz54bSFlwWqOTaYf7uzu7R88PXw26Pp0/MPJaQ31dd6gnJ9abLxXK/Z7NWA+pHuT/cEgq0MmpqxdGHx1neQynAnYAsRLVaoUv2HBokuZMIrmrjKLkaqlYYBu4Tt/gDIwqg6cWBdv8KVXF/JlqJiYOElZncS5lq3Ra9pUPMGcuaLzvvY22vr2vLYARee7O8s1XXS6G8+F83vZ3YV+V2uGaV3OrcYgJLG4gbXTC5qCO3t9stdMSSFzOa11/LFHjbz2GbZcH9VoRf5XE7nqG7/co5XO7P1kOBiuXnL+mjeF0Rdm5/p6CA8ydNG/jjl6dqC+H6V5PQSF3rzaEP8cg1K7kNCYzG5fdlcpUWobthCA6u263syq24J2fiZvtaC8i9v20Jwp4xUZ2Au1C4qG+8o5miZtx2fV8AHTw2bY6lZjYRiAoFZ0MTrgyIyKDBJCLmdsCUlmC2sqQ9Mfv00VszjDfVH1JaoZQBAl8wprbmAU2OkzlhcYU6ONZYbFjIH7L5SGSuUcfUCEGkiom5Y5VaFmVWU6Kqtcdag8loI11q/pVGtTZHGWqFobVBECXJqaosszdeYDGCgoq8oCS+A6toKGy9ZEhqHRosjLKWgCbU9KlehKYScIrz2jPnwMqiCcv1s9v29w5FGjlEPNFKxug+HGxT5/m55Zo7qX/feie528b63sZh9M8BFYrhWGq7DJ3jkuv1U5iNklxIdgwU/7nB/4iStnpoucYz1RbqyFFjt1CqqM3rKcHG8Wr9z3CFB5IhVRDNLSbzXTrU0AT7gWI5lMryoHtBUHVvcJCVlYJI1g6V+WVdvK2hcu2R4AMYqzG2+tj65w9UdwL1NqBj2GsOekvGFK8cwxK42Si30+vQe3R4qcWQtUM0ZGz1FcQbLNsmB65MX06MyqljxFGMlb5tTmjpPsghVk+IwMDo92Do6GA7xLPTl7fjT4v/4y3Nn7vy9YWtqFw78IVj6eU0GnTOF3w8Q9Ohy4D5WSa0WdLkEMYbdzbWRRsMy/gP+rVfrX4SCx/39IMm3+upMMk51kRxfmr8Od3Z3vImI0Aj3CUnWdse5C6Ys+Zq0h+dBT1uE38hU+Miakyy8MMhzPzsjdTP2CQGBBZT1Tnlv9LbiWCqZ8AadwkgoDHhN7ZmN9ZLzhaSlzr6RxRdBcrztXLxhqd9NwQ+f18Ky2r1FuYs3IhgpgTy3fgiU656pTvEGYnj0Cne8StQNeeYciBCPQj+2hKAL8XiWnWG8DjsNClt5yJU8Cbu4eBgtXoqYSBq2K/qBy6nAEr0fVGLKKjg1dZoIfAjULO3ok7HSo5oBHlJUjNM/jBV5pWW/i1HS3sHE5iOelAn6qyCJcEV53xoETEYr8Wj1fa5m6cBNch1uUL1OTwlVPDjt4RYJJI2bIcoafFWKAwyXEkdWtRr34iKFiGZQ3OHE41CENV83R7d11tTqaCd1xqDqy1kSMKyi9rgzuzYtQ+6Jrn6E7HXYVKiq+Ps/FUjsfXNv7/kJOI2/zHNXGmopRFdzwJmpIRnZGcxySFjqU3VHX0W0WOJIvlnpu9dSZMUW2BR517HRWjl2ogr+HbvQiDSM+wXYlvaofRt+h2PfHVf+4tEakmG7d1r2ltoyKUb2+jM23MDpZzJZx6QofZtYWUm3Hc0cwjh0N6Gb1IJ6CUu5Eq6WoY/AQ5VOL1wnj/gwqmA8jgLdHdZnihgzyw11NuVeQbqMKtOrony2rXmIW+RD01eijThZsTKDrpKuIJRrwREPa3Zsxwd2xY3U9KwSDMRPOhgZ4QYzW1hmBRKYcjXMJwRiaGzbqYJpLKODl2tCRUoRL/rra/1G7X7G6C3MNzOYmIO/eviA5F9e+NNjd/TM9Xza5zo+C7Yoh1I2ncehciKdFQXEcWcy9oPTUStBHToIjMA/tQa0Ynq5zKeA2E47ccCMK9Gyviu/SgQIirpW3DXNs/2UwAF/jysvD9fWVjnTE27TGSS5pZ9T0W66vCYwA9qHiUnGsztUUhNrJKqJlDomUOirf+U4zd3sGqMH9lbvrQ13A7tzkFtivhFSrdEe+FYnNV+CL47+zDIb9CEI9jMPUKYUr4IDEwPLMcDDo8F/OKXcNo12j/KUsYd3rN0ruREBJAvWEdQSQrl8g2iEWzh9pDSTqXIqABlLN1fABLQkbXDfuCHy5lBWod6/0rs0LX4cFE1ZvO9IhWr3xKFQyQvj9zRtmR7XiAHpwDUqv69XP2QeaGgKVZlwNe6cTRQEBcTiAh626www3QS1q3bDIrL/HrdUdlIISvBhgHCao75/agXnXhe3Pocp5MBbCiHE19KjWHj7l75V8fEVslHvppBN3yVgW/uCOQk3DSkDAspuVO59CKoXm2sR6t+PM2NVoQuPvrpYETscL+IyZJTP0axrlcppo+D3xvyepzNgo8cLXf10dr7E3v8oQwhxpN0VLUandCqNUm3DFFjSP3I3npxdbIRq19kZQvx1bE240kQsRZsRibvZ8r6q0hXFTWWCA7+3oRmFKAeH2KfK0ztOGqlUSke++J8RLyI/eFLoQ5/iuMOIIvDOs4lJuuSy0+/R3KdZYSPBuI7WGkt0QleCwKxwQQkebS8BwMNd1kVwxmnmdzB3WntGrC5/omMQN6JmjimeNLfo0ZQUWowmT+tqYUGGf2u0vBZh+56du8o2zUsmCbR/PtWEqo/ONqFw3HY8Vu0Eb1z9+cbmxhSYn+emno/m8Eiac5v6p/mD/aDDY2GqI0Xam0RfmpTIzrh4Y8wjhgXUHVCOUb0OX4z4GP27ASd9DlsJAwujsIJUi3wqojGJydY8wYddbRxGSTq5mEGAgI8cXIgV1cwtllxSUTufU8SVJm1HonzF20fmVoHBKnWtKtUr3kQcxTtN0EDA2NEbzGpkE4cYFRLbfMG341GNX9/CsYFUIDDl3Q+O9ABf9jBVm1hodjyR36Vc5e/A+W8QJfq7eqQDDkxQ5Tdmt9sktdkm15T/JPpkvOywUmGJ7f+fpMGPZuD/ZHw/6ezvDw/7h08mgv0fTvcOnA7p7OGF3Wy+eHyaU1sqEPqf0Y3VCrR5RaqZ8Ul+IjOhO5JuUAq15ql2mWZRuBe7Seif6hsfh03J782zVk/mOduG+W7hPyYDVhxs/mMHFDoFfxSN7j/J6LC3bMVyPmjQa5oiyU5DxTbU64aFWWAudPMv2Kd3r04PD/f5euj/p052dcX9vb29yOBjvpunO4aroGsWn05U8n7dXmjitZdTVWMwNv3oKv3veOYWu1trwpiK+mzb4onr+DrPnTWNm0ttDou6L3RpzkjcuI3RCe+U2T70XXX2K3ov3QVa+J+R7EH3vhf1UlGNdjvEzhEeC8o9/W41M4Uc4Aza6JOiK4o+7oAIv/vzfd2Q1H2Pb7EYKLDTeacWjQHaxJmNrFtaD012Wrv0VYvV9XiqU5EO574+/59BX3BU7cVZndGEC+g1cwfoDyif++r+pyLalqpAltSjbnuskE27nxkuc8txfwJOXVZTDr8/PX/7TdzrVVYqvE+x6K8GX3eHg7joaabDgJIYuASxDajbwCedDFYXmLnQeJVUWY8I/wV7bfEFdtJoLXssxMcoP3Xmv6S/AqiXWGEYOLYDhAME7uI4wVGqwdNrayqRUXcdwPcJ8sVUUvnTl+UBrvaFqaXmmyKmxvJ+Qn5jCcHnobsQ+zGip4fIwd7VYUAbUlVirLAUHOY/zQF3t5hvWg5tU6A2Q9UjGFUuNVEuruqdqWZg4sAJlD+uRGc8yJnqQloH/SpEve05x7JGF4qbj4m7z1w3/7EaPbODTvk/AKnlpMmNXmk8FJpNnfGoPGJpbld7MVnG0PrwrEXaOJmGyKjCeT9EQcxcQtzcgiePZAhbaX817Aeh6tQW7A8ztMKRvHAveKPukgnAX18Ok8pshbSpwO25RZ3Rn/+CBpMdUqI+Yyiuof1HAKoe7Rz8DZK+ipdo6tDetJHoo09hPXEzXp5ZsNprmrconUa5FyBgDmR4Vb51TUU5oGuoF0OrS94aJTKqk5pkMhnFsCxwXlqu+f30BnSG6OsfMEzsnSz4UaQIXgg8l9XoT9e++RqulcBMEpZvkkxJb7ORyOrVbHMSenCpazHjqKy4Fh0c8KmT6NoLpjCq18fORF4zeMFKKyknHfbMYfLV6xRsR1fiVt4VqUgqXpt5eMehmcvXu1eXbdxeXZ6dXb1+/vnzokpVYOrldsPJRHGEXOHwtbAEyLlGUNRELYQXkRKpC1tJr7ouZYXS+5k1vp3jMnQ/jSeW2tgvO8PvdaYtJtdHDoPfc8Gd/++kfvxy+PDz++0NJ6x3Cn6D8ndr9BMmHtXzQwBx4KNiNEAJbMMcITsv2EbEz2Bn2B/a/y+HO0XBwtDtYPSegiZ/dnyuptneceJsXRvpYjlhGdOx77OMcccnf6zVBbpMXrv+z70ss53hwQGQLpHVGycC1WwRoEVS7SrBqhpS5rkJHbli+xEoZqICggGureJ9yNoNQ/EQyd2sWePU45QbqeEY6hi+N4It/RPozI2Osle4SGaIF6RTrtLYWH5HZ96RTVw72/YwrMCB90w20hla1pyD1CZmt9n7dmkqjPKPHMv8qi8kZq1gZA6sDdRuE+Fvo2Q/DuAVE06os4P5vNLdTjdxVAbd7hWkyAiyiUCeXlY0J95ZNTKV/20d7RHORhuH8LYSH2+9SqC3ZyCOOa2Q9euMHGDz4guvBhAGglkmQ0TqI3hpcF5R+/DgFwZlBuQTRFbeVj2vGZYrfRMHb0NLbXVdFV0gtDLdncs62ae4pHzC1w13hMJ+KbCdznyqw1bH1+B3Y1i+0QDD7s7zSMoWPJO1Me4ry3IuCqZRqhgdA7doXDtc8BJLEDdpXlUosnyR/jg5QFpOvvQuUxeGr7AQFgP87d4PKJ8mX2hHKwvYn6QoVofLFd4aKYP3Su0NFoH4NHaIicL+mLlEx2F9pp6gIhS+8W1QE6ZfeMcqC+qV2jYr7KK0A3L9z56jai19Z96ga7F9TB6ka4F9wF6kanF9sJ6kalF9HN6lukL/cjlI1eL/YrlI1KL+WzlKdQH+53aXifkuf6Wj9WjtM1V78CrpM1eD9gjtNAZxfebcpi8MX3nEqjmo2TKzTUoUbojBLj7APaV5m/tIxZxQ+Z/KOAiPBpQ0X/DOqo/QJP7AmT3zwvaEqmf6+1QM/dxgTZoOKjCJ2ZocM+icb0983euDN3sARNjryxAsnf0NUqlTXHWENjxiPAlO4Qv8+MgWuq5pxpXFAamDZgP5rgbZ1D4p8uVsbP3QIKYArueZErdHDoG4W4uJsab6gSw0LRI1dWkdtmMaHHMOQ1hYEboCmNs1GLHDiXWu4coaQsDoery6fX/R8HWpCBc3lVJYu1YQc55DJYhg6oi6MYnROnhyfXmz1Qh1ity3CqK4WIzwKvWHCFcq/SijDkucsI//n6fHlcUJ+kYIl51VABlYem0uX8FzLhfe1OYx0oaOhfF0mFyKXNIvrPYNTRDADNbePTy/gks3X8qio7u7apJofkdHJ0fuCmtl7I99bmEG7DrviSMs5uwpMOkIKjBrfhpHdnV5VjcZvlKryQvVWgm1b6hOOmgXuojetWIqhaL3UfLh6AOJRKu4o85xYpF3nmMR+HvXwWjW+igLG6y7VGy9iZB1+RFpO1xbq80bxOVVLjJOGPMUfz0+37rxX3RwOBsP67W8VZb1uCONYq07o2reh9pBK5tn+muB7ebqPU7Qn1TM6XNOsFz8dD++YtoqFXcPEO/sHd0y9P1zF3/PAqfeHO7dOrTPG1sWEFxenZ2dvoqlX2LRcrK/Rw7kdu0p/9WoNnh6V5uLTRJo7eGf/YPdwt76H53zO1nnd+vL85Rl6sn0ARBwdiLZmvLOJVP5olJOaN4KQEhrI+DTIxWKRcCpoItV0G8t5gMGxPWcZp33w88afkw8zM89/PT9+dRwdbhOecpqjV/ifPRfV4K9cE/Kz1Qg76tJbVQCvGcY569XSm7FVQqgjG6Ee+h2tyErz9XHSS8tIMdm5IDI1NK+4i3Ym/W0ODvYGDRb6xKCpjpipEOxEoSwpRLfVN/8ateBXjcPGHfKhT2tlXfjawRiZ5+KAWiTzlkJTm5cLsbY4DUwNsxNsgsKtYj/oHaem1W0eD6TP3Jz1udfU4sC5XmP5gmnXEZVVM9+yKNrpflFZ27eteME+R6zRyZt39TgjQ9WUmSoNszPWaPVAowIyzgsq1hVSh4YJVG+HaVrqX8+nD0Isowtr6WM8aAOvTwq/L1gSAbZubKNvH4jsG1rFLayCnB1+zbEDAbub+j3xPTE7SHaTZweDQTJ8ujfcvweKfF6s0TO2eYzOMIeUu8WG+ubkzRnuNGtdOyhIvw8d8eCxuC0Hsb80irtHPTQwiJszLENB6MRAkjhSzJWyUK7VYiozhhXyK2mmqNAhu0hjcVXfs8H3X1i4tgdUTH3dNEWDawagx+zMegi5cuoRNTXFbMIVY0ssTTHO5XQbaz33rWphZdP2zmC4tz0YboOfgotp34We9ZE4fZermFidrW1PD9KDw8Fuusee7ewM7YcspfvPDnYpzXYPsmxyDwbxES1XsBnWqFaEnfAp0uzizfH5q8vk7B9n90DRpdmsGy83zafgtxHE9fsPx2fenwWfX4cCrheYcrsqAe5/A9bhUraD2G0NBknNQRgFN6OSgE4irFTENdmwf260WXh4sHu4VwMUj+mrr1oFu0RVA5QwKH20nENlns/WDB9WC4yuJ8h7GVdQUMFBstXiuVD9IJRCWmu1D6iQc35KnrwDj5uqKndGWXdPLhruONTlV3HKfdgfPEuoc0vzGxRpa7/VcjmR0bwu5OrJxfGrrQRtKjCyQ1mAriRRWpoZVgSlIqulIsGSjktTOb/dZS85f+NvypnukdNXFyTGmJAn0ImE51lKVaadW57NKc+r99qE/T5h2PYgSeXK97RAe+jhrBKEc50Hiie+qyMFYvfJySvgGwsE5AFHJAzEbWHr2qeDl4/8xKczcqx1qahIGblg6oYpcnL8MCKUwqwt9aYiAMxCnpxsYcfSJn7vLh4CfFTqgGXrXMjTeCK3jqcPWceTv7676JHXf/XreS7SHnn97q9WI4uKhfXIyau/3rHmYet80trnMqV5q5zroy++n8bLmxdbLaXJsoeVFH/nbPEQTKSaUuHq7a0Zm3gqTZ68/oTNfC7ST0WW5lel4OtSHLtwpjmxM1rU3z0A9wajPwR/bSjkUF2B0rq+2urh6LTzYTFsnC8cnJc9cgGqy5sWS5/QnE+kEpzeC0UhzRUYjyvgdJu39pLPwdpDq7GZvQ0dkECXBlNUaJ4xhcW9eDvDfWewM+gPnvaHB2SwezTcP9p99h+DwdFgcG+ssMXTOtHCmrkroDR81h8cAkrDo73B0c7+A1CCEsbp1TVbrr0y0HGrGJAvToDlHgASO3IL1bcX9zsXIqTSUt2sa2NdYhXDGxaFVjHC8tw+kLqfKrSi8kKQuBoOP66jQkn+PqdFBMG1KfZ3hg+lBPtQSMHum23UyBfEIcICZgxc143lC3U6VsDqYH9/96mn+qqdsh6A/Sfa5lDf3lrmzlKKVlUXNEWLnZu2er8z2Fu5NCXArJniNL+qRfc/NuO6trI4VVWuX5cVF3efgtAEJVSBT5dRc8ZJ3AAZ1r6YUVcPv0d4HOSKDkIf4CXB1MqtFmLtpZCFHYZOZxSyVFWbuvv7z3/44dnJ09OzH54Pnh0Onp0Od05Oju8nLUKFi7VLwCi4amIJGZdcCmU2IinxM6s6geOddCAKHt0T6OnFBflRkhdUTMkJVGNyQZ/LhFwwFrylU25m5RgcpVOZUzHdnsrtcS7H21M5TIZ721ql21jOadsSBv5JpvIvL3Z3n/Zf7O7vtuiPwRr9+8pnZ8T/MZarDqarB6OJFUbOJtNcjmketDzBVr7waCD5R1imn2iYeuC/BMu0VZ3MuYCwr98tpunF5V8r1bVHXvz1ggry3BqdXKcyMl171nxJwFB93HX/YqzSGuYPQuWPNktv26i1JfxkzL4AG7SB6P1w+TPbk+5Od71qUZRgbCd1ekqL63bvhjzErDLcbK6u84/uzzvKOv/IpC9anEJ3H6WWLiYeyjTSKtgLKuBYWBXDiloQJO4hrbUuAGV8ymR4Ja7/6DsIMWzljxHbLJ2Bglg1ZrSQnb/x2p5U7vZY9XVZFDkPJbs+qVQ+N8t1VVI88QKyfc8phVGM1vsqYosIJsxV2gqMexR4Lhey76obpa1AyzD7pu6G+dXK2laFyJoI+6pWmtJN1gZYKjMjx2AL0AaAoLZccS3XResTpxmdX7wGYrcVhuNOkNbFig6czpU9oYI2qor5bfsRUKZMXsXFROoSW4opN2WGNSNzauCP9lXUf5ONXIqNI9J/upscDPcOdwc9spFTs3FE9vaT/cH+s+Eh+Z/6NeA6s4TeWRnj0x4bUUs0kKbn68xhUxw5IVNFRZnTWut2M2NLK1MZStPoav3EG6aNHrFcofRNoTOa7uEdaS6lcjZzL5i97U6iCF5eJS+jutoDOYcnZT0zrMqIQfcKF9bwlnMQ75H8bl/wj6U2UvSztLYuhdSG5uvaVZtvYHgUX82ULVgLD26tMCf0XWg0LYoaKoeWqGNGroVcuJYtFhWYSCryy/mb2MDBFopVFfgFz1i+xIPM20TQ9Ac+tmn3bG+wt7LHVLGpVULWKKzewgx3yar+3066YFqTtHLwdAqrv5VszOo8193S7XGOTNfZkfzu2oLFTNYLmsr58avj6LlOwN1BtH2spnDk0u0fSiakvjrmin2kJW47I8nrd+GLu/sWYZqRU/OsNOroXgjP6KopQaOm4eO2KMrknPK1pcnGCkIIXIe/kBDQJHTOXG/RuHt7rd2yIC9Oj9/Y/X+MTeCrYpgIf5wOFxJk1hVd4/ynvO7Oq5CSmCGD2THboSvF5zo2Y5oDQMl39VymmG9/8n/fYZj4lg6ebStOjVqPcrPg2j0XfJhxC1I8URuhndDEL3gzlXfU2VGY6w5DXp7u9yAhbYtgSR7mVIKEHGeZB2oSGsFgeKobYrwkuVyAS9kH5tdBxBOfeg8r1lHAxsGaFVRBeUI3Mq2fXk+0oNfYU61HsDnyjO5e7Q93tgKCVc53dc5pZkJ6chtpeDgqS11CZ56bYPZSoiB01uo5TEC/WQwWJGegYvSDlegG9LLxX3TXBQUjBYJUhh5zWZXYhSBCdm+4pVw6U5M8MTl66gvWI4rZybDe9dYjGIGfO43y82dQ/jHJk39M3uQXkjIZRJ90Fcu96PN/39lqC/paNVtt4c117vanFRtcaENF1O747OQC3k2+9xKqswut1ZfbralgUimq7ed1GGhFNaNFwQTLwMcGqm4VTDBnVJcKa9EtqIYmkiIBXF1YZD0FaUZVtqCK9UJtnTlWENY9cirTa4yuMJQLMIHsxv/Pcgzp/NAFOQuFGT9l39+erPQoymMV0u3qSMTzdVVDvjqoR0ynRZmUmk5XObKhn3x2dXuX+jdMWZMS0qfgDMDVg4iW0Pjd3cNWbdft09A9vmb5cIOngeu9ja3rIzXqIqW5xXtCrbZkKVTrax9pWUfwByVmIWEe4MFefKtb8S902rlhik69olGZ2e513QvdyAcA6TAYXxphuophWtUEy7i+ThSjWRJn7D70St9IU12A+yxg8mRKyynbgk5d9vBMmdaT0hrmT+h0qtg06i5AkO40zwE0veUq3IeyLNgzjqQyz+9ZcQ9Qxd5g68fVzmOY+CPR/Xx2CFoMchKJTS/lvTFymyVSVZPHnZHGW8IOsrmpb7NRwohSkVfM/HD++qJmvcBMWCm2PXYFdDRTGBGsI5f8ojqK1L9+dfn64vWqSzFlMvmC3PEAzp/FJV9H5gt1yyOQX5xrPgbrC3HPW5C+eBe9BfKbm/7LdNPbtfnmqn90V70l65foro/g+jJc9hagP7/bvu4EWBPlN39yY8daWrSpzo0z8KqcQk0WMycVRx6yEfgD7V5RzJRKaO9PBh3VWecfcXU/Dj7Oz426cdxA7FgHOqLZanyRxBJe6VnZ6Push2uMOaOCi+mkzK3UXMpSESZuuJJQTika/swvuYuwVxhz7qzN0ZhRgxX3mlQoPkIFXnThCb4RXjSTNINPkqbrYhby8vgknjZQwCIupHE127F2FQjKt89PyNPB3g70Pi6nU6hVfETOaDojMjXMkCeujVmPHPbHvEqstvbeFna7dJqt8zIsJPk1RF3/k8zYB5qxlM9pjk0ANZnyG+87hzWtDBnkc5yYQjO3UriWzFwYNmUqIRdoUvIb9yBeeznfuuvMG0acLYsZ6zg8N3/dGAz6g0F//wz+3e3v7G70SOvLPd8g+/Z7lsdZvld37nOI33Jpw7DDo90d7ep3gn9wLimvt4Dh/VtJcyhFFcaM7ETw+lHUgJyrv/IXldqSHNIVrHKniF3KDPo1WVO3vnxG2ucbm8i17k/YFGqCP4br4TanA1whyRI8nTTP/dTAOtBEpdXJG0TRo7kcGqgWNL1mK5UIXw1ZN94Xhy4X61taxVIGoYQe6S8E13WvbcD7D8JX6mRC5zxfV7j56wuC45MnXmdTLJtR0yMZG3MqemSiGBvrrEcW6CBrF8DAJ1twl3n+eFB/5jIkrZsFlND1SnChIpXzLXW7vmhqqfxS/ovetNb2minBHpFKd+OAswWwwbBTdOEaNbQg30v2kkF/ONzpu/voJvSP63v4MlY4rsjoCHXbkv6jSQ8fEfK51tPP5/ZuyoSRukfKcSlMedd+pWrBW/t1jTV1Nt9plIYjN8/IeRugP7VhU6n47/iEbCLJhZGVYloZm2MlaQYmFVNQgRXkGG8UV/KPa0YmMs/lwo7sDJh6UVXyxMeTsK0jkmPx+TlNgaKCf6hyIhettrPnCNLrC2v9bG5CTw+8nwNnjDOlXBxGzvH+jdXbj9snxpUOF66SE/ImZ1RDIUlSanDK2LNGFsz3KYEUT5zq7OSiZ6laKFlIzQg3kU/MFa5va+GA5j2OpPVW/Gvx+aoCazhIhnvJsAZtm6sfx064dL31GjbCc6nISS7LLNza+AslzMiAq3zXyhcqEuX8mpGR2UnmLOPlfJRYZrqZV9zWvjIK9/Y9bE0T7rB8Bb84E6QyzsOIXUZ63VYoixUr8t6mVF2wVIpMVwrRjGoyZkwQjFqrL9vuzn4czmFMLQLzp8vLN/D37eEcz338WkiasS9hx37Ibw7yp1S5lz2amdBEwiNlLS2VexGj2G8l048Qi+kHGsts+RD1/KO9tS7i6nIN8AnM2iT64eHT20F01ZNXANKXxfpjzvBLZ1njct+J708szyVZSOWaPbTwXsOqXMLVvL5rbZ5YYMGBjj0vO07r4d5u91KtLQ5289j5+5qhsNAFq0ZrcOwrF0KYy6n20SFhLdOcQwMRi6OGclBQ3hRKilLfFio8bVeUZ1WYJEo6vI4hQoq+NlRkVGUIBhKt8jeP/tF/i5D1z0+rRiFS2V9OHKBcCvtrR0XFnV22t3/wtM8On437w51st0/39g/6ezsHB8O94dO9ewS0+EWaMzOTa1uo2lrgVHd1w1cMPFfc2PMIomJDL5fQlxfDz+vREaMfzy5H1ZE0mjLju6L8yC5H4Piz1nGzuI3XtOp3TG3Cv3l9cdlNvTU3F9h8yV1ZwaBW2v3YlP8RRUPU1LyEUL58WQ/8G1ON3gJ/UkcN42IBVVHTKn7u+dEJvtC/BB3ZtcElJ3JeUOWtznkMMg2DWvUvUhrCbJubmsTDulG9QjJjeeE89xkzLHU9IRSjRpMQek3InOtUigmfQvcpt6nbK8nndMq2p3zlArqexopNmFJrywF+64avWDHeOi2Z62trjHM5jeuBbTdg14UUmn32cx2nXfVgj4H8Wk/2uzC+/Wj3mH/us91B+7DD3QH9R4s+B8bjyb5oCR9R+LlRO6Qf/vIQ8VeTdWFUp7w8isxzxNWGmlJ3RDF8eovV+r7BibqDGfYG9Zjo9Rr3ANdtjrUhGO9VIyTnY4+twfPal3fn5IUB4rw8X+NMsVQqq1jCRQLW9MWP9XlJzZyGAt2Kuebw4yW2iUXWcGlNE67YguZ5jyhZQuuPXFK7OXIqUqa2wqjVNvkQtkkYa0ZFBh4kGu4cUimEuz4g5Ny9TrXdCm5MSqxSl0fDVCRA4PxYmgktFdxqEF1QAS0Ot3BPx3D4i5YOUnSkPXy6pUxzTtdVazqwDs6Cdx3VSlapfb2OYDC/qpUXxbLs3Lc5Qh0XSMxBB+4RWRr3QZFs/ru1jiASrVoSQeddbiz34qrSZG1mYEWv89MmsWpsX1Hr4tXLN639Q8j5acfJt7IptcYQx/N4LdjtHNFuyWRmH4G/KvQwjeXXC/fnHblJp620IbDJ7EmWy+kUTiiWzqjgem6Zy38JJrWFPqoRA0Z5lapkBWC1Wh9NV2pN58b1MjS1ZgKEtm5btdrPH6Ux1+1IvdS5nIaJxiw60iA/k4wsuPhY8v2ohoh/q+qMJp0fE5KnXI/YOoZWvbBIsCwe//tgy45LQxR1TlMyQpi/H0E6pXDe1LOTC0e+R0iICv0/16XVtVpYWYJDAwCwepBWqWV2a/o3bjTDhr2rx9VKva2qrT+puIEsqBabmwYzcDDjJMDXI5mE9QpdVe/yGGzfULWdy+n2pBTQCUQnfqOtIFHi7jaPeivw2ntRLFYhHtovQ72AU6CN41wZU8rdHmhHIDeUAlMLGuWzG6YgoNk0Ss7C6S1cbvJUQmIgsj0MghcMsG/cvJlkuCq4sZb27UpBX8oSvHFFaeLdFva6lUoeGAK9D1HRuMCt7n/ainPX5Jz5lUSRNFpQJUY9MmJK2f/h8E+la9C8w1vHlHL+iUjUTpsehEeLdo0DQHEid9Lbs9C1ckTdzJfJLXUJQijeWPEoaU61D+DighvuUgSrGUB3cJYKJWmpjZx3RxlINfX9JrA/UjKW0mijaJH84D/ViIUOP+jgleS8GSR87xAaO0QUR1NrxEi58Pab4zkIl0DMneMxzkVr7JcGqns7t+KxzmSIJg88Fnbh+66KAv7qOBQTcf3fa5Id4wLBDZ8afK+arPsVOy7IhKofdXuDBb5J/kVvaCfRS5GusXhki+RuOrsr0NndovJHeIf7QpAhlR3E1ArwY+/426B00m7ODIWclViWuzSV6AxE6TnnJmaLG07dMOHGXzNG3j4/0WR/b2fPIr07PNhLOuBPJjTlOTfLZB2uhM0IQ1f5mfgJW8cbYEtvKM/pOI8VgePU2tuwU2SElbW7LVq3ZCRT4QOOq7TjMKR9d2e3zbg7u3fSaI1SIqKUPan76BFbmVgNPCCF6WkXLoXiUq1WhPZ+S91YZj9Pm6EfuMSsGpJrcki+r4jzH0FZSMKIcJSGQub2fQV9Ggj7ULDU3fX7gGzquKeRn/5s2HHTt7vfRdYAwP230Ud3TFCSVt4xNdXZHS1QoB4aG0YCI9YWq8o9zYkrSQNUajqrzk8vtnqxYmg1uxbwbmdOpSW8s5f8j6PkTtCtngmHmdczLbDacJGaSJ21+qbVeGSBil9ewZ3KAm3yhm7ZCUpryTtlQljwdWsOfzQzhAnrmQIrMQH4J2/hgMiu+AMXP4Kite5nzkxoRJDHPplX0VcfKZcV4r9rhWPQkTufl8IZAWiByxumnIZCqyo1EI7gx4kLv+iau8NHuj+kzIwf3QdAuWGbSaJUODXpEQq9VAbQurYRdNKPaiVHU2IXRHXDU9BsQ9SKczLES4685B3pgXZPkE+3M6YNOX+je+AQ1724Qr0Gc2zBlW91sdWI0kOV3enbyBURkHYrVXBuhpIDYYyaq6wdk1GhpWuLHGEzZj6mo9KRKoIt2LiikiXlCK65Rx0j9Vxc4oSmbCzl9SgOBRiZhVVd1agRaoLoRzeEYxZXvjEyVGzDrOPfSqaWXEzbe5byeY27Oi5wW3b9fS5vN/H2Fm9tsbkxUwod/WNptxSU+GjEJp1PyAjZBG+URxgBY1nGGh/W9vffK5c83SMjv4/dT6jF8Iqaupx3HFYHhzUCOOFillfrDPrynai9K1VA1r9Hzm4LLBCHO4NqsmB57uRfwKdQ0shU5lUafV00Rm2EiJEy79OpkNrYQ9GHdhnpeb2S/5O8HnLd3Tk66oViGSTn05nZDsTr8wyK6HXog0ez1/+hX+399B8vf9x/+V/bh7Nz9Y83v6V7v/zt98Ffa0sRWGMNfqaNUz+4Vwz81jSKTiY8Td6Lt75zDAvhVVSxo/eCvA/EeU++9xeb7wUh37ubTfzMxViWIsM/ZGmiv7jrxOxe+uD/ikcm35NSAHO/F+8FCOU5LQoreEBMae/YtQeeM4DmUnAjlS+5wj6YXjxkh8e3CkyDkjiaQIUNS5UbzhY9V9MxZK5q8n7DI7wRDy0Veb/hsN9I7oTXk1oqUjDF58ww1YI/Htujcjf8NcCbyxomqtGjEzlcpo0eeb8RFg3+Cou24bD1yxYRInkvKvdS7RXnYEqV1DBrgIjAFNA0HkP9uEY3VAwp9ArD2hsNBcgbYWYhYQk1qBzu0jtMkqDXi+Za1oZFMCtMwuS1Gd2m6JjL56bHg/rR/MVIBMRlFWMfRdS7zJBJmcO35xdv7AEeD/n3N6/CiRri/ZONttcJaFkTIxOpFlRlLLv6lOz2qnUx3sFETsjoJ3crUCj5oR09NXy2kwyTYVL3qnIq6Hq7ckBpiDf+sHiFNv4TL8gXi0ViYUikmm5TrfkU8hT0tj9e+ghc+4vkw8zM863KHLlwxwooIblrcuLf0m7xac6nwh1ooBu/YuZ5LhcYtgyfXHZBGBeinVG7L116QRdO7dZ4dUILsRKJb/c/vgopsYKp+KKXZpk7gV3ij+V8r47c5FS4h2NncbW3IH5GMDW3fPb3F8evkMN+63PR/w2/MBSvh7kmrvRAQo5zq+RFdeUQHn93aKdNeAZkhc/ukhFgj2Bq3ONaXSIMCXBoJjJ36Q0yABYNghTtzj0c7CTD3wgTKS10mbsQDSMjMY8RMA1L+BfGrnvkZ66YnlF1nWwFgn8sCMMikDjs1rRjgObtUIxauE5rd68cZRFhsEZnyGtn2SMytwVd3IrOPUNj1ogI1ImY8hsmXDIeFpSGjCJnOlR1rPyma6LzI0Ru/8wnvAZ2Z1L7XQZPl3HjM9kfYt64dzsMnOqXDhPH/xiG9MZOt5GzU4879CJ5DXr1pouWe31xTl7KjOWoqS3irLrjyJ3wgi6ZCgAl3RY6WM+jHhllQo/ANTDSerY+ozjkxYWwa38Hvw6KXbitGQouVApBD8JmuNCG0SxSVv8T54l3XSglU8UG5UDbJ2VW9IhJix7hxc1Bn6fzokeYSZOtddHPpA3yrSkzdAVec0c28lliKbCHdIgarxaapT1S8DmQZV1EsVPXqPI1H2F/hsMr3LC7UeBp56d+HX93V3HzKDizWeEcvIE0FDLp2dOqRO+7VB1u3IyBdVN1hjYsNT0/PgaoYBTgR0fs1zVoZ33bIwbro+h6b7uQ8xwiX3xNcxyUipRhySSHKhh9IdG4FcFvJFGlWJ0ARMuJsdMlvnBZs8a6vzfRPfCtWvsKrGUujCq1cy/jQbtdKMAXxvWFobwqWrkX3MCom7phY5D+f/bev6mNnNkX//++ChXn1iXZr21sfiVQ9dS9DpAN9RBCMNnds8spI8/Itg5jyavRAN5b971/S92SRuMxxNieLMl6z3N2wYyl7pam1d3q/nQwI+QZJDIF27s0tJFq++KjL1r4H7ny8PszuFmgSfLExYLV4S45mvcJFb6GA6SOfKZ+X6QuJxT3Rprb3U/IG7iwo2KGh+JRg3xkKUDE/ZmxDAcmJ1dnANEPXctTH2kcKwmIZHloxw/jO30ohvGOvFLRyQMS5U6OOiu4DWFhzvxiXp171y2IFRlKdKPy/HuI0AfJ5OhBG/EAkok/MIxWxA0BGIzhEFpiEhrvT1zxgws0EtLBUgKqRoUImB/X1dxOu1RTRQXu3gpKC4yjPF1aQAJ8jxAMxBIyr/K3YF9eII11KcGz/aWSDH/42oISx99nsUGJoe/ZjAtZ+M6tuRJTZTje1UUkrBZ2iLzulsCHyJ7g7jEdDGUX+Q0gVQxyG4tnhe2RdWovFWrkxEba8zPo+OPvNfLhskbO2MA8YRy9aYFeZL2ER10cZv7m7OumBuumBuumBuumBuumBuumBuumBuumBuumBvPhMEz1NCjaufml4AojGc7frzyU4QML32ssw6Fbr4MZy+AilIT4w0czyix/7+EMx9H3HM8o8PDDBDQcV98wosFFJEdh0s9iEY0cKYLiqFOnhdVWpWgGRDH8oF+JZhx//H1uSS6WAJgn+OXQY7NP8Yo63RSa3JQp8JJaN72Z2hsrbHqzOr/4KEcXeHItXe4+PAjLYwEKMBlKy/DEc6m1RbC1IMc2Nxv6efaev+X0N49mrhEkU3gIL+PLCiLVgAr+17RLeNonQoaACZDnzFjM4hB63dKVsL4mbDTWMxy5VhfSZjs/FxZi3ZbD/uFlNG1Yt+VYt+VYt+VYt+VYt+X4XtpyjJWMs2geHOJFA3l2hkcMmikS022L7O7xAZjiNKm2AsYFxuxkNuxVNN0ra18yLGL/5m7TkOENBWTgjVw9cdGcV7Y9KBkr5q5SXGVNPtJkzNLGLLQvV/ukQkx5Z/QB9Fecwn/G8B8wwOAHmSQMAMIwOmd+ypPcZtT+F4JTOb6tiGUVKGG/wMDzbbjOZESFngpvz3x/V0Ka32rB2ZljOUVDlmqoX4DvumzT6c+/2n/FpgIGFUSKobPtCqV865rCrE7HjaiAXrCK0EiTbOzO+OWACXi3Wr3Yvjj1qhAL8D08JlVqQpzZQsOqYb8R7lo9pmlrXi0fJVmqmaoyjFS4j7fTPZe8TFVlPX+5PHPEGcE7UdutswzN1e6Sq9AxWUy4cME7zqPFVSw8jE+gu615X/N9C7U89BZKhBMalR2q26zH6mgZzG2yBM57VWdsMAWh/T6CRtlYIcJqvOpLhV5OXTNBhS5rRAI52Tobz7DaLerivDw7jfit3mA3n1VNFPjPVWtYH8NSXR/LuB7F0f3cZqfnp0I/xfVam58XW5Q9LxMV0h6eou6NR8sLK07Na6MEA3QZIUc0hrBFIrO4LzMRq0l5x+VfeZq/R18zf8BPff4V7KNwHFc6wIQyegIsRnSqgjvZHJAokqMxFS5aJpXNXClYm1PZHiEYUuoR/IcsGQNMFFWKCjQW+jwxQoVxoJubCw5yEbMHcMoEPOgCjJ6MnJ9VYDtXdj31ZWYzLj21JI3SYbE6cr51ECjcaS58lzu6hU3svdJOfvY83Rbik8Pz9siBszftdMxjeWP0u4wZrwPGXwkYf8fR4u9bS6w4VPwdx4nXQeJ1kHiuCumXHiEOITDogIUn/UXw0ZMHfG4tPn6+g3WYapokLPaFvm5WR9+pdiOkBLQnZKmVhnJfyzNEUREFx0rK/wpHhVxkP7QlBMe0Nbf5WJBoCl1eosDMWyokpqIh1yzSmapKadi1KkxVWvWHt/vd/SL6QC/jSVxxvG6zbd+lmasJ6slQMR2t8dslf83dbvGfBPggHhPKaDmuSedDGysMBBbCMwCWc0PMAIDs7/bfsLcHcbzf6jUP3r7ttbYZazabvYO3B/v7b/ffvGk1o3jeFz8asug2zao6247s8CVhOQ7BY7ljCqFUZx3J+297O9sHMT14e7DDdnabBwfRm/gtjfei3kF0sFu8ngkmr4ij42JlCOCnFbWDp/zTmAkPyazkQNER3JskVAwyiEpKu6VSSI7dUizhtJewLdbv84jnVe8kxxwoepYozm4aycrO+VMRw9KIARnK+5BhaFngV9RW+2UpU3UoR6mRQSJ7NCnJBT+exQibx1OOqZ5p9l0ZhQgYYDPpK0ou4RETaWW20RkOb5tL5THTkDL3sgd6wphU1BgPStuzAmSKFgaOGDr7So5I5+L4N+KmO+OpNiJQoc2RpryXsBxCLx3HDwCfZ4dMt16X9Ux7TKMh8wNvN5oV+gczj4hginznyKJhXl2/rAuqhyjJwrrx0oYKe09lqdqCrb91xJKEqq2B3Go1WtuNg+n+wIC+XlnA/oMcGZIxCuYnC69IvGUD9itPc1PFdyslTzSg8LC60ugys5nmPW+MwTMH189qTuF2TKHpbvkc2d7eaX0z58iFpsu2ACQ+Wv/A2aHhFsOebJMxq7kOdHpIi4/gpVZ+BQFxCQ9Gc0jUeFQj8fh2UCM9xe5rRJgPBmxUIyKDj/+bqvI7r8Zz39BUa4m5BS3OEnaD3W4chE5B0R84IR+gl+8iHsGv6AeSC6m02frk5IFFGf746uLktW/l812Y20cXXwrTEE3VgGkfJoYuTyXze393buuxEL6vpJBEQNEnTFPIoMDWgBZcNyZUw1M8YdD1rxzY4ZGSRuuRI6nGUhWhrL7CZvVWpWc1LpuXz+T0gobV2V/hzIxdsVvlWZvym57J1n5jp3Gw32w2Wm92W3vz8sdH4yFNK2uqmUPjg3MzAgR8xLa/OLE92NrCUUHqdWggCo+RgC5i/mJzzl3iQp+LAVNjxYUmPS4Abxsupgnta6agTbURl+9zgU1JIxmzetjGkligT+fOpmRIoUghypQyVjsapwhDGA3h7gzQ87Wi3h0G6jHC9lWo/fv7+0afK8YmDPD2e4kcbOmhYlTXFcMmhFvbzdbuVrO1pRWNbrkY1Ec0MfZIHYVTNxNyMWgM9SgpH1TNaP9tcyfaZQfb2y3zQxzRvYP9HUrjnf04nrvfuuuj0YXXoOqSOCPIZTRY56J9en7VOPntZF7+qk2m9EzNyqh8JnMbXj9fP7RP3CkMP09f5G08zX3Ae+QqlJ1hEHz09JX2XJFCN8XsC2nzOvtLaejBCJ0ALOpcsXc89NxxwxEebwVbMeiGO0LAuwZWTt246cc8viGyr5kgqaaT1MWkcSrCdcqSPqHCr67hasxRzZgH0R93/QngsgvJzePKy9k5g6oqlDfbStGJxW0H4VE1yAAQvmaEobSP10PGUi+VSaaZ64Ocq8ghI8wbeoGK+0gnRiljJgFKbKyksaagEJxrflcoN59Z0wV+YY+LrTQdbtTIRj0x/85Spsx/W82G+b/W/nRRl5FbF4AknucwTUUimBhof0S5PWPGhlSJybRnUiiACrocOKhY2wbDcGx+62XRLdOECppMUp4SKchQ3vshR8Zs82tC7o0/7ZWClrhGwatEPsJp4r8wQvlT4UfkNhyFhkSapWMecZmlvqdVeQmeYc7GrJvygaAQl475gKW6S5OBVFwPq4qRQg6NPfCIn8wbAoaewtpNLRii/ZoFw8Zpg4ynQ+K5sA0gqG/vaisXfVEdNMn2Q7oKbaPK4UkFoM5WReV941A2ObllqadDur23v6Do2QNPvwp03pMyYVTMkuk7/FPY5pb3Cc3FEvYmKL2yRp1tLki5+YmLQYX9mMx2CaKA8+4TnvpHXROl6U5k5nXN+hRcRSxZzQNFmB0fduBkeStixRJ2Z7uwtMdmV/30qQNoGOV9EclRw8zJGg/jqAE5/IuKWlOdVXe0fO02KOgAR5CU2SJ3GjSR2BUjUpOxlgNFx0MeYbfyND+jwlHvaMLjEFfKuO0qS7Wbz5jgd4xkIgfotT2F3Vfzr7jk4nx8P+w9TUkm4CqIzeipf3J5+emy++X86vJL5+rkuHv56dPVokuWARxMVbBBHRy+YIlC5g6qspUGBaY404yOKn7pzRSrfPNhPLh+g/oUuIXMr7zRqG/kL3p+BD/vhT/5/OG3399+fNv+ZVHRmhNK09F4DuE+djl0bN4nKmK8Nvc9kfzmwEPBvAh4oW9eJWjxA6dl+YjYbm636k3zv6vW9mGrebjT/H3RIwPez7muvp448TY7WrrmkqGOmPHeGzefTwGl8Rh9rPzrj33P2WTGn4ODg8UIvaSHPLcjCmkwAItUgBE3ZoaUiWvIZUw3lkzwNhoNEFRwZXN6mbMZlOKSYp5tWUC+Mh9wTZOijYFX22YzDSgXqS64HBDXmWC/uELL/5lqnRbW4is6+7lyGo2oiLsJnwuz5Z4ncUS9CltJel9Ryu+zJHFUEUMVbhRwF2wzf6vspnM2nY/nJ7W+3pSPh1uWJknubATyh9rEkheyhBcYuoCkDj0wFfGe37zLxJJ+4xvcGnyk0dCIvHBzYNXBydn7R24N3u7X5784MJz0Jpp1pYorq6N9NzGWGfszg9tP2X+c+DOudcLIiYg5ndsAMDxE46xb4TXi0cWXQjXuowycCu0jvvMRrhhs1W5wYC5yrp48aIX1Nph54bINfJtLQ+5mml+buXwS65jmRoUGldbLeKIx4RrChXEDsu2o8DidfXqLB4gNGWMrCZn3spiLf/YAsfo5OO8nVGsmWDyL/TNb3IzDsZgwxLjDmjw8FqHc+Tm0DeH2skF7VVeo/lK8kTG7K+x29Q6PpxzP7VX73enrRVgBBMaKmMC7XgR5fOw9eQ6tZpdWROox1ZTgXXJAqJ13AVKZ0GoSojGvLKXCCjWfYBWSRSjQqrM4N5oPrQ1wuH2bdEd0bk8+i+y0S3u8InK//r45yZ9xkT2QT51FJF/hEWV3ylOn1HMo/eYKb4G3z97zrurswOFWdHa4HpNzECdY4HWWGoXB5YC7/rI1CfgCI0wbjYauoWV53YP4AzMLZf28vDjDhl7tVRUA5pqhEQfEIYf0JiTNevWpZrSQUimYsepvQo4bP9087/X2X4yGfHsxBVqAgZlKfOb19M/MRlJ6tMcTricQole8l4Vis3QstMxwBMjxPBk4zyK/M6RCSEHs8CSiSWTb5eam3VKE9xNa2bWg2YgduzfhLYPJFqOzwqyAEplhfeHzqHTI/13Z76esqhv/EsE425IkL54SComecxHqOyOEBTfPo7fCM7RErhlqMSrvuNIZTboWf3XVdmGJUjufw3tdjugqkoMfpXiBnTCAcNA3Olphsr/7aEWOFzha7RefYY4s+uJYyTmB+U21EL0Vv+RTtD7/NR9SxeJuwnsKEgIrItVZpjgd8dPhNRKkCPA0YOhZPGiW9CvMyXTDk3Qy6kmbumheq+d7JWKpaiTXMySIVRP4+qzLpNZ+vblX3965ar49bO4d7uw23u7tzH+hhKgpFV4/Po40MuvOkU01e0AthjeR0GYXbkR6AcwLVslhA/E0BAb0o8o+uQdQ6UJ9NxToQJ8lR0g9v7/78uX0uEY6k3QkhUv+Iz9/OT1O87pv6BPsknhh5gxYTSb+rhR7p/mmsnBNWub6SIpUqyyCWzRqc+qSiR0ulBygZEdyZKgaKxppHkEp4IhrPgiv5S9Oj4liWQpw/fcsSaDsN7jEpU6akd9hEhAW+YjVCI2UTNNpcBvi2pwY6clUz7hji7aj3b29+KB/cLDzZm/uUtL8cmV1u/AbI0e0pxIEiy9vkCA4JbHwemdKJnxWs7/npfBdwc0V13hbXczky9uCwbbSTI1cU0ZAMWvMahCfGwu0h7YCjOnRO/PJ3FtuEdGgGjHMrDX/wKXcjBLC1s6bebeOeQEbo3ivIvX18XgPpyhPmg49xuKqZ+18aLeemDZPjqtg4u29/Sem3mvNE+9YcOq91vajU6cxY/NkcSw0def45OQimHqOffddw9xsuiMNwwb++x05YpAyQyJbao+15zYrSpGUj3gyqwBwWnuNqTIqZJ3A/bwE7nkqM3LJrlO8v2WKtxX8OtP7b8v0nr0C31HC92wG1nnf1eV9PyLxdfr3i0//fmTlfpws8NkMrpPBV5cM/oiEf7Sc8EfYXKeGV5QaPlve6wzxr4lrnSj+HSSK29X6cfLFA4a+97TxgJXvMns8pP8fnEQeiOGl5pIHJP4gKeVljl58ZnmZ5JeeYF6m+HvIMy9T/T2lm8+g/jvNOi9z8sKTz8sEv/Qc9IDil5qKHpC4zkhfVGLfW2L6LBa+p/z0WfS/4DT1WeS+2Gz1WcR+H0nrT1L+cnPXZ5H9YlPYZxH7vWSyP0X7y01oL1C9zmtfTGLfQ3r7LLJfcJZ7SO53nuwesPLd5Lw7mr+f1HdP8ToDfp0B/zdnwLu9+FIT4avJdX+OYNbZ8PNL65smxT+TrG+XNv98wr5hYv3zifuGqffPJe6lJedb4l5gjv43SsOfX0Zj9i3u+avuJpMz8w/pK5Mz/ON2mMl5/NF7zeScrrvOrLvOzLNPfvj+M57Tf2InmrIcBnOFJ54VDT7NvWrLLzRpCSrqbOKv8+x6zIxvvOjnGmLjaepLyfrP69ro292U1mB3e3f7mcSB2zWHcJ8Vs7JZpNVFrUBBxY3Vb4srGJicHq9CtpbKCvWTJTe8UfQE4+z15nOJ5vplx1+83wCUTkUmzA6Ez2sYkkNHwtfr0dTvUZAZOQpyG33p3qEfsh/0H6ekp+R9yhRJmQZtxrUlwkWB7lkP28fCaS10MiFyzESQRT7vKmRjQ/nzdnfRcWSRFHFRhQ2pUWNMkGxc2i2tne3nGmz3UhljoBtzxSIt1QrdjtXvGrM5LMHEEzxd+jstlK2hHLEtmvCIzS2bH8Oj/Oe4kj+0D/kPcB7XXiNZe41Pb5Af3l38x/uJL9FB9MR9e/fPTf2SnDtvvv2NrtsUDS/BMfMkvUC364k378fxyZxU/j6Py1Hw0v2p+bfDCpwtR51iA55qKwvbj/oy/OzxhtTvgV2CDaTB3rKHjR/A7AR0Fyw5yP5i7ZqhwDLMTl65JfrJFUrBLOReca2ZbYPdoynb3yVMRDI2RlX+Cr6XyjOuyozXSJpFQ/MWdpj+xZh/Jw9QuHLJBp8zpib2s1oRjABaXadj3PEyT8eCYjRM0bpJxl3z2U3DI2jIsTU2e5l2JkOArMS0s3rvmHIVFoAckWez+rp9owcuT37uvjs9b1/+J3LOYmfBluzJ3z+/y9pHzfYvn99dtdvtNvyO//xrXjsDlhhPoK9BLk1V8BcX8ghhCbBq1yyjeVFwXFcv5IVy4RmmKaEuWXjWN0H+di3cQjdg+VMuBkEal33ebwaYkrwywuz8XgOhnvx20T4/7nZ+f43rHib7eBq4zp0bKZgd105p68Ah681OCBvVjP7xy9nVKcwFY7vhkoT0cirvqOJQkZkATBsOK7IRUzwCXvOda8Y8/vXT5TFu3JOfu5/NbwXSg10WbCKPHxSziI9oQhSz+dLoc71ijQG52Wht3MxITdr8Y+Po8Fppeq1Y3NV6fN3j4no0oeNxgz2wZ8DawcYqZxevBtVHUxFTFRfXG49Rqy0cTkY6zSFuiXm5GPK7Khho93qK3XFYL3A8XJTLzFc6Rj78++zjvATfskkF9H7gd6wOpw6/s1mCsg+p+SViO5/eX/3avjy5zp0ip6rPr66P0GKxhY/XpyNjxrznCSMnkGZoNugnmDS9vufCEGr23dxeE9XDCtgHZBEzdggcYpaqZoaDNxR09KyFu15aIP41nyGY62PWywaDoDLuKxIK6VyliM4D9xnBCe1ZXtog81GcG0ug1Yq2Uv7R46bSZoBvmTJtjuoRs8hUfRqZg5hqRsb8TmKWspKZiAklY84A68PRZ/SYO7sA4wUegEMgRIOzcbDUmMYAfyQmZJxQ8yQX5oQ5OerYzFNyFZJgh8YIk6HE6oJRjaQaglTudJJ9AJ+BKdAmsGcjV4HxkvuSFptPkBsrxcaN56RtFGSkmPbZ5UZCpxeu5omlLsTmAnwiZgqSpGtE9lKm7piquVT1fEdom2RbI1HCmdA14h41b4lg2hjRjb5U91TFLO7ycYOc9slEZoSOx8zi65xeOL2tZU49H9/U4ElDkjbmAgoNJEbJgN8xYVjQit9xmiSTGhHSWP7GBLsfMr/NuYbJKAQSe5Mc7TSY6rB1sN1oNrYbrT1XGbSMKV1hOLedJHh20HTIUtweUhhBKbfhrMWFeEfutaiBDL12yVJ0NgE5LperHdWIfMiSsdlOKdeZDcqCVM1Um8pskRRQ0oa0iFwFYdgc45Sn5BUigTHF+hK+YTaaUaVwGHoC5kcDgeT9CuVrxscCeB+yNh8FlQyzBX+C75YXR/g8HiWMvP98fJ7WSCxHlAsss6+Br5lai81+ZDZ5wmn6jNp7Pk8Sr3+oxLXV56cXM5krxhrSykCY3P4G/KupRYDPZi2Cz83/iqz8OZPZVXKHjPv9iRPGPGNfdii7cXcgDuoN4kG2JgVLZcTE604inbzowDhOhgBb6OiKdghNmNIBt0IioAswlntUdpPBFEEBkR0Nr0icf4CuVEC43YWHTjc7ouIRT+HqyxjSSibmMNPmuEtr7lFDGLwFp8edrdOLTv6HPlfsniaJ2cis54YMkEaCBzKVWJS0tEaYiBH7JWbaFrYaVYFHW8rIq5Pjy9ckhVi6L1xiOlqBhqaZHsqq9rAxj8wbPKCC/2UPSKnIOGVZLMVk5F41JAJedfjJaFiJiFQsLihVWEO34/yOAe1e2Peha9fRVNXPpIqf4cdFVLPBSiN3xZfbTWDFYo1HO1RQeMlsZxt7TjkReJmYsyrfNK7GbrYo2lqz0dg4X6eBBXfG6O3c3m3lF+xX4MGX7tZh2e1yOznMZvJdIqNbotifGUs1WIrjrJfwiByfd7Ay7sPV1UWHbJGrsw5gE8pIJuncR0tV5ZVt5PH0GNUXT13V4D3XQ6z4JmkkEebH2MYDMDO9TZrHb5zanLlxnrVhWs3WvHJJeMREWtUlTOhm2ZmsZY421NOawYsGq9aMS0RjRugd5cnMAr/2mEZDRrYbc6fcVXoBxQq3tMAnhAIdhOp878XZp6N/d4/PO13zEnSvzjrz8qYYXNxEVTG4eekmIF8uz8zq0a8hj4dr7Vd35mng/2rEaIY3Fj2etTbAinDPm5spiWWU5fXKxdnAXTNv5uZmvp+E1PkuqhknIkRYpCTh4hb4wbQLJDDBSywUQc/5JvkhZ5G8wAgqRypd3gYTjXt+y8cs5rQh1WDL/La10PIaC6wy7JnzqZ2bMl0jY5nwaFJDiwUtAkhE9KeucbfgzX7W2Y8lryM26uVQYnmAzgZPuxdW5Xffo/U1r5yy7IXofojrSOWzGLyM4EhI8zMBnafgMEBMh68fB0WFWT4WWs0m/v+8sqs2be0K3mLMWNsiit3xdNp06DHDNewdiJrYTi5l1hpf4cknZICEQ9epk3/yhPPUts+ZRXaQLTS1Nz0QyDJ/E4R6pyKSQtjl6XtDHV0hotiAKgjLpgzclrQWPI/r3+N4cYv6tJ/Ie7iXU3HuSb2XilwdXdhRaxY6zJGJtEWM3+UZNFxwzWlCOv95TsY0umX6VeoQE+2gZsCcFrz0wb3oja7pmayCTCYlefyPXAs4uUCiHLWDQ4TS+keERjpD3IWUWWR/NSIbfrwNoz/gVAuGdVSIKcJThPy3f7beo1XeRotrypM0PyzsiEgKYLeLgVvgfIqQDxsy6RQmQL8auLAjBjDn4Jz+dyZwU8DFF0Yd7bdnDZaLVkhdGrIPKtgsI2YjTrvaRzj8lmOheLeGYTIaxyRlIyo0j/Aa6gHOWCoIe8BUxVpBqfMUQmv9LDGP3XHDLv+L5TfQhlGmNC3E3lzcVPk5+sahdmMKVKHuIMHAqb3yTDVPEsIwXIfYShAxAF87COKCwPo8SbxuouOxkmPFqWa+pcNSTvfciF4LGVTwNuCRaBfMh7cLWFF01OODTGZpMsFdDt/x2h/ucVNfxJ3wVJvVPL2oEeridhCCzgR/IKk0+6dByH/mEqfJPZ2kGNAvHuX03tHk3oebhv3gBkVWtN2Esa7yq+s4c+0VIFTe4OMbQ8pNA8m6qZGYjRncChBpbQkiRRCRNMfsVOIQTRsFvMVFcocsSA6OQ2iSSE+lDXRIIUcyS62KQLnnH3sCrQaxA71qd85fl2BpIMmYRsM8MoWixCxPNuPk3mvtH0zzHIZnXiLWwPzZSp8CTmZn7P0s5SBh5OzsqCCFGck+8+R2Popg+A7SegBKJcDihDfRbgRU2OUFertbDLjAdv4KZQvlEiA1OH4xpj1gshFxPamqOdER15PZq/NRCq0YTcrkSKG5YGIWds5KaLq6l/UEk5YA58YfcC6nAmbfTGfTfd6e1xAuMlORgM8LXZ/sZGWipdJD0oYsHDqDyExoNenyVFYl8yOcgpx2PoHQSxQetR8lq6qtaUmaucpHVNC4LCnQ8CXnpkTOgMluCCBfROCTYsB1FqMpklANv5Rj2f+XbCRSbByS+pudxn5r9+1Os0Y2Eqo3DsnuXmOvuXfQekv+32aJyArjU5tfUqbqzqSYit1S4sRTIxSjKWhgyj4ZKCqyhKqwv5sesgmJAMzNWNQFbDV79OtiPIwrNBYjJvAuBSoZEokpZj2mckQsZ7XnhyySl+QAsxgzrZHI6agwge9cApSjeRCdC7DFzdk9gjN+wKTjthy46clUS1GPo9LajGWqaVLVW7Z5AcOjWqNpKiNezJfzJBdaXmXGVMytXpud4VNLRnTi41y3Qt4LyGkkhhUEJVPk99MLEvBEYGuDSXlH1YTc89hYMnA82rcaLhHxx7L8Dnabu3OHY41YFRtwKapUYJcww1P6q/756DG6KtJglqaZCuxzxnqsvP+Mdf+XnO5mtZpj1ZWdmPF9AN9rBJf1edo+bwfPzSTeHlRbbTWAY5luvcuYkGm3zRWb//pm/BUuZ2cF5AlCOTI82E+vTi/uds1uP724239dtKNGNKriff7YPppNzFSwW0gbyEZrFd+0y/dH5E1zdxtQOLPBANCMD8mJcSJkpJkmr2wIskbe1ns8t8GNrfsaex1a08heUd5L8kc2HjMV0ZT9FxmyB+pScKHbW0oG/M7FHMM8POLIx4kxKToTtmcvF5oNmGqQThZFLE35nX0QXdiUjaly3fKoH3E4GQ/ZDO3bbNabzfreCfx7p769U1gpQXVjiZyRzStFRWqDM1BXFgYTetQcFOftKx+js7iJ3Hpp+eEnyVjxO6Nujz/+/jpYzuKhA6o7kTQmPZpQEcGxF6QWSEWUzMxpOOXgGj7Hcq5CsmcVbIUCgGrZlysCjHI9w9crluzhtxfy7IqFa+VlWLKY0Io9VAeETFffMMXi7iyfcsUNvvlgyFIdTOpkhHPXgJHxmMWe5KznXFG/5O/z8rBaUAoBw9nok7FKNvpSNuxzjUiONoyS2gg/eLyLOEZwASMV4AlZxFNjldgW4BDxSvitLZvEPII06/f5gx8Rnnk11Hp8uLWFj+ATDakGrxvkClMstURz6oGP/KVVb0JSPhonE6Lpbb6uGCFLaKpBuSa0x5IULSchNaTIIRKw4f7q7Dj15+hGJBvZ7UZZ/QXSKOwKL/Yqd4OfBDa9dwz6mXmb/8xoglDQQSKgy84KDPU8LQ9T4dhDxMboUEAuFnwNUwKKW8Vu9wYhp8JYqFRpHoTVSYkCUB62Xan5f/t3m8HlvRdwM7LEVohHVORxdVLcV7VAArY1QFpmqMcSeT97m89+J4rvTSjbjfv7+wajqW6MJnYE3Bj4ZtBUb+TdzE9tY1YcZUhzsGjkFct+3DS5zbaRZr3tRpr1WoWXr1bYxDl5BaBhK4VgjI0avnNCEq0oT8wrM2aKyxltWw0D89p7Wo67wMY30Hqs32fQq9fMajeK5f4Vuzo7fl1Dl8n7S7ncvdBQddTctRsoAbNl3V4JXpJGWUFOz+uHDSptzSrBPvi+NSNoxceUYr4S86lH+Lywb7KUqUa1WyaM0uWltT7jN8hlILL/2LFIBTk7bl8YldVGjo/9UOFe2Sxzx0aUJxUx98VwABMUm8kUCDDac8UYHt/4vsGwuZnmxwCEmp5IK0t6TGlywkWqmd1YBYnAZeLftu0wn6TyfYdMVpZL83iXCpsvY9Np4Hpty2V3z9ieSGeFgdNwJXCyMhFVwiFZSYG2gVoVCL8prAUqJN5hoRGqJUGokGIy4n8FmdkoQv/rl5T1s8S8DDfABY/xdhZ+MdzdeBMgkqKPazWd7CfiGVaVcf5mbaqvIrOsZivZ1YIpp9/uTr1V36tvt+rbze3d7d2D1vabt2/q2/sH27vbB7vN3fr2zl7rYG//zdv9eqvZbJaZWF1I8Bvrwc7QeJ/CoroncsDFk6KiDfaoDlQyqQx3oe3qCWErw0zuVgKij5bmRwsJbnmPCtql8YiLjRrZUAysbjHomgG/Wl0Q5o45IMIgecx99GRxJ3PfLqUi6fBvWEwBEYo8Qzpou3xPUxLJJGERAADZT6+gq5gdGMreJjIjfS5ifB29ckjkILVawXefcXNDWTBm49k3tS+lFlKzQzKD/hGdYAFp0q9jczXrxtnnLOZX4yeEj7AfIkpi4yeSJwB7QeAXDP8WS9F+yWeauMQhKGWN5AiSRBSRmR5IhFPA4oEagRw0NCWTidsRH+Q9g9JO7RqopBgTmofeUWacVakNz0b3GYXm1sSY1ugBSqmn5MR0nhtqM2ALK485b4WtZbu+2XRQvOPJm76kuWByks1iGDXgoe2KErPDhnLzhRZS+azEadosahsiXFiuXHImfr2Rb8Aydflaf4U8M2hpER3N6jHq7CZ5krIXnOvVtlcBWJIKV6EuGZH7TVl830EvTLt+ASwI+XJ5mhe1ubuGV3x8t3uI4V1F/uDju/3/gl9fYxKYYphN54cFvIRXmBaWzuoH9Ga7sb3faDa2D/d2d+aGZGbijispRmyuXuwLyfQ0T6/CCiw/oxVzqGt5SlQmRBGqx0ZVABbLPagyASrII2GFA6fklYXkw5sxTQdcDGrkc7sWHMd3LJHjERT+MB01XtdK9Bnf3fcGw3Rbc9RSB+DiqMojDvYty8G60E72StOosaCGMQ3i3oa7YPLyEucszb264yEbMUWTChvZnbg5SqZd8Ma84n2AwmEPPDXbd+p14TERxlZNkonF4UxdszXFAFgvxU52N07AxgiOJUuN9i9L6i3d7e81m/2CMCqxamf08fOZ8rCN8y1x2p/e6ZEcjRVPA9Nf9hH0QciY2eyLAsu5XvFbBgwHCNzELJ0hWPuVUhO+kBiLRDWit+Zc12Qs05T3ECzO2yl5KMrYK2Yjj5hWPELbBYCOpqyXInSCMZwgYBxlCVVArx+SjbiGxM7cYPR/O5faJhhzxHgQDI/slLH8C/ZNKpABsWxZEHv+/gepzFg5jM4s1eTGfM96VsbRgl+N9MHMpjOCqPHOG7bHen3WpGw/2j14sx332EG/2XqzS1v7O296vbfbu2/6+4X9WFHOQiEm4TYbZoA/eWoV6+KCXerfTLDzASDD7heaJPIel9/3ew82s1d6IFWVQU29j4cD2kLRS0ZLweXlOz0L9535GyJ8mD88IazpQlPg4CShqeaRRaAovEXOYQ4j53jRmKXaJyuTICj8jlGdzhoEQ6tWCUMHyrFH8/OPmoW8yV17RFPpmxcD72aC/p0zgvMhH3X7uhU3kYxZpflobjdRvyVgyik9E+wEfS9RF4UHZHhsC5tG7v8Gr2lQehjiW0J6FRjaCPNRCxbBse7VYp5O1nNdR/2g9jjxlDmoFzfafHtpSiUHJJR31BQB5llc86AOrbhR7R5sGBLM9OkMA8kcemJzMw8rAKS1tdvhFg+Y87PVpm71pHJEWiCMEHw7j2RIeKO5GGQ8HfpVy19KeKXNeUGyceGot+ecTA2pJAw4WVxDKxcBVjDkLXiVULatZu6aXMG43fOa1FEreBlbpkZUYPFSymaYCW6+etP+0ypqaOvJrX2O1focVqxr1+NHdj3cIq89kOeIa+2jrH2Ul+CjzL9j117M2otZ2It5xjZb+zlrP2ft56zWz5n/9UsDkNmVlggicjGB8aekMTdApaWxIpxwuCZ2OELPPo3gi1PtrdAun3EHXLBXvKVQuIREToJJTtwin/ZxEKn8GFSxKeqm3/JHFPy9s+BuCrr75iu6/ZkLNhPHZjVr9kux5ZpbMndvP4c3bTW9liSR8pZQczQiLibTeG06dWMfdHnzZ0hZXjuN7cbc7Qb/vrfOp7fgbfE6ArLaCIgV6zoC8iNHQNwiryMgzxHXOgKyjoB8JxEQu2PXEZB1BKTKCIjbZusIyDoCso6AfPMIiH39XnQExNK4joB8LxEQu2DrCMjX5LTe0S9hRz+JPP0P2a8+KJdHiFy5Uf7JE9VG+JQr1HHtfUqQxyRlWGfSD1CrHeTvFgKuBAUeaaF5UIBBbDYGLcIi1yxeSwhkDrC21kwIwVCQqgIRIUR03ssuZCrAWf4KwnKIZ2NhlnOeHgMSDmaJpEh5DKgORmbGtUi4YGFTXETLtaP2HAQx1BSLIt/pYxM6MRSF6fZ6iJh9GtS6YejJj+1iDhbywiFJIga0q2ryDguU0WFTtdnPOSl4LhE2zov7+8JTtnJf4ymv8ZTXeMp/K54yvomuZXmuBP9GUGUkaQ2qvAZVXoMqr0GV16DKa1DlNajyGlR5Dao8L6gy2k8vBFQZiFmDKr8YUGW7O74CJmy0MkQg8uNPepzhmYDCQa8vohWFGJsYvHiA5UfF0VhSHi8QYHl+V+8boixb/UBeEspy6ICuUZbXKMtrlOU1yvIaZXmNsrxGWV6jLK+MiDXK8hpleY2yvEZZXqMsr1GWZ9D5QlCW9VAxilK2WU9X+SePZz1tvMdsFfOaJjRNeX/iCkGgGCthyvwYRRIb7xvDys5FNH2QQo4m15bCa28UGYY/nl5dnpD21dX/Ovr39UP7hPQVHTFjUzWuRSkxymgDw2+BknxgSwfm+XgvhysbAnAxsdPjTo2c//z+V1uz5vK7KYnkaGS0tCW5kQ8N8WVgqKFppHnU+CkkbMSogMbuLiFM21iENYpd63Ui+/mY2o9pCbve4KMxjfT1xutGYUYWDUEhPD1pPjKmotxyAVEOsHFpNPQ4yb2Ju6bSmIeH89Rg3aJIjsYJT+HOJh9yIGniyWQihhtGEjNhtKfx0zDxzpC+8T/IkqlLTCgeDaEKcY73ERGyZ7516AkYGeT3UVzExqWWKiWy998s0qmdz4WObZYdFXHB+A8AlSFy7YbkUmzlBM+d7B3w2PAkzcEt0jyL20/wlyAN8BGuZ3C7HNWNf1JS0zJCeulZUMslOi0sGWeJRVXZuxt5/fR116i17h0TsVR1wTKt4M7aUXDdVQDKft3NUvhPoAWNHjyXgm2dyfutjyzm2WjrAx8Mr7tpRJM85ZEL0h5DZuADabujvXN1+hvZbrTCEy4Y9xckyGc15xQRGNw3BaBxzGJzfEZZquXI5d1ei5OHMWjzcNQ7e7+u2OG1IOQnyCzouAo395Fg+NOZvMcfkDf82TC4Mb3y+MByqx6sUEXLfuzSMPCotYUCmOxrBBxnkbtbzA/baVZPL8hDA/4PktexcQDknyT8jimnRttikDBFTv69pCqF0EXFSA0BmoA30zwF9nq0EEIhr7jKuz74/SX71o/nUrwuCW485Onw/0zH/xcWTJ8nrEHhhpbN48HHeaFX0fk8g+sNY3RDIJ0niEnhhp5ZDC2kBovSPI3nS0puGRsTrWh0i7vKfB3GbXzFGJ+PU20LeKuD63AuCYggny8QQNt/aK8K8qya3oT4CAb5wBTb3EyhjFHU2cOQZimEZpz5hXooMKeM/aQYYVZnYX62S/o5JFRFQ37Hali1D+tSy2NGNcJEpCZjzeI86M8eWJRpViNDHsdM1IhiNMZ/m2OuZu2CGrlXXM8oENn8Y8M9axwsfPqrjtVcaxnJmHVTPhDUmOmNmA9Yqrs0GUjF9XBU1QLDfShNwdLzk/lSJ0MPhtCVjCBM6kU5FZAPC0s9F1Dqanwm2D08JTabwl/hQD5/HkCZBKXF5kkFIBQ2pp8DkKBscnLL65QO6fbe3GWf868K4ml8JQjSkzJhVMwS9zv8U+gEcqhIcjMYIdmElrKHb9yhCraa+YmLQYWYJWaTBWGqeXdX0LKngJER4LpALXCfRoYRTL4hqezre6M30HxrBGMyV8yfEsUSdmdd4/bY7MWfPnWgdGzW/cuoYeZkjYdx1Bgr+TCpYBU01VmVsEvc/DgdxfSlaBFTtnKJESRl9mr0M7zDSuRgANnoRsXKgaLjIY8IU8o4jz6bMxz1jiY8DrNrpTIOfqrdfOSM0TtGMhHUk/VdnhZ8Nf+KyyfPx/fDmnM6E9GQRbez8BlOLi8/XXa/nF9dfulcnRx3Lz99uqpgNTPws6vKq+zg8AX4D8h0RbVZssR5pKR5L8iRVGOp6LMay8zNtGZ0VLEWMVOsUpXAeFJZXWHLQ50CsThQQe8vP+gzNcjJ5w+//f7249v2LxVI3Zyhmo7myRh8zN49Ni8oFTGavPe+ItFtKTybzJs1YIJhpiPUKcJ5Xj6ptpvbrXrT/O+qtX3Yah7uNH+v4OQCXTCXof/EmbzZ0VI59y/QRzN0DImGxXyXX4xiwv5s+dcf+55zzjF2CoGrGgp9yHMjqJCJ4nq25RrR2EhSJharg9oOewTUHVpPqEzLpmtF1gPo5iVXYLZZhFfAA65pUjSQjEcNGVF0QLlIg7DVkJEeF8b1gEBsAbVq5ulCC8v0laNjdSI03vRyDup7Y1HDOOYcB49yXp8UimBxixa+vxLOzEgrdrxzr9OCI1AssYEy+dmuuAO1s3FhGMbuCHRPs7GhgNyMzFQ3FhuLm/eSpeQGuAjgFMw3IKr236Bv3KUcOCrm0RpJuYj8cJCkIHK6fT6ekdAqpByzAFJi9QExi8aATTODNOKQjZLHFdNVMOa896p481kgOQaT803tXUKDnPr6bpvniZpIhVEtrM6sWf82r0wqyWVrKEdsiyb5ei0lH0NEFydfVkQzX79jBREZZhECH5XRVV58xVM8ppw9lNv3gvzKRSzv06laEIwa5DX0vl4Dj0Ojs0LJRzKZVcK25H0CyJMl/QaEkTQDF7KibfeRRkOArAimcm/Tydn72W/Uw9v9+v7c6DlfYbI30awrVbz8tnmExXcT4ziyPzO4jZD9x/k641onjJyImNNVOCGGvWicdcv4QStj7ujiSwFC6FHeToVmyap4sodzNy6hkT3rSD150IpC/BSUlUcS9UUiZsbN1B+sDXKKxNjwXe7zaDCQehlPNCLOjcY8sRozcji8PUb69BYt1RFNwJECVqRKl7z28KJhD2Op5rr27ydUayZm3/yf2cAzDsdiwhIGcMQYxwbTfDJmKyN7yGjMVIP2eHcmutLK9usUwJLZru0gZvYOTWS4x+7TiJFX7Xenr1fMJWTeVMTfB5gCk3seeydXxEbQ+n3lxoixYjU172LAg513tVwwodUkrPdfWYGdXYp8gorXAzNbKn5/NjeaD60NRFHGFuyJ5yddiQUfcpR2aY9XxMnXX3u3XmdcZA/kU2fF61XhqWy33lMH84qY+ObaerVKgI9WelzicNUfl6mtLZ6D7sez+zbbglC4xA5T3oTNkMNyHBoNiZ2svJEKnsstm9jIW+692Os6ix6WMp8wGAKc9SYkzXp1zMPxQ0JBoGBUD8lNyHHjp5uVaRk/ZjTk24tp/0LaXtEwHvJ6+mdmg+U92uMJ15McWbyA8hiFhccrY8ucPHI8T8DgWZx1hlQIKYgdnkQ0ibLE1hv48uqKeOondFCV7WR2dsdudnijYbKVs1BhYUqJgzDvcGUMOBCeruz3U1ZV05YSLzhbddyk/K951uU5GHMlHjx+kZls5axUaFGUOEGw3hUzcMeVzmjSnT9/71kWeYkJO1+x1LECfhbfWgsws9qtNVi+jGB+QwMm+7sNDeR4tYaGHfMZdtuiL6kVqpOl34qrZqViXTPFxkq1zZAqFncT3lNU8coSRJ1PgNMRP12xhijndVXsaZb0Kyw+dcOTdDLqyQTrT80rvFIH01BbZRQD7oj9LDXCHqIki12yQsIo/BzL2b2dfBYIXP5AplEBfsMPnJJXLoFbU9UY/PW6BjdCfkyPigB4+F6f2av+mLzaGPy1UYN7nw0cYWNG/71xcEIsLvS+VLcrruqfOgbMPrmFK+A85w77HE7BHdLgVt6/Hl5onwSGZGpBr0I/tE97gqv86YlKo/tB7SykbW/WERXbLCvVZkPYNYJpXF06DGnhW/CCLp/PD2y+gdUnkCJb5OP86n2nhpoAbsZpIgcyg9t5Kkg7AbQtzTAg2tGK0RF51T7uvHbpMcwtuR8Vwf7xUSz/dleU/52l2nhrCYvJ/zxuX7Ub5HcpWOM0TxrDRm8juLUsNMjpTdyNJWQOQNq+TRtISSzvRSJp7BD3C6VgpC1I+7gDF+YODyyXur03l2p0SG6ODq/HVA+vtbw2NIPz4t+lw1SOWNdv0huUwM3Up35kez+PF6qhueCSXMhN/q0GuSlP6Nos+SGDb5r3JaSi9KXph/MHIGcu3x1ZkkB/zZp90Px8U8PEivCqFzZegMwQvP7hIgYu++KaYFBZpuKF4iOqJhbR4fSYvPr59Pj1k+kTm61ms7UKSyyvpa2arzD3dCZPq0p6MIdvYxTvVcTVx+M9ON9XcaTDOOmQtiqitfOh3Vo5sXmlRAXkbu/tr5zgvdY8gcwFCd5rba+Y4DRmrKpXstM5Pjm5WBnBXJSwiVdXUChKUPZ5alFuadrC7ZKC3N7b33m7swoVOeIjVmW2yMfTjyd4K+XSyMKMc4t/GyhOIpUzZWS/EGYjBOqLyVDrcXq4tXV/f9/gVNCGVIMtmqZ8gF2Yt0Ys5rQOty/hz42HoR4lf5y2fUsAY4z0ecRpgnc1/1WzWV4uLaRBfjV2/whTRKkAexCY4akrvOlZQDc/5kimOu+1FLLuMHFWsWzVbc2PABLeL+xHGWma5Nt1NmrqZnN/t7mSPblk3uyMtFmf72qcNhlju9IVkPqNIKfsOoQea+DKGhfHlS75pNHS8ji3dDWuo7wXlaXPgasOE2yCd6dmYimsyqIy5vfqGFk9qsR75y+ECdy1qd3gwxIzMnYLoYc4yGl9Xsbu1mo30Jh9i2TTo4svxURTbEDp/fnZyaYryTQdQwn/mIqq8rdPPTI3TlNyQmquIS0k6dsMxTqWR0yxXFVR3Jh9A9QKL4ipDicLyOGChm1gluLb/Lfi1CzP+F0xa+aZTO83dhoH+81mo/Vmt7W3Gu75aFwlHmIbo9CWX5vTA4CH5OIE32rSFsRSQep1AIqGx0hAFzF/mepo2udiwNRYcaGxfgqgj+6MouxrpohiKEzb1tB1lIxkzOrAZ65vFRWpry9OsY+1jKJMKRbXLOYYtifFGh1raSrqQ5hAPWJBFKu3lDVLqS4YxH2uGJuA5tnqJXKwhWAldWO3GT24td1s7W41W1sQz+NiULdpyXUUTt3CHzSMrTyjV0O0/7a5E+2yg+3tlvkhjujewf4OpfHOfhz3V7N3XJphF16hCk0s//4sozk7F+3T86vGyW8nq+HeFtpWzbKdZhnWN/ypAUCENloMP38aM0SFIh2EBVmBbJ5/pT7jBsgMYvQEeJaFyHxQtYN2EUZnzaBQxLZhfp0BSN3a33m7CnsBLZPuSzdHr9CAAoPUWFHpZJRwcbuS6+YK4xCw+OCMv8JdHnMF3QMs/WU0JvPYCnjKKousXzn48dNj8uoLBNUVSVmUKa4nIS7Aq85UxB2dq+ri7g97zYMGtVdZ/A51eOW37hYGIpjXJuO+6rTPXzfQoYZAjwdkmgWZQTM9lCBCgDUOKqJh+/QynV+YOWTkvAkVS2vk+LxDQo4JeWUbrMURVXFqr/IKgGF5pnC+HD81bEfyRiRXtiw8TTOmGshClYerWxcLEQvnzKujc9iIhggATAmk6+VeEoRtCw8RdEDXI+00zRQVESMdbA59NHebz7nlA83uKpcNdtd7dfQaDMh0mvUvnRXzFUBTsbjK5T8OJ7Krf7zI6h/960unRj79y+2CUxHVyKcv/4LGKTlWXo0cnf/riZ3i38Wqdgy0q8whfaraMm4ap9vOXpcsUrOpjFb6hbP7FTMZ4rFWzGg4VUpefVpCcZyKqEI50KSbCV6VwT5LHDQhZkYjlS8LiGXqzVmxaFJNoby6C35EdRC1/tw38xnTx83nT/2rGumAjXdRekeOaML7Ugm+CqAG4F5I3YUAwRzsPnZxccVH4NFjZGAaN4enREhwbyDcIFIeQ+MpAJ0pLfJ2c7tZb76pt/ZJc+ewtXe4c/D/NZuHzbkbtc7DcI/15Vyx24U57nOV6nm4bR3Um2+B29bhbvNwe2+13GJPpO4tm1QOQ9kuIU86nKmwgdMtK7/Yl52VHWoBv1Gm7qp6iY0PA+MHObKMsCQxD0T2TznHAcwloG74Q52nAWCnu3wtyUfwVI/3tlsVCIk9jKVgzy0pnsImwCH8sscMLmumFt1juM3B8P7e3s4btyAiZg9TjUFk1MXg4nTDkNUJZsmoDTQl5H/5EFWwF9IxjTCWw3XZe9pu7r5dFTspU5wm3bkR+5doYINTOSx+OFL9azH7dIdmT6AgU81ENMkBfl1zdcyIhB0zHlKRQbvmGuFhPQWGqV06rgQnNzGGl/FUPSaNHzoaUsDRUGXB7+29f/fu4OjN8cm7982Dt82D49b20VF7ZZrJo59VrohPi32pCqigHoIt0Ei/MrwcGDEjszTshYcmSV9mApCbf5bkjIoBOQLAUFspMGmQDmM+nD/gepj1IJI/kAkVg62B3Oolsrc1kK1Ga3crVdEWIo5uGcHAvxoD+R9nOztv6mc7ezvltkeQglZf4TFhgy5/Tzgh9fEER8Y0w1iJ0RgkskcTb/MKtoorvin+/45wQXXRAsfXSwgXlBB5baDPvJyPxgs6V//KbfwaOftXhwryXlER8TSSQTyhZrzDBkQPvtlueTGhgoJQVs3l3x0reEwpFBa+SqZfQGBgSgYrY/Mf6uTbPItqLcEAAsVMak2z0jbeWZYplepuytg87+aj7juWRE3DJXOhjQs3wGY8tloLHHnswscALHmoi92CjVfjyZvmdhPiGa1Wvbl31XpzuL13uPum0WwujaQ8YLIRcT2pCpz8yOnfcuKAFFoxuiRCHtAvhebGc+xGpbTglTBxdS/rFgYzKuWt+9k309mMni9pbRZZrGidzgvg8XayMitS6SFpgwO1pFJBrsCe6/JUVrV0R9ZkPO18grUrm0srWR3ko6p3yPIwc3cdUUGXhds1PACaa8lSKdE/YLIbYscVTyspBlxnMerDhGr4pazL/i/ZSKTYOCT1NzuN/dbu251mjWwkVG8ckt29xl5z76D1lvy/Fai2Kot7v6RM1R3UwlTqJSVOnjUHEI19PWWfDBQVWUJV2P5CD9mERNT40z2ZhSWzRy5CYcYIkpW4wrrXiAnNVIpN9fuJlMoGT2o+/hG7rmZ+UCQvycFZ0Jeokciby8Uy8LyQFaNzXEAjxREUMA+YdNyW04N6MtVS1OMlb6DMYo5lqmlSlabYvIDhUcNPl2fDAjoeC5D/0C0vzyC3mdUeEHlEJx4K9VbIewHd0ohhBSaSivx+ehF6s4TYZAnbN+uexyyZYJmxc4Ch+zX8WBb4wW5zd8mwvxG2YgNj6VWomi9hhqc0c/3zkrjOASMV6WbLxEzV/DljPbaCfW8My7+kqMSyce2kzfju/M9Vl2u8fNo+bwfPzeTWWgVbbTUAy4huvcuYkGm3zVWAFbWQFPg8JZP+oWe3LszTl4p9C4ns+5fyib6FrcZ2Y6exZA5kQr+pOwIQHC/OGxlRdcvFoKGTqmpkN64U7fd5RM4My+RCSS0jmUCk1FjzloK0QS5dKBsvXfOuqGG7VPIT+fXD6dUJdj79+fLk5Bx/bH98d3KJP16eHJfaof465HrJ2yZXxtel80RYVrVl3Kxh5zAvD3/2ffudYzbyHGJ47Jrt61oCUE98j+gFtMTu7pIRC5uXXlXY5apoX+bsb6YuJb68nIn6q5upZEizJTW8YtDPsbJA2qUbn3y5PCMJF7dQOihDvJxZzfCe3MzuqsqWqQc5RVv+S1vNZrO1vbPk6WCMmNSYewDKH5aFr9yt+eRArmEWaH6qmUAzuEdTtr9LmIhkbPR0bgm/l8rD5ThiicQqCCnS3JToMA1W88kDqJxLNvicMTWxn9WK/a8iCe+ZFLFv32MRiIyCgovhm2TcNZ/d5IkBcmwXtJdpt3WDxqIYyFEskndMOZRaaGCWo+v5tlBGpV2e/Nx9d3revvxP5NwfCDOAaT6/y9pHzfYvn99dtdvtNvyO//xrlTsAQRK/1nzUZVzPXOcjVxJu9L1ZZfNC4LgOutnL7MLLAw0mxDac9U1YHrtUnmTYHSkXgyR3cuzzfq9gYvorI+vO7zWQ+clvF+3z427n99cWMCpfoJwGrvNiNoAUg3HtlLYFSYohdJgQ9rEZ/eOXs6tTmAvGdsNBdyc/4h1VHED5EyYGeojD2gwC4DXf2GbM418/XR7jvj75ufvZ/FYgPdiEwR7zHmbMIj4qAQ2QV6wxIDcbrY2bGUhom39sHB1eK02vFYu7Wo+ve1xcjyZ0PG6wB7Z0P+LivitXqKymhaWmIqYqLm4HxMm0usZjb00LAHfMipgc8ulUr5Xw1+71FLvDeAKcsa7+2sxXOlY+/Pvs44r4uWWTCtj5wO9YXbEEi0ygFEr2Aaa0nHLx6f3Vr+3Lk+u8Vs4dE+dX10eZUkxoe+NzfTqiA4alSifQnNvs/k8waXp9z4Uh1GzqFQmnXGq2Eum8zwHOcpACbE4OKXzCHh+zlv16aXl5FTNDbtfHrJcNBssipnkBhmxUdRmByVvWCiltr9UwlEZUCKa6qaZzAf8+5kVAoN4Q3v5l6+T40jaSddi9GTT872dJMiEx09jGfkQTHnGZpWG9HbRD/nJ5VvYhluTTuvnL8HiOHpBZHT6CTqmhiQwAM7KXMnXHYqOy4yyy6E7gU0GP0llZK9tLhiwrLJ3cuLJNRQoOoT+j0Qw9mhipfALOwWDggnSuTn8j241mI4wYlMMKhxgmoJmWQo5kltbRn7AfK837NNL4m4e3KYUhYjmiXNSNjPBRKK+r0zhW+LvZX/gTH9/tBn/g47t9++vUmCMaBc+NMs0e8EfjC9ufsMUy/uKaJeNvmUquBQmH/AnqNes0guA1PnWP2q3ulEr9lk3wLw97zYN6kPhUCqJ4PpbbOplKGii9qlyqYxjdabRMJbnVuAHFKL7McSMwuk8FSeWIkYimEJYwjuuITgi4yhYv9fTCnCdbUmF4ArdHMskxkSgpsEYcSI7AFxcbLQJ6aR4DRUiGgXR2/A0OcYNXGiGFyJAhzFaCGjoTrpmiCTm9uNv3YzIRJdKmuN/8cYMYov91Q16dnly9J5fvj/yg2292tl8jTeGDecatcwPctYqHDrbAcY7cPCwFZJcs56Lkl99DlUM4+87jubR9RbOfPMej9d2qlHGDgs7IsAHnwX++Ko/uGnymTBPeJ1wjxm9aM5tZSE3YHVMTMwUiCU99f2pwN+2YKS5jMspS7FLcc2hfLEaXi7mctdwkgId7jGyMxWAjT/oG4OiG+eyfAWRtdl5fUQCNr2rjXSDgc6DALBYMvG7/cROoMy3HG1OLfPMfN1i7pcmYqhzt0BK9bM8BEECWJHMwPxUPWT04xGkf4Y2/XJ5hJwZElaFCG106kZkyJ2CudSfBxgH47jxCwAW5cazdAFIZwOzoQq9dxSIpUq0ysCUhPTBsCwGwPTkbGMd/NIpZ1IeHu7s7Wwia87///Jf9HH//Dy3Hy6+ZU08vYd02vwh/seHVJmzzlKQM7kNyeXo5zlAvXBDB9L1Ut2QkBddScTFAreWtYneO95hRj3a7WOhNmoYbgILHQBI5sPkd5qtGA/c1EwhuHpqheE1B9bDwAob7ZcTsVvRf88PS1PV0dYTWAP0mYZh4KqQua6+Fto4Z7ZE/L7+rxjRNAwW3ctRrO7xTYvZoXTK/GAmfC/fmqZDuhQ3EBIQFmtmKfGMVtD77su3rzX3MGfMo8bu75WKepe/TDCd/ZqyyqhWw12AC+wL6PCxgEv9io9KzGPfvsFm9qReldMb+bzhj0agLmxKEszTM+USL5rqQ5rugXVQefsBS64D2hrX1FdbRwXy9TPunasFkyCyahX5EbEMhCBuNdU4PkI5P3thvT6HRxbwPF3cakqt6TN+zoAu1mVTfS3SRVmFIoBfKFIu71bqEVxD8HQwZ6HA3KZw5OHENhDQeM69r0qyHf5q6divYxsFY+DCEmjf6UobXkxsA6BV+MH1koI1tFyNmmqkR5DmOFYt4ypKJayyS8FSThN8W6nTTrN/nD35EeOaVOSwOt7bwEXyiIdXgdYNcqYm7jR2PlXzgIyz25im0sOKjcTIhmt4WM1Ss+W3WP6E9lqR4e2PsTDiA71mSAPdXZ8dprgcj2chuZ+CYrQwRwuyjNBqy6jJPOzD646oejuVp/wdv+G8OZxrjSO8jB/wKxOG2bpWvk5/ENajBRFwMuP6Z0QTtO/sMuH7WyQwSY5PEiQQLbNhDxMZoJQ2lbS+JHdSmXjerLxoQt6EgXF5o/DJNARTtcJwLlSf83fZn9tnC4CoZIxFmjqgQMjdwC+9mLZBAHo6ZZqjHEnk/W1XM1itF3RPKFmNXNNWN0cSOgC8Xaheaam9s+FiRHaXgcwOvqS3X8trPbeY0622bDdQqKLBaQRHk5OHhY70qB0+Wj7GBkTFzbmlFeZIHH2YoBJouWflotr6W4y4w+A0OFNbv25QkY2bjFrJyecWuzo5f1zBo5hOR8xXJnURQzDXXTQhUbKgpgtdnRmhmet48Bpc/adYPdsj3fe7AmfPYkZOvxHyHD3y+/GZzYPEVbbIvdvjVej9rtMSXhpa4BkqcUzQ/BEbiGh6xAnjEHx0ZcQ2KuMZD/KpU/lEoCf8kFMR/DADiPwj7cA17+Dz5rBEPyzL5fsEO1ziHLwPncA1x+DIgDv/B6IY/ILDhGtOwyj3yYvz7FcIZ/tOQDH98EMN/Ln7hjwFdCGmMLG5QLUc8qtoewts/nCsofEETE1IdLT0eS4qJO66kGIUZp0zEUKoNCYQ2LxJyKEsi6dG47u+QFwpBOfnAw99GPHjZbI+zkqxmSSmQjJfWM6QESJzQ3z8d0u29/WXkVFlftikhdXlcgpQwfmhmeTeU+abes7nuH+xQxvbqb/dpq75L91v1XpPt15tRHO20duJmq7dQ11YvCeMnfythmLmWlQdPWI9RXX/baDaa9e3mdqvR3Gts79SbzWaztVCcw8miwjq6KVFoW1UHM+PLElEMhPhMaw0FPkhnkBvvC+YH/A6Ss60YpwXl/9DFHHCVzd/SsK/oiJlXsSJphDWutjjST5n34s0UNtelmhkf9C/E6YkSmqa8X6xF0TTSPEIcHxYNMczgL+ot0BPO1DBWop3KjsWjIpSPzcDwvVB7rmYVsB6gPjGtEWbOA8SF0ISLAUs1lIXCga6YVtKB5ISFM3QwQPZgkcuRhY+nV5cnpH119b+O/l1Yk4GS2bhBE06rSg/YuDKa3EzwiqXeU4F5IUBAofBJ9glUv0PNmVYZnPmutDUseIRdTbGncXSLYqSFi25bWODbVpq/Getv0rgWvw6hRknqcEjF/sw49E+eyAyWKUsZoQWhQQtaJNrz0iiVT27+QTY+0gGLqNLkZ3h6f4PMjxeBq1HZMQJLkZ8dz1oDEHwoteXXIBd8OO5ca8DjsvB/bjZ9nHZOSVfoqW9Mgz99xzseMtNK8n5/ej63tYTirhqRCmSuCrBUzxB+YXOHu35x4edDztj088m+wE55EVzck2pNo9vGiGvFjLO9Bd9Ot+Cl2Jp3mXIHj6aNud26x+4ebFzeBuRpAiCYeEyBde+r8+3ph8UL+cdeePhnjxTX7py/Nv78nxlLgq7EKWE0GnpzX+K6YHdyVjb5Wnut/YOFBBNGFlasQlZfh/cpIHY2yujPUg4SRs7O5kaGzaURSdE3C1DdK52buNddPWTXXUQAqQuWaQXYwo6C6y72h7/uwi0CPh680+dSsK0zeb/1kcU8G2194IPhdTeNaMKIw5zmgrTHYyZi/kDaTnlY0IlWbk0W4Cd+QYLc/WFAEYHBU1+aGMdYUhhlqZYj9HXTxrU4eRgDdEk4agEfk5CfADK6g3Ow2H0kLDDEmbzHH5A3/NkwWFIY+MDzVzpYlYqW+rhQy+V8GQrYjw73JL/Rs2b3NHunF+ShAf9XxE2JWcLvmHJeYFsMEqbIyb/njgDmkoC00YZNG63esXsUYreQvlrEz/T7SPafws8cD3k6/D8L5ClNNTLBolo2j9n6WNLK5hm1jk4OJWAW0A09szTYHKc0SeBp60CRW8bGeFjj7oFyXzPu/LVs09xprXgvqxAfsg1AebKPbOfzBUy3/Yc2zJujmfcmZJxQ3Zdq1CAfmGKbm2bXCCnq7GFIsxQysRMbNka9Eri51r5hVgehPeMqnA8JVRECbUVyNIZE6biWY+bUCBNwm8ri/PKcAXAWq5Ehj2MmakQxGuO/zVFVs+d5DSCoZlRIbf6x4Z7dqJENfPoZqHtT6xfJmHX91XMj5sanrvwaHMsRaQqBJ1rKQTL0YEIGov08XrQR3C3mF+gpom5YLBCewl9YnBcAAZKUH9LqzNTYq/CkgjR6W/fhC0IJyia4nS+tzfOCpE+vRKGe9TGws56UCaNilojf4Z8Auh8hQgjvGwPfpxnw1ME3lJP7tcrYiraU+YmLQbcyx30THXefWDHvLuKpf9R+GzcCHY8TVxY3oiLr0wgRVsC7cZhTFmytEYzJQqCMhN1Z7IP22Oy5nz51AM9lVi3OqGHmZI2HcdQYK/kwWZHkNdVZdXr5aSDjqft2IGX2CvQzrGFK5GAAScSQgDJQdDzkEWFKSZXmIdhwVEjNDNuaSEWMv6rdfOSM0TtGMpGDn3IP8wdfzb9SzhLww5qzNhPRkBknt7yAJ5eXny67X86vLr90rk6Ou5efPl2taAXx+rSqZhIdmwUhCs2YYqcGS9axg4gkR1KNpQojuEsyqhkdVawhzBSrVBMwnlRWD2Dtr1cOYyWNRd7ItYIf9Jna4eTzh99+f/vxbfuXFUnanH2ajuZpePCYPXpcBvAvbB08X8xb47KJYwS8hnN4JkZ/q940/7tqbR+2moc7z8Dn/wq75t2ey/h+4izd7GipnOsV6JdZmUXRsFjZ/ItRNFQ73+oxXYPfc84wAOHA5zFW4xVQygs1x1DpV4B3NvaMlImFAaX2OoSA+kJLB5Vj2bRc4akP+nVJqc82YaAomA+4pknRmDEeLNS70wHlIsCfM9/ocWHcAQvqHKzPzBOCFpbmK+p/ObEZ73U55xDweGEcc/6CNzevPwgYYLgVC99fmBvz7RU7urnHZ7TtiGmKfciGVAwecX3xbx7CH4aJHPy8cQ2zMfQguRmZqTySv3nnWEpugIscztFitBMa/zfoEtdgDRwGvH1MIcXIDgcZ0SKn26MqGAktKtmY3fHK4ojHMLhFFEM1Z3uwhKSXvJ352wBOM+M85Kr4ceMjyFm+CXhKbJy9QU59mrpF5UDNosIIETbhrFl/Mu+6VpLF1lCO2BZN8jV6tkzMxF2ccFmxzHy1jqHUw7YVfUIuRQQ3OF6cvZLb2cI135jChULPPE//9xn+eIwZHRRKG2oByhp1gVg7yJAl/QaEZDQDl62i7fWRRkMuGAmncm/Kydn72W/Lw9v9+v7ceNozGOtNIIOyuoY87ybGUbMtLAw/j/JyxrVOGDkRMaeLOgCGpWicdStMADq6+OIj5U+uzanQbO6+wLP4sIdnNzjXFjn+Th40VL/EqHDGMk15L2E5upqZcTP1h2CDnCIxNuSV+xiIrNjLeAJZfsae5InVepE5nCyWcZ/aa9sRTcBxAVZkXn6ziDjYw1iquYDt+wnVmgn/6cxcXhyOxYQlDHLWMMYLZjH2jVmc1CGjMVMN2uNdm7Bb0V4MMnXdVmwHcaZ3aJ7CfWyfRoy8ar87fb0CziDdqiKePsAUmNH12Du2BOlmh1dlIEDXIMDND+i28y5PORNaTcKuxStDrbQizyeoQO4SY07Vvg+bG82H1gbE/TwAruPhGciKT3CRdmmPV0T9119dty5nXGQP5FNnBetS4Ulpt9VTh+UShH9zzbr8i4w42is7wnC4ao6wFC+w56FVsCAWNhXNdw3OLGgUXMwJgroAIcZoNCR2svImKXgBt2zimtDkLe4KSOEps0MjbLnLMOlNSJr16pj74YcE+EPBqB6Sm5Djxk83S2kKP0405NuLaepCGljR+BzyevpnZoPBPdf3L+YphgUCKVo6VrEJ4OiR43kc62dx0xlSIaQgdngS0STKElSA3jpdJR/9hM7VNmgRjWF2bcduZHhDYbKVkF1hzmyJ6jBfbSmiXVf+ruz3U1ZV6WGJfpxttRw8HxDC7f2wx+nTdLvJADpiJeRXeLKXqDdDrYToO650RpPu/Llez7J0S4Tb+VxO10p5WHzbLMDA8tsG+ph8qwMfJvu7D3zkePkD347zDJtp0ZfOCtLJz2+5VZBfsb6YIn1pjQGQCF1EJOHVI63CdMRPF0A+8TTgbxmWNEv6Q5rO00BjEVbc8CSdjHoSOlsN4ZVc2imrumXY+0L3rfm6fv0QzbKmBN2X6rZKqJPNttkPt3DVmOdhwcUoTVMZ8bzRMw1ufP3W94L6JDBEUSOUKGZv/dzQPkUGromnJyqN7ge1s5C2vcFN7ukkxf5s2mwCuy4wjetMbPusA9g7Xhbl8/mBzTewYgDSI4t8nF+979ju13ADSxM5kFlqOxe2LfAyw+BfRytGR+RV+7jz2qVYMLfMflQgKsVHsT7KXZdBM6SIJgmLyf88bl+1G+R3KVgjAHjiaQ7FnKVBOXFv4lvXa2nTsV23aRLLe5FIWmiq4st0SFuQ9nEHLmknY2OEBnve3dVKNTokN0eH12Oqh9daXhuawVnw789hKkes6zfpDUrgZupTP7K9Ew7AGOwr5ZImyE3+rQa5KU94M92QPPimeV9CKkpfmn44fwDyq/LdkTdCxgfNzzc1vMAPrx1h4wGB5Yb6wSLO3+Z36u0fVJbJdqH4iKqJLX87PSavfj49fv3kNf1mq9lsLWo1wTzfhJcwB3EmH8tcrgOExSjeq4iTj8d7cEYveiw7hI1WRfR1PrRbKyEwz26vgMTtvf2VELnXmieYtyCRe63tFRCZxoxV9Vp1OscnJxdLEclFjgm38uItM3beD9CZhniu5tafLXotKbPtvf2dtzuLqrMRH7EqMw4+nn48wVsUl1oUZgxjzCBUckQqZ17IfiEERRDtsdDxkFNBoXyZpikfAJZPujViMad1uEUIf248DPUo+eO0fd4ODIQ+jzhN8M7hv2wLSJ9m0CC/Gvt7hCmBVICNBswYcwpvvHq28YofcyRT7dFhC6zbpmqL7sFRdVvwo9mB4SpwQWSkoXOx3ZY0DGTnu6+5v9tceO8tmRs5IzXS5zQaJ8n2E11U3hU6K+dTR7u1xTzoUO4uOoxYzPG1SXylZXCu3+LumbwXlaVRgQsME2yCB6Vm1pUvY83M2brzb6uqf+/s8DABtza16t7Fn5GJWXDj4yBv8XmZmFvLb5Qx+xYJhUcXX4rJhJqqAdPeN56dULhwNuEYypnHVFSVf4v+KuAPwDQl476WAz1R7bLT6pi6PsXmKouOxuwbVOp75oNPF+T9guYpRAvwav5bcRqPZ/aumIXxTEb3GzuNg/1ms9F6s9uaG1uvzDEfjSsMy262MRLr0PQwRwQaZ5OLE3xLSVsQSwWp16HlIjxGArqI+ctU39k+FwOmxooLjbUqANlyZ5QddL4HFPAxt1fuUhGJQG0yZnXgM9eZiorU12OmZEjvGJFRlCnA1cHGF/fYrxDqJKzFp6gP7wH1WAtfrJRR1jykumCY9rlibAJaZauXyMEWgjLUjS1l9NrWdrO1u9VsbUGsi4tB3aab1lE4dVsK3jA2azkm04z23zZ3ol12sL3dMj/EEd072N+hNN7Zj+P+4vvFpZ514VWp0ATy78kymrBz0T49v2qc/HayOMe2MLFqNu00y7C74TU/AD7ZiCn8/GnMEM2GdBD+YEF5LNk+Am87oIEEF+i9FSLSQeUE2i0YlTSDQpHQhvl1RnPG1v7O20XPdrQcui/dRLxCAweMRGPlpJNRwsXtwtejFfr0sMjg2L7CHRxzBXiTluYycox5bEE+ssoix1dDOGwUBI2/QNBY5bhsQV30q85URBmdmdXGldc9OIn4u3pwzlqKf3rzzSdl8p113XyCl5fQiuM7a7f5hDRfTB+OhfpsPsHY391/o/IGm3Py/gJ6cXyTzppPiOMHbdwxi+MfrpfmY0z+OE00Z3H4o3XP/AqP/9y2mV8RzD+rX+ZXhPE9NMqcxcK6Q+Y37JA5cwHWrTG/XWvMmQvwg/fEfJrn76sZ5lO8vATX+/vpgvmUJF+M271Q+8unOPu7/e6V9r2cl9EX4GQ/t+HlU6z9gxzm77LFZciISnU3ZWyed+1RVxhLV6bhULnQxk0aYKMLW1UDTrFvjZbywVCHVgtWrnjypjnchHhAq1Vv7l213hxu7x3uvmk0mwshpQ6YbERcT6oCFj5yerN8iS2FVowugLYFNEuhufHIulEpPXQlhF/dy7qFyItKecp+9s10NnPnC1h6RbYqWo/zAsCznaxMvlR6SNrgpCygGJATsKW6PJVVLdGRNddOO59gjcpmy8KrgLRX9U5YumfunCMq6CJwmoZuQG4sWQwlmgdMdkNMquJpIsWA6yxGPZZQDb+UddD/JRuJFBuHpP5mp7Hf2n2706yRjYTqjUOyu9fYa+4dtN6S/7egSqqyYPJLylTdlZ1PpeZhs1xbeahtqeodS8zfBoqKLKEqhJnXQzYhETX+aE9mYRnikfPqdbHBHVdYSxgxYVz3Gl6uJ1IqG3Co+ZhB7Dr9+EFdx2MPPIH2eo1E3jwtltPmxYEYueICGoeNoCh0wKTjtpx60pOplqIeL3CTYhZwLFNNk6re/M0LGB4183SZKyya46sAvw2dovKMYZtV60FOR3Ti4RBvhbwX0EGIGFZgIqnI76cXoWdIiL2stz1m7nnMkgmWazpnUkv3Y1nIB7vN3QVC3EbAig2MxVWher2EGZ7SrvXPC+CzBsRXpF8t4TPV6+eM9diCe9oYdX9JUYm1MUQAaWLGd+dzrorSLBqazXjaPm8Hz83k0J7aW201AGuFbr3LmJBpt81VgGszN+d8nvI0/9Cz23Pl6TDF3lxE9v1L9kRvrlZju7HTWCBHLqHf1OQHCIIXYfGPqLrlYtDQSVV1hxtXivb7PCJnhk1yoaSWkUwgQmisZ0tB2rgWly5uizeDeSu/sMcf+Yn8+uH06gTb9f18eXJyjj+2P747ucQfL0+OSz384EsLCMjWT3XpPKGIVe0NN2vYQsfLwB9U32aLmF06B+uP3RF9/bUHeAffqHSB1353dwE33yYcVxWfmO5k7CfeTF2uc3nZEvVXN1PJkGYLqOaqGwVfFnoEJ1zcQs2WDAFAZnV8enKjunsWW9cbJKls+S9tNZvN1vbOAmrdWBapsbUAFTuso125H/HJodXCLNClTzOBNmiPpmx/lzARydgo29wMfS+Vx/xwxBKJaexSpPlZ32EaTNaTB1Ahl2zwOWNqYj+rFRvBRBLeISli3+vCwqgYhQO3lzfJuGs+u8lvqeXYLmIv026LBt3wMPqhWCTvmHKwldC9J4f28r1SjIq6PPm5++70vH35n8i5V+oz0DU+v8vaR832L5/fXbXb7Tb8jv/8a9lVRyS2r3XMcym2M9f2yNXTGp1tVtZsfBzX4bR6OV14GaBFg2Bqs74JS2KXx5MMOyLlYpDkXoV93u8PzER+ZeTb+b0Gcj757aJ9ftzt/P7aIt3ki5LTwHVeaQT4RzCundLi+6cYO4YJYe+a0T9+Obs6hblgbDcctD/xI95RxQE5O2FioIc4rL3aBl7zzWzGPP710+Ux7uWTn7ufzW8F0oONF+wr79LFLOKjUmU2ecUaA3Kz0dq4mQHbtPnHxtHhtdL0WrG4q/X4usfF9WhCx+MGe2ALNcss7rVyucFq+rFpKmKq4uIWQDA+q1M8UNA007hLlmBsyKfziFbCU7vXU+wOHXU4J11Rq5mvdEx8+PfZxyV4uGWTClj4wO9YHTriG1MFalZkHzAPy3f+n95f/dq+PLnOi5ec2j+/uj7KlGJC2yuN69MRHTCsLzmBrrBmZ3+CSdPrey4MoWbDLiGQch3QSiTyPkdayqu6sRMu5IEJewTMWt7rpWXkVcYMWV0fs142GCwC3eSFFpJeVRQeM4Os9VDaRoszkUZUCKa6qaZzIYQ+Zs1DtNoQ2/5l6+T40nY5dCCfGXSO7mdJMiEx09gbeUQTHnGZpWEBFPTk/HJ5VrblF+DN+s/L8HWO3odZBT6Cln6h2Vpsi27bqiNiAfgz0ExvVqrE9gLxvApr1jauLJJ/wQHzZyiahkcTI4lPwC0c6Fy4bv7NRuiLl91123WfZloKOZJZWke73n6sNO/TSONvHsej5N7HckS5qBu54KNQ71Sncazwd7OP8Cc+vtsN/sDHd/v216kxRzQKnhtlmj3gj8b3tD9hn0/8xXXsxN8ylVwLEg75ExTN1WkE0Vx86h61Vd0pjPotm+BfHvaaB/Ugw6YUnPB8PH+7ZCppoMSqcm2OYXSnoTKV5JbcBlQW+FqzjcAQPhUklSNGIpqC62+cxhGdEHBTLfji6YU5E7akwhAAbolkkgO+UFJgjThkENtuHTuIARRiHjjEGvaBdLb1DQ5xg3H9kEJkyBBmy/EMnQnXTNGEnF7c7fsxmYgSaXOdb/64QUDC/7ohr05Prt6Ty/dHftDtNzvbr5Gm8ME8PdOZ5u5uwWOPWpQrR24e7gGyS9ZsUfL/P3vvutRIrgQI/5+nUNARX8P57MI2mEtvzE7QmD7DHvqyDT1zdmdPgFwl2xrKUnVJBe3+ta+xr7dPsqHUpVQXQxkwGLo7JiawXSVlplKpzFRe7sY3S6/7mje/dhR26aNu8rygpWv5kipzxGvVCUzXpGjsWXV0261OEInoCFGpi4SKlmJgxiUiVySdqSl0KdLS+6XB7bQJSSmP0DQTuoXm0JYvIpE2fYgNjsqPdXh4SNBawsZreVQwVJsN1Hcvt/qt4rZRiqFy9LKY7ZOuEusJKlMkA7bVqwtPbEmerJUW9uLVhU7EkSjBaV6OzQB9lwLjgHQWxw0QLvkfHj6z/nik66B++XyiS63rEhum2/SMZ9D5OpeoM49BoM5vbpFThi4sahdQeglqjshCg8iUhJwJmWagA0Icml/3HWqY5Gho3/dc72BR1r3Z3t7a1BVEfvv6q/lef34leXK3dbKiZxXW6vUX5i4AnEgEdhZIELg3yGnoaFcjOihDjMhrnl6iKWdU8pSysZZITpu15/KQKNFnWMTUAMTCX3QM2j2K+dgEKqhXlXQdScJ05WNfldSufSwn5c7pjkemxLCfe80Ni4VtVmgBbenu10RHNTIuq5LpTuyiRpvz8904KcFCeMLrwcvjmuGtgDJH5R2CVDWwjQqC3OQe/WQcHx4wnqQ1pF27K3wLXz7d3oFDnRNzAd7ermZs3Ol+SUH/NSNLS1MA3QomMBvKBQgBYvoX48mtQ9btSbVKJcavnI2/wdmoFTC/Ark/S6DOGFxUpxlX74K0SHPTX+e7erAHRhfXDdsxzDfMpHuq5U2mkdUqnBtR15xniEwTmcMDoOsnL8zbpfJaER3BpZaECKAhkdfEa5cKjfmvuTZh7qoAaGuQpCQ6X66ZdgbO0/GEgBy2k8K5oSduAWGShDjZIbKh/ql0JVXQXb2x9MPgql0bce5f161B5SL/i7LY1zqwWYCISJJOIeguSUlIBYlntnNATIVEMb0sJFSKbDSi39yI8My6EvhvNjf1I/qJgKfjjQCdpTN7O5kkKf9Gpzr7lgroLUOnSTxDEl8Wwy6MeqzWPMZDEgt9y6F0QjhEr0kcA/ZnJwORy7iQB9llTcGme6XcK94R4YQsL/TxFEafL7rhOC3bJPpm++JNrbKs4Z1zMN+RBJZFl7lt3CS204SO/tSOzK8ZjrUuZp4BE8wYe140ZhxbMuhMC/ItJInWaCbc9GXTLYxK28rIhQB8JhgISgsdHMoQQPYG1XNpwQi/m8ajLkQVzBel0MHMIWaM58poYQ+2PArkrpAyQkMS8+t6kVAvP4oyxqet9hthIYPpzIygN5GWIlhIpzA4P40ZpWD7Aq7C5Oo4KWcZWGTDnmKgbkFQtQobPgdPHyzG6rH1mfIx1rRXSp1JMsU0zp0ANRsfizuktCl2lzw5B6Qe4bAgo5EJs1FqsGYbQ4t1cnYy2GhpJ5WLfs1XITfcQOi2bCsQEJ++RPC2TI1bpDxv7vPKn1RrBlzxvM8UOE/mHSf5SjQ7WOD7uzGYrTy9JMb6Yoa/v3XysxTcKpSC+1kF7gZyPNsCcD9rvz1Q7beXWPbtB6349rPYWx0lXnza+ksv8faiq7u98MJuP2u63U6TH7Wc2/Ou5PaziNvTFXH7Wb/t6eq3/WCl215I1bafBdsemhdWxla+Z622H6FM28us0PZjFWd7vnXZbCB+gGOKl+X+X1PqL0ywToSTsHZq0+JfEFg7SPiCcG2ZZoCqzf7w8wMg/A7r/mnhpVY2ccGvbWL4XKsd9Zti7lnwv9ifEwj15dIfMiVfMwq92mY8gzuvTBCE0fvjs89H6ODs7P87/Be0wfJK4DgUPHSDSvbB67/Q2r/bB2PC5BpqngXplmZpzYlgXWhUWZDcRIV7R8jBgco6kJiDhmSCryhPfeq565Ypj0hMjGpZIZ5P/HqK+4PWEN/BSKMqoU87/X5vYfIuUcdYK5cpeFYkhlvlCpEPoneURQtTOYmxVMJqqTLGTfK49PYztf7wM7UO/jytpEodfM9s3hP8iQ4GptbK4Sf9xwllmUmfmuLw46n+84OONIYP/pAfRyMaErS109fPnWJs3rC9+9itHGHZwB+3jiMcfeuFnJnwTkJu2eU1gD/SQo2NxXjEp41ll/vvyQLDzT9zHIwFDKqrYO1yLCUOL4MplSmB3vV2gE2QkZsLL89SsyYn5t5eqW4Lbli3Aj4hF9qw2lGod8x73R9VfzjjPC7sXoYabqPalVMYVhdMTdJ0MaTShMLHUQdgqrpFCND/uBHhgpYGo7QK4UZonXwL5vOpfkVsnh10Op3eJtqoUgx+qSPMMg9yP4nc8mpjIvk0qTDI/YlUpVExZ79EpkeWtFkarxKx/OGrhGs6SpGuJJyAH/xxtqad7d670w60GDntW2LzrNvp79dwH3w/h0IPu0cfJDfsBsl7ozq/8DrM0a6Wtg6HfDrFLILLkFONBRvrZtFJSux1fHWNnkhANKbnLfbL0ujZ/N05hBXZ8LFkBQSma4Hhz3pf+euPdT/ydjrdeaIj6HQa31zPIe4Kipn5kmTBBbrZVFvyAn3i1yQ9nZC4udZav0JPI2Qak9on7zzNfsmkXuz9m5fDLUas/S+SSthuJ/q6bpzyLHmDtFZdasOumN55ZSVHWL2l7DCm64VCHqAwdSgEGvEwE4hr76sdH6HE1qWlUpB4BGcShZJqcO8QzxC+4jQSiLJ2RBJIN8TxTFCRh7prEL4F/c6+GdW/pBvR2AZom8r7CqlfaogiU1Nnyt/RlkIhTSZL896f6nxRc3FgS23oKTU7RlnqvtYluXxSV8Tlyen50eHg96Pzz6cH538en/1+fnB0et7t7Z0fvj0811fpTTdqGFPCZFCNt3/wFOuj921bslJIzKI2jjkrXrlySBzNg0g0bJVYqExkwDzTTMIfbcihFbq2LbqoonQeTqBYjYBroTzQxA0KKTk6qVXfIWAJmSvVlirHx0HQ+GZsHiRLIvEB1JDkowKtvclNRbEpviQoS8oX3o4YAOJNa3GnNchr79hVwNKE++ShPboiC0Q8+mGQWq4AXNVkjL/W9KKstZD9q7kn0sA5wWISTKP+khbmsCCx2Fip4hRi4+y2fz/oo4iOib7KHBx9dutnLhgd9fioyZYpBVrpjC0OJUUUrsb/5WftueCrukArXXbVxVbBGJWV6Lzb3Tncfdc77PffvhvsDvaO9t7uvdt+++7tu87h/lHjRgb+mogJ7j7Zopz+ftB99quyf7S1vzXY3+pu7e3t7Q16e3u9nZ3D3mC/2+91twfdQffw8Ohtr3HcVWl18qPmSdan19+pXyFHw6v87vz+K5SPqlfqYfbNzt7uu52dnYNOf/voXXf3oLN31HvX6+70jg7ebh++PewMejv9o+5gd2+3//Zod/vtu63D3W7v8GC/Nzh41zjE2+CokxCWtGg18VVeBqAt2w4Q2E+g2tUeRIUKit4qVVweeUrSZ84lOjyA1KVjNkqxrpaUpQSdETxtocHhry5bdnD46wK5HGbyv/HWso5vLQR0kaG8wL+eV0DB80jp2BOdMD5DCUkVqykWOz092cz1boQmmEVigi+r5Z+ibdIfdveinWG/H+52e7u9vf2tXq8b7u8Mca95rxxDjofI8hhgSTYhE8LTkaFCm56kSdKHvzNr8iNe9zq9bruj/juDvIg3nc5ivRs8fO+d9bEowuUkkNuQ7e7vdh4CWSgSlS4zHvNAKd4hjmMlLBk6/XBsZKokcSxMMA9kEuoMmQkXEqSK5Pob76y08gHCx6UkU+361PeHyphCkgfoT135rxBrfoVpjIdKJLhAczfumCjKJ1TbwRcRUQJOd74yRSXrk8UWriJpaa5l5VPK54pEziWxI8utEnk607+BKB7wMJu6gvIPJIlFluhmP+fall5WkIkzq8w09bpDwYjX30xIHPM6g2WOBd/r75z/8/C9suC39raVPZM/eHQ4uOlRty5rd7J/ftYFeLq6AP4S/OhFAWpp8cwqAtTgsArpDc+sHEANFVcmv+FOtQBqEHrq3IalFwK4BecVyHV4lCoANWR4ockRPqYvLv+/jNzLSf73MXtpmf9zcPtx0/7nEOTHyvmfQ4TnkPDvg/4z2/8Rs/0LhP+Z6v94qf4Fwr/wPP96XJ9Xkn8dDqtgAj+fDP86Cq6M+Xun9P46jJ7a/n3Q3P7bEFwBY3fRxP46lH4Aw/VZpvQv056ZE8CYWzi2zeyYXhFmrkla+kITJ0lMQzyMqzfRgoRJr7+TNrZciJB4GINgb4DpkPOYYFaH0Fv9ExrFuICWKf9+dnKKGBlzSfV91TUWXhtOpXg6lUqmmAlo1G7iZBkiDPQh9TljjMSNtxsj3+S5DZl91KV0cbpDAl8B3CQK0CdTV1/bWIgW23gcH3w4yNsnr/udgihmGMKWsVBa6pQwKTZlLNqusZrCoa3HnftD8G0ip/ErHCesbWFs00hslEKkTEeW3GiI+TVJocVIbfurzW7QmOlSIrLpUhmOilJwNTCcmRfawjhsFXt90wpOmUsbs5m+T1/NiF8D26IRv1WUniridx4kSyLxMiN+/bW40xqsZsSvgfPFRPzaZXrOEb/+mryMiN+nXJWHjvgtrc4LifhtuEL5qM8w4tfguNSI39OFYnsrMb35GaFhrZhyjxLbayb/G28tLYisPrhXT/xgwb1b+9vb21083Onv9rdJr9fZHXZJd7jd3x1u7Wx3mxdw0vR4qCtcIfE0qcS6msDOVQju9fB9kFvdRRB+9OBeg+xyA01PG4eUlgRyjQCoBB0tTQD8jIN8ujhIfwl+9DjIWlo8szjIGhxW4RLomcVB1lBxZS6C7hQHWYPQU98DLT0O8hacV+Bq6FHiIGvI8EKvk3xMX1wcZBm5lxMH6WP20uIg5+D248ZBziHIjxUHOYcIzyEO0gf9ZxzkI8ZBFgj/Mw7y8eIgC4R/4XGQ9bg+rzjIOhxWwQR+PnGQdRRcGfP3TnGQdRg9tf37oHGQtyG4AsbuonGQdSj9AIbrs4yDLF7TPzS0H7RqhhKcuqsNe92c4FSYeC34nqd0TBXz6ei0moucoNfYOW7XYsnhgR8U9WP6nUQ6hA6usF10IBwiPpq3oWgLj85F0LFdgpmtjVyHUxWjOfgUsHltVHaaq462+0eCGejRtmFUyHV1fyUmZIpDEvxiID/QD6fEXFjB/T5PlHkOoXp6EKwjQTHE77WQyMIJhAJAywgipI4NhbACM67aaTQksHMxirDEQ0XsrxlJZ4Hmi5z7R6N9vLe/1x3uhmHUx780IKnG4hFpWiYbfNb1WIUuppzEBJEroGFML4lPMhOoNiTKpESSj4kilTad7JWeGRkrszp1hJ1gFsXaBHOTUCZJ2jYBlSSytBZlum4PR/u90VZ/d3e4tR3hHbwVkv3eftQhHbK9u7VTJKeF9ZGJaqdtzK/+O1TXUJrQ8UQRC0BW713z9BJNCRZZaixKYGLHlIaBHcl9NraHRImYnc6os7OLcWeI9zu94a5HvCzVAssUIP7y+QQ+zi9A/OXziS0tDOddpJRUqPajjT+upjTnIU6lMsi/fD4R+nrSPGmBV/gPU4IvKRujiF8zxR4ciXBCpqSFdBGnFkqwnJj3ObLhtPepKawHXpKgfj2A0S2bZGmcC521Yv2pNccaCB0zJPiUQGS0kk6KzlM80yWzTfz68SdFhU1FWkXviKYklPGs5fwOuIiatqcDNTY4M9TYLR0f7i6X0TW4McZczaF+ujC1szTlfAg1Qgowc0et4IypJCmO0fGnqx03JmFhzI1j8eKvC1i7i/9coPXjo7N36PO7Qzdob3ert6Fh8h/MfSTWzwJRwUNFn0TCzjD7zYLrRtRgvy4feDWVv1zygo1vXxZHQAMABVZOOB1cq6SunbxGPTFb26EGvASxvZENu4sJjvTukd5SnVVHpwJBeIEgElElnUyIdUvxJeNSif90BnXZJ3A8Ft8vDW6nTUhKeYSmmZAwyFBJeAUfiYonRJ6roB8eErSWsLFXHku9vhao77y5PnBpopOvdXE4gxfoOwrO/PSykAq0bs1ZidNg/H2jBZi7MYFsWOnuzA8UdIy1vjb+vtbS8OgR1jaq/JQYr5VlolGKx9Nmzuk78dAnnkqjjRuxguDqSm+CVxeekJE8WSut18WrC30XJQsKsgXaoOdwyeImaqwNPjFfPnLzl+ORbqqhThdoPUqnSipiBkfhjGdQwT2XeTNvrYXkfjgXZegiS+NAjXcB2VEQZAoyU+9bKsBlyXRYE4m0uQdapxVEoD65IQXP0rA+xcUm4uTS6M329tamIDgNJ799/dV8rz+/kjwprI0VDiu/Pq+/sCmPlMoU5RIN2FYgQQgr0M3Rq2bnU4aY7rWIppxRyZVBowUKH4LCE7nTckiU5DJsASuZEiz8hcaQLIZiPhYtd55BVwNJGPpbySZnUJigYVBAChvK54spMSznXnPDYqHk7DUWDtBWQUFiXFYFy51YRI025+cC9yRYCE/2PHhekRk+7xEBB1hQgkFOFufe0jxyUprDk3+GEGulaXm64M2hdni8MSZ0LRw8l6UVOLa3qzcL29tbBaDAplym2gETGGbVvw6J1j70LyY/rw4Hx++KpiWmqpwvv8H5onUT39XizxIomY2LCiTj6l3YiWl+RabDJjzYA6N9pvouDuYbZtI91fIm08hq7caNCLkDmCEyTWQOD4Cun7wwb4eYKSni7ocp5CYwSbEkaEjkNSHFVEt5zbXSXjpEdfYlSUl0vlx748yzIvNJQdRaC0rhmyQk7yydDfVP3jJWtDVvLP0wGHhrI879CKM1tSBr/hdlSam1PkPXiEiSTikjkTo/QypIbBI7MCT5GfdDfjMtstGIfnMjwjOQz/pmc1M/op8IeDreCNBZOjOVhXGSpPwbnepYDSqULSLoNIlnSILFWVUI1VLGeEhioaRPDOoSnDvXJI4B+7OTgcgFTciD7HKtKsLLAVjOlwaG7bL44BRGny8W4WApK9c6IuDiTa16qOGdc0QVMbMMtUwmd5OALDfKsD7uZ+hrhmOtbJhnmO46DwIplwM4ji122ktPvoUk0Uf2hCsrRr2Wscho1pVdHICpjq1zw7MryhCA/9DkrWvpBL+H2jvp/D3SdoeDmUPMGM+VrcKOaXkUyC3wMkJDEutEleoGrt/tRYng01a7K7CQwXRmRtAsr/c8FnItKLsHzCgF2wxwFeZ+x8kky5ciG/YCkQ27BbHSKmzPHDwt3Y0qb2Pl8zHWtDNEHQwyxTTOjdSabYpF4+tOyZNzQOMRhDkZjUgIuQZKs9OMYrBfJ2cng42W9oZcMn7NFAlzuuf2BwjFlvUygnjzt7a3SWoM9fK8uXPF66oW8inwwfOW+SDv54n7fCWaCX74vsA3mSDpEkMJvpjhaxRuHwLtMTUuXvt5vo8XuBBc+cbTazVHRJlWipWAwEOeacEJj2pbDVrTkSvsTGHjVQQrz3GJ6WKn+GOCrwh4YgiEdvDUc+kwmVIijNoIk4BY4SlYhgxeo5GVFNYdjRnCkHxvrEd9AniCcmoW7l5t6SaYjYkIlisN/C7X2tvL01lOclCFpwTC3fhoni6HGToZHHxSpD3QzDxwQ/lioHlZdIM7JBstkbGL2UzNayMZ8NSh+sBhPA/feFTh+VrkCkBLaQyu60XFfjyIhySV6IgyIQlli5IEeP3JeBZmf2qm1SRYWrPf6nWhq8AE2JtGnGImJJluJjGWSqAuzNsaiyUeLP4q6skWBdFL0X9wHvviGsaaYg3QSSbVLUkLh9QI7vC1tGQIM85mU/rd8/1q8ruPXwQZZbHahBfqpYBGF4oH9QeF4IVTOkPORnqdcVw8GFlUo8dngkSLs2uZUcM8n+MhmdTeKoiaNN/Tdrfdb/e67V6nt93b3u/2dvd2272d/d52b3+7s93ubfW7+/2d3b2ddrezQGlrg2KVi++K5MOL59MJT41NyFMU87F3sVtHKxyQO4rmlMdLS2d2tYh0eIaaCWGtukma73Ojo5VQev3X2iUdYobPcTSlbK2F1lICRiIbn6sBF6jw8+K0JXeFbA2FH1IhzLFfUZUwB/CnUlhDlB9YLSwT4bkqhmU8VlI1zIH8qRzeRznM6fiC1cMcyR9bQczp8EOoiE+hQfhxT6uoHDQPunkAzcFC91KVgiJ+K3neF0F8/KPczv/zlJ57SlsSPdcD2FU2X62ztbmku+fB66J0foQzVeJ0TOQP6ZowqK+oX8JAt6p6xxM4JQxFXqrysSgFVlI9WRSJlfRFGAh/qjj3cUQYIj5XJag5hiumJj2yC8IQ4QXrSn6w1Dke20weL2QK5d82CJzSY9jwKQa5+1Dbd0p0bDxGw5Rfe9nSbnefTcjMZKOICb9G6iRi6JoMbQow5K6ooSgb54H2Jvk/c6DaIPf7xzpFRE37WGLczFZeY/ppwhm5xXZZCkA5SatSB49wSgtALZCf9XSqHPO45bzALWUM3/PvNI7xZj/ooHW9Bv8FHX76YtYDfTxF3d55V4dwvseh+uLfG+ggSWLyJxn+i8rNnU4/6AbdvoNz/V+/n70/ael3/knCS75hi41sdntBB73nQxqTzW7/qLu9Z4i8udPZNq2hHKlFMMJTGi8rgebjKdLjo3Ub+ZmSaIJlC0VkSDFroVFKyFBELXRNWcSvxUaFgPrJCtzNMixX0/T+qEtssLFRD605wPzEZNfqI4VSXVoJrnCXZpj3/G98Rco0uiQpI8sy2io46Nkc2LpCCL6ety+2g+2g0+52e20oCErDMvQraM7de4VtmQFvfect6b/L9LAmxGOtp53P7N2QMMlFC2XDjMnspv2K02ta2a8KsKWZCUIHv1+YeUzlBbAWsCRjntLv+gleRpIyyd3iKnFsjqxhynEEZQFJGirFH+QYJcKzIT66xwVBIx7H/FqNbPoJ5rnSkAm37moObbxBMWXZtxaa4hAoyui3PFnD0LVaNuLjKZrx7PXrVJ3wGPIyIAXApB2ZZOCYCtkyaf5enocuLeCGTHiSKRsqCtCnmGBBUEwkygRkRKDhTBGKqRkw02VA9VRHh6ctRdUk5QkXBFEvPxBHEfSKrMb0A5pNNWUuguWWuarweVOB1e0E3fIBulxQvfpht6hR6tD3lPCr2ByYRv3+4+TgQxPFWz1nVW6c5jmcxoScob1OL+h+RRKP18WGTh5LcHhJpCtgJHTuBxaIsjGUMoGuGvpPGB8LwUNqqvSpIZhN7gbbHYx7hbXbmNiVDjaT6SPRdpR0O+WDznEPFPZ1WKQk5GmkhqNsHBtsJR5DmhlIhwzKQUAbS7t4E10AQQH6tU1Z+ysiLMSJyDSUomVcD3WQoULeupwlNPTy3Uy2BZR4wS5BXxAmeIrWSTAO0P8k5LKF/qQpEROcXm5A9jm9IvEMOfMMHE0pHkFl5RIlKGMknbuqegikHzLI5Qss0LrNIzGjmt+K+G/MQfJm9DR+ZtxFsbwBPS3tfrHiPJ45+UuZk1AKd1bDK4rRdVcjYskh8XgMssAM+XFo2455zG25N/C53JwCNfxnHzdDOt72XUtQq8XtClNXzDqkIirClIADrLzDzJgAgTfevHUZ0ZRc4zgWLZQC84uW9oDgCA1xjFlIUvEA9u/SnLCA6PFAGxaKVfJ61W5VqnK86Vm0RPP4Y2KqdwIG4HpaBAeeSUGjWyqhu9MgixlJ8ZC6yrL2WKj8MP98UMdDYaAGmW24ZmpUSXOzraVzx9S90sq0wrfUkhDQcoqPrAKh5H8aTqgkul8XICgr9MIQhiTyfN8zUBxN0RWrbbedPFgf+bckA7CC1VynX06PNtQfupFCDA+6QfMXbNVFnqJ3Zp9vFDJV867WXzMcz8Q4w2kU6L+hGvjXazKckDjZHPFzqAwUbyr9MCbRmKihNwsInltdm4hgIqd//XcYyAFWJEb+7H82auvC2BpXNhexqla+/mvN4rXATW4Yq8PFJpEviUugOURhIldQtUAFEfI010QLi5P7evxyNtAsBHqPh1dCbFaL4v5x2riCtwfxipnZFVp6X9QTEracOdmEO+hxDGemP23d23M2RXhFgimVKdG93pVE2xzhr8Dc8avwipxDwu25B5w4D1OizKq/DqGgvJvWl7SU6BP76FvChZIXh38c+Rj+p7Kqx0zZUB9Pke5Gg3pBtxfstPxyLkVyGFvw86fDBdp7E+jNsOxtYWWndysF+pG+PKXihqWpbom6JarZE0dNSbA0PUVhbjE2AmH9eLBhiwuYhhuFohx1RyfSOd4BOvbTslFWvOgzE5hB7a10la7lM6Mp619PsDyn4lxtARptGF4v83juGCjz+vHgPzVr1NYdjjqdTuMuN1DZkyyvPvkBSokuqzZfwBS0bCNtdKnVKZV0rI0kRwu7GI77o9K6lAlTvyLhmLaHlKlvwSscjulv6o9fHR13ut0FyKgY73ypzG9sTZ4iEWJWz6q1Pa+6ne5esAhTqPEZSYMrwiK+rMruZ6ZYzLxjHUBAGoQKWmeE4WHcvI1RyFMSDPMGODchM4o5rj1GX5+qYXTFiBSzsblF7QQdpX93O0HH1H1Rf6IhsbcQUy4kEuSKpH5twbdKsRRmRK5sVKWnCUGEmMK1LUjtJOZUWqJMiUxpKNA6lhKHl+gKQnxyv6cu6/eNylkLJSm9ojEZE1P12MR1SJLq0s8bLUSnCQ5lPqofpaHGcOOq18YpDKuGMvFWAJNp+QoFp+coATVKl1XQgXXbEQ8zhfJGRT/tB/3FlpiwK5pypkZrdPv5SGt95IN126JjNkOuaCVwiVmhFrrLCsHdPk2JGl+swBJJMk14ukqrc2Ygum1h4ApximWmCa1IGlGvkFarcF7btQofbl80pPByPepgvn+wnVMK/o/cYF7/8MdgIz/soeqYhNbVjkawDMCfmF1SNgZH9toJv15robX3JKLZdE1z89rvdDxZgyVQxhm66qlFdeLTjQicIMpuSoggzOeSMFU+1lbQMdWrZuBpjMiIsmJZXjVC/nBhjTwugieoQPyakUhrL5jhsfZEvTv+fHoWfEzHulkOWocvlPBEX07burs/46ydpHxEPVPLa1PTQtcTroQBFbaWtuRoQuIE5D743QUJgTmVZgtyQmlfCWde4zdJ8FQgHKZcaMX5mqdxNIdF2VUUMCpkMOZX4KloG1EE7FoVBvoKpRmrmiVZonbhVr1Ww4C6T4p6ICjsIYih5xs0Wo8dzZKU8pRKsxAoJWOcQoyBJwLuRsGKEq+mCd3Ut3glv/U7+74zEjrkHJZav994X0WF0gJifTjomxptiaiNZd2TarN8K/XnF4UenL7fkuruHfEMxXw8Nt0j0NnJKVLCVN/3RHRM4SS0nfnydnuOIiTMpNLx0JAynFKlx5xuvj9+f1ScjZmo9yGP4Bk4QHE8E1BOGQq1Wyg5+P0v3Z7901Zz95ud6cBYoTtZqLdbUMHb3QZDROCF+gG6IF0EMIwZcYLFhAjLb4Ojz23C1KlRbLevxIyLWTdtB9SbF9DmBYrjFy5hhiS/bHa3g/p2SwOiXg7EBPf6OxcbDr2jK7OoWOaBuH7j3Iqz2d4w5ddvolUExZJC92LS9PDrVBp3tFpt48BCFzIWgdc36sK0jzAjws9hTAmThqD3vyvBMWxgddxARsOy4kVd8y3TIM+b19TBXD89+LAR6Eg+NY9AVzidqRMhLG1TUBtsT1CtQHhrBS6fITT1VNsTojj1iuZNNBT3Dz6cIh9jhNbVULaMtTDqeiFRhFRbgL7+h1f1u7H2YXp2P0nLSddx8m7N2mt68i/ei9/h/xRtKEUZteZ9KA3cq9B6crHV050nXWdJpVq10Mcvv5b6z0OvyRtW2u2Vu674yrScfK+YQkmFPyi5XhCJp+4yebeNe8zCe+C5As0mF0O7xNkLov5Cm1IyLs+hDU0DdKL8vC3aC3RKEHT4oeGkohTqVgAxZ2NiWnVHUNH6Csc0qvG59jrtzm67u4M6W2+6/Tdb+/9/p/Omeb6PQkjfUy0TI/A9NMGmu9/u7AE23TfbnTe9/mLYeH3jl90E/MB1yrcBQ/qCX1aa65exXKDNtodPmKVXy9pEcAGuxte4mHAWEsfqgdD85HXO93qbe5YZ0m3jLVms86KCv7JRk36v8RWBRwTyLeGsWdMpr69JAdcjM0Te8YKkUHq8uGg6uKEZQjv9/tauM08j8q0Uac7Dcx1fVo5Ab464oN+bLP48pMFFQb+7CxBvLUWCQ2WgoSGVVe2819nea+5mSSmOl9uj1yRJ6qnsnSkcOY5t6083cJmAABKSsND3Z4/MTTaUcIcVTyaY6fa6LUSlFxuurVhpPA0cjKRYKRZw7ZEkOmTcDZ139asQtt9/9/bt/uHu4Ojtu87+Xmd/0O0dHh40b8Bv3RlLF3THxZTpQrd2C4QvEf4kEDo5nRK4CvKL0Osj2bpf0D85OsFsjA7TWSI5iukwxeksQKeEuJvUMZWTbAjxTWMeYzbeHPPNYcyHm2PeDbrbmyINN0MYYFPZ9PC/YMxfnWxt7bZPtvrVnkRKLe/vtBcQw3nX/ycwN4WzN+c1R79/b3uH31OYk3e3Ji3cq2BOlkWPddSozTPXnjw9+zXXQVvo5NdCI3/P3tS+fLAuH2y1V8aULCC9KBZPbUvO25SFhbsPUitgOJZwbIzGCzUCbQf8pWo6XjaR9oCD6lFhs62bgG6rmd+gIYGrbczCCU/1x3ZoIx7Nfc5b/UwBhP8KYx/azkvmTFKvu/sJe7UAN6FxbJpbgvtZgVrrMYeUqAkX0hPUmk44pq55ZYLlxD7sPVgDoPo3IElKQri1aMPNQf4iXNPAJ1rMjsLMpmcV4FP4BZJOyXebfz8fPB0FX3p4Ssc6LtNcHRRG1xQpDMths5iv9IfzOr6Zg7pbHwi7gVCAcZbCoujJ6vBrQHq1Qv5zN6IFg951TW8cWRFXqftEBJQJ6TlRb6URuCX0u8i+i2hkt0UY8yzKd8Ch+mjjCFI0JRJHWOL6TfHe/KqDQcLCqxBwmNsjOIrO4YFzO6R6MiRC6GAzf48UMIeXAjrFY6/u7by7Kb/eyZS28TCMur2tWsmSs86xGhsdD1ygo0bE0sowzit0oNYQHuJx5LOwBVVhFmh4LRVuhXcee9QOcyOLeLNb0M8bEOxmABwR3EgLw1AQW/eEoul28eCY4nBCGTn3crnvCoYZyk8LbwqFHx927knJu4Iyb7ym8CQpBwl7bwYxAy3OHykZ57rqXWcvDFI7sxVzEQ8vYR8ZOTewn2uEgv4N9Ch13scxgebfIOT0b0piiQlP5bk+aXL9yKoXer62k3Fz1AAHVhMq5HfzxcEK4lKfg1AdzP1YR0aPlPWv1JJzzlRKgi4+G8h0b0svOGvpzWaT3n060yIWvUJnHwcf36Df+bVSpKY40dUUfqvAUlBp0M1qDZp/PiF3RmkQAsvTStP4ZR7bGD7/3T5TGfqYjbjP3ebwg3aoVtJ5DK2+r2VnczoeHZ76+dq2Z6cISCiC2TQOzHM6gRCn2tfMOGvnb5bqEPN5jTob7Yz5S1mosWeHGHIeE8waLscopxWkMuVsUp2Xi2CY0bg6ZZUDnPay1t0bdDv7a83A+XiKYAY/wqgekJBHpHbf3ASLkCmR4aQ5MHYWXSyUzRzHXmZDkjIiIXjCcOi//O9qxs1/d9poUbXMB0U+f94sn/OXbpXRBaDvyo3ltUh4VC/AFhILHm0Srl1x1WVXU2U1p8FdZ/rEI/TleFA/EU0q8xS+aj7F8afqDODISHD4cGTLR6xOxqPK8XTPyWxJrDmTlUzH+09oB6zL01cz/t///X+EqYFVBcmcNv+497nm/Xw+xUlC2dg8u/aPhkLFw8mcw1OcVEGGwqbaM7lycHuw1QMvSAzpRasHuoOsHvCUJDENsShWTEX35t583DmbJiJJzGfTkiPl/hPn486ZGFysoyx+cJS9gedMfYv+e9eJ3bDmPieiI8hTlbrnsm00n1ceTTMm6ZRs2KPdnKL5uf7JfVEDgfkxP9GdO6XuBM7HRg90/JJvTU0HM3eQx8ffYD6Up+HXjKSViXwAKytkKQOvFhW6/I0yWqguH/w2xkA3eeFrYWtUnLkITYlJ7w1PXa2G8pyF4gnFWWt/YjydlqJSatFvWHLZ/stdkVAU/xe7U/7mMb+kuI0zySMqIPkt3zb/Tf+KBuaXGfKfQ55H8FaHbM1Qvt5s4HBDzruqMM8F2mNdzHW7bS828t3bSx4TyMJHDjSvcFw9NI39V40AOcLhxJRRnuBCkQIT1BdihoYEESon+VpEKMp0RRSJU5kllif0QBTqvE91fQR3LwE5IAlO8ZRIhXJqciZhrYkEk1x3wIcv1MeWScIH0CDTCsdqCCl0ZNPxJ/2EEViIRi1Ij4EkygJIkHIlBVCmnrgmeyRJeZSFTY3wRiSGIDt31pgJlJnosL4JoCUwXwGg18JVVlz3YNq4BSgvaf/BYNKjupgKRzKPs4Q6hKHiJWX1EGbpnMS2u8P15fMJmvBrHS2mATG7AmC8aQnDLCVN92vRHTMHnj8nBDZiTpNrLNwmM04tnMmJOq9sTaMUMS6dR4KLrxlJZ+Zy2Mjgj4Uv/ck9Efn/AgAA//+AzPrs" } diff --git a/x-pack/osquerybeat/internal/config/osquery.go b/x-pack/osquerybeat/internal/config/osquery.go index 6db2ac0ca13..3bc100672c6 100644 --- a/x-pack/osquerybeat/internal/config/osquery.go +++ b/x-pack/osquerybeat/internal/config/osquery.go @@ -59,12 +59,15 @@ type Events struct { } type OsqueryConfig struct { - Options map[string]interface{} `config:"options" json:"options,omitempty"` - Schedule map[string]Query `config:"schedule" json:"schedule,omitempty"` - Packs map[string]Pack `config:"packs" json:"packs,omitempty"` - Filepaths map[string][]string `config:"file_paths" json:"file_paths,omitempty"` - Views map[string]string `config:"views" json:"views,omitempty"` - Events *Events `config:"events" json:"events,omitempty"` + Options map[string]interface{} `config:"options" json:"options,omitempty"` + Schedule map[string]Query `config:"schedule" json:"schedule,omitempty"` + Packs map[string]Pack `config:"packs" json:"packs,omitempty"` + Filepaths map[string][]string `config:"file_paths" json:"file_paths,omitempty"` + Views map[string]string `config:"views" json:"views,omitempty"` + Events *Events `config:"events" json:"events,omitempty"` + Yara map[string]interface{} `config:"yara" json:"yara,omitempty"` + PrometheusTargets map[string]interface{} `config:"prometheus_targets" json:"prometheus_targets,omitempty"` + AutoTableConstruction map[string]interface{} `config:"auto_table_construction" json:"auto_table_construction,omitempty"` } func (c OsqueryConfig) Render() ([]byte, error) { diff --git a/x-pack/osquerybeat/osquerybeat.reference.yml b/x-pack/osquerybeat/osquerybeat.reference.yml index 13dfcc2089e..53f7f52f922 100644 --- a/x-pack/osquerybeat/osquerybeat.reference.yml +++ b/x-pack/osquerybeat/osquerybeat.reference.yml @@ -94,66 +94,6 @@ seccomp.enabled: false # length of its retry interval each time, up to this maximum. #max_retry_interval: 30s - # The spool queue will store events in a local spool file, before - # forwarding the events to the outputs. - # Note: the spool queue is deprecated and will be removed in the future. - # Use the disk queue instead. - # - # The spool file is a circular buffer, which blocks once the file/buffer is full. - # Events are put into a write buffer and flushed once the write buffer - # is full or the flush_timeout is triggered. - # Once ACKed by the output, events are removed immediately from the queue, - # making space for new events to be persisted. - #spool: - # The file namespace configures the file path and the file creation settings. - # Once the file exists, the `size`, `page_size` and `prealloc` settings - # will have no more effect. - #file: - # Location of spool file. The default value is ${path.data}/spool.dat. - #path: "${path.data}/spool.dat" - - # Configure file permissions if file is created. The default value is 0600. - #permissions: 0600 - - # File size hint. The spool blocks, once this limit is reached. The default value is 100 MiB. - #size: 100MiB - - # The files page size. A file is split into multiple pages of the same size. The default value is 4KiB. - #page_size: 4KiB - - # If prealloc is set, the required space for the file is reserved using - # truncate. The default value is true. - #prealloc: true - - # Spool writer settings - # Events are serialized into a write buffer. The write buffer is flushed if: - # - The buffer limit has been reached. - # - The configured limit of buffered events is reached. - # - The flush timeout is triggered. - #write: - # Sets the write buffer size. - #buffer_size: 1MiB - - # Maximum duration after which events are flushed if the write buffer - # is not full yet. The default value is 1s. - #flush.timeout: 1s - - # Number of maximum buffered events. The write buffer is flushed once the - # limit is reached. - #flush.events: 16384 - - # Configure the on-disk event encoding. The encoding can be changed - # between restarts. - # Valid encodings are: json, ubjson, and cbor. - #codec: cbor - #read: - # Reader flush timeout, waiting for more events to become available, so - # to fill a complete batch as required by the outputs. - # If flush_timeout is 0, all available events are forwarded to the - # outputs immediately. - # The default value is 0s. - #flush.timeout: 0s - # Sets the maximum number of CPUs that can be executing simultaneously. The # default is the number of logical CPUs available in the system. #max_procs: @@ -470,6 +410,13 @@ output.elasticsearch: # The pin is a base64 encoded string of the SHA-256 fingerprint. #ssl.ca_sha256: "" + # A root CA HEX encoded fingerprint. During the SSL handshake if the + # fingerprint matches the root CA certificate, it will be added to + # the provided list of root CAs (`certificate_authorities`), if the + # list is empty or not defined, the matching certificate will be the + # only one in the list. Then the normal SSL validation happens. + #ssl.ca_trusted_fingerprint: "" + # Enable Kerberos support. Kerberos is automatically enabled if any Kerberos setting is set. #kerberos.enabled: true @@ -602,6 +549,13 @@ output.elasticsearch: # The pin is a base64 encoded string of the SHA-256 fingerprint. #ssl.ca_sha256: "" + # A root CA HEX encoded fingerprint. During the SSL handshake if the + # fingerprint matches the root CA certificate, it will be added to + # the provided list of root CAs (`certificate_authorities`), if the + # list is empty or not defined, the matching certificate will be the + # only one in the list. Then the normal SSL validation happens. + #ssl.ca_trusted_fingerprint: "" + # The number of times to retry publishing an event after a publishing failure. # After the specified number of retries, the events are typically dropped. # Some Beats, such as Filebeat and Winlogbeat, ignore the max_retries setting @@ -718,19 +672,13 @@ output.elasticsearch: # Set to false to disable template loading. #setup.template.enabled: true -# Select the kind of index template. From Elasticsearch 7.8, it is possible to -# use component templates. Available options: legacy, component, index. -# By default osquerybeat uses the legacy index templates. -#setup.template.type: legacy - # Template name. By default the template name is "osquerybeat-%{[agent.version]}" # The template name and pattern has to be set in case the Elasticsearch index pattern is modified. #setup.template.name: "osquerybeat-%{[agent.version]}" -# Template pattern. By default the template pattern is "-%{[agent.version]}-*" to apply to the default index settings. -# The first part is the version of the beat and then -* is used to match all daily indices. +# Template pattern. By default the template pattern is "osquerybeat-%{[agent.version]}" to apply to the default index settings. # The template name and pattern has to be set in case the Elasticsearch index pattern is modified. -#setup.template.pattern: "osquerybeat-%{[agent.version]}-*" +#setup.template.pattern: "osquerybeat-%{[agent.version]}" # Path to fields.yml file to generate the template #setup.template.fields: "${path.config}/fields.yml" @@ -777,17 +725,8 @@ setup.template.settings: # output.elasticsearch.index is ignored, and the write alias is used to set the # index name. -# Enable ILM support. Valid values are true, false, and auto. When set to auto -# (the default), the Beat uses index lifecycle management when it connects to a -# cluster that supports ILM; otherwise, it creates daily indices. -#setup.ilm.enabled: auto - -# Set the prefix used in the index lifecycle write alias name. The default alias -# name is 'osquerybeat-%{[agent.version]}'. -#setup.ilm.rollover_alias: 'osquerybeat' - -# Set the rollover index pattern. The default is "%{now/d}-000001". -#setup.ilm.pattern: "{now/d}-000001" +# Enable ILM support. Valid values are true, false. +#setup.ilm.enabled: true # Set the lifecycle policy name. The default policy name is # 'beatname'. @@ -885,6 +824,13 @@ setup.kibana: # The pin is a base64 encoded string of the SHA-256 fingerprint. #ssl.ca_sha256: "" + # A root CA HEX encoded fingerprint. During the SSL handshake if the + # fingerprint matches the root CA certificate, it will be added to + # the provided list of root CAs (`certificate_authorities`), if the + # list is empty or not defined, the matching certificate will be the + # only one in the list. Then the normal SSL validation happens. + #ssl.ca_trusted_fingerprint: "" + # ================================== Logging =================================== @@ -956,11 +902,6 @@ logging.files: # file. Defaults to true. # rotateonstartup: true - # Rotated files are either suffixed with a number e.g. osquerybeat.1 when - # renamed during rotation. Or when set to date, the date is added to - # the end of the file. On rotation a new file is created, older files are untouched. - #suffix: count - # ============================= X-Pack Monitoring ============================== # Osquerybeat can export internal metrics to a central Elasticsearch monitoring # cluster. This requires xpack monitoring to be enabled in Elasticsearch. The @@ -1088,6 +1029,13 @@ logging.files: # The pin is a base64 encoded string of the SHA-256 fingerprint. #ssl.ca_sha256: "" + # A root CA HEX encoded fingerprint. During the SSL handshake if the + # fingerprint matches the root CA certificate, it will be added to + # the provided list of root CAs (`certificate_authorities`), if the + # list is empty or not defined, the matching certificate will be the + # only one in the list. Then the normal SSL validation happens. + #ssl.ca_trusted_fingerprint: "" + # Enable Kerberos support. Kerberos is automatically enabled if any Kerberos setting is set. #kerberos.enabled: true diff --git a/x-pack/packetbeat/Jenkinsfile.yml b/x-pack/packetbeat/Jenkinsfile.yml index a2550062fb7..1771a576f07 100644 --- a/x-pack/packetbeat/Jenkinsfile.yml +++ b/x-pack/packetbeat/Jenkinsfile.yml @@ -42,7 +42,7 @@ stages: macos: mage: "mage build unitTest" platforms: ## override default label in this specific stage. - - "macosx&&x86_64" + - "orka && darwin && poc" when: ## Override the top-level when. comments: - "/test x-pack/packetbeat for macos" diff --git a/x-pack/packetbeat/packetbeat.reference.yml b/x-pack/packetbeat/packetbeat.reference.yml index 3377abc029a..739fe5c5332 100644 --- a/x-pack/packetbeat/packetbeat.reference.yml +++ b/x-pack/packetbeat/packetbeat.reference.yml @@ -692,66 +692,6 @@ packetbeat.ignore_outgoing: false # length of its retry interval each time, up to this maximum. #max_retry_interval: 30s - # The spool queue will store events in a local spool file, before - # forwarding the events to the outputs. - # Note: the spool queue is deprecated and will be removed in the future. - # Use the disk queue instead. - # - # The spool file is a circular buffer, which blocks once the file/buffer is full. - # Events are put into a write buffer and flushed once the write buffer - # is full or the flush_timeout is triggered. - # Once ACKed by the output, events are removed immediately from the queue, - # making space for new events to be persisted. - #spool: - # The file namespace configures the file path and the file creation settings. - # Once the file exists, the `size`, `page_size` and `prealloc` settings - # will have no more effect. - #file: - # Location of spool file. The default value is ${path.data}/spool.dat. - #path: "${path.data}/spool.dat" - - # Configure file permissions if file is created. The default value is 0600. - #permissions: 0600 - - # File size hint. The spool blocks, once this limit is reached. The default value is 100 MiB. - #size: 100MiB - - # The files page size. A file is split into multiple pages of the same size. The default value is 4KiB. - #page_size: 4KiB - - # If prealloc is set, the required space for the file is reserved using - # truncate. The default value is true. - #prealloc: true - - # Spool writer settings - # Events are serialized into a write buffer. The write buffer is flushed if: - # - The buffer limit has been reached. - # - The configured limit of buffered events is reached. - # - The flush timeout is triggered. - #write: - # Sets the write buffer size. - #buffer_size: 1MiB - - # Maximum duration after which events are flushed if the write buffer - # is not full yet. The default value is 1s. - #flush.timeout: 1s - - # Number of maximum buffered events. The write buffer is flushed once the - # limit is reached. - #flush.events: 16384 - - # Configure the on-disk event encoding. The encoding can be changed - # between restarts. - # Valid encodings are: json, ubjson, and cbor. - #codec: cbor - #read: - # Reader flush timeout, waiting for more events to become available, so - # to fill a complete batch as required by the outputs. - # If flush_timeout is 0, all available events are forwarded to the - # outputs immediately. - # The default value is 0s. - #flush.timeout: 0s - # Sets the maximum number of CPUs that can be executing simultaneously. The # default is the number of logical CPUs available in the system. #max_procs: @@ -1068,6 +1008,13 @@ output.elasticsearch: # The pin is a base64 encoded string of the SHA-256 fingerprint. #ssl.ca_sha256: "" + # A root CA HEX encoded fingerprint. During the SSL handshake if the + # fingerprint matches the root CA certificate, it will be added to + # the provided list of root CAs (`certificate_authorities`), if the + # list is empty or not defined, the matching certificate will be the + # only one in the list. Then the normal SSL validation happens. + #ssl.ca_trusted_fingerprint: "" + # Enable Kerberos support. Kerberos is automatically enabled if any Kerberos setting is set. #kerberos.enabled: true @@ -1200,6 +1147,13 @@ output.elasticsearch: # The pin is a base64 encoded string of the SHA-256 fingerprint. #ssl.ca_sha256: "" + # A root CA HEX encoded fingerprint. During the SSL handshake if the + # fingerprint matches the root CA certificate, it will be added to + # the provided list of root CAs (`certificate_authorities`), if the + # list is empty or not defined, the matching certificate will be the + # only one in the list. Then the normal SSL validation happens. + #ssl.ca_trusted_fingerprint: "" + # The number of times to retry publishing an event after a publishing failure. # After the specified number of retries, the events are typically dropped. # Some Beats, such as Filebeat and Winlogbeat, ignore the max_retries setting @@ -1401,6 +1355,13 @@ output.elasticsearch: # The pin is a base64 encoded string of the SHA-256 fingerprint. #ssl.ca_sha256: "" + # A root CA HEX encoded fingerprint. During the SSL handshake if the + # fingerprint matches the root CA certificate, it will be added to + # the provided list of root CAs (`certificate_authorities`), if the + # list is empty or not defined, the matching certificate will be the + # only one in the list. Then the normal SSL validation happens. + #ssl.ca_trusted_fingerprint: "" + # Enable Kerberos support. Kerberos is automatically enabled if any Kerberos setting is set. #kerberos.enabled: true @@ -1565,6 +1526,13 @@ output.elasticsearch: # The pin is a base64 encoded string of the SHA-256 fingerprint. #ssl.ca_sha256: "" + # A root CA HEX encoded fingerprint. During the SSL handshake if the + # fingerprint matches the root CA certificate, it will be added to + # the provided list of root CAs (`certificate_authorities`), if the + # list is empty or not defined, the matching certificate will be the + # only one in the list. Then the normal SSL validation happens. + #ssl.ca_trusted_fingerprint: "" + # -------------------------------- File Output --------------------------------- #output.file: @@ -1584,7 +1552,7 @@ output.elasticsearch: #path: "/tmp/packetbeat" # Name of the generated files. The default is `packetbeat` and it generates - # files: `packetbeat`, `packetbeat.1`, `packetbeat.2`, etc. + # files: `packetbeat-{datetime}.ndjson`, `packetbeat-{datetime}-1.ndjson`, etc. #filename: packetbeat # Maximum size in kilobytes of each file. When this size is reached, and on @@ -1602,6 +1570,7 @@ output.elasticsearch: # Configure automatic file rotation on every startup. The default is true. #rotate_on_startup: true + # ------------------------------- Console Output ------------------------------- #output.console: # Boolean flag to enable or disable the output module. @@ -1700,19 +1669,13 @@ output.elasticsearch: # Set to false to disable template loading. #setup.template.enabled: true -# Select the kind of index template. From Elasticsearch 7.8, it is possible to -# use component templates. Available options: legacy, component, index. -# By default packetbeat uses the legacy index templates. -#setup.template.type: legacy - # Template name. By default the template name is "packetbeat-%{[agent.version]}" # The template name and pattern has to be set in case the Elasticsearch index pattern is modified. #setup.template.name: "packetbeat-%{[agent.version]}" -# Template pattern. By default the template pattern is "-%{[agent.version]}-*" to apply to the default index settings. -# The first part is the version of the beat and then -* is used to match all daily indices. +# Template pattern. By default the template pattern is "packetbeat-%{[agent.version]}" to apply to the default index settings. # The template name and pattern has to be set in case the Elasticsearch index pattern is modified. -#setup.template.pattern: "packetbeat-%{[agent.version]}-*" +#setup.template.pattern: "packetbeat-%{[agent.version]}" # Path to fields.yml file to generate the template #setup.template.fields: "${path.config}/fields.yml" @@ -1759,17 +1722,8 @@ setup.template.settings: # output.elasticsearch.index is ignored, and the write alias is used to set the # index name. -# Enable ILM support. Valid values are true, false, and auto. When set to auto -# (the default), the Beat uses index lifecycle management when it connects to a -# cluster that supports ILM; otherwise, it creates daily indices. -#setup.ilm.enabled: auto - -# Set the prefix used in the index lifecycle write alias name. The default alias -# name is 'packetbeat-%{[agent.version]}'. -#setup.ilm.rollover_alias: 'packetbeat' - -# Set the rollover index pattern. The default is "%{now/d}-000001". -#setup.ilm.pattern: "{now/d}-000001" +# Enable ILM support. Valid values are true, false. +#setup.ilm.enabled: true # Set the lifecycle policy name. The default policy name is # 'beatname'. @@ -1867,6 +1821,13 @@ setup.kibana: # The pin is a base64 encoded string of the SHA-256 fingerprint. #ssl.ca_sha256: "" + # A root CA HEX encoded fingerprint. During the SSL handshake if the + # fingerprint matches the root CA certificate, it will be added to + # the provided list of root CAs (`certificate_authorities`), if the + # list is empty or not defined, the matching certificate will be the + # only one in the list. Then the normal SSL validation happens. + #ssl.ca_trusted_fingerprint: "" + # ================================== Logging =================================== @@ -1938,11 +1899,6 @@ logging.files: # file. Defaults to true. # rotateonstartup: true - # Rotated files are either suffixed with a number e.g. packetbeat.1 when - # renamed during rotation. Or when set to date, the date is added to - # the end of the file. On rotation a new file is created, older files are untouched. - #suffix: count - # ============================= X-Pack Monitoring ============================== # Packetbeat can export internal metrics to a central Elasticsearch monitoring # cluster. This requires xpack monitoring to be enabled in Elasticsearch. The @@ -2070,6 +2026,13 @@ logging.files: # The pin is a base64 encoded string of the SHA-256 fingerprint. #ssl.ca_sha256: "" + # A root CA HEX encoded fingerprint. During the SSL handshake if the + # fingerprint matches the root CA certificate, it will be added to + # the provided list of root CAs (`certificate_authorities`), if the + # list is empty or not defined, the matching certificate will be the + # only one in the list. Then the normal SSL validation happens. + #ssl.ca_trusted_fingerprint: "" + # Enable Kerberos support. Kerberos is automatically enabled if any Kerberos setting is set. #kerberos.enabled: true diff --git a/x-pack/winlogbeat/_meta/config/output-elasticsearch.yml.tmpl b/x-pack/winlogbeat/_meta/config/output-elasticsearch.yml.tmpl new file mode 100644 index 00000000000..ed83c8f6103 --- /dev/null +++ b/x-pack/winlogbeat/_meta/config/output-elasticsearch.yml.tmpl @@ -0,0 +1,15 @@ +{{subheader "Elasticsearch Output"}} +output.elasticsearch: + # Array of hosts to connect to. + hosts: ["localhost:9200"] + + # Protocol - either `http` (default) or `https`. + #protocol: "https" + + # Authentication credentials - either API key or username/password. + #api_key: "id:api_key" + #username: "elastic" + #password: "changeme" + + # Pipeline to route events to security, sysmon, or powershell pipelines. + pipeline: "winlogbeat-%{[agent.version]}-routing" diff --git a/x-pack/winlogbeat/_meta/config/winlogbeat.event_logs.yml.tmpl b/x-pack/winlogbeat/_meta/config/winlogbeat.event_logs.yml.tmpl index bf3d2423a78..5ee2b373dff 100644 --- a/x-pack/winlogbeat/_meta/config/winlogbeat.event_logs.yml.tmpl +++ b/x-pack/winlogbeat/_meta/config/winlogbeat.event_logs.yml.tmpl @@ -5,55 +5,14 @@ winlogbeat.event_logs: - name: System - name: Security - processors: - - script: - lang: javascript - id: security - file: ${path.home}/module/security/config/winlogbeat-security.js - name: Microsoft-Windows-Sysmon/Operational - processors: - - script: - lang: javascript - id: sysmon - file: ${path.home}/module/sysmon/config/winlogbeat-sysmon.js - name: Windows PowerShell event_id: 400, 403, 600, 800 - processors: - - script: - lang: javascript - id: powershell - file: ${path.home}/module/powershell/config/winlogbeat-powershell.js - name: Microsoft-Windows-PowerShell/Operational event_id: 4103, 4104, 4105, 4106 - processors: - - script: - lang: javascript - id: powershell - file: ${path.home}/module/powershell/config/winlogbeat-powershell.js - name: ForwardedEvents tags: [forwarded] - processors: - - script: - when.equals.winlog.channel: Security - lang: javascript - id: security - file: ${path.home}/module/security/config/winlogbeat-security.js - - script: - when.equals.winlog.channel: Microsoft-Windows-Sysmon/Operational - lang: javascript - id: sysmon - file: ${path.home}/module/sysmon/config/winlogbeat-sysmon.js - - script: - when.equals.winlog.channel: Windows PowerShell - lang: javascript - id: powershell - file: ${path.home}/module/powershell/config/winlogbeat-powershell.js - - script: - when.equals.winlog.channel: Microsoft-Windows-PowerShell/Operational - lang: javascript - id: powershell - file: ${path.home}/module/powershell/config/winlogbeat-powershell.js diff --git a/x-pack/winlogbeat/cmd/export.go b/x-pack/winlogbeat/cmd/export.go new file mode 100644 index 00000000000..ce6ecc5f9bf --- /dev/null +++ b/x-pack/winlogbeat/cmd/export.go @@ -0,0 +1,60 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License; +// you may not use this file except in compliance with the Elastic License. + +package cmd + +import ( + "fmt" + "os" + + "github.com/spf13/cobra" + + "github.com/elastic/beats/v7/libbeat/cmd/instance" + "github.com/elastic/beats/v7/libbeat/common" + "github.com/elastic/beats/v7/winlogbeat/module" +) + +// GenTemplateConfigCmd is the command used to export the elasticsearch template. +func GenExportPipelineCmd(settings instance.Settings) *cobra.Command { + genExportPipelineCmd := &cobra.Command{ + Use: "pipelines", + Short: "Export pipelines", + Run: func(cmd *cobra.Command, args []string) { + version, _ := cmd.Flags().GetString("es.version") + dir, _ := cmd.Flags().GetString("dir") + + if version == "" { + fatalf("--es.version is required") + } + + ver, err := common.NewVersion(version) + if err != nil { + fatalf("Unable to parse ES version from %s: %+v", version, err) + } + + b, err := instance.NewInitializedBeat(settings) + if err != nil { + fatalf("Failed to initialize 'pipeline' command: %+v", err) + } + + err = module.ExportPipelines(b.Info, *ver, dir) + if err != nil { + fatalf("Failed to export pipelines: %+v", err) + } + + fmt.Fprintf(os.Stdout, "Exported pipelines") + }, + } + + genExportPipelineCmd.Flags().String("es.version", settings.Version, "Elasticsearch version (required)") + genExportPipelineCmd.Flags().String("dir", "", "Specify directory for exporting pipelines. Default is current directory.") + + return genExportPipelineCmd +} + +func fatalf(msg string, vs ...interface{}) { + fmt.Fprintf(os.Stderr, msg, vs...) + fmt.Fprintln(os.Stderr) + os.Exit(1) +} diff --git a/x-pack/winlogbeat/cmd/root.go b/x-pack/winlogbeat/cmd/root.go index ae56c4de83f..9ac4f71a891 100644 --- a/x-pack/winlogbeat/cmd/root.go +++ b/x-pack/winlogbeat/cmd/root.go @@ -7,6 +7,7 @@ package cmd import ( "github.com/elastic/beats/v7/libbeat/cmd" winlogbeatCmd "github.com/elastic/beats/v7/winlogbeat/cmd" + "github.com/elastic/beats/v7/x-pack/winlogbeat/module" // Register fields. _ "github.com/elastic/beats/v7/x-pack/libbeat/include" @@ -23,4 +24,6 @@ func init() { settings := winlogbeatCmd.WinlogbeatSettings() settings.ElasticLicensed = true RootCmd = winlogbeatCmd.Initialize(settings) + RootCmd.ExportCmd.AddCommand(GenExportPipelineCmd(settings)) + module.Init() } diff --git a/x-pack/journalbeat/main.go b/x-pack/winlogbeat/module/pipeline.go similarity index 50% rename from x-pack/journalbeat/main.go rename to x-pack/winlogbeat/module/pipeline.go index 232a3e6fc49..baa335e4b2a 100644 --- a/x-pack/journalbeat/main.go +++ b/x-pack/winlogbeat/module/pipeline.go @@ -2,18 +2,18 @@ // or more contributor license agreements. Licensed under the Elastic License; // you may not use this file except in compliance with the Elastic License. -package main +package module import ( - "os" + "embed" - "github.com/elastic/beats/v7/x-pack/journalbeat/cmd" - - _ "github.com/elastic/beats/v7/journalbeat/include" + "github.com/elastic/beats/v7/winlogbeat/module" ) -func main() { - if err := cmd.RootCmd.Execute(); err != nil { - os.Exit(1) - } +// pipelineFS holds the yml representation of the ingest node pipelines +//go:embed */ingest/*.yml +var pipelinesFS embed.FS + +func Init() { + module.PipelinesFS = &pipelinesFS } diff --git a/x-pack/winlogbeat/module/powershell/config/winlogbeat-powershell.js b/x-pack/winlogbeat/module/powershell/config/winlogbeat-powershell.js deleted file mode 100644 index 698b12711bf..00000000000 --- a/x-pack/winlogbeat/module/powershell/config/winlogbeat-powershell.js +++ /dev/null @@ -1,690 +0,0 @@ -// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one -// or more contributor license agreements. Licensed under the Elastic License; -// you may not use this file except in compliance with the Elastic License. - -var powershell = (function () { - var path = require("path"); - var processor = require("processor"); - var windows = require("windows"); - - var normalizeCommonFieldNames = new processor.Convert({ - fields: [ - { - from: "winlog.event_data.Engine Version", - to: "winlog.event_data.EngineVersion", - }, - { - from: "winlog.event_data.Pipeline ID", - to: "winlog.event_data.PipelineId", - }, - { - from: "winlog.event_data.Runspace ID", - to: "winlog.event_data.RunspaceId", - }, - { - from: "winlog.event_data.Host Version", - to: "winlog.event_data.HostVersion", - }, - { - from: "winlog.event_data.Script Name", - to: "winlog.event_data.ScriptName", - }, - { - from: "winlog.event_data.Path", - to: "winlog.event_data.ScriptName", - }, - { - from: "winlog.event_data.Command Path", - to: "winlog.event_data.CommandPath", - }, - { - from: "winlog.event_data.Command Name", - to: "winlog.event_data.CommandName", - }, - { - from: "winlog.event_data.Command Type", - to: "winlog.event_data.CommandType", - }, - { - from: "winlog.event_data.User", - to: "winlog.event_data.UserId", - }, - ], - mode: "rename", - ignore_missing: true, - fail_on_error: false, - }) - - // Builds a dissect tokenizer. - // - // - chunks: number of chunks dissect needs to look for. - // - delimiter: indicates what is the delimiter between chunks, - // in addition to `\n` which is already expected. - // - sep: separator between key value pairs. - // - // example: - // For a string like "Foo=Bar\n\tBar=Baz", chunks: 2, delimiter: '\t', sep: '=' - var buildNewlineSpacedTokenizer = function (chunks, delimiter, sep) { - var tokenizer = ""; - for (var i = 0; i < chunks; i++) { - if (i !== 0) { - tokenizer += "\n%{}"; - } - tokenizer += delimiter+"%{*p"+i+"}"+sep+"%{&p"+i+"}"; - } - return tokenizer; - }; - - var dissectField = function (fromField, targetPrefix, chunks, delimiter, sep) { - return new processor.Dissect({ - field: fromField, - target_prefix: targetPrefix, - tokenizer: buildNewlineSpacedTokenizer(chunks, delimiter, sep), - fail_on_error: false, - }); - }; - - // countChunksDelimitedBy will return the number of chunks contained in a field - // that are delimited by the given delimiter. - var countChunksDelimitedBy = function(evt, fromField, delimiter) { - var str = evt.Get(fromField); - if (!str) { - return 0; - } - return str.split(delimiter).length-1; - }; - - var dissect4xxAnd600 = function (evt) { - var delimiter = "\t"; - var chunks = countChunksDelimitedBy(evt, "winlog.event_data.param3", delimiter); - - dissectField("winlog.event_data.param3", "winlog.event_data", chunks, delimiter, "=").Run(evt); - - // these fields contain redundant information. - evt.Delete("winlog.event_data.param1"); - evt.Delete("winlog.event_data.param2"); - evt.Delete("winlog.event_data.param3"); - }; - - var dissect800Detail = function (evt) { - var delimiter = "\t"; - var chunks = countChunksDelimitedBy(evt, "winlog.event_data.param2", delimiter); - - dissectField("winlog.event_data.param2", "winlog.event_data", chunks, "\t", "=").Run(evt); - - // these fields contain redundant information. - evt.Delete("winlog.event_data.param1"); - evt.Delete("winlog.event_data.param2"); - }; - - var dissect4103 = function (evt) { - var delimiter = " "; - var chunks = countChunksDelimitedBy(evt, "winlog.event_data.ContextInfo", delimiter); - - dissectField("winlog.event_data.ContextInfo", "winlog.event_data", chunks, delimiter, " = ").Run(evt); - - // these fields contain redundant information. - evt.Delete("winlog.event_data.ContextInfo"); - evt.Delete("winlog.event_data.Severity"); - }; - - var addEngineVersion = function (evt) { - var version = evt.Get("winlog.event_data.EngineVersion"); - evt.Delete("winlog.event_data.EngineVersion"); - if (!version) { - return; - } - - evt.Put("powershell.engine.version", version); - }; - - var addPipelineID = function (evt) { - var id = evt.Get("winlog.event_data.PipelineId"); - evt.Delete("winlog.event_data.PipelineId"); - if (!id) { - return; - } - - evt.Put("powershell.pipeline_id", id); - }; - - var addRunspaceID = function (evt) { - var id = evt.Get("winlog.event_data.RunspaceId"); - evt.Delete("winlog.event_data.RunspaceId"); - if (!id) { - return; - } - - evt.Put("powershell.runspace_id", id); - }; - - var addScriptBlockID = function (evt) { - var id = evt.Get("winlog.event_data.ScriptBlockId"); - evt.Delete("winlog.event_data.ScriptBlockId"); - if (!id) { - return; - } - - evt.Put("powershell.file.script_block_id", id); - }; - - var addScriptBlockText = function (evt) { - var text = evt.Get("winlog.event_data.ScriptBlockText"); - evt.Delete("winlog.event_data.ScriptBlockText"); - if (!text) { - return; - } - - evt.Put("powershell.file.script_block_text", text); - }; - - var splitCommandLine = function (evt, source, target) { - var commandLine = evt.Get(source); - if (!commandLine) { - return; - } - evt.Put(target, windows.splitCommandLine(commandLine)); - }; - - var addProcessArgs = function (evt) { - splitCommandLine(evt, "process.command_line", "process.args"); - var args = evt.Get("process.args"); - if (args && args.length > 0) { - evt.Put("process.args_count", args.length); - } - }; - - var addExecutableVersion = function (evt) { - var version = evt.Get("winlog.event_data.HostVersion"); - evt.Delete("winlog.event_data.HostVersion"); - if (!version) { - return; - } - - evt.Put("powershell.process.executable_version", version); - }; - - var addFileInfo = function (evt) { - var scriptName = evt.Get("winlog.event_data.ScriptName"); - evt.Delete("winlog.event_data.ScriptName"); - if (!scriptName) { - return; - } - - evt.Put("file.path", scriptName); - evt.Put("file.name", path.basename(scriptName)); - evt.Put("file.directory", path.dirname(scriptName)); - - // path returns extensions with a preceding ., e.g.: .tmp, .png - // according to ecs the expected format is without it, so we need to remove it. - var ext = path.extname(scriptName); - if (!ext) { - return; - } - - if (ext.charAt(0) === ".") { - ext = ext.substr(1); - } - evt.Put("file.extension", ext); - }; - - var addCommandValue = function (evt) { - var value = evt.Get("winlog.event_data.CommandLine") - evt.Delete("winlog.event_data.CommandLine"); - if (!value) { - return; - } - - evt.Put("powershell.command.value", value.trim()); - }; - - var addCommandPath = function (evt) { - var commandPath = evt.Get("winlog.event_data.CommandPath"); - evt.Delete("winlog.event_data.CommandPath"); - if (!commandPath) { - return; - } - - evt.Put("powershell.command.path", commandPath); - }; - - var addCommandName = function (evt) { - var commandName = evt.Get("winlog.event_data.CommandName"); - evt.Delete("winlog.event_data.CommandName"); - if (!commandName) { - return; - } - - evt.Put("powershell.command.name", commandName); - }; - - var addCommandType = function (evt) { - var commandType = evt.Get("winlog.event_data.CommandType"); - evt.Delete("winlog.event_data.CommandType"); - if (!commandType) { - return; - } - - evt.Put("powershell.command.type", commandType); - }; - - var detailRegex = /^(.+)\((.+)\)\:\s*(.+)?$/; - var parameterBindingRegex = /^.*name\=(.+);\s*value\=(.+)$/ - - // Parses a command invocation detail raw line, and converts it to an object, based on its type. - // - // - for unexpectedly formatted ones: {value: "the raw line as it is"} - // - for all: - // * related_command: describes to what command it is related to - // * value: the value for that detail line - // * type: the type of the detail line, i.e.: CommandInvocation, ParameterBinding, NonTerminatingError - // - additionally, ParameterBinding adds a `name` field with the parameter name being bound. - var parseRawDetail = function (raw) { - var matches = detailRegex.exec(raw); - if (!matches || matches.length !== 4) { - return {value: raw}; - } - - if (matches[1] !== "ParameterBinding") { - return {type: matches[1], related_command: matches[2], value: matches[3]}; - } - - var nameValMatches = parameterBindingRegex.exec(matches[3]); - if (!nameValMatches || nameValMatches.length !== 3) { - return {value: matches[3]}; - } - - return { - type: matches[1], - related_command: matches[2], - name: nameValMatches[1], - value: nameValMatches[2], - }; - }; - - var addCommandInvocationDetails = function (evt, from) { - var rawDetails = evt.Get(from); - if (!rawDetails) { - return; - } - - var details = []; - rawDetails.split("\n").forEach(function (raw) { - details.push(parseRawDetail(raw)); - }); - - if (details.length === 0) { - return; - } - - evt.Delete(from); - evt.Put("powershell.command.invocation_details", details); - }; - - var addCommandInvocationDetailsForEvent800 = function (evt) { - addCommandInvocationDetails(evt, "winlog.event_data.param3"); - }; - - var addCommandInvocationDetailsForEvent4103 = function (evt) { - addCommandInvocationDetails(evt, "winlog.event_data.Payload"); - }; - - var addUser = function (evt) { - var userParts = evt.Get("winlog.event_data.UserId").split("\\"); - evt.Delete("winlog.event_data.UserId"); - if (userParts.length === 2) { - evt.Put("user.domain", userParts[0]); - evt.Put("user.name", userParts[1]); - evt.AppendTo("related.user", userParts[1]); - } - }; - - var addConnectedUser = function (evt) { - var userParts = evt.Get("winlog.event_data.Connected User").split("\\"); - evt.Delete("winlog.event_data.Connected User"); - if (userParts.length === 2) { - evt.Put("powershell.connected_user.domain", userParts[0]); - if (evt.Get("user.domain")) { - evt.Put("destination.user.domain", evt.Get("user.domain")); - } - evt.Put("source.user.domain", userParts[0]); - evt.Put("user.domain", userParts[0]); - - evt.Put("powershell.connected_user.name", userParts[1]); - if (evt.Get("user.name")) { - evt.Put("destination.user.name", evt.Get("user.name")); - } - evt.Put("source.user.name", userParts[1]); - evt.Put("user.name", userParts[1]); - evt.AppendTo("related.user", userParts[1]); - } - }; - - var removeEmptyEventData = function (evt) { - var eventData = evt.Get("winlog.event_data"); - if (eventData && Object.keys(eventData).length === 0) { - evt.Delete("winlog.event_data"); - } - }; - - var event4xxAnd600Common = new processor.Chain() - .Add(dissect4xxAnd600) - .Convert({ - fields: [ - { - from: "winlog.event_data.SequenceNumber", - to: "event.sequence", - type: "long", - }, - { - from: "winlog.event_data.NewEngineState", - to: "powershell.engine.new_state", - }, - { - from: "winlog.event_data.PreviousEngineState", - to: "powershell.engine.previous_state", - }, - { - from: "winlog.event_data.NewProviderState", - to: "powershell.provider.new_state", - }, - { - from: "winlog.event_data.ProviderName", - to: "powershell.provider.name", - }, - { - from: "winlog.event_data.HostId", - to: "process.entity_id", - }, - { - from: "winlog.event_data.HostApplication", - to: "process.command_line", - }, - { - from: "winlog.event_data.HostName", - to: "process.title", - }, - ], - mode: "rename", - ignore_missing: true, - fail_on_error: false, - }) - .Add(addEngineVersion) - .Add(addPipelineID) - .Add(addRunspaceID) - .Add(addProcessArgs) - .Add(addExecutableVersion) - .Add(addFileInfo) - .Add(addCommandValue) - .Add(addCommandPath) - .Add(addCommandName) - .Add(addCommandType) - .Add(removeEmptyEventData) - .Build(); - - var event400 = new processor.Chain() - .AddFields({ - fields: { - category: ["process"], - type: ["start"], - }, - target: "event", - }) - .Add(event4xxAnd600Common) - .Build() - - var event403 = new processor.Chain() - .AddFields({ - fields: { - category: ["process"], - type: ["end"], - }, - target: "event", - }) - .Add(event4xxAnd600Common) - .Build() - - var event600 = new processor.Chain() - .AddFields({ - fields: { - category: ["process"], - type: ["info"], - }, - target: "event", - }) - .Add(event4xxAnd600Common) - .Build() - - var event800 = new processor.Chain() - .Add(dissect800Detail) - .AddFields({ - fields: { - category: ["process"], - type: ["info"], - }, - target: "event", - }) - .Convert({ - fields: [ - { - from: "winlog.event_data.SequenceNumber", - to: "event.sequence", - type: "long", - }, - { - from: "winlog.event_data.HostId", - to: "process.entity_id", - }, - { - from: "winlog.event_data.HostApplication", - to: "process.command_line", - }, - { - from: "winlog.event_data.HostName", - to: "process.title", - }, - { - from: "winlog.event_data.DetailTotal", - to: "powershell.total", - type: "long", - }, - { - from: "winlog.event_data.DetailSequence", - to: "powershell.sequence", - type: "long", - }, - ], - mode: "rename", - ignore_missing: true, - fail_on_error: false, - }) - .Add(addEngineVersion) - .Add(addPipelineID) - .Add(addRunspaceID) - .Add(addProcessArgs) - .Add(addExecutableVersion) - .Add(addFileInfo) - .Add(addCommandValue) - .Add(addCommandPath) - .Add(addCommandName) - .Add(addCommandType) - .Add(addUser) - .Add(addCommandInvocationDetailsForEvent800) - .Add(removeEmptyEventData) - .Build(); - - var event4103 = new processor.Chain() - .Add(dissect4103) - .AddFields({ - fields: { - category: ["process"], - type: ["info"], - }, - target: "event", - }) - .Convert({ - fields: [ - { - from: "winlog.event_data.Sequence Number", - to: "event.sequence", - type: "long", - }, - { - from: "winlog.event_data.Host ID", - to: "process.entity_id", - }, - { - from: "winlog.event_data.Host Application", - to: "process.command_line", - }, - { - from: "winlog.event_data.Host Name", - to: "process.title", - }, - { - from: "winlog.event_data.Shell ID", - to: "powershell.id", - }, - ], - mode: "rename", - ignore_missing: true, - fail_on_error: false, - }) - .Convert({ - fields: [ - { - from: "winlog.user.identifier", - to: "user.id", - type: "string", - }, - ], - mode: "copy", - ignore_missing: true, - fail_on_error: false, - }) - .Add(normalizeCommonFieldNames) - .Add(addEngineVersion) - .Add(addPipelineID) - .Add(addRunspaceID) - .Add(addProcessArgs) - .Add(addExecutableVersion) - .Add(addFileInfo) - .Add(addCommandValue) - .Add(addCommandPath) - .Add(addCommandName) - .Add(addCommandType) - .Add(addUser) - .Add(addConnectedUser) - .Add(addCommandInvocationDetailsForEvent4103) - .Add(removeEmptyEventData) - .Build(); - - var event4104 = new processor.Chain() - .AddFields({ - fields: { - category: ["process"], - type: ["info"], - }, - target: "event", - }) - .Convert({ - fields: [ - { - from: "winlog.event_data.MessageNumber", - to: "powershell.sequence", - type: "long", - }, - { - from: "winlog.event_data.MessageTotal", - to: "powershell.total", - type: "long", - }, - ], - mode: "rename", - ignore_missing: true, - fail_on_error: false, - }) - .Convert({ - fields: [ - { - from: "winlog.user.identifier", - to: "user.id", - type: "string", - }, - ], - mode: "copy", - ignore_missing: true, - fail_on_error: false, - }) - .Add(normalizeCommonFieldNames) - .Add(addFileInfo) - .Add(addScriptBlockID) - .Add(addScriptBlockText) - .Add(removeEmptyEventData) - .Build(); - - var event4105And4106Common = new processor.Chain() - .Add(addRunspaceID) - .Add(addScriptBlockID) - .Add(removeEmptyEventData) - .Convert({ - fields: [ - { - from: "winlog.user.identifier", - to: "user.id", - type: "string", - }, - ], - mode: "copy", - ignore_missing: true, - fail_on_error: false, - }) - .Build(); - - var event4105 = new processor.Chain() - .Add(event4105And4106Common) - .AddFields({ - fields: { - category: ["process"], - type: ["start"], - }, - target: "event", - }) - .Build(); - - var event4106 = new processor.Chain() - .Add(event4105And4106Common) - .AddFields({ - fields: { - category: ["process"], - type: ["end"], - }, - target: "event", - }) - .Build(); - - return { - 400: event400.Run, - 403: event403.Run, - 600: event600.Run, - 800: event800.Run, - 4103: event4103.Run, - 4104: event4104.Run, - 4105: event4105.Run, - 4106: event4106.Run, - - process: function(evt) { - var eventId = evt.Get("winlog.event_id"); - var processor = this[eventId]; - if (processor === undefined) { - return; - } - evt.Put("event.module", "powershell"); - processor(evt); - }, - }; -})(); - -function process(evt) { - return powershell.process(evt); -} diff --git a/x-pack/winlogbeat/module/powershell/ingest/powershell.yml b/x-pack/winlogbeat/module/powershell/ingest/powershell.yml new file mode 100644 index 00000000000..117f7288a94 --- /dev/null +++ b/x-pack/winlogbeat/module/powershell/ingest/powershell.yml @@ -0,0 +1,433 @@ +--- +description: Pipeline for Windows Powershell events +processors: + - kv: + description: Split Event 800 event data fields. + field: winlog.event_data.param2 + target_field: winlog.event_data + field_split: "\n\t" + trim_key: "\n\t" + trim_value: "\n\t" + value_split: "=" + if: ctx?.winlog?.event_id == "800" + - kv: + description: Split Events 4xx and 600 event data fields. + field: winlog.event_data.param3 + target_field: winlog.event_data + field_split: "\n\t" + trim_key: "\n\t" + trim_value: "\n\t" + value_split: "=" + if: ctx?.winlog?.event_id != "800" + + ## ECS and Event fields. + + - set: + field: ecs.version + value: '1.12.0' + - set: + field: log.level + copy_from: winlog.level + ignore_empty_value: true + ignore_failure: true + if: ctx?.winlog?.level != "" + - date: + field: winlog.time_created + formats: + - ISO8601 + ignore_failure: true + if: ctx?.winlog?.time_created != null + + - set: + field: event.ingested + value: '{{_ingest.timestamp}}' + - set: + field: event.kind + value: event + - set: + field: event.code + value: '{{winlog.event_id}}' + - set: + field: event.category + value: process + - set: + field: event.type + value: start + if: ctx?.event.code == "400" + - set: + field: event.type + value: end + if: ctx?.event.code == "403" + - set: + field: event.type + value: info + if: ctx?.event?.type == null + - convert: + field: winlog.event_data.SequenceNumber + target_field: event.sequence + type: long + ignore_failure: true + ignore_missing: true + - convert: + field: winlog.record_id + type: string + ignore_failure: true + ignore_missing: true + + ## Process fields. + + - rename: + field: winlog.event_data.HostId + target_field: process.entity_id + ignore_failure: true + ignore_missing: true + if: ctx?.winlog?.event_data?.HostId != "" + - rename: + field: winlog.event_data.HostApplication + target_field: process.command_line + ignore_failure: true + ignore_missing: true + if: ctx?.winlog?.event_data?.HostApplication != "" + - rename: + field: winlog.event_data.HostName + target_field: process.title + ignore_failure: true + ignore_missing: true + if: ctx?.winlog?.event_data?.HostName != "" + + ## User fields. + + - split: + field: winlog.event_data.UserId + target_field: "_temp.user_parts" + separator: '\\' + if: ctx?.winlog?.event_data?.UserId != null + - set: + field: user.domain + value: "{{_temp.user_parts.0}}" + ignore_failure: true + ignore_empty_value: true + if: ctx?._temp?.user_parts != null && ctx._temp.user_parts.size() == 2 + - set: + field: user.name + value: "{{_temp.user_parts.1}}" + ignore_failure: true + ignore_empty_value: true + if: ctx?._temp?.user_parts != null && ctx._temp.user_parts.size() == 2 + - append: + field: related.user + value: "{{user.name}}" + ignore_failure: true + allow_duplicates: false + if: ctx?.user?.name != null + + ## PowerShell fields. + + - rename: + field: winlog.event_data.NewEngineState + target_field: powershell.engine.new_state + ignore_failure: true + ignore_missing: true + if: ctx?.winlog?.event_data?.NewEngineState != "" + - rename: + field: winlog.event_data.PreviousEngineState + target_field: powershell.engine.previous_state + ignore_failure: true + ignore_missing: true + if: ctx?.winlog?.event_data?.PreviousEngineState != "" + - rename: + field: winlog.event_data.NewProviderState + target_field: powershell.provider.new_state + ignore_failure: true + ignore_missing: true + if: ctx?.winlog?.event_data?.NewProviderState != "" + - rename: + field: winlog.event_data.ProviderName + target_field: powershell.provider.name + ignore_failure: true + ignore_missing: true + if: ctx?.winlog?.event_data?.ProviderName != "" + - convert: + field: winlog.event_data.DetailTotal + target_field: powershell.total + type: long + ignore_failure: true + ignore_missing: true + if: ctx?.winlog?.event_data?.DetailTotal != "" + - convert: + field: winlog.event_data.DetailSequence + target_field: powershell.sequence + type: long + ignore_failure: true + ignore_missing: true + if: ctx?.winlog?.event_data?.DetailSequence != "" + - rename: + field: winlog.event_data.EngineVersion + target_field: powershell.engine.version + ignore_missing: true + ignore_failure: true + if: ctx?.winlog?.event_data?.EngineVersion != "" + - rename: + field: winlog.event_data.PipelineId + target_field: powershell.pipeline_id + ignore_missing: true + ignore_failure: true + if: ctx?.winlog?.event_data?.PipelineId != "" + - rename: + field: winlog.event_data.RunspaceId + target_field: powershell.runspace_id + ignore_missing: true + ignore_failure: true + if: ctx?.winlog?.event_data?.RunspaceId != "" + - rename: + field: winlog.event_data.HostVersion + target_field: powershell.process.executable_version + ignore_missing: true + ignore_failure: true + if: ctx?.winlog?.event_data?.HostVersion != "" + - rename: + field: winlog.event_data.CommandLine + target_field: powershell.command.value + ignore_failure: true + ignore_missing: true + if: ctx?.winlog?.event_data?.CommandLine != "" + - rename: + field: winlog.event_data.CommandPath + target_field: powershell.command.path + ignore_failure: true + ignore_missing: true + if: ctx?.winlog?.event_data?.CommandPath != "" + - rename: + field: winlog.event_data.CommandName + target_field: powershell.command.name + ignore_failure: true + ignore_missing: true + if: ctx?.winlog?.event_data?.CommandName != "" + - rename: + field: winlog.event_data.CommandType + target_field: powershell.command.type + ignore_failure: true + ignore_missing: true + if: ctx?.winlog?.event_data?.CommandType != "" + + - split: + description: Split Event 800 command invocation details. + field: winlog.event_data.param3 + separator: "\n" + ignore_failure: true + ignore_missing: true + if: ctx.event.code == "800" + - script: + description: |- + Parses all command invocation detail raw lines, and converts them to an object, based on their type. + - for unexpectedly formatted ones: {value: "the raw line as it is"} + - for all: + * related_command: describes to what command it is related to + * value: the value for that detail line + * type: the type of the detail line, i.e.: CommandInvocation, ParameterBinding, NonTerminatingError + - additionally, ParameterBinding adds a `name` field with the parameter name being bound. + lang: painless + if: ctx.event.code == "800" + params: + field: param3 + source: |- + def parseRawDetail(String raw) { + Pattern detailRegex = /^(.+)\((.+)\)\:\s*(.+)?$/; + Pattern parameterBindingRegex = /name\=(.+);\s*value\=(.+)$/; + + def matcher = detailRegex.matcher(raw); + if (!matcher.matches()) { + return ["value": raw]; + } + def matches = new ArrayList(); + for (def i = 0; i <= matcher.groupCount(); i++) { + matches.add(matcher.group(i)); + } + + if (matches.length != 4) { + return ["value": raw]; + } + + if (matches[1] != "ParameterBinding") { + return [ + "type": matches[1], + "related_command": matches[2], + "value": matches[3] + ]; + } + + matcher = parameterBindingRegex.matcher(matches[3]); + if (!matcher.matches()) { + return ["value": matches[4]]; + } + def nameValMatches = new ArrayList(); + for (def i = 0; i <= matcher.groupCount(); i++) { + nameValMatches.add(matcher.group(i)); + } + if (nameValMatches.length !== 3) { + return ["value": matches[3]]; + } + + return [ + "type": matches[1], + "related_command": matches[2], + "name": nameValMatches[1], + "value": nameValMatches[2] + ]; + } + + if (ctx?._temp == null) { + ctx._temp = new HashMap(); + } + + if (ctx._temp.details == null) { + ctx._temp.details = new ArrayList(); + } + + def values = ctx?.winlog?.event_data[params["field"]]; + if (values != null && values.length > 0) { + for (v in values) { + ctx._temp.details.add(parseRawDetail(v)); + } + } + - rename: + field: _temp.details + target_field: powershell.command.invocation_details + if: ctx?._temp?.details != null && ctx?._temp?.details.length > 0 + + - script: + description: Implements Windows-like SplitCommandLine + lang: painless + if: ctx?.process?.command_line != null && ctx.process.command_line != "" + source: |- + // appendBSBytes appends n '\\' bytes to b and returns the resulting slice. + def appendBSBytes(StringBuilder b, int n) { + for (; n > 0; n--) { + b.append('\\'); + } + return b; + } + + // readNextArg splits command line string cmd into next + // argument and command line remainder. + def readNextArg(String cmd) { + def b = new StringBuilder(); + boolean inquote; + int nslash; + for (; cmd.length() > 0; cmd = cmd.substring(1)) { + def c = cmd.charAt(0); + if (c == (char)' ' || c == (char)0x09) { + if (!inquote) { + return [ + "arg": appendBSBytes(b, nslash).toString(), + "rest": cmd.substring(1) + ]; + } + } else if (c == (char)'"') { + b = appendBSBytes(b, nslash/2); + if (nslash%2 == 0) { + // use "Prior to 2008" rule from + // http://daviddeley.com/autohotkey/parameters/parameters.htm + // section 5.2 to deal with double double quotes + if (inquote && cmd.length() > 1 && cmd.charAt(1) == (char)'"') { + b.append(c); + cmd = cmd.substring(1); + } + inquote = !inquote; + } else { + b.append(c); + } + nslash = 0; + continue; + } else if (c == (char)'\\') { + nslash++; + continue; + } + b = appendBSBytes(b, nslash); + nslash = 0; + b.append(c); + } + return [ + "arg": appendBSBytes(b, nslash).toString(), + "rest": '' + ]; + } + + // commandLineToArgv splits a command line into individual argument + // strings, following the Windows conventions documented + // at http://daviddeley.com/autohotkey/parameters/parameters.htm#WINARGV + // Original implementation found at: https://github.com/golang/go/commit/39c8d2b7faed06b0e91a1ad7906231f53aab45d1 + def commandLineToArgv(String cmd) { + def args = new ArrayList(); + while (cmd.length() > 0) { + if (cmd.charAt(0) == (char)' ' || cmd.charAt(0) == (char)0x09) { + cmd = cmd.substring(1); + continue; + } + def next = readNextArg(cmd); + cmd = next.rest; + args.add(next.arg); + } + return args; + } + + ctx.process.args = commandLineToArgv(ctx.process.command_line); + ctx.process.args_count = ctx.process.args.length; + + - script: + description: Adds file information. + lang: painless + if: ctx?.winlog?.event_data?.ScriptName != null && ctx.winlog.event_data.ScriptName.length() > 1 + source: |- + def path = ctx.winlog.event_data.ScriptName; + def idx = path.lastIndexOf("\\"); + if (idx > -1) { + if (ctx?.file == null) { + ctx.file = new HashMap(); + } + ctx.file.name = path.substring(idx+1); + ctx.file.directory = path.substring(0, idx); + + def extIdx = path.lastIndexOf("."); + if (extIdx > -1) { + ctx.file.extension = path.substring(extIdx+1); + } + } + - rename: + field: winlog.event_data.ScriptName + target_field: file.path + ignore_failure: true + ignore_missing: true + if: ctx?.winlog?.event_data?.ScriptName != "" + + ## Cleanup. + + - remove: + field: + - _temp + - winlog.event_data.param1 + - winlog.event_data.param2 + - winlog.event_data.param3 + - winlog.event_data.SequenceNumber + - winlog.event_data.DetailTotal + - winlog.event_data.DetailSequence + - winlog.event_data.UserId + - winlog.time_created + - winlog.level + ignore_missing: true + ignore_failure: true + - script: + description: Remove all empty values from event_data. + lang: painless + source: ctx?.winlog?.event_data?.entrySet().removeIf(entry -> entry.getValue() == null || entry.getValue().equals("")); + - remove: + description: Remove empty event data. + field: winlog.event_data + ignore_missing: true + ignore_failure: true + if: ctx?.winlog?.event_data != null && ctx.winlog.event_data.size() == 0 + +on_failure: + - set: + field: "error.message" + value: "{{ _ingest.on_failure_message }}" diff --git a/x-pack/winlogbeat/module/powershell/ingest/powershell_operational.yml b/x-pack/winlogbeat/module/powershell/ingest/powershell_operational.yml new file mode 100644 index 00000000000..d508f0d7341 --- /dev/null +++ b/x-pack/winlogbeat/module/powershell/ingest/powershell_operational.yml @@ -0,0 +1,492 @@ +--- +description: Pipeline for Windows Powershell/Operational events +processors: + - kv: + description: Split Event 4103 event data fields. + field: winlog.event_data.ContextInfo + target_field: winlog.event_data + field_split: "\n" + trim_key: " \n\t" + trim_value: " \n\t" + value_split: "=" + if: ctx?.winlog?.event_id == "4103" + - script: + description: Remove spaces from all event_data keys. + lang: painless + if: ctx?.winlog?.event_data != null + source: |- + def newEventData = new HashMap(); + for (entry in ctx.winlog.event_data.entrySet()) { + def newKey = /\s/.matcher(entry.getKey().toString()).replaceAll(""); + newEventData.put(newKey, entry.getValue()); + } + ctx.winlog.event_data = newEventData; + + ## ECS and Event fields. + + - set: + field: ecs.version + value: '1.12.0' + - set: + field: log.level + copy_from: winlog.level + ignore_empty_value: true + ignore_failure: true + if: ctx?.winlog?.level != "" + - date: + field: winlog.time_created + formats: + - ISO8601 + ignore_failure: true + if: ctx?.winlog?.time_created != null + + - set: + field: event.ingested + value: '{{_ingest.timestamp}}' + - set: + field: event.kind + value: event + - set: + field: event.code + value: '{{winlog.event_id}}' + - set: + field: event.category + value: process + - set: + field: event.type + value: start + if: ctx?.event.code == "4105" + - set: + field: event.type + value: end + if: ctx?.event.code == "4106" + - set: + field: event.type + value: info + if: ctx?.event?.type == null + - convert: + field: winlog.event_data.SequenceNumber + target_field: event.sequence + type: long + ignore_failure: true + ignore_missing: true + - convert: + field: winlog.record_id + type: string + ignore_failure: true + ignore_missing: true + + ## Process fields. + + - rename: + field: winlog.event_data.HostID + target_field: process.entity_id + ignore_failure: true + ignore_missing: true + if: ctx?.winlog?.event_data?.HostID != "" + - rename: + field: winlog.event_data.HostApplication + target_field: process.command_line + ignore_failure: true + ignore_missing: true + if: ctx?.winlog?.event_data?.HostApplication != "" + - rename: + field: winlog.event_data.HostName + target_field: process.title + ignore_failure: true + ignore_missing: true + if: ctx?.winlog?.event_data?.HostName != "" + + ## User fields. + + - set: + field: user.id + copy_from: winlog.user.identifier + ignore_failure: true + ignore_empty_value: true + - split: + field: winlog.event_data.User + target_field: "_temp.user_parts" + separator: '\\' + if: ctx?.winlog?.event_data?.User != null + - set: + field: user.domain + value: "{{_temp.user_parts.0}}" + ignore_failure: true + ignore_empty_value: true + if: ctx?._temp?.user_parts != null && ctx._temp.user_parts.size() == 2 + - set: + field: user.name + value: "{{_temp.user_parts.1}}" + ignore_failure: true + ignore_empty_value: true + if: ctx?._temp?.user_parts != null && ctx._temp.user_parts.size() == 2 + - append: + field: related.user + value: "{{user.name}}" + ignore_failure: true + allow_duplicates: false + if: ctx?.user?.name != null + - split: + field: winlog.event_data.ConnectedUser + target_field: "_temp.connected_user_parts" + separator: '\\' + if: ctx?.winlog?.event_data?.ConnectedUser != null + - set: + field: source.user.domain + value: "{{_temp.connected_user_parts.0}}" + ignore_failure: true + ignore_empty_value: true + if: ctx?._temp?.connected_user_parts != null && ctx._temp.connected_user_parts.size() == 2 + - set: + field: source.user.name + value: "{{_temp.connected_user_parts.1}}" + ignore_failure: true + ignore_empty_value: true + if: ctx?._temp?.connected_user_parts != null && ctx._temp.connected_user_parts.size() == 2 + - append: + field: related.user + value: "{{source.user.name}}" + ignore_failure: true + allow_duplicates: false + if: ctx?.source?.user?.name != null + - rename: + field: user.domain + target_field: destination.user.domain + ignore_failure: true + ignore_missing: true + if: ctx?.source?.user != null + - rename: + field: user.name + target_field: destination.user.name + ignore_failure: true + ignore_missing: true + if: ctx?.source?.user != null + - set: + field: user.domain + copy_from: source.user.domain + ignore_failure: true + ignore_empty_value: true + if: ctx?.source?.user != null + - set: + field: user.name + copy_from: source.user.name + ignore_failure: true + ignore_empty_value: true + if: ctx?.source?.user != null + + ## PowerShell fields. + + - convert: + field: winlog.event_data.MessageNumber + target_field: powershell.sequence + type: long + ignore_failure: true + ignore_missing: true + - convert: + field: winlog.event_data.MessageTotal + target_field: powershell.total + type: long + ignore_failure: true + ignore_missing: true + - rename: + field: winlog.event_data.ShellID + target_field: powershell.id + ignore_failure: true + ignore_missing: true + if: ctx?.winlog?.event_data?.ShellID != "" + - rename: + field: winlog.event_data.EngineVersion + target_field: powershell.engine.version + ignore_missing: true + ignore_failure: true + if: ctx?.winlog?.event_data?.EngineVersion != "" + - rename: + field: winlog.event_data.PipelineID + target_field: powershell.pipeline_id + ignore_missing: true + ignore_failure: true + if: ctx?.winlog?.event_data?.PipelineID != "" + - rename: + field: winlog.event_data.RunspaceID + target_field: powershell.runspace_id + ignore_missing: true + ignore_failure: true + if: ctx?.winlog?.event_data?.RunspaceID != "" + - rename: + field: winlog.event_data.RunspaceId + target_field: powershell.runspace_id + ignore_missing: true + ignore_failure: true + if: ctx?.winlog?.event_data?.RunspaceId != "" + - rename: + field: winlog.event_data.HostVersion + target_field: powershell.process.executable_version + ignore_missing: true + ignore_failure: true + if: ctx?.winlog?.event_data?.HostVersion != "" + - rename: + field: winlog.event_data.CommandLine + target_field: powershell.command.value + ignore_failure: true + ignore_missing: true + if: ctx?.winlog?.event_data?.CommandLine != "" + - rename: + field: winlog.event_data.CommandPath + target_field: powershell.command.path + ignore_failure: true + ignore_missing: true + if: ctx?.winlog?.event_data?.CommandPath != "" + - rename: + field: winlog.event_data.CommandName + target_field: powershell.command.name + ignore_failure: true + ignore_missing: true + if: ctx?.winlog?.event_data?.CommandName != "" + - rename: + field: winlog.event_data.CommandType + target_field: powershell.command.type + ignore_failure: true + ignore_missing: true + if: ctx?.winlog?.event_data?.CommandType != "" + - rename: + field: winlog.event_data.ScriptBlockId + target_field: powershell.file.script_block_id + ignore_failure: true + ignore_missing: true + if: ctx?.winlog?.event_data?.ScriptBlockId != "" + - rename: + field: winlog.event_data.ScriptBlockText + target_field: powershell.file.script_block_text + ignore_failure: true + ignore_missing: true + if: ctx?.winlog?.event_data?.ScriptBlockText != "" + + - split: + description: Split Event 800 command invocation details. + field: winlog.event_data.Payload + separator: "\n" + ignore_failure: true + ignore_missing: true + if: ctx.event.code == "4103" + - script: + description: |- + Parses all command invocation detail raw lines, and converts them to an object, based on their type. + - for unexpectedly formatted ones: {value: "the raw line as it is"} + - for all: + * related_command: describes to what command it is related to + * value: the value for that detail line + * type: the type of the detail line, i.e.: CommandInvocation, ParameterBinding, NonTerminatingError + - additionally, ParameterBinding adds a `name` field with the parameter name being bound. + lang: painless + if: ctx.event.code == "4103" + params: + field: Payload + source: |- + def parseRawDetail(String raw) { + Pattern detailRegex = /^(.+)\((.+)\)\:\s*(.+)?$/; + Pattern parameterBindingRegex = /name\=(.+);\s*value\=(.+)$/; + + def matcher = detailRegex.matcher(raw); + if (!matcher.matches()) { + return ["value": raw]; + } + def matches = new ArrayList(); + for (def i = 0; i <= matcher.groupCount(); i++) { + matches.add(matcher.group(i)); + } + + if (matches.length != 4) { + return ["value": raw]; + } + + if (matches[1] != "ParameterBinding") { + return [ + "type": matches[1], + "related_command": matches[2], + "value": matches[3] + ]; + } + + matcher = parameterBindingRegex.matcher(matches[3]); + if (!matcher.matches()) { + return ["value": matches[4]]; + } + def nameValMatches = new ArrayList(); + for (def i = 0; i <= matcher.groupCount(); i++) { + nameValMatches.add(matcher.group(i)); + } + if (nameValMatches.length !== 3) { + return ["value": matches[3]]; + } + + return [ + "type": matches[1], + "related_command": matches[2], + "name": nameValMatches[1], + "value": nameValMatches[2] + ]; + } + + if (ctx?._temp == null) { + ctx._temp = new HashMap(); + } + + if (ctx._temp.details == null) { + ctx._temp.details = new ArrayList(); + } + + def values = ctx?.winlog?.event_data[params["field"]]; + if (values != null && values.length > 0) { + for (v in values) { + ctx._temp.details.add(parseRawDetail(v)); + } + } + - rename: + field: _temp.details + target_field: powershell.command.invocation_details + if: ctx?._temp?.details != null && ctx?._temp?.details.length > 0 + + - script: + description: Implements Windows-like SplitCommandLine + lang: painless + if: ctx?.process?.command_line != null && ctx.process.command_line != "" + source: |- + // appendBSBytes appends n '\\' bytes to b and returns the resulting slice. + def appendBSBytes(StringBuilder b, int n) { + for (; n > 0; n--) { + b.append('\\'); + } + return b; + } + + // readNextArg splits command line string cmd into next + // argument and command line remainder. + def readNextArg(String cmd) { + def b = new StringBuilder(); + boolean inquote; + int nslash; + for (; cmd.length() > 0; cmd = cmd.substring(1)) { + def c = cmd.charAt(0); + if (c == (char)' ' || c == (char)0x09) { + if (!inquote) { + return [ + "arg": appendBSBytes(b, nslash).toString(), + "rest": cmd.substring(1) + ]; + } + } else if (c == (char)'"') { + b = appendBSBytes(b, nslash/2); + if (nslash%2 == 0) { + // use "Prior to 2008" rule from + // http://daviddeley.com/autohotkey/parameters/parameters.htm + // section 5.2 to deal with double double quotes + if (inquote && cmd.length() > 1 && cmd.charAt(1) == (char)'"') { + b.append(c); + cmd = cmd.substring(1); + } + inquote = !inquote; + } else { + b.append(c); + } + nslash = 0; + continue; + } else if (c == (char)'\\') { + nslash++; + continue; + } + b = appendBSBytes(b, nslash); + nslash = 0; + b.append(c); + } + return [ + "arg": appendBSBytes(b, nslash).toString(), + "rest": '' + ]; + } + + // commandLineToArgv splits a command line into individual argument + // strings, following the Windows conventions documented + // at http://daviddeley.com/autohotkey/parameters/parameters.htm#WINARGV + // Original implementation found at: https://github.com/golang/go/commit/39c8d2b7faed06b0e91a1ad7906231f53aab45d1 + def commandLineToArgv(String cmd) { + def args = new ArrayList(); + while (cmd.length() > 0) { + if (cmd.charAt(0) == (char)' ' || cmd.charAt(0) == (char)0x09) { + cmd = cmd.substring(1); + continue; + } + def next = readNextArg(cmd); + cmd = next.rest; + args.add(next.arg); + } + return args; + } + + ctx.process.args = commandLineToArgv(ctx.process.command_line); + ctx.process.args_count = ctx.process.args.length; + + - rename: + field: winlog.event_data.Path + target_field: winlog.event_data.ScriptName + ignore_failure: true + ignore_missing: true + if: ctx?.winlog?.event_data?.Path != "" + - script: + description: Adds file information. + lang: painless + if: ctx?.winlog?.event_data?.ScriptName != null && ctx.winlog.event_data.ScriptName.length() > 1 + source: |- + def path = ctx.winlog.event_data.ScriptName; + def idx = path.lastIndexOf("\\"); + if (idx > -1) { + if (ctx?.file == null) { + ctx.file = new HashMap(); + } + ctx.file.name = path.substring(idx+1); + ctx.file.directory = path.substring(0, idx); + + def extIdx = path.lastIndexOf("."); + if (extIdx > -1) { + ctx.file.extension = path.substring(extIdx+1); + } + } + - rename: + field: winlog.event_data.ScriptName + target_field: file.path + ignore_failure: true + ignore_missing: true + if: ctx?.winlog?.event_data?.ScriptName != "" + + ## Cleanup. + + - remove: + field: + - _temp + - winlog.event_data.SequenceNumber + - winlog.event_data.User + - winlog.event_data.ConnectedUser + - winlog.event_data.ContextInfo + - winlog.event_data.Severity + - winlog.event_data.MessageTotal + - winlog.event_data.MessageNumber + - winlog.event_data.Payload + - winlog.time_created + - winlog.level + ignore_missing: true + ignore_failure: true + - script: + description: Remove all empty values from event_data. + lang: painless + source: ctx?.winlog?.event_data?.entrySet().removeIf(entry -> entry.getValue() == null || entry.getValue().equals("")); + - remove: + description: Remove empty event data. + field: winlog.event_data + ignore_missing: true + ignore_failure: true + if: ctx?.winlog?.event_data != null && ctx.winlog.event_data.size() == 0 + +on_failure: + - set: + field: "error.message" + value: "{{ _ingest.on_failure_message }}" diff --git a/x-pack/winlogbeat/module/powershell/test/powershell_windows_test.go b/x-pack/winlogbeat/module/powershell/test/powershell_windows_test.go deleted file mode 100644 index 46c4f463f40..00000000000 --- a/x-pack/winlogbeat/module/powershell/test/powershell_windows_test.go +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one -// or more contributor license agreements. Licensed under the Elastic License; -// you may not use this file except in compliance with the Elastic License. - -package test - -import ( - "testing" - - "github.com/elastic/beats/v7/x-pack/winlogbeat/module" - - // Register required processors. - _ "github.com/elastic/beats/v7/libbeat/cmd/instance" - _ "github.com/elastic/beats/v7/libbeat/processors/timestamp" -) - -// Ignore these fields because they can be different on different versions -// of windows. -var ignoreFields = []string{ - "message", -} - -func TestPowerShell(t *testing.T) { - module.TestPipeline(t, "testdata/*.evtx", "../config/winlogbeat-powershell.js", - module.WithFieldFilter(ignoreFields)) -} diff --git a/x-pack/winlogbeat/module/routing/ingest/routing.yml b/x-pack/winlogbeat/module/routing/ingest/routing.yml new file mode 100644 index 00000000000..52f8825f1ef --- /dev/null +++ b/x-pack/winlogbeat/module/routing/ingest/routing.yml @@ -0,0 +1,20 @@ +--- +description: Winlogbeat Routing Pipeline +processors: + - pipeline: + name: '{< IngestPipeline "security" >}' + if: ctx?.winlog?.channel == 'Security' && ['Microsoft-Windows-Eventlog', 'Microsoft-Windows-Security-Auditing'].contains(ctx?.winlog?.provider_name) + - pipeline: + name: '{< IngestPipeline "sysmon" >}' + if: ctx?.winlog?.channel == 'Microsoft-Windows-Sysmon/Operational' + - pipeline: + name: '{< IngestPipeline "powershell" >}' + if: ctx?.winlog?.channel == 'Windows Powershell' + - pipeline: + name: '{< IngestPipeline "powershell_operational" >}' + if: ctx?.winlog?.channel == 'Microsoft-Windows-PowerShell/Operational' +on_failure: + - set: + field: error.message + value: |- + Processor "{{ _ingest.on_failure_processor_type }}" with tag "{{ _ingest.on_failure_processor_tag }}" in pipeline "{{ _ingest.on_failure_pipeline }}" failed with message "{{ _ingest.on_failure_message }}" diff --git a/x-pack/winlogbeat/module/security/config/winlogbeat-security.js b/x-pack/winlogbeat/module/security/config/winlogbeat-security.js deleted file mode 100644 index 76ef1f0b21e..00000000000 --- a/x-pack/winlogbeat/module/security/config/winlogbeat-security.js +++ /dev/null @@ -1,2764 +0,0 @@ -// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one -// or more contributor license agreements. Licensed under the Elastic License; -// you may not use this file except in compliance with the Elastic License. - -var security = (function () { - var path = require("path"); - var processor = require("processor"); - var windows = require("windows"); - - // Logon Types - // https://docs.microsoft.com/en-us/windows/security/threat-protection/auditing/basic-audit-logon-events - var logonTypes = { - "2": "Interactive", - "3": "Network", - "4": "Batch", - "5": "Service", - "7": "Unlock", - "8": "NetworkCleartext", - "9": "NewCredentials", - "10": "RemoteInteractive", - "11": "CachedInteractive", - }; - - // User Account Control Attributes Table - // https://support.microsoft.com/es-us/help/305144/how-to-use-useraccountcontrol-to-manipulate-user-account-properties - var uacFlags = [ - [0x0001, 'SCRIPT'], - [0x0002, 'ACCOUNTDISABLE'], - [0x0008, 'HOMEDIR_REQUIRED'], - [0x0010, 'LOCKOUT'], - [0x0020, 'PASSWD_NOTREQD'], - [0x0040, 'PASSWD_CANT_CHANGE'], - [0x0080, 'ENCRYPTED_TEXT_PWD_ALLOWED'], - [0x0100, 'TEMP_DUPLICATE_ACCOUNT'], - [0x0200, 'NORMAL_ACCOUNT'], - [0x0800, 'INTERDOMAIN_TRUST_ACCOUNT'], - [0x1000, 'WORKSTATION_TRUST_ACCOUNT'], - [0x2000, 'SERVER_TRUST_ACCOUNT'], - [0x10000, 'DONT_EXPIRE_PASSWORD'], - [0x20000, 'MNS_LOGON_ACCOUNT'], - [0x40000, 'SMARTCARD_REQUIRED'], - [0x80000, 'TRUSTED_FOR_DELEGATION'], - [0x100000, 'NOT_DELEGATED'], - [0x200000, 'USE_DES_KEY_ONLY'], - [0x400000, 'DONT_REQ_PREAUTH'], - [0x800000, 'PASSWORD_EXPIRED'], - [0x1000000, 'TRUSTED_TO_AUTH_FOR_DELEGATION'], - [0x04000000, 'PARTIAL_SECRETS_ACCOUNT'], - ]; - - // Kerberos TGT and TGS Ticket Options - // https://docs.microsoft.com/en-us/windows/security/threat-protection/auditing/event-4768 - // https://docs.microsoft.com/en-us/windows/security/threat-protection/auditing/event-4769 - var ticketOptions = [ - "Reserved", - "Forwardable", - "Forwarded", - "Proxiable", - "Proxy", - "Allow-postdate", - "Postdated", - "Invalid", - "Renewable", - "Initial", - "Pre-authent", - "Opt-hardware-auth", - "Transited-policy-checked", - "Ok-as-delegate", - "Request-anonymous", - "Name-canonicalize", - "Unused", - "Unused", - "Unused", - "Unused", - "Unused", - "Unused", - "Unused", - "Unused", - "Unused", - "Unused", - "Disable-transited-check", - "Renewable-ok", - "Enc-tkt-in-skey", - "Unused", - "Renew", - "Validate"]; - - // Kerberos Encryption Types - // https://docs.microsoft.com/en-us/windows/security/threat-protection/auditing/event-4768 - // https://docs.microsoft.com/en-us/windows/security/threat-protection/auditing/event-4768 - var ticketEncryptionTypes = { - "0x1": "DES-CBC-CRC", - "0x3": "DES-CBC-MD5", - "0x11": "AES128-CTS-HMAC-SHA1-96", - "0x12": "AES256-CTS-HMAC-SHA1-96", - "0x17": "RC4-HMAC", - "0x18": "RC4-HMAC-EXP", - "0xffffffff": "FAIL", - }; - - // Kerberos Result Status Codes - // https://docs.microsoft.com/en-us/windows/security/threat-protection/auditing/event-4768 - // https://docs.microsoft.com/en-us/windows/security/threat-protection/auditing/event-4768 - var kerberosTktStatusCodes = { - "0x0": "KDC_ERR_NONE", - "0x1": "KDC_ERR_NAME_EXP", - "0x2": "KDC_ERR_SERVICE_EXP", - "0x3": "KDC_ERR_BAD_PVNO", - "0x4": "KDC_ERR_C_OLD_MAST_KVNO", - "0x5": "KDC_ERR_S_OLD_MAST_KVNO", - "0x6": "KDC_ERR_C_PRINCIPAL_UNKNOWN", - "0x7": "KDC_ERR_S_PRINCIPAL_UNKNOWN", - "0x8": "KDC_ERR_PRINCIPAL_NOT_UNIQUE", - "0x9": "KDC_ERR_NULL_KEY", - "0xA": "KDC_ERR_CANNOT_POSTDATE", - "0xB": "KDC_ERR_NEVER_VALID", - "0xC": "KDC_ERR_POLICY", - "0xD": "KDC_ERR_BADOPTION", - "0xE": "KDC_ERR_ETYPE_NOTSUPP", - "0xF": "KDC_ERR_SUMTYPE_NOSUPP", - "0x10": "KDC_ERR_PADATA_TYPE_NOSUPP", - "0x11": "KDC_ERR_TRTYPE_NO_SUPP", - "0x12": "KDC_ERR_CLIENT_REVOKED", - "0x13": "KDC_ERR_SERVICE_REVOKED", - "0x14": "KDC_ERR_TGT_REVOKED", - "0x15": "KDC_ERR_CLIENT_NOTYET", - "0x16": "KDC_ERR_SERVICE_NOTYET", - "0x17": "KDC_ERR_KEY_EXPIRED", - "0x18": "KDC_ERR_PREAUTH_FAILED", - "0x19": "KDC_ERR_PREAUTH_REQUIRED", - "0x1A": "KDC_ERR_SERVER_NOMATCH", - "0x1B": "KDC_ERR_MUST_USE_USER2USER", - "0x1F": "KRB_AP_ERR_BAD_INTEGRITY", - "0x20": "KRB_AP_ERR_TKT_EXPIRED", - "0x21": "KRB_AP_ERR_TKT_NYV", - "0x22": "KRB_AP_ERR_REPEAT", - "0x23": "KRB_AP_ERR_NOT_US", - "0x24": "KRB_AP_ERR_BADMATCH", - "0x25": "KRB_AP_ERR_SKEW", - "0x26": "KRB_AP_ERR_BADADDR", - "0x27": "KRB_AP_ERR_BADVERSION", - "0x28": "KRB_AP_ERR_MSG_TYPE", - "0x29": "KRB_AP_ERR_MODIFIED", - "0x2A": "KRB_AP_ERR_BADORDER", - "0x2C": "KRB_AP_ERR_BADKEYVER", - "0x2D": "KRB_AP_ERR_NOKEY", - "0x2E": "KRB_AP_ERR_MUT_FAIL", - "0x2F": "KRB_AP_ERR_BADDIRECTION", - "0x30": "KRB_AP_ERR_METHOD", - "0x31": "KRB_AP_ERR_BADSEQ", - "0x32": "KRB_AP_ERR_INAPP_CKSUM", - "0x33": "KRB_AP_PATH_NOT_ACCEPTED", - "0x34": "KRB_ERR_RESPONSE_TOO_BIG", - "0x3C": "KRB_ERR_GENERIC", - "0x3D": "KRB_ERR_FIELD_TOOLONG", - "0x3E": "KDC_ERR_CLIENT_NOT_TRUSTED", - "0x3F": "KDC_ERR_KDC_NOT_TRUSTED", - "0x40": "KDC_ERR_INVALID_SIG", - "0x41": "KDC_ERR_KEY_TOO_WEAK", - "0x42": "KRB_AP_ERR_USER_TO_USER_REQUIRED", - "0x43": "KRB_AP_ERR_NO_TGT", - "0x44": "KDC_ERR_WRONG_REALM", - }; - - // event.category, event.type, event.action - var eventActionTypes = { - "1100": [["process"], ["end"], "logging-service-shutdown"], - "1102": [["iam"], ["admin", "change"], "audit-log-cleared"], // need to recategorize - "1104": [["iam"], ["admin"],"logging-full"], - "1105": [["iam"], ["admin"],"auditlog-archieved"], - "1108": [["iam"], ["admin"],"logging-processing-error"], - "4610": [["configuration"], ["access"], "authentication-package-loaded"], - "4611": [["configuration"], ["change"], "trusted-logon-process-registered"], - "4614": [["configuration"], ["access"], "notification-package-loaded"], - "4616": [["configuration"], ["change"], "system-time-changed"], - "4622": [["configuration"], ["access"], "security-package-loaded"], - "4624": [["authentication"], ["start"], "logged-in"], - "4625": [["authentication"], ["start"], "logon-failed"], - "4634": [["authentication"], ["end"], "logged-out"], - "4647": [["authentication"], ["end"], "logged-out"], - "4648": [["authentication"], ["start"], "logged-in-explicit"], - "4657": [["registry", "configuration"], ["change"], "registry-value-modified"], - "4670": [["iam", "configuration"],["admin", "change"],"permissions-changed"], - "4672": [["iam"], ["admin"], "logged-in-special"], - "4673": [["iam"], ["admin"], "privileged-service-called"], - "4674": [["iam"], ["admin"], "privileged-operation"], - "4688": [["process"], ["start"], "created-process"], - "4689": [["process"], ["end"], "exited-process"], - "4697": [["iam", "configuration"], ["admin", "change"],"service-installed"], // remove iam and admin - "4698": [["iam", "configuration"], ["creation", "admin"], "scheduled-task-created"], // remove iam and admin - "4699": [["iam", "configuration"], ["deletion", "admin"], "scheduled-task-deleted"], // remove iam and admin - "4700": [["iam", "configuration"], ["change", "admin"], "scheduled-task-enabled"], // remove iam and admin - "4701": [["iam", "configuration"], ["change", "admin"], "scheduled-task-disabled"], // remove iam and admin - "4702": [["iam", "configuration"], ["change", "admin"], "scheduled-task-updated"], // remove iam and admin - "4706": [["configuration"], ["creation"], "domain-trust-added"], - "4707": [["configuration"], ["deletion"], "domain-trust-removed"], - "4713": [["configuration"], ["change"], "kerberos-policy-changed"], - "4714": [["configuration"], ["change"], "encrypted-data-recovery-policy-changed"], - "4715": [["configuration"], ["change"], "object-audit-policy-changed"], - "4716": [["configuration"], ["change"], "trusted-domain-information-changed"], - "4717": [["iam", "configuration"],["admin", "change"],"system-security-access-granted"], - "4718": [["iam", "configuration"],["admin", "deletion"],"system-security-access-removed"], - "4719": [["iam", "configuration"], ["admin", "change"], "changed-audit-config"], // remove iam and admin - "4720": [["iam"], ["user", "creation"], "added-user-account"], - "4722": [["iam"], ["user", "change"], "enabled-user-account"], - "4723": [["iam"], ["user", "change"], "changed-password"], - "4724": [["iam"], ["user", "change"], "reset-password"], - "4725": [["iam"], ["user", "deletion"], "disabled-user-account"], - "4726": [["iam"], ["user", "deletion"], "deleted-user-account"], - "4727": [["iam"], ["group", "creation"], "added-group-account"], - "4728": [["iam"], ["group", "change"], "added-member-to-group"], - "4729": [["iam"], ["group", "change"], "removed-member-from-group"], - "4730": [["iam"], ["group", "deletion"], "deleted-group-account"], - "4731": [["iam"], ["group", "creation"], "added-group-account"], - "4732": [["iam"], ["group", "change"], "added-member-to-group"], - "4733": [["iam"], ["group", "change"], "removed-member-from-group"], - "4734": [["iam"], ["group", "deletion"], "deleted-group-account"], - "4735": [["iam"], ["group", "change"], "modified-group-account"], - "4737": [["iam"], ["group", "change"], "modified-group-account"], - "4738": [["iam"], ["user", "change"], "modified-user-account"], - "4739": [["configuration"], ["change"], "domain-policy-changed"], - "4740": [["iam"], ["user", "change"], "locked-out-user-account"], - "4741": [["iam"], ["creation", "admin"], "added-computer-account"], // remove admin - "4742": [["iam"], ["change", "admin"], "changed-computer-account"], // remove admin - "4743": [["iam"], ["deletion", "admin"], "deleted-computer-account"], // remove admin - "4744": [["iam"], ["group", "creation"], "added-distribution-group-account"], - "4745": [["iam"], ["group", "change"], "changed-distribution-group-account"], - "4746": [["iam"], ["group", "change"], "added-member-to-distribution-group"], - "4747": [["iam"], ["group", "change"], "removed-member-from-distribution-group"], - "4748": [["iam"], ["group", "deletion"], "deleted-distribution-group-account"], - "4749": [["iam"], ["group", "creation"], "added-distribution-group-account"], - "4750": [["iam"], ["group", "change"], "changed-distribution-group-account"], - "4751": [["iam"], ["group", "change"], "added-member-to-distribution-group"], - "4752": [["iam"], ["group", "change"], "removed-member-from-distribution-group"], - "4753": [["iam"], ["group", "deletion"], "deleted-distribution-group-account"], - "4754": [["iam"], ["group", "creation"], "added-group-account"], - "4755": [["iam"], ["group", "change"], "modified-group-account"], - "4756": [["iam"], ["group", "change"], "added-member-to-group"], - "4757": [["iam"], ["group", "change"], "removed-member-from-group"], - "4758": [["iam"], ["group", "deletion"], "deleted-group-account"], - "4759": [["iam"], ["group", "creation"], "added-distribution-group-account"], - "4760": [["iam"], ["group", "change"], "changed-distribution-group-account"], - "4761": [["iam"], ["group", "change"], "added-member-to-distribution-group"], - "4762": [["iam"], ["group", "change"], "removed-member-from-distribution-group"], - "4763": [["iam"], ["group", "deletion"], "deleted-distribution-group-account"], - "4764": [["iam"], ["group", "change"], "type-changed-group-account"], - "4767": [["iam"], ["user", "change"], "unlocked-user-account"], - "4768": [["authentication"], ["start"], "kerberos-authentication-ticket-requested"], - "4769": [["authentication"], ["start"], "kerberos-service-ticket-requested"], - "4770": [["authentication"], ["start"], "kerberos-service-ticket-renewed"], - "4771": [["authentication"], ["start"], "kerberos-preauth-failed"], - "4776": [["authentication"], ["start"], "credential-validated"], - "4778": [["authentication", "session"], ["start"], "session-reconnected"], - "4779": [["authentication", "session"], ["end"], "session-disconnected"], - "4781": [["iam"], ["user", "change"], "renamed-user-account"], - "4798": [["iam"], ["user", "info"], "group-membership-enumerated"], // process enumerates the local groups to which the specified user belongs - "4799": [["iam"], ["group", "info"], "user-member-enumerated"], // a process enumerates the members of the specified local group - "4817": [["iam", "configuration"], ["admin", "change"],"object-audit-changed"], - "4902": [["iam", "configuration"], ["admin", "creation"],"user-audit-policy-created"], - "4904": [["iam", "configuration"], ["admin", "change"],"security-event-source-added"], - "4905": [["iam", "configuration"], ["admin", "deletion"], "security-event-source-removed"], - "4906": [["iam", "configuration"], ["admin", "change"], "crash-on-audit-changed"], - "4907": [["iam", "configuration"], ["admin", "change"], "audit-setting-changed"], - "4908": [["iam", "configuration"], ["admin", "change"], "special-group-table-changed"], - "4912": [["iam", "configuration"], ["admin", "change"], "per-user-audit-policy-changed"], - "4950": [["configuration"], ["change"], "windows-firewall-setting-changed"], - "4954": [["configuration"], ["change"], "windows-firewall-group-policy-changed"], - "4964": [["iam"], ["admin", "group"], "logged-in-special"], - "5024": [["process"], ["start"], "windows-firewall-service-started"], - "5025": [["process"], ["end"], "windows-firewall-service-stopped"], - "5033": [["driver"], ["start"], "windows-firewall-driver-started"], - "5034": [["driver"], ["end"], "windows-firewall-driver-stopped"], - "5037": [["driver"], ["end"], "windows-firewall-driver-error"], - }; - - // Services Types - // https://docs.microsoft.com/en-us/windows/security/threat-protection/auditing/event-4697 - var serviceTypes = { - "0x1": "Kernel Driver", - "0x2": "File System Driver", - "0x8": "Recognizer Driver", - "0x10": "Win32 Own Process", - "0x20": "Win32 Share Process", - "0x110": "Interactive Own Process", - "0x120": "Interactive Share Process", - }; - - - // Audit Categories Description - // https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-gpac/77878370-0712-47cd-997d-b07053429f6d - var auditDescription = { - "0CCE9210-69AE-11D9-BED3-505054503030":["Security State Change", "System"], - "0CCE9211-69AE-11D9-BED3-505054503030":["Security System Extension", "System"], - "0CCE9212-69AE-11D9-BED3-505054503030":["System Integrity", "System"], - "0CCE9213-69AE-11D9-BED3-505054503030":["IPsec Driver", "System"], - "0CCE9214-69AE-11D9-BED3-505054503030":["Other System Events", "System"], - "0CCE9215-69AE-11D9-BED3-505054503030":["Logon", "Logon/Logoff"], - "0CCE9216-69AE-11D9-BED3-505054503030":["Logoff","Logon/Logoff"], - "0CCE9217-69AE-11D9-BED3-505054503030":["Account Lockout","Logon/Logoff"], - "0CCE9218-69AE-11D9-BED3-505054503030":["IPsec Main Mode","Logon/Logoff"], - "0CCE9219-69AE-11D9-BED3-505054503030":["IPsec Quick Mode","Logon/Logoff"], - "0CCE921A-69AE-11D9-BED3-505054503030":["IPsec Extended Mode","Logon/Logoff"], - "0CCE921B-69AE-11D9-BED3-505054503030":["Special Logon","Logon/Logoff"], - "0CCE921C-69AE-11D9-BED3-505054503030":["Other Logon/Logoff Events","Logon/Logoff"], - "0CCE9243-69AE-11D9-BED3-505054503030":["Network Policy Server","Logon/Logoff"], - "0CCE9247-69AE-11D9-BED3-505054503030":["User / Device Claims","Logon/Logoff"], - "0CCE921D-69AE-11D9-BED3-505054503030":["File System","Object Access"], - "0CCE921E-69AE-11D9-BED3-505054503030":["Registry","Object Access"], - "0CCE921F-69AE-11D9-BED3-505054503030":["Kernel Object","Object Access"], - "0CCE9220-69AE-11D9-BED3-505054503030":["SAM","Object Access"], - "0CCE9221-69AE-11D9-BED3-505054503030":["Certification Services","Object Access"], - "0CCE9222-69AE-11D9-BED3-505054503030":["Application Generated","Object Access"], - "0CCE9223-69AE-11D9-BED3-505054503030":["Handle Manipulation","Object Access"], - "0CCE9224-69AE-11D9-BED3-505054503030":["File Share","Object Access"], - "0CCE9225-69AE-11D9-BED3-505054503030":["Filtering Platform Packet Drop","Object Access"], - "0CCE9226-69AE-11D9-BED3-505054503030":["Filtering Platform Connection ","Object Access"], - "0CCE9227-69AE-11D9-BED3-505054503030":["Other Object Access Events","Object Access"], - "0CCE9244-69AE-11D9-BED3-505054503030":["Detailed File Share","Object Access"], - "0CCE9245-69AE-11D9-BED3-505054503030":["Removable Storage","Object Access"], - "0CCE9246-69AE-11D9-BED3-505054503030":["Central Policy Staging","Object Access"], - "0CCE9228-69AE-11D9-BED3-505054503030":["Sensitive Privilege Use","Privilege Use"], - "0CCE9229-69AE-11D9-BED3-505054503030":["Non Sensitive Privilege Use","Privilege Use"], - "0CCE922A-69AE-11D9-BED3-505054503030":["Other Privilege Use Events","Privilege Use"], - "0CCE922B-69AE-11D9-BED3-505054503030":["Process Creation","Detailed Tracking"], - "0CCE922C-69AE-11D9-BED3-505054503030":["Process Termination","Detailed Tracking"], - "0CCE922D-69AE-11D9-BED3-505054503030":["DPAPI Activity","Detailed Tracking"], - "0CCE922E-69AE-11D9-BED3-505054503030":["RPC Events","Detailed Tracking"], - "0CCE9248-69AE-11D9-BED3-505054503030":["Plug and Play Events","Detailed Tracking"], - "0CCE922F-69AE-11D9-BED3-505054503030":["Audit Policy Change","Policy Change"], - "0CCE9230-69AE-11D9-BED3-505054503030":["Authentication Policy Change","Policy Change"], - "0CCE9231-69AE-11D9-BED3-505054503030":["Authorization Policy Change","Policy Change"], - "0CCE9232-69AE-11D9-BED3-505054503030":["MPSSVC Rule-Level Policy Change","Policy Change"], - "0CCE9233-69AE-11D9-BED3-505054503030":["Filtering Platform Policy Change","Policy Change"], - "0CCE9234-69AE-11D9-BED3-505054503030":["Other Policy Change Events","Policy Change"], - "0CCE9235-69AE-11D9-BED3-505054503030":["User Account Management","Account Management"], - "0CCE9236-69AE-11D9-BED3-505054503030":["Computer Account Management","Account Management"], - "0CCE9237-69AE-11D9-BED3-505054503030":["Security Group Management","Account Management"], - "0CCE9238-69AE-11D9-BED3-505054503030":["Distribution Group Management","Account Management"], - "0CCE9239-69AE-11D9-BED3-505054503030":["Application Group Management","Account Management"], - "0CCE923A-69AE-11D9-BED3-505054503030":["Other Account Management Events","Account Management"], - "0CCE923B-69AE-11D9-BED3-505054503030":["Directory Service Access","Account Management"], - "0CCE923C-69AE-11D9-BED3-505054503030":["Directory Service Changes","Account Management"], - "0CCE923D-69AE-11D9-BED3-505054503030":["Directory Service Replication","Account Management"], - "0CCE923E-69AE-11D9-BED3-505054503030":["Detailed Directory Service Replication","Account Management"], - "0CCE923F-69AE-11D9-BED3-505054503030":["Credential Validation","Account Logon"], - "0CCE9240-69AE-11D9-BED3-505054503030":["Kerberos Service Ticket Operations","Account Logon"], - "0CCE9241-69AE-11D9-BED3-505054503030":["Other Account Logon Events","Account Logon"], - "0CCE9242-69AE-11D9-BED3-505054503030":["Kerberos Authentication Service","Account Logon"], - }; - - - // Descriptions of failure status codes. - // https://docs.microsoft.com/en-us/windows/security/threat-protection/auditing/event-4625 - // https://docs.microsoft.com/en-us/windows/security/threat-protection/auditing/event-4776 - var logonFailureStatus = { - "0xc000005e": "There are currently no logon servers available to service the logon request.", - "0xc0000064": "User logon with misspelled or bad user account", - "0xc000006a": "User logon with misspelled or bad password", - "0xc000006d": "This is either due to a bad username or authentication information", - "0xc000006e": "Unknown user name or bad password.", - "0xc000006f": "User logon outside authorized hours", - "0xc0000070": "User logon from unauthorized workstation", - "0xc0000071": "User logon with expired password", - "0xc0000072": "User logon to account disabled by administrator", - "0xc00000dc": "Indicates the Sam Server was in the wrong state to perform the desired operation.", - "0xc0000133": "Clocks between DC and other computer too far out of sync", - "0xc000015b": "The user has not been granted the requested logon type (aka logon right) at this machine", - "0xc000018c": "The logon request failed because the trust relationship between the primary domain and the trusted domain failed.", - "0xc0000192": "An attempt was made to logon, but the Netlogon service was not started.", - "0xc0000193": "User logon with expired account", - "0xc0000224": "User is required to change password at next logon", - "0xc0000225": "Evidently a bug in Windows and not a risk", - "0xc0000234": "User logon with account locked", - "0xc00002ee": "Failure Reason: An Error occurred during Logon", - "0xc0000413": "Logon Failure: The machine you are logging onto is protected by an authentication firewall. The specified account is not allowed to authenticate to the machine.", - "0xc0000371": "The local account store does not contain secret material for the specified account", - "0x0": "Status OK.", - }; - - // Message table extracted from msobjs.dll on Windows 2019. - // https://gist.github.com/andrewkroh/665dca0682bd0e4daf194ab291694012 - var msobjsMessageTable = { - "279": "Undefined Access (no effect) Bit 7", - "1536": "Unused message ID", - "1537": "DELETE", - "1538": "READ_CONTROL", - "1539": "WRITE_DAC", - "1540": "WRITE_OWNER", - "1541": "SYNCHRONIZE", - "1542": "ACCESS_SYS_SEC", - "1543": "MAX_ALLOWED", - "1552": "Unknown specific access (bit 0)", - "1553": "Unknown specific access (bit 1)", - "1554": "Unknown specific access (bit 2)", - "1555": "Unknown specific access (bit 3)", - "1556": "Unknown specific access (bit 4)", - "1557": "Unknown specific access (bit 5)", - "1558": "Unknown specific access (bit 6)", - "1559": "Unknown specific access (bit 7)", - "1560": "Unknown specific access (bit 8)", - "1561": "Unknown specific access (bit 9)", - "1562": "Unknown specific access (bit 10)", - "1563": "Unknown specific access (bit 11)", - "1564": "Unknown specific access (bit 12)", - "1565": "Unknown specific access (bit 13)", - "1566": "Unknown specific access (bit 14)", - "1567": "Unknown specific access (bit 15)", - "1601": "Not used", - "1603": "Assign Primary Token Privilege", - "1604": "Lock Memory Privilege", - "1605": "Increase Memory Quota Privilege", - "1606": "Unsolicited Input Privilege", - "1607": "Trusted Computer Base Privilege", - "1608": "Security Privilege", - "1609": "Take Ownership Privilege", - "1610": "Load/Unload Driver Privilege", - "1611": "Profile System Privilege", - "1612": "Set System Time Privilege", - "1613": "Profile Single Process Privilege", - "1614": "Increment Base Priority Privilege", - "1615": "Create Pagefile Privilege", - "1616": "Create Permanent Object Privilege", - "1617": "Backup Privilege", - "1618": "Restore From Backup Privilege", - "1619": "Shutdown System Privilege", - "1620": "Debug Privilege", - "1621": "View or Change Audit Log Privilege", - "1622": "Change Hardware Environment Privilege", - "1623": "Change Notify (and Traverse) Privilege", - "1624": "Remotely Shut System Down Privilege", - "1792": "", - "1794": "", - "1795": "Enabled", - "1796": "Disabled", - "1797": "All", - "1798": "None", - "1799": "Audit Policy query/set API Operation", - "1800": "", - "1801": "Granted by", - "1802": "Denied by", - "1803": "Denied by Integrity Policy check", - "1804": "Granted by Ownership", - "1805": "Not granted", - "1806": "Granted by NULL DACL", - "1807": "Denied by Empty DACL", - "1808": "Granted by NULL Security Descriptor", - "1809": "Unknown or unchecked", - "1810": "Not granted due to missing", - "1811": "Granted by ACE on parent folder", - "1812": "Denied by ACE on parent folder", - "1813": "Granted by Central Access Rule", - "1814": "NOT Granted by Central Access Rule", - "1815": "Granted by parent folder's Central Access Rule", - "1816": "NOT Granted by parent folder's Central Access Rule", - "1817": "Unknown Type", - "1818": "String", - "1819": "Unsigned 64-bit Integer", - "1820": "64-bit Integer", - "1821": "FQBN", - "1822": "Blob", - "1823": "Sid", - "1824": "Boolean", - "1825": "TRUE", - "1826": "FALSE", - "1827": "Invalid", - "1828": "an ACE too long to display", - "1829": "a Security Descriptor too long to display", - "1830": "Not granted to AppContainers", - "1831": "...", - "1832": "Identification", - "1833": "Impersonation", - "1840": "Delegation", - "1841": "Denied by Process Trust Label ACE", - "1842": "Yes", - "1843": "No", - "1844": "System", - "1845": "Not Available", - "1846": "Default", - "1847": "DisallowMmConfig", - "1848": "Off", - "1849": "Auto", - "1872": "REG_NONE", - "1873": "REG_SZ", - "1874": "REG_EXPAND_SZ", - "1875": "REG_BINARY", - "1876": "REG_DWORD", - "1877": "REG_DWORD_BIG_ENDIAN", - "1878": "REG_LINK", - "1879": "REG_MULTI_SZ (New lines are replaced with *. A * is replaced with **)", - "1880": "REG_RESOURCE_LIST", - "1881": "REG_FULL_RESOURCE_DESCRIPTOR", - "1882": "REG_RESOURCE_REQUIREMENTS_LIST", - "1883": "REG_QWORD", - "1904": "New registry value created", - "1905": "Existing registry value modified", - "1906": "Registry value deleted", - "1920": "Sunday", - "1921": "Monday", - "1922": "Tuesday", - "1923": "Wednesday", - "1924": "Thursday", - "1925": "Friday", - "1926": "Saturday", - "1936": "TokenElevationTypeDefault (1)", - "1937": "TokenElevationTypeFull (2)", - "1938": "TokenElevationTypeLimited (3)", - "2048": "Account Enabled", - "2049": "Home Directory Required' - Disabled", - "2050": "Password Not Required' - Disabled", - "2051": "Temp Duplicate Account' - Disabled", - "2052": "Normal Account' - Disabled", - "2053": "MNS Logon Account' - Disabled", - "2054": "Interdomain Trust Account' - Disabled", - "2055": "Workstation Trust Account' - Disabled", - "2056": "Server Trust Account' - Disabled", - "2057": "Don't Expire Password' - Disabled", - "2058": "Account Unlocked", - "2059": "Encrypted Text Password Allowed' - Disabled", - "2060": "Smartcard Required' - Disabled", - "2061": "Trusted For Delegation' - Disabled", - "2062": "Not Delegated' - Disabled", - "2063": "Use DES Key Only' - Disabled", - "2064": "Don't Require Preauth' - Disabled", - "2065": "Password Expired' - Disabled", - "2066": "Trusted To Authenticate For Delegation' - Disabled", - "2067": "Exclude Authorization Information' - Disabled", - "2068": "Undefined UserAccountControl Bit 20' - Disabled", - "2069": "Protect Kerberos Service Tickets with AES Keys' - Disabled", - "2070": "Undefined UserAccountControl Bit 22' - Disabled", - "2071": "Undefined UserAccountControl Bit 23' - Disabled", - "2072": "Undefined UserAccountControl Bit 24' - Disabled", - "2073": "Undefined UserAccountControl Bit 25' - Disabled", - "2074": "Undefined UserAccountControl Bit 26' - Disabled", - "2075": "Undefined UserAccountControl Bit 27' - Disabled", - "2076": "Undefined UserAccountControl Bit 28' - Disabled", - "2077": "Undefined UserAccountControl Bit 29' - Disabled", - "2078": "Undefined UserAccountControl Bit 30' - Disabled", - "2079": "Undefined UserAccountControl Bit 31' - Disabled", - "2080": "Account Disabled", - "2081": "Home Directory Required' - Enabled", - "2082": "Password Not Required' - Enabled", - "2083": "Temp Duplicate Account' - Enabled", - "2084": "Normal Account' - Enabled", - "2085": "MNS Logon Account' - Enabled", - "2086": "Interdomain Trust Account' - Enabled", - "2087": "Workstation Trust Account' - Enabled", - "2088": "Server Trust Account' - Enabled", - "2089": "Don't Expire Password' - Enabled", - "2090": "Account Locked", - "2091": "Encrypted Text Password Allowed' - Enabled", - "2092": "Smartcard Required' - Enabled", - "2093": "Trusted For Delegation' - Enabled", - "2094": "Not Delegated' - Enabled", - "2095": "Use DES Key Only' - Enabled", - "2096": "Don't Require Preauth' - Enabled", - "2097": "Password Expired' - Enabled", - "2098": "Trusted To Authenticate For Delegation' - Enabled", - "2099": "Exclude Authorization Information' - Enabled", - "2100": "Undefined UserAccountControl Bit 20' - Enabled", - "2101": "Protect Kerberos Service Tickets with AES Keys' - Enabled", - "2102": "Undefined UserAccountControl Bit 22' - Enabled", - "2103": "Undefined UserAccountControl Bit 23' - Enabled", - "2104": "Undefined UserAccountControl Bit 24' - Enabled", - "2105": "Undefined UserAccountControl Bit 25' - Enabled", - "2106": "Undefined UserAccountControl Bit 26' - Enabled", - "2107": "Undefined UserAccountControl Bit 27' - Enabled", - "2108": "Undefined UserAccountControl Bit 28' - Enabled", - "2109": "Undefined UserAccountControl Bit 29' - Enabled", - "2110": "Undefined UserAccountControl Bit 30' - Enabled", - "2111": "Undefined UserAccountControl Bit 31' - Enabled", - "2304": "An Error occured during Logon.", - "2305": "The specified user account has expired.", - "2306": "The NetLogon component is not active.", - "2307": "Account locked out.", - "2308": "The user has not been granted the requested logon type at this machine.", - "2309": "The specified account's password has expired.", - "2310": "Account currently disabled.", - "2311": "Account logon time restriction violation.", - "2312": "User not allowed to logon at this computer.", - "2313": "Unknown user name or bad password.", - "2314": "Domain sid inconsistent.", - "2315": "Smartcard logon is required and was not used.", - "2432": "Not Available.", - "2436": "Random number generator failure.", - "2437": "Random number generation failed FIPS-140 pre-hash check.", - "2438": "Failed to zero secret data.", - "2439": "Key failed pair wise consistency check.", - "2448": "Failed to unprotect persistent cryptographic key.", - "2449": "Key export checks failed.", - "2450": "Validation of public key failed.", - "2451": "Signature verification failed.", - "2456": "Open key file.", - "2457": "Delete key file.", - "2458": "Read persisted key from file.", - "2459": "Write persisted key to file.", - "2464": "Export of persistent cryptographic key.", - "2465": "Import of persistent cryptographic key.", - "2480": "Open Key.", - "2481": "Create Key.", - "2482": "Delete Key.", - "2483": "Encrypt.", - "2484": "Decrypt.", - "2485": "Sign hash.", - "2486": "Secret agreement.", - "2487": "Domain settings", - "2488": "Local settings", - "2489": "Add provider.", - "2490": "Remove provider.", - "2491": "Add context.", - "2492": "Remove context.", - "2493": "Add function.", - "2494": "Remove function.", - "2495": "Add function provider.", - "2496": "Remove function provider.", - "2497": "Add function property.", - "2498": "Remove function property.", - "2499": "Machine key.", - "2500": "User key.", - "2501": "Key Derivation.", - "4352": "Device Access Bit 0", - "4353": "Device Access Bit 1", - "4354": "Device Access Bit 2", - "4355": "Device Access Bit 3", - "4356": "Device Access Bit 4", - "4357": "Device Access Bit 5", - "4358": "Device Access Bit 6", - "4359": "Device Access Bit 7", - "4360": "Device Access Bit 8", - "4361": "Undefined Access (no effect) Bit 9", - "4362": "Undefined Access (no effect) Bit 10", - "4363": "Undefined Access (no effect) Bit 11", - "4364": "Undefined Access (no effect) Bit 12", - "4365": "Undefined Access (no effect) Bit 13", - "4366": "Undefined Access (no effect) Bit 14", - "4367": "Undefined Access (no effect) Bit 15", - "4368": "Query directory", - "4369": "Traverse", - "4370": "Create object in directory", - "4371": "Create sub-directory", - "4372": "Undefined Access (no effect) Bit 4", - "4373": "Undefined Access (no effect) Bit 5", - "4374": "Undefined Access (no effect) Bit 6", - "4375": "Undefined Access (no effect) Bit 7", - "4376": "Undefined Access (no effect) Bit 8", - "4377": "Undefined Access (no effect) Bit 9", - "4378": "Undefined Access (no effect) Bit 10", - "4379": "Undefined Access (no effect) Bit 11", - "4380": "Undefined Access (no effect) Bit 12", - "4381": "Undefined Access (no effect) Bit 13", - "4382": "Undefined Access (no effect) Bit 14", - "4383": "Undefined Access (no effect) Bit 15", - "4384": "Query event state", - "4385": "Modify event state", - "4386": "Undefined Access (no effect) Bit 2", - "4387": "Undefined Access (no effect) Bit 3", - "4388": "Undefined Access (no effect) Bit 4", - "4389": "Undefined Access (no effect) Bit 5", - "4390": "Undefined Access (no effect) Bit 6", - "4391": "Undefined Access (no effect) Bit 7", - "4392": "Undefined Access (no effect) Bit 8", - "4393": "Undefined Access (no effect) Bit 9", - "4394": "Undefined Access (no effect) Bit 10", - "4395": "Undefined Access (no effect) Bit 11", - "4396": "Undefined Access (no effect) Bit 12", - "4397": "Undefined Access (no effect) Bit 13", - "4398": "Undefined Access (no effect) Bit 14", - "4399": "Undefined Access (no effect) Bit 15", - "4416": "ReadData (or ListDirectory)", - "4417": "WriteData (or AddFile)", - "4418": "AppendData (or AddSubdirectory or CreatePipeInstance)", - "4419": "ReadEA", - "4420": "WriteEA", - "4421": "Execute/Traverse", - "4422": "DeleteChild", - "4423": "ReadAttributes", - "4424": "WriteAttributes", - "4425": "Undefined Access (no effect) Bit 9", - "4426": "Undefined Access (no effect) Bit 10", - "4427": "Undefined Access (no effect) Bit 11", - "4428": "Undefined Access (no effect) Bit 12", - "4429": "Undefined Access (no effect) Bit 13", - "4430": "Undefined Access (no effect) Bit 14", - "4431": "Undefined Access (no effect) Bit 15", - "4432": "Query key value", - "4433": "Set key value", - "4434": "Create sub-key", - "4435": "Enumerate sub-keys", - "4436": "Notify about changes to keys", - "4437": "Create Link", - "4438": "Undefined Access (no effect) Bit 6", - "4439": "Undefined Access (no effect) Bit 7", - "4440": "Enable 64(or 32) bit application to open 64 bit key", - "4441": "Enable 64(or 32) bit application to open 32 bit key", - "4442": "Undefined Access (no effect) Bit 10", - "4443": "Undefined Access (no effect) Bit 11", - "4444": "Undefined Access (no effect) Bit 12", - "4445": "Undefined Access (no effect) Bit 13", - "4446": "Undefined Access (no effect) Bit 14", - "4447": "Undefined Access (no effect) Bit 15", - "4448": "Query mutant state", - "4449": "Undefined Access (no effect) Bit 1", - "4450": "Undefined Access (no effect) Bit 2", - "4451": "Undefined Access (no effect) Bit 3", - "4452": "Undefined Access (no effect) Bit 4", - "4453": "Undefined Access (no effect) Bit 5", - "4454": "Undefined Access (no effect) Bit 6", - "4455": "Undefined Access (no effect) Bit 7", - "4456": "Undefined Access (no effect) Bit 8", - "4457": "Undefined Access (no effect) Bit 9", - "4458": "Undefined Access (no effect) Bit 10", - "4459": "Undefined Access (no effect) Bit 11", - "4460": "Undefined Access (no effect) Bit 12", - "4461": "Undefined Access (no effect) Bit 13", - "4462": "Undefined Access (no effect) Bit 14", - "4463": "Undefined Access (no effect) Bit 15", - "4464": "Communicate using port", - "4465": "Undefined Access (no effect) Bit 1", - "4466": "Undefined Access (no effect) Bit 2", - "4467": "Undefined Access (no effect) Bit 3", - "4468": "Undefined Access (no effect) Bit 4", - "4469": "Undefined Access (no effect) Bit 5", - "4470": "Undefined Access (no effect) Bit 6", - "4471": "Undefined Access (no effect) Bit 7", - "4472": "Undefined Access (no effect) Bit 8", - "4473": "Undefined Access (no effect) Bit 9", - "4474": "Undefined Access (no effect) Bit 10", - "4475": "Undefined Access (no effect) Bit 11", - "4476": "Undefined Access (no effect) Bit 12", - "4477": "Undefined Access (no effect) Bit 13", - "4478": "Undefined Access (no effect) Bit 14", - "4479": "Undefined Access (no effect) Bit 15", - "4480": "Force process termination", - "4481": "Create new thread in process", - "4482": "Set process session ID", - "4483": "Perform virtual memory operation", - "4484": "Read from process memory", - "4485": "Write to process memory", - "4486": "Duplicate handle into or out of process", - "4487": "Create a subprocess of process", - "4488": "Set process quotas", - "4489": "Set process information", - "4490": "Query process information", - "4491": "Set process termination port", - "4492": "Undefined Access (no effect) Bit 12", - "4493": "Undefined Access (no effect) Bit 13", - "4494": "Undefined Access (no effect) Bit 14", - "4495": "Undefined Access (no effect) Bit 15", - "4496": "Control profile", - "4497": "Undefined Access (no effect) Bit 1", - "4498": "Undefined Access (no effect) Bit 2", - "4499": "Undefined Access (no effect) Bit 3", - "4500": "Undefined Access (no effect) Bit 4", - "4501": "Undefined Access (no effect) Bit 5", - "4502": "Undefined Access (no effect) Bit 6", - "4503": "Undefined Access (no effect) Bit 7", - "4504": "Undefined Access (no effect) Bit 8", - "4505": "Undefined Access (no effect) Bit 9", - "4506": "Undefined Access (no effect) Bit 10", - "4507": "Undefined Access (no effect) Bit 11", - "4508": "Undefined Access (no effect) Bit 12", - "4509": "Undefined Access (no effect) Bit 13", - "4510": "Undefined Access (no effect) Bit 14", - "4511": "Undefined Access (no effect) Bit 15", - "4512": "Query section state", - "4513": "Map section for write", - "4514": "Map section for read", - "4515": "Map section for execute", - "4516": "Extend size", - "4517": "Undefined Access (no effect) Bit 5", - "4518": "Undefined Access (no effect) Bit 6", - "4519": "Undefined Access (no effect) Bit 7", - "4520": "Undefined Access (no effect) Bit 8", - "4521": "Undefined Access (no effect) Bit 9", - "4522": "Undefined Access (no effect) Bit 10", - "4523": "Undefined Access (no effect) Bit 11", - "4524": "Undefined Access (no effect) Bit 12", - "4525": "Undefined Access (no effect) Bit 13", - "4526": "Undefined Access (no effect) Bit 14", - "4527": "Undefined Access (no effect) Bit 15", - "4528": "Query semaphore state", - "4529": "Modify semaphore state", - "4530": "Undefined Access (no effect) Bit 2", - "4531": "Undefined Access (no effect) Bit 3", - "4532": "Undefined Access (no effect) Bit 4", - "4533": "Undefined Access (no effect) Bit 5", - "4534": "Undefined Access (no effect) Bit 6", - "4535": "Undefined Access (no effect) Bit 7", - "4536": "Undefined Access (no effect) Bit 8", - "4537": "Undefined Access (no effect) Bit 9", - "4538": "Undefined Access (no effect) Bit 10", - "4539": "Undefined Access (no effect) Bit 11", - "4540": "Undefined Access (no effect) Bit 12", - "4541": "Undefined Access (no effect) Bit 13", - "4542": "Undefined Access (no effect) Bit 14", - "4543": "Undefined Access (no effect) Bit 15", - "4544": "Use symbolic link", - "4545": "Undefined Access (no effect) Bit 1", - "4546": "Undefined Access (no effect) Bit 2", - "4547": "Undefined Access (no effect) Bit 3", - "4548": "Undefined Access (no effect) Bit 4", - "4549": "Undefined Access (no effect) Bit 5", - "4550": "Undefined Access (no effect) Bit 6", - "4551": "Undefined Access (no effect) Bit 7", - "4552": "Undefined Access (no effect) Bit 8", - "4553": "Undefined Access (no effect) Bit 9", - "4554": "Undefined Access (no effect) Bit 10", - "4555": "Undefined Access (no effect) Bit 11", - "4556": "Undefined Access (no effect) Bit 12", - "4557": "Undefined Access (no effect) Bit 13", - "4558": "Undefined Access (no effect) Bit 14", - "4559": "Undefined Access (no effect) Bit 15", - "4560": "Force thread termination", - "4561": "Suspend or resume thread", - "4562": "Send an alert to thread", - "4563": "Get thread context", - "4564": "Set thread context", - "4565": "Set thread information", - "4566": "Query thread information", - "4567": "Assign a token to the thread", - "4568": "Cause thread to directly impersonate another thread", - "4569": "Directly impersonate this thread", - "4570": "Undefined Access (no effect) Bit 10", - "4571": "Undefined Access (no effect) Bit 11", - "4572": "Undefined Access (no effect) Bit 12", - "4573": "Undefined Access (no effect) Bit 13", - "4574": "Undefined Access (no effect) Bit 14", - "4575": "Undefined Access (no effect) Bit 15", - "4576": "Query timer state", - "4577": "Modify timer state", - "4578": "Undefined Access (no effect) Bit 2", - "4579": "Undefined Access (no effect) Bit 3", - "4580": "Undefined Access (no effect) Bit 4", - "4581": "Undefined Access (no effect) Bit 5", - "4582": "Undefined Access (no effect) Bit 6", - "4584": "Undefined Access (no effect) Bit 8", - "4585": "Undefined Access (no effect) Bit 9", - "4586": "Undefined Access (no effect) Bit 10", - "4587": "Undefined Access (no effect) Bit 11", - "4588": "Undefined Access (no effect) Bit 12", - "4589": "Undefined Access (no effect) Bit 13", - "4590": "Undefined Access (no effect) Bit 14", - "4591": "Undefined Access (no effect) Bit 15", - "4592": "AssignAsPrimary", - "4593": "Duplicate", - "4594": "Impersonate", - "4595": "Query", - "4596": "QuerySource", - "4597": "AdjustPrivileges", - "4598": "AdjustGroups", - "4599": "AdjustDefaultDacl", - "4600": "AdjustSessionID", - "4601": "Undefined Access (no effect) Bit 9", - "4602": "Undefined Access (no effect) Bit 10", - "4603": "Undefined Access (no effect) Bit 11", - "4604": "Undefined Access (no effect) Bit 12", - "4605": "Undefined Access (no effect) Bit 13", - "4606": "Undefined Access (no effect) Bit 14", - "4607": "Undefined Access (no effect) Bit 15", - "4608": "Create instance of object type", - "4609": "Undefined Access (no effect) Bit 1", - "4610": "Undefined Access (no effect) Bit 2", - "4611": "Undefined Access (no effect) Bit 3", - "4612": "Undefined Access (no effect) Bit 4", - "4613": "Undefined Access (no effect) Bit 5", - "4614": "Undefined Access (no effect) Bit 6", - "4615": "Undefined Access (no effect) Bit 7", - "4616": "Undefined Access (no effect) Bit 8", - "4617": "Undefined Access (no effect) Bit 9", - "4618": "Undefined Access (no effect) Bit 10", - "4619": "Undefined Access (no effect) Bit 11", - "4620": "Undefined Access (no effect) Bit 12", - "4621": "Undefined Access (no effect) Bit 13", - "4622": "Undefined Access (no effect) Bit 14", - "4623": "Undefined Access (no effect) Bit 15", - "4864": "Query State", - "4865": "Modify State", - "5120": "Channel read message", - "5121": "Channel write message", - "5122": "Channel query information", - "5123": "Channel set information", - "5124": "Undefined Access (no effect) Bit 4", - "5125": "Undefined Access (no effect) Bit 5", - "5126": "Undefined Access (no effect) Bit 6", - "5127": "Undefined Access (no effect) Bit 7", - "5128": "Undefined Access (no effect) Bit 8", - "5129": "Undefined Access (no effect) Bit 9", - "5130": "Undefined Access (no effect) Bit 10", - "5131": "Undefined Access (no effect) Bit 11", - "5132": "Undefined Access (no effect) Bit 12", - "5133": "Undefined Access (no effect) Bit 13", - "5134": "Undefined Access (no effect) Bit 14", - "5135": "Undefined Access (no effect) Bit 15", - "5136": "Assign process", - "5137": "Set Attributes", - "5138": "Query Attributes", - "5139": "Terminate Job", - "5140": "Set Security Attributes", - "5141": "Undefined Access (no effect) Bit 5", - "5142": "Undefined Access (no effect) Bit 6", - "5143": "Undefined Access (no effect) Bit 7", - "5144": "Undefined Access (no effect) Bit 8", - "5145": "Undefined Access (no effect) Bit 9", - "5146": "Undefined Access (no effect) Bit 10", - "5147": "Undefined Access (no effect) Bit 11", - "5148": "Undefined Access (no effect) Bit 12", - "5149": "Undefined Access (no effect) Bit 13", - "5150": "Undefined Access (no effect) Bit 14", - "5151": "Undefined Access (no effect) Bit 15", - "5376": "ConnectToServer", - "5377": "ShutdownServer", - "5378": "InitializeServer", - "5379": "CreateDomain", - "5380": "EnumerateDomains", - "5381": "LookupDomain", - "5382": "Undefined Access (no effect) Bit 6", - "5383": "Undefined Access (no effect) Bit 7", - "5384": "Undefined Access (no effect) Bit 8", - "5385": "Undefined Access (no effect) Bit 9", - "5386": "Undefined Access (no effect) Bit 10", - "5387": "Undefined Access (no effect) Bit 11", - "5388": "Undefined Access (no effect) Bit 12", - "5389": "Undefined Access (no effect) Bit 13", - "5390": "Undefined Access (no effect) Bit 14", - "5391": "Undefined Access (no effect) Bit 15", - "5392": "ReadPasswordParameters", - "5393": "WritePasswordParameters", - "5394": "ReadOtherParameters", - "5395": "WriteOtherParameters", - "5396": "CreateUser", - "5397": "CreateGlobalGroup", - "5398": "CreateLocalGroup", - "5399": "GetLocalGroupMembership", - "5400": "ListAccounts", - "5401": "LookupIDs", - "5402": "AdministerServer", - "5403": "Undefined Access (no effect) Bit 11", - "5404": "Undefined Access (no effect) Bit 12", - "5405": "Undefined Access (no effect) Bit 13", - "5406": "Undefined Access (no effect) Bit 14", - "5407": "Undefined Access (no effect) Bit 15", - "5408": "ReadInformation", - "5409": "WriteAccount", - "5410": "AddMember", - "5411": "RemoveMember", - "5412": "ListMembers", - "5413": "Undefined Access (no effect) Bit 5", - "5414": "Undefined Access (no effect) Bit 6", - "5415": "Undefined Access (no effect) Bit 7", - "5416": "Undefined Access (no effect) Bit 8", - "5417": "Undefined Access (no effect) Bit 9", - "5418": "Undefined Access (no effect) Bit 10", - "5419": "Undefined Access (no effect) Bit 11", - "5420": "Undefined Access (no effect) Bit 12", - "5421": "Undefined Access (no effect) Bit 13", - "5422": "Undefined Access (no effect) Bit 14", - "5423": "Undefined Access (no effect) Bit 15", - "5424": "AddMember", - "5425": "RemoveMember", - "5426": "ListMembers", - "5427": "ReadInformation", - "5428": "WriteAccount", - "5429": "Undefined Access (no effect) Bit 5", - "5430": "Undefined Access (no effect) Bit 6", - "5431": "Undefined Access (no effect) Bit 7", - "5432": "Undefined Access (no effect) Bit 8", - "5433": "Undefined Access (no effect) Bit 9", - "5434": "Undefined Access (no effect) Bit 10", - "5435": "Undefined Access (no effect) Bit 11", - "5436": "Undefined Access (no effect) Bit 12", - "5437": "Undefined Access (no effect) Bit 13", - "5438": "Undefined Access (no effect) Bit 14", - "5439": "Undefined Access (no effect) Bit 15", - "5440": "ReadGeneralInformation", - "5441": "ReadPreferences", - "5442": "WritePreferences", - "5443": "ReadLogon", - "5444": "ReadAccount", - "5445": "WriteAccount", - "5446": "ChangePassword (with knowledge of old password)", - "5447": "SetPassword (without knowledge of old password)", - "5448": "ListGroups", - "5449": "ReadGroupMembership", - "5450": "ChangeGroupMembership", - "5451": "Undefined Access (no effect) Bit 11", - "5452": "Undefined Access (no effect) Bit 12", - "5453": "Undefined Access (no effect) Bit 13", - "5454": "Undefined Access (no effect) Bit 14", - "5455": "Undefined Access (no effect) Bit 15", - "5632": "View non-sensitive policy information", - "5633": "View system audit requirements", - "5634": "Get sensitive policy information", - "5635": "Modify domain trust relationships", - "5636": "Create special accounts (for assignment of user rights)", - "5637": "Create a secret object", - "5638": "Create a privilege", - "5639": "Set default quota limits", - "5640": "Change system audit requirements", - "5641": "Administer audit log attributes", - "5642": "Enable/Disable LSA", - "5643": "Lookup Names/SIDs", - "5648": "Change secret value", - "5649": "Query secret value", - "5650": "Undefined Access (no effect) Bit 2", - "5651": "Undefined Access (no effect) Bit 3", - "5652": "Undefined Access (no effect) Bit 4", - "5653": "Undefined Access (no effect) Bit 5", - "5654": "Undefined Access (no effect) Bit 6", - "5655": "Undefined Access (no effect) Bit 7", - "5656": "Undefined Access (no effect) Bit 8", - "5657": "Undefined Access (no effect) Bit 9", - "5658": "Undefined Access (no effect) Bit 10", - "5659": "Undefined Access (no effect) Bit 11", - "5660": "Undefined Access (no effect) Bit 12", - "5661": "Undefined Access (no effect) Bit 13", - "5662": "Undefined Access (no effect) Bit 14", - "5663": "Undefined Access (no effect) Bit 15", - "5664": "Query trusted domain name/SID", - "5665": "Retrieve the controllers in the trusted domain", - "5666": "Change the controllers in the trusted domain", - "5667": "Query the Posix ID offset assigned to the trusted domain", - "5668": "Change the Posix ID offset assigned to the trusted domain", - "5669": "Undefined Access (no effect) Bit 5", - "5670": "Undefined Access (no effect) Bit 6", - "5671": "Undefined Access (no effect) Bit 7", - "5672": "Undefined Access (no effect) Bit 8", - "5673": "Undefined Access (no effect) Bit 9", - "5674": "Undefined Access (no effect) Bit 10", - "5675": "Undefined Access (no effect) Bit 11", - "5676": "Undefined Access (no effect) Bit 12", - "5677": "Undefined Access (no effect) Bit 13", - "5678": "Undefined Access (no effect) Bit 14", - "5679": "Undefined Access (no effect) Bit 15", - "5680": "Query account information", - "5681": "Change privileges assigned to account", - "5682": "Change quotas assigned to account", - "5683": "Change logon capabilities assigned to account", - "5684": "Change the Posix ID offset assigned to the accounted domain", - "5685": "Undefined Access (no effect) Bit 5", - "5686": "Undefined Access (no effect) Bit 6", - "5687": "Undefined Access (no effect) Bit 7", - "5688": "Undefined Access (no effect) Bit 8", - "5689": "Undefined Access (no effect) Bit 9", - "5690": "Undefined Access (no effect) Bit 10", - "5691": "Undefined Access (no effect) Bit 11", - "5692": "Undefined Access (no effect) Bit 12", - "5693": "Undefined Access (no effect) Bit 13", - "5694": "Undefined Access (no effect) Bit 14", - "5695": "Undefined Access (no effect) Bit 15", - "5696": "KeyedEvent Wait", - "5697": "KeyedEvent Wake", - "5698": "Undefined Access (no effect) Bit 2", - "5699": "Undefined Access (no effect) Bit 3", - "5700": "Undefined Access (no effect) Bit 4", - "5701": "Undefined Access (no effect) Bit 5", - "5702": "Undefined Access (no effect) Bit 6", - "5703": "Undefined Access (no effect) Bit 7", - "5704": "Undefined Access (no effect) Bit 8", - "5705": "Undefined Access (no effect) Bit 9", - "5706": "Undefined Access (no effect) Bit 10", - "5707": "Undefined Access (no effect) Bit 11", - "5708": "Undefined Access (no effect) Bit 12", - "5709": "Undefined Access (no effect) Bit 13", - "5710": "Undefined Access (no effect) Bit 14", - "5711": "Undefined Access (no effect) Bit 15", - "6656": "Enumerate desktops", - "6657": "Read attributes", - "6658": "Access Clipboard", - "6659": "Create desktop", - "6660": "Write attributes", - "6661": "Access global atoms", - "6662": "Exit windows", - "6663": "Unused Access Flag", - "6664": "Include this windowstation in enumerations", - "6665": "Read screen", - "6672": "Read Objects", - "6673": "Create window", - "6674": "Create menu", - "6675": "Hook control", - "6676": "Journal (record)", - "6677": "Journal (playback)", - "6678": "Include this desktop in enumerations", - "6679": "Write objects", - "6680": "Switch to this desktop", - "6912": "Administer print server", - "6913": "Enumerate printers", - "6930": "Full Control", - "6931": "Print", - "6948": "Administer Document", - "7168": "Connect to service controller", - "7169": "Create a new service", - "7170": "Enumerate services", - "7171": "Lock service database for exclusive access", - "7172": "Query service database lock state", - "7173": "Set last-known-good state of service database", - "7184": "Query service configuration information", - "7185": "Set service configuration information", - "7186": "Query status of service", - "7187": "Enumerate dependencies of service", - "7188": "Start the service", - "7189": "Stop the service", - "7190": "Pause or continue the service", - "7191": "Query information from service", - "7192": "Issue service-specific control commands", - "7424": "DDE Share Read", - "7425": "DDE Share Write", - "7426": "DDE Share Initiate Static", - "7427": "DDE Share Initiate Link", - "7428": "DDE Share Request", - "7429": "DDE Share Advise", - "7430": "DDE Share Poke", - "7431": "DDE Share Execute", - "7432": "DDE Share Add Items", - "7433": "DDE Share List Items", - "7680": "Create Child", - "7681": "Delete Child", - "7682": "List Contents", - "7683": "Write Self", - "7684": "Read Property", - "7685": "Write Property", - "7686": "Delete Tree", - "7687": "List Object", - "7688": "Control Access", - "7689": "Undefined Access (no effect) Bit 9", - "7690": "Undefined Access (no effect) Bit 10", - "7691": "Undefined Access (no effect) Bit 11", - "7692": "Undefined Access (no effect) Bit 12", - "7693": "Undefined Access (no effect) Bit 13", - "7694": "Undefined Access (no effect) Bit 14", - "7695": "Undefined Access (no effect) Bit 15", - "7936": "Audit Set System Policy", - "7937": "Audit Query System Policy", - "7938": "Audit Set Per User Policy", - "7939": "Audit Query Per User Policy", - "7940": "Audit Enumerate Users", - "7941": "Audit Set Options", - "7942": "Audit Query Options", - "8064": "Port sharing (read)", - "8065": "Port sharing (write)", - "8096": "Default credentials", - "8097": "Credentials manager", - "8098": "Fresh credentials", - "8192": "Kerberos", - "8193": "Preshared key", - "8194": "Unknown authentication", - "8195": "DES", - "8196": "3DES", - "8197": "MD5", - "8198": "SHA1", - "8199": "Local computer", - "8200": "Remote computer", - "8201": "No state", - "8202": "Sent first (SA) payload", - "8203": "Sent second (KE) payload", - "8204": "Sent third (ID) payload", - "8205": "Initiator", - "8206": "Responder", - "8207": "No state", - "8208": "Sent first (SA) payload", - "8209": "Sent final payload", - "8210": "Complete", - "8211": "Unknown", - "8212": "Transport", - "8213": "Tunnel", - "8214": "IKE/AuthIP DoS prevention mode started", - "8215": "IKE/AuthIP DoS prevention mode stopped", - "8216": "Enabled", - "8217": "Not enabled", - "8218": "No state", - "8219": "Sent first (EM attributes) payload", - "8220": "Sent second (SSPI) payload", - "8221": "Sent third (hash) payload", - "8222": "IKEv1", - "8223": "AuthIP", - "8224": "Anonymous", - "8225": "NTLM V2", - "8226": "CGA", - "8227": "Certificate", - "8228": "SSL", - "8229": "None", - "8230": "DH group 1", - "8231": "DH group 2", - "8232": "DH group 14", - "8233": "DH group ECP 256", - "8234": "DH group ECP 384", - "8235": "AES-128", - "8236": "AES-192", - "8237": "AES-256", - "8238": "Certificate ECDSA P256", - "8239": "Certificate ECDSA P384", - "8240": "SSL ECDSA P256", - "8241": "SSL ECDSA P384", - "8242": "SHA 256", - "8243": "SHA 384", - "8244": "IKEv2", - "8245": "EAP payload sent", - "8246": "Authentication payload sent", - "8247": "EAP", - "8248": "DH group 24", - "8272": "System", - "8273": "Logon/Logoff", - "8274": "Object Access", - "8275": "Privilege Use", - "8276": "Detailed Tracking", - "8277": "Policy Change", - "8278": "Account Management", - "8279": "DS Access", - "8280": "Account Logon", - "8448": "Success removed", - "8449": "Success Added", - "8450": "Failure removed", - "8451": "Failure Added", - "8452": "Success include removed", - "8453": "Success include added", - "8454": "Success exclude removed", - "8455": "Success exclude added", - "8456": "Failure include removed", - "8457": "Failure include added", - "8458": "Failure exclude removed", - "8459": "Failure exclude added", - "12288": "Security State Change", - "12289": "Security System Extension", - "12290": "System Integrity", - "12291": "IPsec Driver", - "12292": "Other System Events", - "12544": "Logon", - "12545": "Logoff", - "12546": "Account Lockout", - "12547": "IPsec Main Mode", - "12548": "Special Logon", - "12549": "IPsec Quick Mode", - "12550": "IPsec Extended Mode", - "12551": "Other Logon/Logoff Events", - "12552": "Network Policy Server", - "12553": "User / Device Claims", - "12554": "Group Membership", - "12800": "File System", - "12801": "Registry", - "12802": "Kernel Object", - "12803": "SAM", - "12804": "Other Object Access Events", - "12805": "Certification Services", - "12806": "Application Generated", - "12807": "Handle Manipulation", - "12808": "File Share", - "12809": "Filtering Platform Packet Drop", - "12810": "Filtering Platform Connection", - "12811": "Detailed File Share", - "12812": "Removable Storage", - "12813": "Central Policy Staging", - "13056": "Sensitive Privilege Use", - "13057": "Non Sensitive Privilege Use", - "13058": "Other Privilege Use Events", - "13312": "Process Creation", - "13313": "Process Termination", - "13314": "DPAPI Activity", - "13315": "RPC Events", - "13316": "Plug and Play Events", - "13317": "Token Right Adjusted Events", - "13568": "Audit Policy Change", - "13569": "Authentication Policy Change", - "13570": "Authorization Policy Change", - "13571": "MPSSVC Rule-Level Policy Change", - "13572": "Filtering Platform Policy Change", - "13573": "Other Policy Change Events", - "13824": "User Account Management", - "13825": "Computer Account Management", - "13826": "Security Group Management", - "13827": "Distribution Group Management", - "13828": "Application Group Management", - "13829": "Other Account Management Events", - "14080": "Directory Service Access", - "14081": "Directory Service Changes", - "14082": "Directory Service Replication", - "14083": "Detailed Directory Service Replication", - "14336": "Credential Validation", - "14337": "Kerberos Service Ticket Operations", - "14338": "Other Account Logon Events", - "14339": "Kerberos Authentication Service", - "14592": "Inbound", - "14593": "Outbound", - "14594": "Forward", - "14595": "Bidirectional", - "14596": "IP Packet", - "14597": "Transport", - "14598": "Forward", - "14599": "Stream", - "14600": "Datagram Data", - "14601": "ICMP Error", - "14602": "MAC 802.3", - "14603": "MAC Native", - "14604": "vSwitch", - "14608": "Resource Assignment", - "14609": "Listen", - "14610": "Receive/Accept", - "14611": "Connect", - "14612": "Flow Established", - "14614": "Resource Release", - "14615": "Endpoint Closure", - "14616": "Connect Redirect", - "14617": "Bind Redirect", - "14624": "Stream Packet", - "14640": "ICMP Echo-Request", - "14641": "vSwitch Ingress", - "14642": "vSwitch Egress", - "14672": "", - "14673": "[NULL]", - "14674": "Value Added", - "14675": "Value Deleted", - "14676": "Active Directory Domain Services", - "14677": "Active Directory Lightweight Directory Services", - "14678": "Yes", - "14679": "No", - "14680": "Value Added With Expiration Time", - "14681": "Value Deleted With Expiration Time", - "14688": "Value Auto Deleted With Expiration Time", - "16384": "Add", - "16385": "Delete", - "16386": "Boot-time", - "16387": "Persistent", - "16388": "Not persistent", - "16389": "Block", - "16390": "Permit", - "16391": "Callout", - "16392": "MD5", - "16393": "SHA-1", - "16394": "SHA-256", - "16395": "AES-GCM 128", - "16396": "AES-GCM 192", - "16397": "AES-GCM 256", - "16398": "DES", - "16399": "3DES", - "16400": "AES-128", - "16401": "AES-192", - "16402": "AES-256", - "16403": "Transport", - "16404": "Tunnel", - "16405": "Responder", - "16406": "Initiator", - "16407": "AES-GMAC 128", - "16408": "AES-GMAC 192", - "16409": "AES-GMAC 256", - "16416": "AuthNoEncap Transport", - "16896": "Enable WMI Account", - "16897": "Execute Method", - "16898": "Full Write", - "16899": "Partial Write", - "16900": "Provider Write", - "16901": "Remote Access", - "16902": "Subscribe", - "16903": "Publish", - }; - - // Trust Types - // https://docs.microsoft.com/en-us/windows/security/threat-protection/auditing/event-4706 - var trustTypes = { - "1": "TRUST_TYPE_DOWNLEVEL", - "2": "TRUST_TYPE_UPLEVEL", - "3": "TRUST_TYPE_MIT", - "4": "TRUST_TYPE_DCE" - } - - // Trust Direction - // https://docs.microsoft.com/en-us/windows/security/threat-protection/auditing/event-4706 - var trustDirection = { - "0": "TRUST_DIRECTION_DISABLED", - "1": "TRUST_DIRECTION_INBOUND", - "2": "TRUST_DIRECTION_OUTBOUND", - "3": "TRUST_DIRECTION_BIDIRECTIONAL" - } - - // Trust Attributes - // https://docs.microsoft.com/en-us/windows/security/threat-protection/auditing/event-4706 - var trustAttributes = { - "0": "UNDEFINED", - "1": "TRUST_ATTRIBUTE_NON_TRANSITIVE", - "2": "TRUST_ATTRIBUTE_UPLEVEL_ONLY", - "4": "TRUST_ATTRIBUTE_QUARANTINED_DOMAIN", - "8": "TRUST_ATTRIBUTE_FOREST_TRANSITIVE", - "16": "TRUST_ATTRIBUTE_CROSS_ORGANIZATION", - "32": "TRUST_ATTRIBUTE_WITHIN_FOREST", - "64": "TRUST_ATTRIBUTE_TREAT_AS_EXTERNAL", - "128": "TRUST_ATTRIBUTE_USES_RC4_ENCRYPTION", - "512": "TRUST_ATTRIBUTE_CROSS_ORGANIZATION_NO_TGT_DELEGATION", - "1024": "TRUST_ATTRIBUTE_PIM_TRUST" - } - - // SDDL Ace Types - // https://docs.microsoft.com/en-us/windows/security/threat-protection/auditing/event-4715 - // https://docs.microsoft.com/en-us/windows/win32/secauthz/ace-strings - // https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-dtyp/f4296d69-1c0f-491f-9587-a960b292d070 - var aceTypes = { - "A": "Access Allowed", - "D": "Access Denied", - "OA": "Object Access Allowed", - "OD": "Object Access Denied", - "AU": "System Audit", - "AL": "System Alarm", - "OU": "System Object Audit", - "OL": "System Object Alarm", - "ML": "System Mandatory Label", - "SP": "Central Policy ID" - } - - // SDDL Permissions - // https://docs.microsoft.com/en-us/windows/security/threat-protection/auditing/event-4715 - // https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-dtyp/f4296d69-1c0f-491f-9587-a960b292d070 - var permissionDescription = { - "GA": "Generic All", - "GR": "Generic Read", - "GW": "Generic Write", - "GX": "Generic Execute", - "RC": "Read Permissions", - "SD": "Delete", - "WD": "Modify Permissions", - "WO": "Modify Owner", - "RP": "Read All Properties", - "WP": "Write All Properties", - "CC": "Create All Child Objects", - "DC": "Delete All Child Objects", - "LC": "List Contents", - "SW": "All Validated", - "LO": "List Object", - "DT": "Delete Subtree", - "CR": "All Extended Rights", - "FA": "File All Access", - "FR": "File Generic Read", - "FX": "FILE GENERIC EXECUTE", - "FW": "FILE GENERIC WRITE", - "KA": "KEY ALL ACCESS", - "KR": "KEY READ", - "KW": "KEY WRITE", - "KX": "KEY EXECUTE" - } - - // Known SIDs - // https://support.microsoft.com/en-au/help/243330/well-known-security-identifier"S-in-window"S-operating-systems - // https://docs.microsoft.com/en-us/windows/win32/secauthz/sid-strings - var accountSIDDescription = { - "AO": "Account operators", - "RU": "Alias to allow previous Windows 2000", - "AN": "Anonymous logon", - "AU": "Authenticated users", - "BA": "Built-in administrators", - "BG": "Built-in guests", - "BO": "Backup operators", - "BU": "Built-in users", - "CA": "Certificate server administrators", - "CG": "Creator group", - "CO": "Creator owner", - "DA": "Domain administrators", - "DC": "Domain computers", - "DD": "Domain controllers", - "DG": "Domain guests", - "DU": "Domain users", - "EA": "Enterprise administrators", - "ED": "Enterprise domain controllers", - "WD": "Everyone", - "PA": "Group Policy administrators", - "IU": "Interactively logged-on user", - "LA": "Local administrator", - "LG": "Local guest", - "LS": "Local service account", - "SY": "Local system", - "NU": "Network logon user", - "NO": "Network configuration operators", - "NS": "Network service account", - "PO": "Printer operators", - "PS": "Personal self", - "PU": "Power users", - "RS": "RAS servers group", - "RD": "Terminal server users", - "RE": "Replicator", - "RC": "Restricted code", - "SA": "Schema administrators", - "SO": "Server operators", - "SU": "Service logon user", - "S-1-0": "Null Authority", - "S-1-0-0": "Nobody", - "S-1-1": "World Authority", - "S-1-1-0": "Everyone", - "S-1-16-0": "Untrusted Mandatory Level", - "S-1-16-12288": "High Mandatory Level", - "S-1-16-16384": "System Mandatory Level", - "S-1-16-20480": "Protected Process Mandatory Level", - "S-1-16-28672": "Secure Process Mandatory Level", - "S-1-16-4096": "Low Mandatory Level", - "S-1-16-8192": "Medium Mandatory Level", - "S-1-16-8448": "Medium Plus Mandatory Level", - "S-1-2": "Local Authority", - "S-1-2-0": "Local", - "S-1-2-1": "Console Logon", - "S-1-3": "Creator Authority", - "S-1-3-0": "Creator Owner", - "S-1-3-1": "Creator Group", - "S-1-3-2": "Creator Owner Server", - "S-1-3-3": "Creator Group Server", - "S-1-3-4": "Owner Rights", - "S-1-4": "Non-unique Authority", - "S-1-5": "NT Authority", - "S-1-5-1": "Dialup", - "S-1-5-10": "Principal Self", - "S-1-5-11": "Authenticated Users", - "S-1-5-12": "Restricted Code", - "S-1-5-13": "Terminal Server Users", - "S-1-5-14": "Remote Interactive Logon", - "S-1-5-15": "This Organization", - "S-1-5-17": "This Organization", - "S-1-5-18": "Local System", - "S-1-5-19": "NT Authority", - "S-1-5-2": "Network", - "S-1-5-20": "NT Authority", - "S-1-5-3": "Batch", - "S-1-5-32-544": "Administrators", - "S-1-5-32-545": "Users", - "S-1-5-32-546": "Guests", - "S-1-5-32-547": "Power Users", - "S-1-5-32-548": "Account Operators", - "S-1-5-32-549": "Server Operators", - "S-1-5-32-550": "Print Operators", - "S-1-5-32-551": "Backup Operators", - "S-1-5-32-552": "Replicators", - "S-1-5-32-554": "Builtin\Pre-Windows 2000 Compatible Access", - "S-1-5-32-555": "Builtin\Remote Desktop Users", - "S-1-5-32-556": "Builtin\Network Configuration Operators", - "S-1-5-32-557": "Builtin\Incoming Forest Trust Builders", - "S-1-5-32-558": "Builtin\Performance Monitor Users", - "S-1-5-32-559": "Builtin\Performance Log Users", - "S-1-5-32-560": "Builtin\Windows Authorization Access Group", - "S-1-5-32-561": "Builtin\Terminal Server License Servers", - "S-1-5-32-562": "Builtin\Distributed COM Users", - "S-1-5-32-569": "Builtin\Cryptographic Operators", - "S-1-5-32-573": "Builtin\Event Log Readers", - "S-1-5-32-574": "Builtin\Certificate Service DCOM Access", - "S-1-5-32-575": "Builtin\RDS Remote Access Servers", - "S-1-5-32-576": "Builtin\RDS Endpoint Servers", - "S-1-5-32-577": "Builtin\RDS Management Servers", - "S-1-5-32-578": "Builtin\Hyper-V Administrators", - "S-1-5-32-579": "Builtin\Access Control Assistance Operators", - "S-1-5-32-580": "Builtin\Remote Management Users", - "S-1-5-32-582": "Storage Replica Administrators", - "S-1-5-4": "Interactive", - "S-1-5-5-X-Y": "Logon Session", - "S-1-5-6": "Service", - "S-1-5-64-10": "NTLM Authentication", - "S-1-5-64-14": "SChannel Authentication", - "S-1-5-64-21": "Digest Authentication", - "S-1-5-7": "Anonymous", - "S-1-5-8": "Proxy", - "S-1-5-80": "NT Service", - "S-1-5-80-0": "All Services", - "S-1-5-83-0": "NT Virtual Machine\Virtual Machines", - "S-1-5-9": "Enterprise Domain Controllers", - "S-1-5-90-0": "Windows Manager\Windows Manager Group" - } - - // Domain-specific SIDs - // https://support.microsoft.com/en-au/help/243330/well-known-security-identifiers-in-windows-operating-systems - var domainSpecificSID = { - "498": "Enterprise Read-only Domain Controllers", - "500": "Administrator", - "501": "Guest", - "502": "KRBTGT", - "512": "Domain Admins", - "513": "Domain Users", - "514": "Domain Guests", - "515": "Domain Computers", - "516": "Domain Controllers", - "517": "Cert Publishers", - "518": "Schema Admins", - "519": "Enterprise Admins", - "520": "Group Policy Creator Owners", - "521": "Read-only Domain Controllers", - "522": "Cloneable Domain Controllers", - "526": "Key Admins", - "527": "Enterprise Key Admins", - "553": "RAS and IAS Servers", - "571": "Allowed RODC Password Replication Group", - "572": "Denied RODC Password Replication Group" - } - - // Object Permission Flags - // https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-dtyp/7a53f60e-e730-4dfe-bbe9-b21b62eb790b - var permsFlags = [ - [0x80000000, 'Generic Read'], - [0x4000000, 'Generic Write'], - [0x20000000, 'Generic Execute'], - [0x10000000, 'Generic All'], - [0x02000000, 'Maximun Allowed'], - [0x01000000, 'Access System Security'], - [0x00100000, 'Syncronize'], - [0x00080000, 'Write Owner'], - [0x00040000, 'Write DACL'], - [0x00020000, 'Read Control'], - [0x00010000, 'Delete'] - ]; - - // lookupMessageCode returns the string associated with the code. key should - // be the name of the field in evt containing the code (e.g. %%2313). - var lookupMessageCode = function (evt, key) { - var code = evt.Get(key); - if (!code) { - return; - } - code = code.replace("%%", ""); - return msobjsMessageTable[code]; - }; - - var addEventFields = function(evt){ - var code = evt.Get("event.code"); - if (!code) { - return; - } - var eventActionDescription = eventActionTypes[code][2]; - if (eventActionDescription) { - evt.Put("event.category", eventActionTypes[code][0]); - evt.Put("event.type", eventActionTypes[code][1]); - evt.Put("event.action", eventActionTypes[code][2]); - } - }; - - var addLogonType = function(evt) { - var code = evt.Get("winlog.event_data.LogonType"); - if (!code) { - return; - } - var descriptiveLogonType = logonTypes[code]; - if (descriptiveLogonType === undefined) { - return; - } - evt.Put("winlog.logon.type", descriptiveLogonType); - }; - - var addFailureCode = function(evt) { - var msg = lookupMessageCode(evt, "winlog.event_data.FailureReason"); - if (!msg) { - return; - } - evt.Put("winlog.logon.failure.reason", msg); - }; - - var addFailureStatus = function(evt) { - var code = evt.Get("winlog.event_data.Status"); - if (!code) { - return; - } - var descriptiveFailureStatus = logonFailureStatus[code]; - if (descriptiveFailureStatus === undefined) { - return; - } - evt.Put("winlog.logon.failure.status", descriptiveFailureStatus); - }; - - var addFailureSubStatus = function(evt) { - var code = evt.Get("winlog.event_data.SubStatus"); - if (!code) { - return; - } - var descriptiveFailureStatus = logonFailureStatus[code]; - if (descriptiveFailureStatus === undefined) { - return; - } - evt.Put("winlog.logon.failure.sub_status", descriptiveFailureStatus); - }; - - var addUACDescription = function(evt) { - var code = evt.Get("winlog.event_data.NewUacValue"); - if (!code) { - return; - } - var uacCode = parseInt(code); - var uacResult = []; - for (var i = 0; i < uacFlags.length; i++) { - if ((uacCode | uacFlags[i][0]) === uacCode) { - uacResult.push(uacFlags[i][1]); - } - } - if (uacResult) { - evt.Put("winlog.event_data.NewUACList", uacResult); - } - var uacList = evt.Get("winlog.event_data.UserAccountControl").replace(/\s/g, '').split("%%").filter(String); - if (!uacList) { - return; - } - evt.Put("winlog.event_data.UserAccountControl", uacList); - }; - - var addAuditInfo = function(evt) { - var subcategoryGuid = evt.Get("winlog.event_data.SubcategoryGuid").replace("{", '').replace("}", '').toUpperCase(); - if (!subcategoryGuid) { - return; - } - if (!auditDescription[subcategoryGuid]) { - return; - } - evt.Put("winlog.event_data.Category", auditDescription[subcategoryGuid][1]); - evt.Put("winlog.event_data.SubCategory", auditDescription[subcategoryGuid][0]); - var codedActions = evt.Get("winlog.event_data.AuditPolicyChanges").split(","); - var actionResults = []; - for (var j = 0; j < codedActions.length; j++) { - var actionCode = codedActions[j].replace("%%", '').replace(' ', ''); - actionResults.push(msobjsMessageTable[actionCode]); - } - evt.Put("winlog.event_data.AuditPolicyChangesDescription", actionResults); - }; - - var addTicketOptionsDescription = function(evt) { - var code = evt.Get("winlog.event_data.TicketOptions"); - if (!code) { - return; - } - var tktCode = parseInt(code, 16).toString(2); - var tktResult = []; - var tktCodeLen = tktCode.length; - for (var i = tktCodeLen; i >= 0; i--) { - if (tktCode[i] == 1) { - tktResult.push(ticketOptions[(32-tktCodeLen)+i]); - } - } - if (tktResult) { - evt.Put("winlog.event_data.TicketOptionsDescription", tktResult); - } - }; - - var addTicketEncryptionType = function(evt) { - var code = evt.Get("winlog.event_data.TicketEncryptionType"); - if (!code) { - return; - } - var encTypeCode = code.toLowerCase(); - evt.Put("winlog.event_data.TicketEncryptionTypeDescription", ticketEncryptionTypes[encTypeCode]); - }; - - var addTicketStatus = function(evt) { - var code = evt.Get("winlog.event_data.Status"); - if (!code) { - return; - } - evt.Put("winlog.event_data.StatusDescription", kerberosTktStatusCodes[code]); - }; - - var translateSID = function(sid){ - var translatedSID = accountSIDDescription[sid]; - if (translatedSID == undefined) { - if (/^S\-1\-5\-21/.test(sid)) { - var uid = sid.match(/[0-9]{1,5}$/g); - if (uid) { - translatedSID = domainSpecificSID[uid]; - } - } - } - if (translatedSID == undefined) { - translatedSID = sid; - } - return translatedSID; - } - - var translatePermissionMask = function(mask) { - if (!mask) { - return; - } - var permCode = parseInt(mask); - var permResult = []; - for (var i = 0; i < permsFlags.length; i++) { - if ((permCode | permsFlags[i][0]) === permCode) { - permResult.push(permsFlags[i][1]); - } - } - if (permResult) { - return permResult; - } else { - return mask; - } - }; - - var translateACL = function(dacl) { - var aceArray = dacl.split(";"); - var aceResult = []; - var aceType = aceArray[0]; - var acePerm = aceArray[2]; - var aceTrustedSid = aceArray[5]; - if (aceTrustedSid) { - aceResult['grantee'] = translateSID(aceTrustedSid); - } - if (aceType) { - aceResult['type'] = aceTypes[aceType]; - } - if (acePerm) { - if (/^0x/.test(acePerm)) { - var perms = translatePermissionMask(acePerm); - } - else { - var perms = [] - var permPairs = acePerm.match(/.{1,2}/g); - for ( var i = 0; i < permPairs.length; i ++) { - perms.push(permissionDescription[permPairs[i]]) - } - } - aceResult['perms'] = perms; - } - return aceResult; - }; - - var enrichSDDL = function(evt, sddl) { - var sddlStr = evt.Get(sddl); - if (!sddlStr) { - return; - } - var sdOwner = sddlStr.match(/^O\:[A-Z]{2}/g); - var sdGroup = sddlStr.match(/^G\:[A-Z]{2}/g); - var sdDacl = sddlStr.match(/(D:([A-Z]*(\(.*\))*))/g); - var sdSacl = sddlStr.match(/(S:([A-Z]*(\(.*\))*))?$/g); - if (sdOwner) { - evt.Put(sddl+"Owner", translateSID(sdOwner)); - } - if (sdGroup) { - evt.Put(sddl+"Group", translateSID(sdGroup)); - } - if (sdDacl) { - // Split each entry of the DACL - var daclList = (sdDacl[0]).match(/\([^*\)]*\)/g); - if (daclList) { - for (var i = 0; i < daclList.length; i++) { - var newDacl = translateACL(daclList[i].replace("(", '').replace(")", '')); - evt.Put(sddl+"Dacl"+i, newDacl['grantee']+" :"+newDacl['type']+" ("+newDacl['perms']+")"); - if ( newDacl['grantee'] === "Administrator" || newDacl['grantee'] === "Guest" || newDacl['grantee'] === "KRBTGT" ) { - evt.AppendTo('related.user', newDacl['grantee']); - } - } - } - } - if (sdSacl) { - // Split each entry of the SACL - var saclList = (sdSacl[0]).match(/\([^*\)]*\)/g); - if (saclList) { - for (var i = 0; i < saclList.length; i++) { - var newSacl = translateACL(saclList[i].replace("(", '').replace(")", '')); - evt.Put(sddl+"Sacl"+i, newSacl['grantee']+" :"+newSacl['type']+" ("+newSacl['perms']+")"); - if ( newSacl['grantee'] === "Administrator" || newSacl['grantee'] === "Guest" || newSacl['grantee'] === "KRBTGT" ) { - evt.AppendTo('related.user', newSacl['grantee']); - } - } - } - } - }; - - var addSessionData = new processor.Chain() - .Convert({ - fields: [ - {from: "winlog.event_data.AccountName", to: "user.name"}, - {from: "winlog.event_data.AccountDomain", to: "user.domain"}, - {from: "winlog.event_data.ClientAddress", to: "source.ip", type: "ip"}, - {from: "winlog.event_data.ClientName", to: "source.domain"}, - {from: "winlog.event_data.LogonID", to: "winlog.logon.id"}, - ], - ignore_missing: true, - fail_on_error: false, - }) - .Add(function(evt) { - var user = evt.Get("winlog.event_data.AccountName"); - evt.AppendTo('related.user', user); - }) - .Add(function(evt) { - var ip = evt.Get("source.ip"); - if (ip) { - evt.Put('related.ip', ip); - } - }) - .Build(); - - var addServiceFields = new processor.Chain() - .Convert({ - fields: [ - {from: "winlog.event_data.ServiceName", to: "service.name"}, - ], - ignore_missing: true, - }) - .Add(function(evt) { - var code = evt.Get("winlog.event_data.ServiceType"); - if (!code) { - return; - } - evt.Put("service.type", serviceTypes[code]); - }) - .Build(); - - var addTrustInformation = new processor.Chain() - .Add(function(evt) { - var code = evt.Get("winlog.event_data.TdoType"); - if (!code) { - return; - } - evt.Put("winlog.trustType", trustTypes[code]); - code = evt.Get("winlog.event_data.TdoDirection"); - if (!code) { - return; - } - evt.Put("winlog.trustDirection", trustDirection[code]); - code = evt.Get("winlog.event_data.TdoAttributes"); - if (!code) { - return; - } - evt.Put("winlog.trustAttribute", trustAttributes[code]); - - }) - .Build(); - - var copyTargetUser = function(evt) { - var targetUserId = evt.Get("winlog.event_data.TargetUserSid"); - if (!targetUserId) targetUserId = evt.Get("winlog.event_data.TargetSid"); - if (targetUserId) { - if (evt.Get("user.id")) evt.Put("user.target.id", targetUserId); - else evt.Put("user.id", targetUserId); - } - var targetUserName = evt.Get("winlog.event_data.TargetUserName"); - if (targetUserName) { - if (targetUserName.indexOf('@')>0) { - targetUserName = targetUserName.split('@')[0]; - } - - evt.AppendTo("related.user", targetUserName); - if (evt.Get("user.name")) evt.Put("user.target.name", targetUserName); - else evt.Put("user.name", targetUserName); - } - - var targetUserDomain = evt.Get("winlog.event_data.TargetDomainName"); - if (targetUserDomain) { - if (evt.Get("user.domain")) evt.Put("user.target.domain", targetUserDomain); - else evt.Put("user.domain", targetUserDomain); - } - } - - var removeIfEmptyOrHyphen = function(evt, key) { - var val = evt.Get(key); - if (!val || val === "-") { - evt.Delete(key); - return true; - } - return false; - } - - var copyTargetUserToEffective = new processor.Chain() - .Convert({ - fields: [ - {from: "winlog.event_data.TargetUserSid", to: "user.effective.id"}, - {from: "winlog.event_data.TargetUserName", to: "user.effective.name"}, - {from: "winlog.event_data.TargetDomainName", to: "user.effective.domain"}, - ], - ignore_missing: true, - }) - .Add(function(evt) { - var user = evt.Get("winlog.event_data.TargetUserName"); - if (user) { - if (user.indexOf('@')>0) { - user = user.split('@')[0]; - evt.Put('user.effective.name', user); - } - } - }) - .Add(function(evt) { - if (!removeIfEmptyOrHyphen(evt, "user.effective.name")) { - evt.AppendTo("related.user", evt.Get("user.effective.name")); - } - removeIfEmptyOrHyphen(evt, "user.effective.domain"); - removeIfEmptyOrHyphen(evt, "user.effective.id"); - }) - .Build(); - - var copyTargetUserToTarget = new processor.Chain() - .Convert({ - fields: [ - {from: "winlog.event_data.TargetSid", to: "user.target.id"}, - {from: "winlog.event_data.TargetUserName", to: "user.target.name"}, - {from: "winlog.event_data.TargetDomainName", to: "user.target.domain"}, - ], - ignore_missing: true, - }) - .Add(function(evt) { - var user = evt.Get("winlog.event_data.TargetUserName"); - if (user) { - if (user.indexOf('@')>0) { - user = user.split('@')[0]; - evt.Put('user.target.name', user); - } - evt.AppendTo('related.user', user); - } - }) - .Add(function(evt) { - if (!removeIfEmptyOrHyphen(evt, "user.target.name")) { - evt.AppendTo("related.user", evt.Get("user.target.name")); - } - removeIfEmptyOrHyphen(evt, "user.target.domain"); - removeIfEmptyOrHyphen(evt, "user.target.id"); - }) - .Build(); - - - var copyMemberToUser = function(evt) { - var member = evt.Get("winlog.event_data.MemberName"); - if (!member) { - return; - } - - var userName = member.split(',')[0].replace('CN=', '').replace('cn=', ''); - - evt.AppendTo("related.user", userName); - evt.Put("user.target.name", userName); - - var domainName = member.split(',')[3]; - if (domainName) { - evt.Put("user.target.domain", domainName.replace('DC=', '').replace('dc=', '')); - } - } - - var copyTargetUserToGroup = new processor.Chain() - .Convert({ - fields: [ - {from: "winlog.event_data.TargetUserSid", to: "group.id"}, - {from: "winlog.event_data.TargetSid", to: "group.id"}, - {from: "winlog.event_data.TargetUserName", to: "group.name"}, - {from: "winlog.event_data.TargetDomainName", to: "group.domain"}, - ], - ignore_missing: true, - }).Add(function(evt) { - if (!evt.Get("user.target")) return; - evt.Put("user.target.group.id", evt.Get("group.id")); - evt.Put("user.target.group.name", evt.Get("group.name")); - evt.Put("user.target.group.domain", evt.Get("group.domain")); - }) - .Build(); - - var copyTargetUserToComputerObject = new processor.Chain() - .Convert({ - fields: [ - {from: "winlog.event_data.TargetSid", to: "winlog.computerObject.id"}, - {from: "winlog.event_data.TargetUserName", to: "winlog.computerObject.name"}, - {from: "winlog.event_data.TargetDomainName", to: "winlog.computerObject.domain"}, - ], - ignore_missing: true, - }) - .Build(); - - var copyTargetUserLogonId = new processor.Chain() - .Convert({ - fields: [ - {from: "winlog.event_data.TargetLogonId", to: "winlog.logon.id"}, - ], - ignore_missing: true, - }) - .Build(); - - var copySubjectUser = new processor.Chain() - .Convert({ - fields: [ - {from: "winlog.event_data.SubjectUserSid", to: "user.id"}, - {from: "winlog.event_data.SubjectUserName", to: "user.name"}, - {from: "winlog.event_data.SubjectDomainName", to: "user.domain"}, - ], - ignore_missing: true, - }) - .Add(function(evt) { - var user = evt.Get("winlog.event_data.SubjectUserName"); - evt.AppendTo('related.user', user); - }) - .Build(); - - var copySubjectUserFromUserData = new processor.Chain() - .Convert({ - fields: [ - {from: "winlog.user_data.SubjectUserSid", to: "user.id"}, - {from: "winlog.user_data.SubjectUserName", to: "user.name"}, - {from: "winlog.user_data.SubjectDomainName", to: "user.domain"}, - ], - ignore_missing: true, - }) - .Add(function(evt) { - var user = evt.Get("winlog.user_data.SubjectUserName"); - evt.AppendTo('related.user', user); - }) - .Build(); - - var copySubjectUserLogonId = new processor.Chain() - .Convert({ - fields: [ - {from: "winlog.event_data.SubjectLogonId", to: "winlog.logon.id"}, - ], - ignore_missing: true, - }) - .Build(); - - var copySubjectUserLogonIdFromUserData = new processor.Chain() - .Convert({ - fields: [ - {from: "winlog.user_data.SubjectLogonId", to: "winlog.logon.id"}, - ], - ignore_missing: true, - }) - .Build(); - - var renameCommonAuthFields = new processor.Chain() - .Convert({ - fields: [ - {from: "winlog.event_data.ProcessId", to: "process.pid", type: "long"}, - {from: "winlog.event_data.ProcessName", to: "process.executable"}, - {from: "winlog.event_data.IpAddress", to: "source.ip", type: "ip"}, - {from: "winlog.event_data.IpPort", to: "source.port", type: "long"}, - {from: "winlog.event_data.WorkstationName", to: "source.domain"}, - ], - mode: "rename", - ignore_missing: true, - fail_on_error: false, - }) - .Add(function(evt) { - var name = evt.Get("process.name"); - if (name) { - return; - } - var exe = evt.Get("process.executable"); - if (!exe) { - return; - } - evt.Put("process.name", path.basename(exe)); - }) - .Add(function(evt) { - var ip = evt.Get("source.ip"); - if (ip) { - evt.Put('related.ip', ip); - } - }) - .Build(); - - var renameNewProcessFields = new processor.Chain() - .Convert({ - fields: [ - {from: "winlog.event_data.NewProcessId", to: "process.pid", type: "long"}, - {from: "winlog.event_data.NewProcessName", to: "process.executable"}, - {from: "winlog.event_data.ParentProcessName", to: "process.parent.executable"} - ], - mode: "rename", - ignore_missing: true, - fail_on_error: false, - }) - .Add(function(evt) { - var name = evt.Get("process.name"); - if (name) { - return; - } - var exe = evt.Get("process.executable"); - if (!exe) { - return; - } - evt.Put("process.name", path.basename(exe)); - }) - .Add(function(evt) { - var name = evt.Get("process.parent.name"); - if (name) { - return; - } - var exe = evt.Get("process.parent.executable"); - if (!exe) { - return; - } - evt.Put("process.parent.name", path.basename(exe)); - }) - .Add(function(evt) { - var cl = evt.Get("winlog.event_data.CommandLine"); - if (!cl) { - return; - } - evt.Put("process.args", windows.splitCommandLine(cl)); - evt.Put("process.command_line", cl); - }) - .Build(); - - // Handles 4634 and 4647. - var logoff = new processor.Chain() - .Add(copyTargetUser) - .Add(copyTargetUserLogonId) - .Add(addLogonType) - .Add(addEventFields) - .Build(); - - // Handles both 4624 - var logonSuccess = new processor.Chain() - .Add(copyTargetUser) - .Add(copyTargetUserLogonId) - .Add(addLogonType) - .Add(renameCommonAuthFields) - .Add(addEventFields) - .Add(function(evt) { - var user = evt.Get("winlog.event_data.SubjectUserName"); - if (user) { - var res = /^-$/.test(user); - if (!res) { - evt.AppendTo('related.user', user); - } - } - }) - .Build(); - - // Handles both 4648 - var event4648 = new processor.Chain() - .Add(copySubjectUser) - .Add(copySubjectUserLogonId) - .Add(renameCommonAuthFields) - .Add(addEventFields) - .Add(copyTargetUserToEffective) - .Add(function(evt) { - var user = evt.Get("winlog.event_data.SubjectUserName"); - if (user) { - var res = /^-$/.test(user); - if (!res) { - evt.AppendTo('related.user', user); - } - } - }) - .Build(); - - var event4625 = new processor.Chain() - .Add(copyTargetUser) - .Add(copySubjectUserLogonId) - .Add(addLogonType) - .Add(addFailureCode) - .Add(addFailureStatus) - .Add(addFailureSubStatus) - .Add(renameCommonAuthFields) - .Add(addEventFields) - .Build(); - - var event4672 = new processor.Chain() - .Add(copySubjectUser) - .Add(copySubjectUserLogonId) - .Add(function(evt) { - var privs = evt.Get("winlog.event_data.PrivilegeList"); - if (!privs) { - return; - } - evt.Put("winlog.event_data.PrivilegeList", privs.split(/\s+/)); - }) - .Add(addEventFields) - .Build(); - - var event4688 = new processor.Chain() - .Add(copySubjectUser) - .Add(copySubjectUserLogonId) - .Add(renameNewProcessFields) - .Add(copyTargetUserToEffective) - .Add(addEventFields) - .Build(); - - var event4689 = new processor.Chain() - .Add(copySubjectUser) - .Add(copySubjectUserLogonId) - .Add(renameCommonAuthFields) - .Add(addEventFields) - .Build(); - - var event4697 = new processor.Chain() - .Add(copySubjectUser) - .Add(copySubjectUserLogonId) - .Add(renameCommonAuthFields) - .Add(addServiceFields) - .Add(addEventFields) - .Build(); - - var userMgmtEvts = new processor.Chain() - .Add(copySubjectUser) - .Add(copySubjectUserLogonId) - .Add(renameCommonAuthFields) - .Add(addUACDescription) - .Add(addEventFields) - .Add(copyTargetUserToTarget) - .Build(); - - var userRenamed = new processor.Chain() - .Add(copySubjectUser) - .Add(copySubjectUserLogonId) - .Add(addEventFields) - .Add(function(evt) { - var userNew = evt.Get("winlog.event_data.NewTargetUserName"); - evt.AppendTo('related.user', userNew); - var userOld = evt.Get("winlog.event_data.OldTargetUserName"); - evt.AppendTo('related.user', userOld); - if (userOld) { - evt.Put('user.target.name', userOld); - } - if (userNew) { - evt.Put('user.changes.name', userNew); - } - }) - .Build(); - - var groupMgmtEvts = new processor.Chain() - .Add(copySubjectUser) - .Add(copySubjectUserLogonId) - .Add(copyMemberToUser) - .Add(copyTargetUserToGroup) - .Add(renameCommonAuthFields) - .Add(addEventFields) - .Build(); - - var auditLogCleared = new processor.Chain() - .Add(copySubjectUserFromUserData) - .Add(copySubjectUserLogonIdFromUserData) - .Add(renameCommonAuthFields) - .Add(addEventFields) - .Build(); - - var auditChanged = new processor.Chain() - .Add(copySubjectUser) - .Add(copySubjectUserLogonId) - .Add(renameCommonAuthFields) - .Add(addAuditInfo) - .Add(addEventFields) - .Build(); - - var auditLogMgmt = new processor.Chain() - .Add(renameCommonAuthFields) - .Add(addEventFields) - .Build(); - - var computerMgmtEvts = new processor.Chain() - .Add(copySubjectUser) - .Add(copySubjectUserLogonId) - .Add(copyTargetUserToComputerObject) - .Add(renameCommonAuthFields) - .Add(addUACDescription) - .Add(addEventFields) - .Add(function(evt) { - var privs = evt.Get("winlog.event_data.PrivilegeList"); - if (!privs) { - return; - } - evt.Put("winlog.event_data.PrivilegeList", privs.split(/\s+/)); - }) - .Build(); - - var sessionEvts = new processor.Chain() - .Add(addSessionData) - .Add(addEventFields) - .Build(); - - var event4964 = new processor.Chain() - .Add(copyTargetUser) - .Add(copyTargetUserLogonId) - .Add(addEventFields) - .Build(); - - var kerberosTktEvts = new processor.Chain() - .Add(copyTargetUser) - .Add(renameCommonAuthFields) - .Add(addTicketOptionsDescription) - .Add(addTicketEncryptionType) - .Add(addTicketStatus) - .Add(addEventFields) - .Add(function(evt) { - var ip = evt.Get("source.ip"); - if (ip) { - if (/::ffff:/.test(ip)) { - evt.Put("source.ip", ip.replace("::ffff:", "")); - evt.Put("related.ip", ip.replace("::ffff:", "")); - } - } - }) - .Build(); - - var event4776 = new processor.Chain() - .Add(copyTargetUser) - .Add(addFailureStatus) - .Add(addEventFields) - .Build(); - - var scheduledTask = new processor.Chain() - .Add(copySubjectUser) - .Add(copySubjectUserLogonId) - .Add(addEventFields) - .Build(); - - var sensitivePrivilege = new processor.Chain() - .Add(copySubjectUser) - .Add(copySubjectUserLogonId) - .Add(renameCommonAuthFields) - .Add(addEventFields) - .Add(function(evt) { - var privs = evt.Get("winlog.event_data.PrivilegeList"); - if (!privs) { - return; - } - evt.Put("winlog.event_data.PrivilegeList", privs.split(/\s+/)); - }) - .Add(function(evt){ - var maskCodes = evt.Get("winlog.event_data.AccessMask"); - if (!maskCodes) { - return; - } - var maskList = maskCodes.replace(/\s+/g, '').split("%%").filter(String); - evt.Put("winlog.event_data.AccessMask", maskList); - var maskResults = []; - for (var j = 0; j < maskList.length; j++) { - var description = msobjsMessageTable[maskList[j]]; - if (description === undefined) { - return; - } - maskResults.push(description); - } - evt.Put("winlog.event_data.AccessMaskDescription", maskResults); - }) - .Build(); - - var trustDomainMgmtEvts = new processor.Chain() - .Add(copySubjectUser) - .Add(copySubjectUserLogonId) - .Add(addEventFields) - .Add(addTrustInformation) - .Build(); - - var policyChange = new processor.Chain() - .Add(copySubjectUser) - .Add(copySubjectUserLogonId) - .Add(addEventFields) - .Build(); - - var objectPolicyChange = new processor.Chain() - .Add(copySubjectUser) - .Add(copySubjectUserLogonId) - .Add(renameCommonAuthFields) - .Add(addEventFields) - .Add(copyTargetUserToTarget) - .Add(function(evt) { - var oldSd = evt.Get("winlog.event_data.OldSd"); - var newSd = evt.Get("winlog.event_data.NewSd"); - if (oldSd) { - enrichSDDL(evt, "winlog.event_data.OldSd"); - } - if (newSd) { - enrichSDDL(evt, "winlog.event_data.NewSd"); - } - }) - .Build(); - - var genericAuditChange = new processor.Chain() - .Add(addEventFields) - .Build(); - - var event4908 = new processor.Chain() - .Add(addEventFields) - .Add(function(evt) { - var sids = evt.Get("winlog.event_data.SidList"); - if (!sids) { - return; - } - var sidList = sids.split(/\s+/); - evt.Put("winlog.event_data.SidList", sids.split(/\s+/)); - var sidListDesc = []; - for (var i = 0; i < sidList.length; i++) { - var sidTemp = sidList[i].replace("%", "").replace("{", "").replace("}", "").replace(" ",""); - if (sidTemp) { - sidListDesc.push(translateSID(sidTemp)); - } - } - evt.Put("winlog.event_data.SidListDesc", sidListDesc); - }) - .Build(); - - var securityEventSource = new processor.Chain() - .Add(copySubjectUser) - .Add(copySubjectUserLogonId) - .Add(renameCommonAuthFields) - .Add(addEventFields) - .Build(); - - return { - - // 1100 - The event logging service has shut down. - 1100: auditLogMgmt.Run, - - // 1102 - The audit log was cleared. - 1102: auditLogCleared.Run, - - // 1104 - The security log is now full. - 1104: auditLogMgmt.Run, - - // 1105 - Event log automatic backup. - 1105: auditLogMgmt.Run, - - // 1108 - The event logging service encountered an error while processing an incoming event published from %1 - 1108: auditLogMgmt.Run, - - // 4624 - An account was successfully logged on. - 4624: logonSuccess.Run, - - // 4625 - An account failed to log on. - 4625: event4625.Run, - - // 4634 - An account was logged off. - 4634: logoff.Run, - - // 4647 - User initiated logoff. - 4647: logoff.Run, - - // 4648 - A logon was attempted using explicit credentials. - 4648: event4648.Run, - - // 4670 - Permissions on an object were changed. - 4670: objectPolicyChange.Run, - - // 4672 - Special privileges assigned to new logon. - 4672: event4672.Run, - - // 4673 - A privileged service was called. - 4673: sensitivePrivilege.Run, - - // 4674 - An operation was attempted on a privileged object. - 4674: sensitivePrivilege.Run, - - // 4688 - A new process has been created. - 4688: event4688.Run, - - // 4689 - A process has exited. - 4689: event4689.Run, - - // 4697 - A service was installed in the system. - 4697: event4697.Run, - - // 4698 - A scheduled task was created. - 4698: scheduledTask.Run, - - // 4699 - A scheduled task was deleted. - 4699: scheduledTask.Run, - - // 4700 - A scheduled task was enabled. - 4700: scheduledTask.Run, - - // 4701 - A scheduled task was disabled. - 4701: scheduledTask.Run, - - // 4702 - A scheduled task was updated. - 4702: scheduledTask.Run, - - // 4706 - A new trust was created to a domain. - 4706: trustDomainMgmtEvts.Run, - - // 4707 - A trust to a domain was removed. - 4707: trustDomainMgmtEvts.Run, - - // 4713 - Kerberos policy was changed. - 4713: policyChange.Run, - - // 4716 - Trusted domain information was modified. - 4716: trustDomainMgmtEvts.Run, - - // 4717 - System security access was granted to an account. - 4717: policyChange.Run, - - // 4718 - System security access was removed from an account. - 4718: policyChange.Run, - - // 4719 - System audit policy was changed. - 4719: auditChanged.Run, - - // 4720 - A user account was created - 4720: userMgmtEvts.Run, - - // 4722 - A user account was enabled - 4722: userMgmtEvts.Run, - - // 4723 - An attempt was made to change an account's password - 4723: userMgmtEvts.Run, - - // 4724 - An attempt was made to reset an account's password - 4724: userMgmtEvts.Run, - - // 4725 - A user account was disabled. - 4725: userMgmtEvts.Run, - - // 4726 - An user account was deleted. - 4726: userMgmtEvts.Run, - - // 4727 - A security-enabled global group was created. - 4727: groupMgmtEvts.Run, - - // 4728 - A member was added to a security-enabled global group. - 4728: groupMgmtEvts.Run, - - // 4729 - A member was removed from a security-enabled global group. - 4729: groupMgmtEvts.Run, - - // 4730 - A security-enabled global group was deleted. - 4730: groupMgmtEvts.Run, - - // 4731 - A security-enabled local group was created. - 4731: groupMgmtEvts.Run, - - // 4732 - A member was added to a security-enabled local group. - 4732: groupMgmtEvts.Run, - - // 4733 - A member was removed from a security-enabled local group. - 4733: groupMgmtEvts.Run, - - // 4734 - A security-enabled local group was deleted. - 4734: groupMgmtEvts.Run, - - // 4735 - A security-enabled local group was changed. - 4735: groupMgmtEvts.Run, - - // 4737 - A security-enabled global group was changed. - 4737: groupMgmtEvts.Run, - - // 4739 - A security-enabled global group was changed. - 4739: policyChange.Run, - - // 4738 - An user account was changed. - 4738: userMgmtEvts.Run, - - // 4740 - An account was locked out - 4740: userMgmtEvts.Run, - - // 4741 - A computer account was created. - 4741: computerMgmtEvts.Run, - - // 4742 - A computer account was changed. - 4742: computerMgmtEvts.Run, - - // 4743 - A computer account was deleted. - 4743: computerMgmtEvts.Run, - - // 4744 - A security-disabled local group was created. - 4744: groupMgmtEvts.Run, - - // 4745 - A security-disabled local group was changed. - 4745: groupMgmtEvts.Run, - - // 4746 - A member was added to a security-disabled local group. - 4746: groupMgmtEvts.Run, - - // 4747 - A member was removed from a security-disabled local group. - 4747: groupMgmtEvts.Run, - - // 4748 - A security-disabled local group was deleted. - 4748: groupMgmtEvts.Run, - - // 4749 - A security-disabled global group was created. - 4749: groupMgmtEvts.Run, - - // 4750 - A security-disabled global group was changed. - 4750: groupMgmtEvts.Run, - - // 4751 - A member was added to a security-disabled global group. - 4751: groupMgmtEvts.Run, - - // 4752 - A member was removed from a security-disabled global group. - 4752: groupMgmtEvts.Run, - - // 4753 - A security-disabled global group was deleted. - 4753: groupMgmtEvts.Run, - - // 4754 - A security-enabled universal group was created. - 4754: groupMgmtEvts.Run, - - // 4755 - A security-enabled universal group was changed. - 4755: groupMgmtEvts.Run, - - // 4756 - A member was added to a security-enabled universal group. - 4756: groupMgmtEvts.Run, - - // 4757 - A member was removed from a security-enabled universal group. - 4757: groupMgmtEvts.Run, - - // 4758 - A security-enabled universal group was deleted. - 4758: groupMgmtEvts.Run, - - // 4759 - A security-disabled universal group was created. - 4759: groupMgmtEvts.Run, - - // 4760 - A security-disabled universal group was changed. - 4760: groupMgmtEvts.Run, - - // 4761 - A member was added to a security-disabled universal group. - 4761: groupMgmtEvts.Run, - - // 4762 - A member was removed from a security-disabled universal group. - 4762: groupMgmtEvts.Run, - - // 4763 - A security-disabled global group was deleted. - 4763: groupMgmtEvts.Run, - - // 4764 - A group\'s type was changed. - 4764: groupMgmtEvts.Run, - - // 4767 - A user account was unlocked. - 4767: userMgmtEvts.Run, - - // 4768 - A Kerberos authentication ticket TGT was requested. - 4768: kerberosTktEvts.Run, - - // 4769 - A Kerberos service ticket was requested. - 4769: kerberosTktEvts.Run, - - // 4770 - A Kerberos service ticket was renewed. - 4770: kerberosTktEvts.Run, - - // 4771 - Kerberos pre-authentication failed. - 4771: kerberosTktEvts.Run, - - // 4776 - The computer attempted to validate the credentials for an account. - 4776: event4776.Run, - - // 4778 - A session was reconnected to a Window Station. - 4778: sessionEvts.Run, - - // 4779 - A session was disconnected from a Window Station. - 4779: sessionEvts.Run, - - // 4781 - The name of an account was changed. - 4781: userRenamed.Run, - - // 4798 - A user's local group membership was enumerated. - 4798: userMgmtEvts.Run, - - // 4799 - A security-enabled local group membership was enumerated. - 4799: groupMgmtEvts.Run, - - // 4817 - Auditing settings on object were changed. - 4817: objectPolicyChange.Run, - - // 4902 - The Per-user audit policy table was created. - 4902: genericAuditChange.Run, - - // 4904 - An attempt was made to register a security event source. - 4904: securityEventSource.Run, - - // 4905 - An attempt was made to unregister a security event source. - 4905: securityEventSource.Run, - - // 4906 - The CrashOnAuditFail value has changed. - 4906: genericAuditChange.Run, - - // 4907 - Auditing settings on object were changed. - 4907: objectPolicyChange.Run, - - // 4908 - Special Groups Logon table modified. - 4908: event4908.Run, - - // 4912 - Per User Audit Policy was changed. - 4912: auditChanged.Run, - - // 4964 - Special groups have been assigned to a new logon. - 4964: event4964.Run, - - process: function(evt) { - var eventId = evt.Get("winlog.event_id"); - var processor = this[eventId]; - if (processor === undefined) { - return; - } - evt.Put("event.module", "security"); - processor(evt); - }, - }; -})(); - -function process(evt) { - return security.process(evt); -} diff --git a/x-pack/winlogbeat/module/security/ingest/security.yml b/x-pack/winlogbeat/module/security/ingest/security.yml new file mode 100644 index 00000000000..7681693f253 --- /dev/null +++ b/x-pack/winlogbeat/module/security/ingest/security.yml @@ -0,0 +1,3364 @@ +--- +description: Pipeline for Windows Security events +processors: + - set: + field: event.ingested + value: '{{_ingest.timestamp}}' + - convert: + field: event.code + type: string + ignore_missing: true + - script: + lang: painless + ignore_failure: false + tag: Set ECS categorization fields + description: Set ECS categorization fields + params: + "1100": + category: + - process + type: + - end + action: logging-service-shutdown + "1102": + category: + - iam + type: + - admin + - change + action: audit-log-cleared + "1104": + category: + - iam + type: + - admin + action: logging-full + "1105": + category: + - iam + type: + - admin + action: auditlog-archieved + "1108": + category: + - iam + type: + - admin + action: logging-processing-error + "4610": + category: + - configuration + type: + - access + action: authentication-package-loaded + "4611": + category: + - configuration + type: + - change + action: trusted-logon-process-registered + "4614": + category: + - configuration + type: + - access + action: notification-package-loaded + "4616": + category: + - configuration + type: + - change + action: system-time-changed + "4622": + category: + - configuration + type: + - access + action: security-package-loaded + "4624": + category: + - authentication + type: + - start + action: logged-in + "4625": + category: + - authentication + type: + - start + action: logon-failed + "4634": + category: + - authentication + type: + - end + action: logged-out + "4647": + category: + - authentication + type: + - end + action: logged-out + "4648": + category: + - authentication + type: + - start + action: logged-in-explicit + "4657": + category: + - registry + - configuration + type: + - change + action: registry-value-modified + "4670": + category: + - iam + - configuration + type: + - admin + - change + action: permissions-changed + "4672": + category: + - iam + type: + - admin + action: logged-in-special + "4673": + category: + - iam + type: + - admin + action: privileged-service-called + "4674": + category: + - iam + type: + - admin + action: privileged-operation + "4688": + category: + - process + type: + - start + action: created-process + "4689": + category: + - process + type: + - end + action: exited-process + "4697": + category: + - iam + - configuration + type: + - admin + - change + action: service-installed + "4698": + category: + - iam + - configuration + type: + - creation + - admin + action: scheduled-task-created + "4699": + category: + - iam + - configuration + type: + - deletion + - admin + action: scheduled-task-deleted + "4700": + category: + - iam + - configuration + type: + - change + - admin + action: scheduled-task-enabled + "4701": + category: + - iam + - configuration + type: + - change + - admin + action: scheduled-task-disabled + "4702": + category: + - iam + - configuration + type: + - change + - admin + action: scheduled-task-updated + "4706": + category: + - configuration + type: + - creation + action: domain-trust-added + "4707": + category: + - configuration + type: + - deletion + action: domain-trust-removed + "4713": + category: + - configuration + type: + - change + action: kerberos-policy-changed + "4714": + category: + - configuration + type: + - change + action: encrypted-data-recovery-policy-changed + "4715": + category: + - configuration + type: + - change + action: object-audit-policy-changed + "4716": + category: + - configuration + type: + - change + action: trusted-domain-information-changed + "4717": + category: + - iam + - configuration + type: + - admin + - change + action: system-security-access-granted + "4718": + category: + - iam + - configuration + type: + - admin + - deletion + action: system-security-access-removed + "4719": + category: + - iam + - configuration + type: + - admin + - change + action: changed-audit-config + "4720": + category: + - iam + type: + - user + - creation + action: added-user-account + "4722": + category: + - iam + type: + - user + - change + action: enabled-user-account + "4723": + category: + - iam + type: + - user + - change + action: changed-password + "4724": + category: + - iam + type: + - user + - change + action: reset-password + "4725": + category: + - iam + type: + - user + - deletion + action: disabled-user-account + "4726": + category: + - iam + type: + - user + - deletion + action: deleted-user-account + "4727": + category: + - iam + type: + - group + - creation + action: added-group-account + "4728": + category: + - iam + type: + - group + - change + action: added-member-to-group + "4729": + category: + - iam + type: + - group + - change + action: removed-member-from-group + "4730": + category: + - iam + type: + - group + - deletion + action: deleted-group-account + "4731": + category: + - iam + type: + - group + - creation + action: added-group-account + "4732": + category: + - iam + type: + - group + - change + action: added-member-to-group + "4733": + category: + - iam + type: + - group + - change + action: removed-member-from-group + "4734": + category: + - iam + type: + - group + - deletion + action: deleted-group-account + "4735": + category: + - iam + type: + - group + - change + action: modified-group-account + "4737": + category: + - iam + type: + - group + - change + action: modified-group-account + "4738": + category: + - iam + type: + - user + - change + action: modified-user-account + "4739": + category: + - configuration + type: + - change + action: domain-policy-changed + "4740": + category: + - iam + type: + - user + - change + action: locked-out-user-account + "4741": + category: + - iam + type: + - creation + - admin + action: added-computer-account + "4742": + category: + - iam + type: + - change + - admin + action: changed-computer-account + "4743": + category: + - iam + type: + - deletion + - admin + action: deleted-computer-account + "4744": + category: + - iam + type: + - group + - creation + action: added-distribution-group-account + "4745": + category: + - iam + type: + - group + - change + action: changed-distribution-group-account + "4746": + category: + - iam + type: + - group + - change + action: added-member-to-distribution-group + "4747": + category: + - iam + type: + - group + - change + action: removed-member-from-distribution-group + "4748": + category: + - iam + type: + - group + - deletion + action: deleted-distribution-group-account + "4749": + category: + - iam + type: + - group + - creation + action: added-distribution-group-account + "4750": + category: + - iam + type: + - group + - change + action: changed-distribution-group-account + "4751": + category: + - iam + type: + - group + - change + action: added-member-to-distribution-group + "4752": + category: + - iam + type: + - group + - change + action: removed-member-from-distribution-group + "4753": + category: + - iam + type: + - group + - deletion + action: deleted-distribution-group-account + "4754": + category: + - iam + type: + - group + - creation + action: added-group-account + "4755": + category: + - iam + type: + - group + - change + action: modified-group-account + "4756": + category: + - iam + type: + - group + - change + action: added-member-to-group + "4757": + category: + - iam + type: + - group + - change + action: removed-member-from-group + "4758": + category: + - iam + type: + - group + - deletion + action: deleted-group-account + "4759": + category: + - iam + type: + - group + - creation + action: added-distribution-group-account + "4760": + category: + - iam + type: + - group + - change + action: changed-distribution-group-account + "4761": + category: + - iam + type: + - group + - change + action: added-member-to-distribution-group + "4762": + category: + - iam + type: + - group + - change + action: removed-member-from-distribution-group + "4763": + category: + - iam + type: + - group + - deletion + action: deleted-distribution-group-account + "4764": + category: + - iam + type: + - group + - change + action: type-changed-group-account + "4767": + category: + - iam + type: + - user + - change + action: unlocked-user-account + "4768": + category: + - authentication + type: + - start + action: kerberos-authentication-ticket-requested + "4769": + category: + - authentication + type: + - start + action: kerberos-service-ticket-requested + "4770": + category: + - authentication + type: + - start + action: kerberos-service-ticket-renewed + "4771": + category: + - authentication + type: + - start + action: kerberos-preauth-failed + "4776": + category: + - authentication + type: + - start + action: credential-validated + "4778": + category: + - authentication + - session + type: + - start + action: session-reconnected + "4779": + category: + - authentication + - session + type: + - end + action: session-disconnected + "4781": + category: + - iam + type: + - user + - change + action: renamed-user-account + "4798": + category: + - iam + type: + - user + - info + action: group-membership-enumerated + "4799": + category: + - iam + type: + - group + - info + action: user-member-enumerated + "4817": + category: + - iam + - configuration + type: + - admin + - change + action: object-audit-changed + "4902": + category: + - iam + - configuration + type: + - admin + - creation + action: user-audit-policy-created + "4904": + category: + - iam + - configuration + type: + - admin + - change + action: security-event-source-added + "4905": + category: + - iam + - configuration + type: + - admin + - deletion + action: security-event-source-removed + "4906": + category: + - iam + - configuration + type: + - admin + - change + action: crash-on-audit-changed + "4907": + category: + - iam + - configuration + type: + - admin + - change + action: audit-setting-changed + "4908": + category: + - iam + - configuration + type: + - admin + - change + action: special-group-table-changed + "4912": + category: + - iam + - configuration + type: + - admin + - change + action: per-user-audit-policy-changed + "4950": + category: + - configuration + type: + - change + action: windows-firewall-setting-changed + "4954": + category: + - configuration + type: + - change + action: windows-firewall-group-policy-changed + "4964": + category: + - iam + type: + - admin + - group + action: logged-in-special + "5024": + category: + - process + type: + - start + action: windows-firewall-service-started + "5025": + category: + - process + type: + - end + action: windows-firewall-service-stopped + "5033": + category: + - driver + type: + - start + action: windows-firewall-driver-started + "5034": + category: + - driver + type: + - end + action: windows-firewall-driver-stopped + "5037": + category: + - driver + type: + - end + action: windows-firewall-driver-error + source: |- + if (ctx?.event?.code == null || params.get(ctx.event.code) == null) { + return; + } + def hm = new HashMap(params.get(ctx.event.code)); + hm.forEach((k, v) -> ctx.event[k] = v); + - script: + lang: painless + ignore_failure: false + tag: Set Logon Type + description: Set Logon Type + # Logon Types + # https://docs.microsoft.com/en-us/windows/security/threat-protection/auditing/basic-audit-logon-events + params: + "2": Interactive + "3": Network + "4": Batch + "5": Service + "7": Unlock + "8": NetworkCleartext + "9": NewCredentials + "10": RemoteInteractive + "11": CachedInteractive + source: |- + if (ctx?.winlog?.event_data?.LogonType == null) { + return; + } + def t = params.get(ctx.winlog.event_data.LogonType); + if (t == null) { + return; + } + if (ctx?.winlog?.logon == null ) { + Map map = new HashMap(); + ctx.winlog.put("logon", map); + } + ctx.winlog.logon.put("type", t) + - script: + lang: painless + ignore_failure: false + tag: Set User Account Control + description: Set User Account Control + # User Account Control Attributes Table + # https://support.microsoft.com/es-us/help/305144/how-to-use-useraccountcontrol-to-manipulate-user-account-properties + params: + "0x00000001": SCRIPT + "0x00000002": ACCOUNTDISABLE + "0x00000008": HOMEDIR_REQUIRED + "0x00000010": LOCKOUT + "0x00000020": PASSWD_NOTREQD + "0x00000040": PASSWD_CANT_CHANGE + "0x00000080": ENCRYPTED_TEXT_PWD_ALLOWED + "0x00000100": TEMP_DUPLICATE_ACCOUNT + "0x00000200": NORMAL_ACCOUNT + "0x00000800": INTERDOMAIN_TRUST_ACCOUNT + "0x00001000": WORKSTATION_TRUST_ACCOUNT + "0x00002000": SERVER_TRUST_ACCOUNT + "0x00010000": DONT_EXPIRE_PASSWORD + "0x00020000": MNS_LOGON_ACCOUNT + "0x00040000": SMARTCARD_REQUIRED + "0x00080000": TRUSTED_FOR_DELEGATION + "0x00100000": NOT_DELEGATED + "0x00200000": USE_DES_KEY_ONLY + "0x00400000": DONT_REQ_PREAUTH + "0x00800000": PASSWORD_EXPIRED + "0x01000000": TRUSTED_TO_AUTH_FOR_DELEGATION + "0x04000000": PARTIAL_SECRETS_ACCOUNT + source: |- + if (ctx?.winlog?.event_data?.NewUacValue == null) { + return; + } + Long newUacValue = Long.decode(ctx.winlog.event_data.NewUacValue); + ArrayList uacResult = new ArrayList(); + for (entry in params.entrySet()) { + Long flag = Long.decode(entry.getKey()); + if ((newUacValue.longValue() & flag.longValue()) == flag.longValue()) { + uacResult.add(entry.getValue()); + } + } + if (uacResult.length == 0) { + return; + } + ctx.winlog.event_data.put("NewUACList", uacResult); + if (ctx?.winlog?.event_data?.UserAccountControl == null) { + return; + } + ArrayList uac_array = new ArrayList(); + for (elem in ctx.winlog.event_data.UserAccountControl.splitOnToken("%%")) { + if (elem.trim().length() > 0) { + uac_array.add(elem.trim()); + } + } + ctx.winlog.event_data.UserAccountControl = uac_array; + - script: + lang: painless + ignore_failure: false + tag: Set Kerberos Ticket Options + description: Set Kerberos Ticket Options + # Kerberos TGT and TGS Ticket Options + # https://docs.microsoft.com/en-us/windows/security/threat-protection/auditing/event-4768 + # https://docs.microsoft.com/en-us/windows/security/threat-protection/auditing/event-4769 + params: + "0x40000000": Forwardable + "0x20000000": Forwarded + "0x10000000": Proxiable + "0x08000000": Proxy + "0x04000000": Allow-postdate + "0x02000000": Postdated + "0x01000000": Invalid + "0x00800000": Renewable + "0x00400000": Initial + "0x00200000": Pre-authent + "0x00100000": Opt-hardware-auth + "0x00080000": Transited-policy-checked + "0x00040000": Ok-as-delegate + "0x00020000": Request-anonymous + "0x00010000": Name-canonicalize + "0x00000020": Disable-transited-check + "0x00000010": Renewable-ok + "0x00000008": Enc-tkt-in-skey + "0x00000002": Renew + "0x00000001": Validate + source: |- + if (ctx?.winlog?.event_data?.TicketOptions == null) { + return; + } + Long tOpts = Long.decode(ctx.winlog.event_data.TicketOptions); + ArrayList tDescs = new ArrayList(); + for (entry in params.entrySet()) { + Long flag = Long.decode(entry.getKey()); + if ((tOpts.longValue() & flag.longValue()) == flag.longValue()) { + tDescs.add(entry.getValue()); + } + } + if (tDescs.length == 0) { + return; + } + ctx.winlog.event_data.put("TicketOptionsDescription", tDescs); + - script: + lang: painless + ignore_failure: false + tag: Set Kerberos Encryption Types + description: Set Kerberos Encryption Types + # Kerberos Encryption Types + # https://docs.microsoft.com/en-us/windows/security/threat-protection/auditing/event-4768 + # https://docs.microsoft.com/en-us/windows/security/threat-protection/auditing/event-4768 + params: + "0x1": DES-CBC-CRC + "0x3": DES-CBC-MD5 + "0x11": AES128-CTS-HMAC-SHA1-96 + "0x12": AES256-CTS-HMAC-SHA1-96 + "0x17": RC4-HMAC + "0x18": RC4-HMAC-EXP + "0xffffffff": FAIL + source: |- + if (ctx?.winlog?.event_data?.TicketEncryptionType == null) { + return; + } + ctx.winlog.event_data.put("TicketEncryptionTypeDescription", + params[ctx.winlog.event_data.TicketEncryptionType.toLowerCase()]) + - script: + lang: painless + ignore_failure: false + tag: Set Kerberos Ticket Status Codes + # Kerberos Result Status Codes + # https://docs.microsoft.com/en-us/windows/security/threat-protection/auditing/event-4768 + # https://docs.microsoft.com/en-us/windows/security/threat-protection/auditing/event-4768 + description: Set Kerberos Ticket Status Codes + params: + "0x0": KDC_ERR_NONE + "0x1": KDC_ERR_NAME_EXP + "0x2": KDC_ERR_SERVICE_EXP + "0x3": KDC_ERR_BAD_PVNO + "0x4": KDC_ERR_C_OLD_MAST_KVNO + "0x5": KDC_ERR_S_OLD_MAST_KVNO + "0x6": KDC_ERR_C_PRINCIPAL_UNKNOWN + "0x7": KDC_ERR_S_PRINCIPAL_UNKNOWN + "0x8": KDC_ERR_PRINCIPAL_NOT_UNIQUE + "0x9": KDC_ERR_NULL_KEY + "0xA": KDC_ERR_CANNOT_POSTDATE + "0xB": KDC_ERR_NEVER_VALID + "0xC": KDC_ERR_POLICY + "0xD": KDC_ERR_BADOPTION + "0xE": KDC_ERR_ETYPE_NOTSUPP + "0xF": KDC_ERR_SUMTYPE_NOSUPP + "0x10": KDC_ERR_PADATA_TYPE_NOSUPP + "0x11": KDC_ERR_TRTYPE_NO_SUPP + "0x12": KDC_ERR_CLIENT_REVOKED + "0x13": KDC_ERR_SERVICE_REVOKED + "0x14": KDC_ERR_TGT_REVOKED + "0x15": KDC_ERR_CLIENT_NOTYET + "0x16": KDC_ERR_SERVICE_NOTYET + "0x17": KDC_ERR_KEY_EXPIRED + "0x18": KDC_ERR_PREAUTH_FAILED + "0x19": KDC_ERR_PREAUTH_REQUIRED + "0x1A": KDC_ERR_SERVER_NOMATCH + "0x1B": KDC_ERR_MUST_USE_USER2USER + "0x1F": KRB_AP_ERR_BAD_INTEGRITY + "0x20": KRB_AP_ERR_TKT_EXPIRED + "0x21": KRB_AP_ERR_TKT_NYV + "0x22": KRB_AP_ERR_REPEAT + "0x23": KRB_AP_ERR_NOT_US + "0x24": KRB_AP_ERR_BADMATCH + "0x25": KRB_AP_ERR_SKEW + "0x26": KRB_AP_ERR_BADADDR + "0x27": KRB_AP_ERR_BADVERSION + "0x28": KRB_AP_ERR_MSG_TYPE + "0x29": KRB_AP_ERR_MODIFIED + "0x2A": KRB_AP_ERR_BADORDER + "0x2C": KRB_AP_ERR_BADKEYVER + "0x2D": KRB_AP_ERR_NOKEY + "0x2E": KRB_AP_ERR_MUT_FAIL + "0x2F": KRB_AP_ERR_BADDIRECTION + "0x30": KRB_AP_ERR_METHOD + "0x31": KRB_AP_ERR_BADSEQ + "0x32": KRB_AP_ERR_INAPP_CKSUM + "0x33": KRB_AP_PATH_NOT_ACCEPTED + "0x34": KRB_ERR_RESPONSE_TOO_BIG + "0x3C": KRB_ERR_GENERIC + "0x3D": KRB_ERR_FIELD_TOOLONG + "0x3E": KDC_ERR_CLIENT_NOT_TRUSTED + "0x3F": KDC_ERR_KDC_NOT_TRUSTED + "0x40": KDC_ERR_INVALID_SIG + "0x41": KDC_ERR_KEY_TOO_WEAK + "0x42": KRB_AP_ERR_USER_TO_USER_REQUIRED + "0x43": KRB_AP_ERR_NO_TGT + "0x44": KDC_ERR_WRONG_REALM + source: |- + if (ctx?.winlog?.event_data?.Status == null || + ctx?.event?.code == null || + !["4768", "4769", "4770", "4771"].contains(ctx.event.code)) { + return; + } + ctx.winlog.event_data.put("StatusDescription", params[ctx.winlog.event_data.Status]); + - script: + lang: painless + ignore_failure: false + tag: Set Service Type and Name + description: Set Service Type and Name + # Services Types + # https://docs.microsoft.com/en-us/windows/security/threat-protection/auditing/event-4697 + params: + "0x1": Kernel Driver + "0x2": File System Driver + "0x8": Recognizer Driver + "0x10": Win32 Own Process + "0x20": Win32 Share Process + "0x110": Interactive Own Process + "0x120": Interactive Share Process + source: |- + if (ctx?.winlog?.event_data?.ServiceName != null) { + if (ctx?.service == null) { + HashMap hm = new HashMap(); + ctx.put("service", hm); + } + ctx.service.put("name", ctx.winlog.event_data.ServiceName); + } + if (ctx?.winlog.event_data?.ServiceType != null) { + if (ctx?.service == null) { + HashMap hm = new HashMap(); + ctx.put("service", hm); + } + ctx.service.put("type", params[ctx.winlog.event_data.ServiceType]); + } + - script: + lang: painless + ignore_failure: false + tag: Set Audit Information + description: Set Audit Information + # Audit Categories Description + # https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-gpac/77878370-0712-47cd-997d-b07053429f6d + params: + "0CCE9210-69AE-11D9-BED3-505054503030": ["Security State Change", "System"] + "0CCE9211-69AE-11D9-BED3-505054503030": ["Security System Extension", "System"] + "0CCE9212-69AE-11D9-BED3-505054503030": ["System Integrity", "System"] + "0CCE9213-69AE-11D9-BED3-505054503030": ["IPsec Driver", "System"] + "0CCE9214-69AE-11D9-BED3-505054503030": ["Other System Events", "System"] + "0CCE9215-69AE-11D9-BED3-505054503030": ["Logon", "Logon/Logoff"] + "0CCE9216-69AE-11D9-BED3-505054503030": ["Logoff", "Logon/Logoff"] + "0CCE9217-69AE-11D9-BED3-505054503030": ["Account Lockout", "Logon/Logoff"] + "0CCE9218-69AE-11D9-BED3-505054503030": ["IPsec Main Mode", "Logon/Logoff"] + "0CCE9219-69AE-11D9-BED3-505054503030": ["IPsec Quick Mode", "Logon/Logoff"] + "0CCE921A-69AE-11D9-BED3-505054503030": ["IPsec Extended Mode", "Logon/Logoff"] + "0CCE921B-69AE-11D9-BED3-505054503030": ["Special Logon", "Logon/Logoff"] + "0CCE921C-69AE-11D9-BED3-505054503030": ["Other Logon/Logoff Events", "Logon/Logoff"] + "0CCE9243-69AE-11D9-BED3-505054503030": ["Network Policy Server", "Logon/Logoff"] + "0CCE9247-69AE-11D9-BED3-505054503030": ["User / Device Claims", "Logon/Logoff"] + "0CCE921D-69AE-11D9-BED3-505054503030": ["File System", "Object Access"] + "0CCE921E-69AE-11D9-BED3-505054503030": ["Registry", "Object Access"] + "0CCE921F-69AE-11D9-BED3-505054503030": ["Kernel Object", "Object Access"] + "0CCE9220-69AE-11D9-BED3-505054503030": ["SAM", "Object Access"] + "0CCE9221-69AE-11D9-BED3-505054503030": ["Certification Services", "Object Access"] + "0CCE9222-69AE-11D9-BED3-505054503030": ["Application Generated", "Object Access"] + "0CCE9223-69AE-11D9-BED3-505054503030": ["Handle Manipulation", "Object Access"] + "0CCE9224-69AE-11D9-BED3-505054503030": ["File Share", "Object Access"] + "0CCE9225-69AE-11D9-BED3-505054503030": ["Filtering Platform Packet Drop", "Object Access"] + "0CCE9226-69AE-11D9-BED3-505054503030": ["Filtering Platform Connection ", "Object Access"] + "0CCE9227-69AE-11D9-BED3-505054503030": ["Other Object Access Events", "Object Access"] + "0CCE9244-69AE-11D9-BED3-505054503030": ["Detailed File Share", "Object Access"] + "0CCE9245-69AE-11D9-BED3-505054503030": ["Removable Storage", "Object Access"] + "0CCE9246-69AE-11D9-BED3-505054503030": ["Central Policy Staging", "Object Access"] + "0CCE9228-69AE-11D9-BED3-505054503030": ["Sensitive Privilege Use", "Privilege Use"] + "0CCE9229-69AE-11D9-BED3-505054503030": ["Non Sensitive Privilege Use", "Privilege Use"] + "0CCE922A-69AE-11D9-BED3-505054503030": ["Other Privilege Use Events", "Privilege Use"] + "0CCE922B-69AE-11D9-BED3-505054503030": ["Process Creation", "Detailed Tracking"] + "0CCE922C-69AE-11D9-BED3-505054503030": ["Process Termination", "Detailed Tracking"] + "0CCE922D-69AE-11D9-BED3-505054503030": ["DPAPI Activity", "Detailed Tracking"] + "0CCE922E-69AE-11D9-BED3-505054503030": ["RPC Events", "Detailed Tracking"] + "0CCE9248-69AE-11D9-BED3-505054503030": ["Plug and Play Events", "Detailed Tracking"] + "0CCE922F-69AE-11D9-BED3-505054503030": ["Audit Policy Change", "Policy Change"] + "0CCE9230-69AE-11D9-BED3-505054503030": ["Authentication Policy Change", "Policy Change"] + "0CCE9231-69AE-11D9-BED3-505054503030": ["Authorization Policy Change", "Policy Change"] + "0CCE9232-69AE-11D9-BED3-505054503030": ["MPSSVC Rule-Level Policy Change", "Policy Change"] + "0CCE9233-69AE-11D9-BED3-505054503030": ["Filtering Platform Policy Change", "Policy Change"] + "0CCE9234-69AE-11D9-BED3-505054503030": ["Other Policy Change Events", "Policy Change"] + "0CCE9235-69AE-11D9-BED3-505054503030": ["User Account Management", "Account Management"] + "0CCE9236-69AE-11D9-BED3-505054503030": ["Computer Account Management", "Account Management"] + "0CCE9237-69AE-11D9-BED3-505054503030": ["Security Group Management", "Account Management"] + "0CCE9238-69AE-11D9-BED3-505054503030": ["Distribution Group Management", "Account Management"] + "0CCE9239-69AE-11D9-BED3-505054503030": ["Application Group Management", "Account Management"] + "0CCE923A-69AE-11D9-BED3-505054503030": ["Other Account Management Events", "Account Management"] + "0CCE923B-69AE-11D9-BED3-505054503030": ["Directory Service Access", "Account Management"] + "0CCE923C-69AE-11D9-BED3-505054503030": ["Directory Service Changes", "Account Management"] + "0CCE923D-69AE-11D9-BED3-505054503030": ["Directory Service Replication", "Account Management"] + "0CCE923E-69AE-11D9-BED3-505054503030": ["Detailed Directory Service Replication", "Account Management"] + "0CCE923F-69AE-11D9-BED3-505054503030": ["Credential Validation", "Account Logon"] + "0CCE9240-69AE-11D9-BED3-505054503030": ["Kerberos Service Ticket Operations", "Account Logon"] + "0CCE9241-69AE-11D9-BED3-505054503030": ["Other Account Logon Events", "Account Logon"] + "0CCE9242-69AE-11D9-BED3-505054503030": ["Kerberos Authentication Service", "Account Logon"] + source: |- + if (ctx?.winlog?.event_data?.SubcategoryGuid == null) { + return; + } + def subCatGuid = ctx.winlog.event_data.SubcategoryGuid.replace("{","").replace("}","").toUpperCase(); + if (!params.containsKey(subCatGuid)) { + return; + } + ctx.winlog.event_data.put("Category", params[subCatGuid][1]); + ctx.winlog.event_data.put("SubCategory", params[subCatGuid][0]); + - script: + lang: painless + ignore_failure: false + tag: Decode message table + description: Decode message table + # Message table extracted from msobjs.dll on Windows 2019. + # https://gist.github.com/andrewkroh/665dca0682bd0e4daf194ab291694012 + # https://docs.microsoft.com/en-us/windows/win32/secauthz/access-rights-and-access-masks + # https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-dtyp/7a53f60e-e730-4dfe-bbe9-b21b62eb790b + params: + descriptions: + "279": "Undefined Access (no effect) Bit 7" + "1536": "Unused message ID" + "1537": "DELETE" + "1538": "READ_CONTROL" + "1539": "WRITE_DAC" + "1540": "WRITE_OWNER" + "1541": "SYNCHRONIZE" + "1542": "ACCESS_SYS_SEC" + "1543": "MAX_ALLOWED" + "1552": "Unknown specific access (bit 0)" + "1553": "Unknown specific access (bit 1)" + "1554": "Unknown specific access (bit 2)" + "1555": "Unknown specific access (bit 3)" + "1556": "Unknown specific access (bit 4)" + "1557": "Unknown specific access (bit 5)" + "1558": "Unknown specific access (bit 6)" + "1559": "Unknown specific access (bit 7)" + "1560": "Unknown specific access (bit 8)" + "1561": "Unknown specific access (bit 9)" + "1562": "Unknown specific access (bit 10)" + "1563": "Unknown specific access (bit 11)" + "1564": "Unknown specific access (bit 12)" + "1565": "Unknown specific access (bit 13)" + "1566": "Unknown specific access (bit 14)" + "1567": "Unknown specific access (bit 15)" + "1601": "Not used" + "1603": "Assign Primary Token Privilege" + "1604": "Lock Memory Privilege" + "1605": "Increase Memory Quota Privilege" + "1606": "Unsolicited Input Privilege" + "1607": "Trusted Computer Base Privilege" + "1608": "Security Privilege" + "1609": "Take Ownership Privilege" + "1610": "Load/Unload Driver Privilege" + "1611": "Profile System Privilege" + "1612": "Set System Time Privilege" + "1613": "Profile Single Process Privilege" + "1614": "Increment Base Priority Privilege" + "1615": "Create Pagefile Privilege" + "1616": "Create Permanent Object Privilege" + "1617": "Backup Privilege" + "1618": "Restore From Backup Privilege" + "1619": "Shutdown System Privilege" + "1620": "Debug Privilege" + "1621": "View or Change Audit Log Privilege" + "1622": "Change Hardware Environment Privilege" + "1623": "Change Notify (and Traverse) Privilege" + "1624": "Remotely Shut System Down Privilege" + "1792": "" + "1794": "" + "1795": "Enabled" + "1796": "Disabled" + "1797": "All" + "1798": "None" + "1799": "Audit Policy query/set API Operation" + "1800": "" + "1801": "Granted by" + "1802": "Denied by" + "1803": "Denied by Integrity Policy check" + "1804": "Granted by Ownership" + "1805": "Not granted" + "1806": "Granted by NULL DACL" + "1807": "Denied by Empty DACL" + "1808": "Granted by NULL Security Descriptor" + "1809": "Unknown or unchecked" + "1810": "Not granted due to missing" + "1811": "Granted by ACE on parent folder" + "1812": "Denied by ACE on parent folder" + "1813": "Granted by Central Access Rule" + "1814": "NOT Granted by Central Access Rule" + "1815": "Granted by parent folder's Central Access Rule" + "1816": "NOT Granted by parent folder's Central Access Rule" + "1817": "Unknown Type" + "1818": "String" + "1819": "Unsigned 64-bit Integer" + "1820": "64-bit Integer" + "1821": "FQBN" + "1822": "Blob" + "1823": "Sid" + "1824": "Boolean" + "1825": "TRUE" + "1826": "FALSE" + "1827": "Invalid" + "1828": "an ACE too long to display" + "1829": "a Security Descriptor too long to display" + "1830": "Not granted to AppContainers" + "1831": "..." + "1832": "Identification" + "1833": "Impersonation" + "1840": "Delegation" + "1841": "Denied by Process Trust Label ACE" + "1842": "Yes" + "1843": "No" + "1844": "System" + "1845": "Not Available" + "1846": "Default" + "1847": "DisallowMmConfig" + "1848": "Off" + "1849": "Auto" + "1872": "REG_NONE" + "1873": "REG_SZ" + "1874": "REG_EXPAND_SZ" + "1875": "REG_BINARY" + "1876": "REG_DWORD" + "1877": "REG_DWORD_BIG_ENDIAN" + "1878": "REG_LINK" + "1879": "REG_MULTI_SZ (New lines are replaced with *. A * is replaced with **)" + "1880": "REG_RESOURCE_LIST" + "1881": "REG_FULL_RESOURCE_DESCRIPTOR" + "1882": "REG_RESOURCE_REQUIREMENTS_LIST" + "1883": "REG_QWORD" + "1904": "New registry value created" + "1905": "Existing registry value modified" + "1906": "Registry value deleted" + "1920": "Sunday" + "1921": "Monday" + "1922": "Tuesday" + "1923": "Wednesday" + "1924": "Thursday" + "1925": "Friday" + "1926": "Saturday" + "1936": "TokenElevationTypeDefault (1)" + "1937": "TokenElevationTypeFull (2)" + "1938": "TokenElevationTypeLimited (3)" + "2048": "Account Enabled" + "2049": "Home Directory Required' - Disabled" + "2050": "Password Not Required' - Disabled" + "2051": "Temp Duplicate Account' - Disabled" + "2052": "Normal Account' - Disabled" + "2053": "MNS Logon Account' - Disabled" + "2054": "Interdomain Trust Account' - Disabled" + "2055": "Workstation Trust Account' - Disabled" + "2056": "Server Trust Account' - Disabled" + "2057": "Don't Expire Password' - Disabled" + "2058": "Account Unlocked" + "2059": "Encrypted Text Password Allowed' - Disabled" + "2060": "Smartcard Required' - Disabled" + "2061": "Trusted For Delegation' - Disabled" + "2062": "Not Delegated' - Disabled" + "2063": "Use DES Key Only' - Disabled" + "2064": "Don't Require Preauth' - Disabled" + "2065": "Password Expired' - Disabled" + "2066": "Trusted To Authenticate For Delegation' - Disabled" + "2067": "Exclude Authorization Information' - Disabled" + "2068": "Undefined UserAccountControl Bit 20' - Disabled" + "2069": "Protect Kerberos Service Tickets with AES Keys' - Disabled" + "2070": "Undefined UserAccountControl Bit 22' - Disabled" + "2071": "Undefined UserAccountControl Bit 23' - Disabled" + "2072": "Undefined UserAccountControl Bit 24' - Disabled" + "2073": "Undefined UserAccountControl Bit 25' - Disabled" + "2074": "Undefined UserAccountControl Bit 26' - Disabled" + "2075": "Undefined UserAccountControl Bit 27' - Disabled" + "2076": "Undefined UserAccountControl Bit 28' - Disabled" + "2077": "Undefined UserAccountControl Bit 29' - Disabled" + "2078": "Undefined UserAccountControl Bit 30' - Disabled" + "2079": "Undefined UserAccountControl Bit 31' - Disabled" + "2080": "Account Disabled" + "2081": "Home Directory Required' - Enabled" + "2082": "Password Not Required' - Enabled" + "2083": "Temp Duplicate Account' - Enabled" + "2084": "Normal Account' - Enabled" + "2085": "MNS Logon Account' - Enabled" + "2086": "Interdomain Trust Account' - Enabled" + "2087": "Workstation Trust Account' - Enabled" + "2088": "Server Trust Account' - Enabled" + "2089": "Don't Expire Password' - Enabled" + "2090": "Account Locked" + "2091": "Encrypted Text Password Allowed' - Enabled" + "2092": "Smartcard Required' - Enabled" + "2093": "Trusted For Delegation' - Enabled" + "2094": "Not Delegated' - Enabled" + "2095": "Use DES Key Only' - Enabled" + "2096": "Don't Require Preauth' - Enabled" + "2097": "Password Expired' - Enabled" + "2098": "Trusted To Authenticate For Delegation' - Enabled" + "2099": "Exclude Authorization Information' - Enabled" + "2100": "Undefined UserAccountControl Bit 20' - Enabled" + "2101": "Protect Kerberos Service Tickets with AES Keys' - Enabled" + "2102": "Undefined UserAccountControl Bit 22' - Enabled" + "2103": "Undefined UserAccountControl Bit 23' - Enabled" + "2104": "Undefined UserAccountControl Bit 24' - Enabled" + "2105": "Undefined UserAccountControl Bit 25' - Enabled" + "2106": "Undefined UserAccountControl Bit 26' - Enabled" + "2107": "Undefined UserAccountControl Bit 27' - Enabled" + "2108": "Undefined UserAccountControl Bit 28' - Enabled" + "2109": "Undefined UserAccountControl Bit 29' - Enabled" + "2110": "Undefined UserAccountControl Bit 30' - Enabled" + "2111": "Undefined UserAccountControl Bit 31' - Enabled" + "2304": "An Error occured during Logon." + "2305": "The specified user account has expired." + "2306": "The NetLogon component is not active." + "2307": "Account locked out." + "2308": "The user has not been granted the requested logon type at this machine." + "2309": "The specified account's password has expired." + "2310": "Account currently disabled." + "2311": "Account logon time restriction violation." + "2312": "User not allowed to logon at this computer." + "2313": "Unknown user name or bad password." + "2314": "Domain sid inconsistent." + "2315": "Smartcard logon is required and was not used." + "2432": "Not Available." + "2436": "Random number generator failure." + "2437": "Random number generation failed FIPS-140 pre-hash check." + "2438": "Failed to zero secret data." + "2439": "Key failed pair wise consistency check." + "2448": "Failed to unprotect persistent cryptographic key." + "2449": "Key export checks failed." + "2450": "Validation of public key failed." + "2451": "Signature verification failed." + "2456": "Open key file." + "2457": "Delete key file." + "2458": "Read persisted key from file." + "2459": "Write persisted key to file." + "2464": "Export of persistent cryptographic key." + "2465": "Import of persistent cryptographic key." + "2480": "Open Key." + "2481": "Create Key." + "2482": "Delete Key." + "2483": "Encrypt." + "2484": "Decrypt." + "2485": "Sign hash." + "2486": "Secret agreement." + "2487": "Domain settings" + "2488": "Local settings" + "2489": "Add provider." + "2490": "Remove provider." + "2491": "Add context." + "2492": "Remove context." + "2493": "Add function." + "2494": "Remove function." + "2495": "Add function provider." + "2496": "Remove function provider." + "2497": "Add function property." + "2498": "Remove function property." + "2499": "Machine key." + "2500": "User key." + "2501": "Key Derivation." + "4352": "Device Access Bit 0" + "4353": "Device Access Bit 1" + "4354": "Device Access Bit 2" + "4355": "Device Access Bit 3" + "4356": "Device Access Bit 4" + "4357": "Device Access Bit 5" + "4358": "Device Access Bit 6" + "4359": "Device Access Bit 7" + "4360": "Device Access Bit 8" + "4361": "Undefined Access (no effect) Bit 9" + "4362": "Undefined Access (no effect) Bit 10" + "4363": "Undefined Access (no effect) Bit 11" + "4364": "Undefined Access (no effect) Bit 12" + "4365": "Undefined Access (no effect) Bit 13" + "4366": "Undefined Access (no effect) Bit 14" + "4367": "Undefined Access (no effect) Bit 15" + "4368": "Query directory" + "4369": "Traverse" + "4370": "Create object in directory" + "4371": "Create sub-directory" + "4372": "Undefined Access (no effect) Bit 4" + "4373": "Undefined Access (no effect) Bit 5" + "4374": "Undefined Access (no effect) Bit 6" + "4375": "Undefined Access (no effect) Bit 7" + "4376": "Undefined Access (no effect) Bit 8" + "4377": "Undefined Access (no effect) Bit 9" + "4378": "Undefined Access (no effect) Bit 10" + "4379": "Undefined Access (no effect) Bit 11" + "4380": "Undefined Access (no effect) Bit 12" + "4381": "Undefined Access (no effect) Bit 13" + "4382": "Undefined Access (no effect) Bit 14" + "4383": "Undefined Access (no effect) Bit 15" + "4384": "Query event state" + "4385": "Modify event state" + "4386": "Undefined Access (no effect) Bit 2" + "4387": "Undefined Access (no effect) Bit 3" + "4388": "Undefined Access (no effect) Bit 4" + "4389": "Undefined Access (no effect) Bit 5" + "4390": "Undefined Access (no effect) Bit 6" + "4391": "Undefined Access (no effect) Bit 7" + "4392": "Undefined Access (no effect) Bit 8" + "4393": "Undefined Access (no effect) Bit 9" + "4394": "Undefined Access (no effect) Bit 10" + "4395": "Undefined Access (no effect) Bit 11" + "4396": "Undefined Access (no effect) Bit 12" + "4397": "Undefined Access (no effect) Bit 13" + "4398": "Undefined Access (no effect) Bit 14" + "4399": "Undefined Access (no effect) Bit 15" + "4416": "ReadData (or ListDirectory)" + "4417": "WriteData (or AddFile)" + "4418": "AppendData (or AddSubdirectory or CreatePipeInstance)" + "4419": "ReadEA" + "4420": "WriteEA" + "4421": "Execute/Traverse" + "4422": "DeleteChild" + "4423": "ReadAttributes" + "4424": "WriteAttributes" + "4425": "Undefined Access (no effect) Bit 9" + "4426": "Undefined Access (no effect) Bit 10" + "4427": "Undefined Access (no effect) Bit 11" + "4428": "Undefined Access (no effect) Bit 12" + "4429": "Undefined Access (no effect) Bit 13" + "4430": "Undefined Access (no effect) Bit 14" + "4431": "Undefined Access (no effect) Bit 15" + "4432": "Query key value" + "4433": "Set key value" + "4434": "Create sub-key" + "4435": "Enumerate sub-keys" + "4436": "Notify about changes to keys" + "4437": "Create Link" + "4438": "Undefined Access (no effect) Bit 6" + "4439": "Undefined Access (no effect) Bit 7" + "4440": "Enable 64(or 32) bit application to open 64 bit key" + "4441": "Enable 64(or 32) bit application to open 32 bit key" + "4442": "Undefined Access (no effect) Bit 10" + "4443": "Undefined Access (no effect) Bit 11" + "4444": "Undefined Access (no effect) Bit 12" + "4445": "Undefined Access (no effect) Bit 13" + "4446": "Undefined Access (no effect) Bit 14" + "4447": "Undefined Access (no effect) Bit 15" + "4448": "Query mutant state" + "4449": "Undefined Access (no effect) Bit 1" + "4450": "Undefined Access (no effect) Bit 2" + "4451": "Undefined Access (no effect) Bit 3" + "4452": "Undefined Access (no effect) Bit 4" + "4453": "Undefined Access (no effect) Bit 5" + "4454": "Undefined Access (no effect) Bit 6" + "4455": "Undefined Access (no effect) Bit 7" + "4456": "Undefined Access (no effect) Bit 8" + "4457": "Undefined Access (no effect) Bit 9" + "4458": "Undefined Access (no effect) Bit 10" + "4459": "Undefined Access (no effect) Bit 11" + "4460": "Undefined Access (no effect) Bit 12" + "4461": "Undefined Access (no effect) Bit 13" + "4462": "Undefined Access (no effect) Bit 14" + "4463": "Undefined Access (no effect) Bit 15" + "4464": "Communicate using port" + "4465": "Undefined Access (no effect) Bit 1" + "4466": "Undefined Access (no effect) Bit 2" + "4467": "Undefined Access (no effect) Bit 3" + "4468": "Undefined Access (no effect) Bit 4" + "4469": "Undefined Access (no effect) Bit 5" + "4470": "Undefined Access (no effect) Bit 6" + "4471": "Undefined Access (no effect) Bit 7" + "4472": "Undefined Access (no effect) Bit 8" + "4473": "Undefined Access (no effect) Bit 9" + "4474": "Undefined Access (no effect) Bit 10" + "4475": "Undefined Access (no effect) Bit 11" + "4476": "Undefined Access (no effect) Bit 12" + "4477": "Undefined Access (no effect) Bit 13" + "4478": "Undefined Access (no effect) Bit 14" + "4479": "Undefined Access (no effect) Bit 15" + "4480": "Force process termination" + "4481": "Create new thread in process" + "4482": "Set process session ID" + "4483": "Perform virtual memory operation" + "4484": "Read from process memory" + "4485": "Write to process memory" + "4486": "Duplicate handle into or out of process" + "4487": "Create a subprocess of process" + "4488": "Set process quotas" + "4489": "Set process information" + "4490": "Query process information" + "4491": "Set process termination port" + "4492": "Undefined Access (no effect) Bit 12" + "4493": "Undefined Access (no effect) Bit 13" + "4494": "Undefined Access (no effect) Bit 14" + "4495": "Undefined Access (no effect) Bit 15" + "4496": "Control profile" + "4497": "Undefined Access (no effect) Bit 1" + "4498": "Undefined Access (no effect) Bit 2" + "4499": "Undefined Access (no effect) Bit 3" + "4500": "Undefined Access (no effect) Bit 4" + "4501": "Undefined Access (no effect) Bit 5" + "4502": "Undefined Access (no effect) Bit 6" + "4503": "Undefined Access (no effect) Bit 7" + "4504": "Undefined Access (no effect) Bit 8" + "4505": "Undefined Access (no effect) Bit 9" + "4506": "Undefined Access (no effect) Bit 10" + "4507": "Undefined Access (no effect) Bit 11" + "4508": "Undefined Access (no effect) Bit 12" + "4509": "Undefined Access (no effect) Bit 13" + "4510": "Undefined Access (no effect) Bit 14" + "4511": "Undefined Access (no effect) Bit 15" + "4512": "Query section state" + "4513": "Map section for write" + "4514": "Map section for read" + "4515": "Map section for execute" + "4516": "Extend size" + "4517": "Undefined Access (no effect) Bit 5" + "4518": "Undefined Access (no effect) Bit 6" + "4519": "Undefined Access (no effect) Bit 7" + "4520": "Undefined Access (no effect) Bit 8" + "4521": "Undefined Access (no effect) Bit 9" + "4522": "Undefined Access (no effect) Bit 10" + "4523": "Undefined Access (no effect) Bit 11" + "4524": "Undefined Access (no effect) Bit 12" + "4525": "Undefined Access (no effect) Bit 13" + "4526": "Undefined Access (no effect) Bit 14" + "4527": "Undefined Access (no effect) Bit 15" + "4528": "Query semaphore state" + "4529": "Modify semaphore state" + "4530": "Undefined Access (no effect) Bit 2" + "4531": "Undefined Access (no effect) Bit 3" + "4532": "Undefined Access (no effect) Bit 4" + "4533": "Undefined Access (no effect) Bit 5" + "4534": "Undefined Access (no effect) Bit 6" + "4535": "Undefined Access (no effect) Bit 7" + "4536": "Undefined Access (no effect) Bit 8" + "4537": "Undefined Access (no effect) Bit 9" + "4538": "Undefined Access (no effect) Bit 10" + "4539": "Undefined Access (no effect) Bit 11" + "4540": "Undefined Access (no effect) Bit 12" + "4541": "Undefined Access (no effect) Bit 13" + "4542": "Undefined Access (no effect) Bit 14" + "4543": "Undefined Access (no effect) Bit 15" + "4544": "Use symbolic link" + "4545": "Undefined Access (no effect) Bit 1" + "4546": "Undefined Access (no effect) Bit 2" + "4547": "Undefined Access (no effect) Bit 3" + "4548": "Undefined Access (no effect) Bit 4" + "4549": "Undefined Access (no effect) Bit 5" + "4550": "Undefined Access (no effect) Bit 6" + "4551": "Undefined Access (no effect) Bit 7" + "4552": "Undefined Access (no effect) Bit 8" + "4553": "Undefined Access (no effect) Bit 9" + "4554": "Undefined Access (no effect) Bit 10" + "4555": "Undefined Access (no effect) Bit 11" + "4556": "Undefined Access (no effect) Bit 12" + "4557": "Undefined Access (no effect) Bit 13" + "4558": "Undefined Access (no effect) Bit 14" + "4559": "Undefined Access (no effect) Bit 15" + "4560": "Force thread termination" + "4561": "Suspend or resume thread" + "4562": "Send an alert to thread" + "4563": "Get thread context" + "4564": "Set thread context" + "4565": "Set thread information" + "4566": "Query thread information" + "4567": "Assign a token to the thread" + "4568": "Cause thread to directly impersonate another thread" + "4569": "Directly impersonate this thread" + "4570": "Undefined Access (no effect) Bit 10" + "4571": "Undefined Access (no effect) Bit 11" + "4572": "Undefined Access (no effect) Bit 12" + "4573": "Undefined Access (no effect) Bit 13" + "4574": "Undefined Access (no effect) Bit 14" + "4575": "Undefined Access (no effect) Bit 15" + "4576": "Query timer state" + "4577": "Modify timer state" + "4578": "Undefined Access (no effect) Bit 2" + "4579": "Undefined Access (no effect) Bit 3" + "4580": "Undefined Access (no effect) Bit 4" + "4581": "Undefined Access (no effect) Bit 5" + "4582": "Undefined Access (no effect) Bit 6" + "4584": "Undefined Access (no effect) Bit 8" + "4585": "Undefined Access (no effect) Bit 9" + "4586": "Undefined Access (no effect) Bit 10" + "4587": "Undefined Access (no effect) Bit 11" + "4588": "Undefined Access (no effect) Bit 12" + "4589": "Undefined Access (no effect) Bit 13" + "4590": "Undefined Access (no effect) Bit 14" + "4591": "Undefined Access (no effect) Bit 15" + "4592": "AssignAsPrimary" + "4593": "Duplicate" + "4594": "Impersonate" + "4595": "Query" + "4596": "QuerySource" + "4597": "AdjustPrivileges" + "4598": "AdjustGroups" + "4599": "AdjustDefaultDacl" + "4600": "AdjustSessionID" + "4601": "Undefined Access (no effect) Bit 9" + "4602": "Undefined Access (no effect) Bit 10" + "4603": "Undefined Access (no effect) Bit 11" + "4604": "Undefined Access (no effect) Bit 12" + "4605": "Undefined Access (no effect) Bit 13" + "4606": "Undefined Access (no effect) Bit 14" + "4607": "Undefined Access (no effect) Bit 15" + "4608": "Create instance of object type" + "4609": "Undefined Access (no effect) Bit 1" + "4610": "Undefined Access (no effect) Bit 2" + "4611": "Undefined Access (no effect) Bit 3" + "4612": "Undefined Access (no effect) Bit 4" + "4613": "Undefined Access (no effect) Bit 5" + "4614": "Undefined Access (no effect) Bit 6" + "4615": "Undefined Access (no effect) Bit 7" + "4616": "Undefined Access (no effect) Bit 8" + "4617": "Undefined Access (no effect) Bit 9" + "4618": "Undefined Access (no effect) Bit 10" + "4619": "Undefined Access (no effect) Bit 11" + "4620": "Undefined Access (no effect) Bit 12" + "4621": "Undefined Access (no effect) Bit 13" + "4622": "Undefined Access (no effect) Bit 14" + "4623": "Undefined Access (no effect) Bit 15" + "4864": "Query State" + "4865": "Modify State" + "5120": "Channel read message" + "5121": "Channel write message" + "5122": "Channel query information" + "5123": "Channel set information" + "5124": "Undefined Access (no effect) Bit 4" + "5125": "Undefined Access (no effect) Bit 5" + "5126": "Undefined Access (no effect) Bit 6" + "5127": "Undefined Access (no effect) Bit 7" + "5128": "Undefined Access (no effect) Bit 8" + "5129": "Undefined Access (no effect) Bit 9" + "5130": "Undefined Access (no effect) Bit 10" + "5131": "Undefined Access (no effect) Bit 11" + "5132": "Undefined Access (no effect) Bit 12" + "5133": "Undefined Access (no effect) Bit 13" + "5134": "Undefined Access (no effect) Bit 14" + "5135": "Undefined Access (no effect) Bit 15" + "5136": "Assign process" + "5137": "Set Attributes" + "5138": "Query Attributes" + "5139": "Terminate Job" + "5140": "Set Security Attributes" + "5141": "Undefined Access (no effect) Bit 5" + "5142": "Undefined Access (no effect) Bit 6" + "5143": "Undefined Access (no effect) Bit 7" + "5144": "Undefined Access (no effect) Bit 8" + "5145": "Undefined Access (no effect) Bit 9" + "5146": "Undefined Access (no effect) Bit 10" + "5147": "Undefined Access (no effect) Bit 11" + "5148": "Undefined Access (no effect) Bit 12" + "5149": "Undefined Access (no effect) Bit 13" + "5150": "Undefined Access (no effect) Bit 14" + "5151": "Undefined Access (no effect) Bit 15" + "5376": "ConnectToServer" + "5377": "ShutdownServer" + "5378": "InitializeServer" + "5379": "CreateDomain" + "5380": "EnumerateDomains" + "5381": "LookupDomain" + "5382": "Undefined Access (no effect) Bit 6" + "5383": "Undefined Access (no effect) Bit 7" + "5384": "Undefined Access (no effect) Bit 8" + "5385": "Undefined Access (no effect) Bit 9" + "5386": "Undefined Access (no effect) Bit 10" + "5387": "Undefined Access (no effect) Bit 11" + "5388": "Undefined Access (no effect) Bit 12" + "5389": "Undefined Access (no effect) Bit 13" + "5390": "Undefined Access (no effect) Bit 14" + "5391": "Undefined Access (no effect) Bit 15" + "5392": "ReadPasswordParameters" + "5393": "WritePasswordParameters" + "5394": "ReadOtherParameters" + "5395": "WriteOtherParameters" + "5396": "CreateUser" + "5397": "CreateGlobalGroup" + "5398": "CreateLocalGroup" + "5399": "GetLocalGroupMembership" + "5400": "ListAccounts" + "5401": "LookupIDs" + "5402": "AdministerServer" + "5403": "Undefined Access (no effect) Bit 11" + "5404": "Undefined Access (no effect) Bit 12" + "5405": "Undefined Access (no effect) Bit 13" + "5406": "Undefined Access (no effect) Bit 14" + "5407": "Undefined Access (no effect) Bit 15" + "5408": "ReadInformation" + "5409": "WriteAccount" + "5410": "AddMember" + "5411": "RemoveMember" + "5412": "ListMembers" + "5413": "Undefined Access (no effect) Bit 5" + "5414": "Undefined Access (no effect) Bit 6" + "5415": "Undefined Access (no effect) Bit 7" + "5416": "Undefined Access (no effect) Bit 8" + "5417": "Undefined Access (no effect) Bit 9" + "5418": "Undefined Access (no effect) Bit 10" + "5419": "Undefined Access (no effect) Bit 11" + "5420": "Undefined Access (no effect) Bit 12" + "5421": "Undefined Access (no effect) Bit 13" + "5422": "Undefined Access (no effect) Bit 14" + "5423": "Undefined Access (no effect) Bit 15" + "5424": "AddMember" + "5425": "RemoveMember" + "5426": "ListMembers" + "5427": "ReadInformation" + "5428": "WriteAccount" + "5429": "Undefined Access (no effect) Bit 5" + "5430": "Undefined Access (no effect) Bit 6" + "5431": "Undefined Access (no effect) Bit 7" + "5432": "Undefined Access (no effect) Bit 8" + "5433": "Undefined Access (no effect) Bit 9" + "5434": "Undefined Access (no effect) Bit 10" + "5435": "Undefined Access (no effect) Bit 11" + "5436": "Undefined Access (no effect) Bit 12" + "5437": "Undefined Access (no effect) Bit 13" + "5438": "Undefined Access (no effect) Bit 14" + "5439": "Undefined Access (no effect) Bit 15" + "5440": "ReadGeneralInformation" + "5441": "ReadPreferences" + "5442": "WritePreferences" + "5443": "ReadLogon" + "5444": "ReadAccount" + "5445": "WriteAccount" + "5446": "ChangePassword (with knowledge of old password)" + "5447": "SetPassword (without knowledge of old password)" + "5448": "ListGroups" + "5449": "ReadGroupMembership" + "5450": "ChangeGroupMembership" + "5451": "Undefined Access (no effect) Bit 11" + "5452": "Undefined Access (no effect) Bit 12" + "5453": "Undefined Access (no effect) Bit 13" + "5454": "Undefined Access (no effect) Bit 14" + "5455": "Undefined Access (no effect) Bit 15" + "5632": "View non-sensitive policy information" + "5633": "View system audit requirements" + "5634": "Get sensitive policy information" + "5635": "Modify domain trust relationships" + "5636": "Create special accounts (for assignment of user rights)" + "5637": "Create a secret object" + "5638": "Create a privilege" + "5639": "Set default quota limits" + "5640": "Change system audit requirements" + "5641": "Administer audit log attributes" + "5642": "Enable/Disable LSA" + "5643": "Lookup Names/SIDs" + "5648": "Change secret value" + "5649": "Query secret value" + "5650": "Undefined Access (no effect) Bit 2" + "5651": "Undefined Access (no effect) Bit 3" + "5652": "Undefined Access (no effect) Bit 4" + "5653": "Undefined Access (no effect) Bit 5" + "5654": "Undefined Access (no effect) Bit 6" + "5655": "Undefined Access (no effect) Bit 7" + "5656": "Undefined Access (no effect) Bit 8" + "5657": "Undefined Access (no effect) Bit 9" + "5658": "Undefined Access (no effect) Bit 10" + "5659": "Undefined Access (no effect) Bit 11" + "5660": "Undefined Access (no effect) Bit 12" + "5661": "Undefined Access (no effect) Bit 13" + "5662": "Undefined Access (no effect) Bit 14" + "5663": "Undefined Access (no effect) Bit 15" + "5664": "Query trusted domain name/SID" + "5665": "Retrieve the controllers in the trusted domain" + "5666": "Change the controllers in the trusted domain" + "5667": "Query the Posix ID offset assigned to the trusted domain" + "5668": "Change the Posix ID offset assigned to the trusted domain" + "5669": "Undefined Access (no effect) Bit 5" + "5670": "Undefined Access (no effect) Bit 6" + "5671": "Undefined Access (no effect) Bit 7" + "5672": "Undefined Access (no effect) Bit 8" + "5673": "Undefined Access (no effect) Bit 9" + "5674": "Undefined Access (no effect) Bit 10" + "5675": "Undefined Access (no effect) Bit 11" + "5676": "Undefined Access (no effect) Bit 12" + "5677": "Undefined Access (no effect) Bit 13" + "5678": "Undefined Access (no effect) Bit 14" + "5679": "Undefined Access (no effect) Bit 15" + "5680": "Query account information" + "5681": "Change privileges assigned to account" + "5682": "Change quotas assigned to account" + "5683": "Change logon capabilities assigned to account" + "5684": "Change the Posix ID offset assigned to the accounted domain" + "5685": "Undefined Access (no effect) Bit 5" + "5686": "Undefined Access (no effect) Bit 6" + "5687": "Undefined Access (no effect) Bit 7" + "5688": "Undefined Access (no effect) Bit 8" + "5689": "Undefined Access (no effect) Bit 9" + "5690": "Undefined Access (no effect) Bit 10" + "5691": "Undefined Access (no effect) Bit 11" + "5692": "Undefined Access (no effect) Bit 12" + "5693": "Undefined Access (no effect) Bit 13" + "5694": "Undefined Access (no effect) Bit 14" + "5695": "Undefined Access (no effect) Bit 15" + "5696": "KeyedEvent Wait" + "5697": "KeyedEvent Wake" + "5698": "Undefined Access (no effect) Bit 2" + "5699": "Undefined Access (no effect) Bit 3" + "5700": "Undefined Access (no effect) Bit 4" + "5701": "Undefined Access (no effect) Bit 5" + "5702": "Undefined Access (no effect) Bit 6" + "5703": "Undefined Access (no effect) Bit 7" + "5704": "Undefined Access (no effect) Bit 8" + "5705": "Undefined Access (no effect) Bit 9" + "5706": "Undefined Access (no effect) Bit 10" + "5707": "Undefined Access (no effect) Bit 11" + "5708": "Undefined Access (no effect) Bit 12" + "5709": "Undefined Access (no effect) Bit 13" + "5710": "Undefined Access (no effect) Bit 14" + "5711": "Undefined Access (no effect) Bit 15" + "6656": "Enumerate desktops" + "6657": "Read attributes" + "6658": "Access Clipboard" + "6659": "Create desktop" + "6660": "Write attributes" + "6661": "Access global atoms" + "6662": "Exit windows" + "6663": "Unused Access Flag" + "6664": "Include this windowstation in enumerations" + "6665": "Read screen" + "6672": "Read Objects" + "6673": "Create window" + "6674": "Create menu" + "6675": "Hook control" + "6676": "Journal (record)" + "6677": "Journal (playback)" + "6678": "Include this desktop in enumerations" + "6679": "Write objects" + "6680": "Switch to this desktop" + "6912": "Administer print server" + "6913": "Enumerate printers" + "6930": "Full Control" + "6931": "Print" + "6948": "Administer Document" + "7168": "Connect to service controller" + "7169": "Create a new service" + "7170": "Enumerate services" + "7171": "Lock service database for exclusive access" + "7172": "Query service database lock state" + "7173": "Set last-known-good state of service database" + "7184": "Query service configuration information" + "7185": "Set service configuration information" + "7186": "Query status of service" + "7187": "Enumerate dependencies of service" + "7188": "Start the service" + "7189": "Stop the service" + "7190": "Pause or continue the service" + "7191": "Query information from service" + "7192": "Issue service-specific control commands" + "7424": "DDE Share Read" + "7425": "DDE Share Write" + "7426": "DDE Share Initiate Static" + "7427": "DDE Share Initiate Link" + "7428": "DDE Share Request" + "7429": "DDE Share Advise" + "7430": "DDE Share Poke" + "7431": "DDE Share Execute" + "7432": "DDE Share Add Items" + "7433": "DDE Share List Items" + "7680": "Create Child" + "7681": "Delete Child" + "7682": "List Contents" + "7683": "Write Self" + "7684": "Read Property" + "7685": "Write Property" + "7686": "Delete Tree" + "7687": "List Object" + "7688": "Control Access" + "7689": "Undefined Access (no effect) Bit 9" + "7690": "Undefined Access (no effect) Bit 10" + "7691": "Undefined Access (no effect) Bit 11" + "7692": "Undefined Access (no effect) Bit 12" + "7693": "Undefined Access (no effect) Bit 13" + "7694": "Undefined Access (no effect) Bit 14" + "7695": "Undefined Access (no effect) Bit 15" + "7936": "Audit Set System Policy" + "7937": "Audit Query System Policy" + "7938": "Audit Set Per User Policy" + "7939": "Audit Query Per User Policy" + "7940": "Audit Enumerate Users" + "7941": "Audit Set Options" + "7942": "Audit Query Options" + "8064": "Port sharing (read)" + "8065": "Port sharing (write)" + "8096": "Default credentials" + "8097": "Credentials manager" + "8098": "Fresh credentials" + "8192": "Kerberos" + "8193": "Preshared key" + "8194": "Unknown authentication" + "8195": "DES" + "8196": "3DES" + "8197": "MD5" + "8198": "SHA1" + "8199": "Local computer" + "8200": "Remote computer" + "8201": "No state" + "8202": "Sent first (SA) payload" + "8203": "Sent second (KE) payload" + "8204": "Sent third (ID) payload" + "8205": "Initiator" + "8206": "Responder" + "8207": "No state" + "8208": "Sent first (SA) payload" + "8209": "Sent final payload" + "8210": "Complete" + "8211": "Unknown" + "8212": "Transport" + "8213": "Tunnel" + "8214": "IKE/AuthIP DoS prevention mode started" + "8215": "IKE/AuthIP DoS prevention mode stopped" + "8216": "Enabled" + "8217": "Not enabled" + "8218": "No state" + "8219": "Sent first (EM attributes) payload" + "8220": "Sent second (SSPI) payload" + "8221": "Sent third (hash) payload" + "8222": "IKEv1" + "8223": "AuthIP" + "8224": "Anonymous" + "8225": "NTLM V2" + "8226": "CGA" + "8227": "Certificate" + "8228": "SSL" + "8229": "None" + "8230": "DH group 1" + "8231": "DH group 2" + "8232": "DH group 14" + "8233": "DH group ECP 256" + "8234": "DH group ECP 384" + "8235": "AES-128" + "8236": "AES-192" + "8237": "AES-256" + "8238": "Certificate ECDSA P256" + "8239": "Certificate ECDSA P384" + "8240": "SSL ECDSA P256" + "8241": "SSL ECDSA P384" + "8242": "SHA 256" + "8243": "SHA 384" + "8244": "IKEv2" + "8245": "EAP payload sent" + "8246": "Authentication payload sent" + "8247": "EAP" + "8248": "DH group 24" + "8272": "System" + "8273": "Logon/Logoff" + "8274": "Object Access" + "8275": "Privilege Use" + "8276": "Detailed Tracking" + "8277": "Policy Change" + "8278": "Account Management" + "8279": "DS Access" + "8280": "Account Logon" + "8448": "Success removed" + "8449": "Success Added" + "8450": "Failure removed" + "8451": "Failure Added" + "8452": "Success include removed" + "8453": "Success include added" + "8454": "Success exclude removed" + "8455": "Success exclude added" + "8456": "Failure include removed" + "8457": "Failure include added" + "8458": "Failure exclude removed" + "8459": "Failure exclude added" + "12288": "Security State Change" + "12289": "Security System Extension" + "12290": "System Integrity" + "12291": "IPsec Driver" + "12292": "Other System Events" + "12544": "Logon" + "12545": "Logoff" + "12546": "Account Lockout" + "12547": "IPsec Main Mode" + "12548": "Special Logon" + "12549": "IPsec Quick Mode" + "12550": "IPsec Extended Mode" + "12551": "Other Logon/Logoff Events" + "12552": "Network Policy Server" + "12553": "User / Device Claims" + "12554": "Group Membership" + "12800": "File System" + "12801": "Registry" + "12802": "Kernel Object" + "12803": "SAM" + "12804": "Other Object Access Events" + "12805": "Certification Services" + "12806": "Application Generated" + "12807": "Handle Manipulation" + "12808": "File Share" + "12809": "Filtering Platform Packet Drop" + "12810": "Filtering Platform Connection" + "12811": "Detailed File Share" + "12812": "Removable Storage" + "12813": "Central Policy Staging" + "13056": "Sensitive Privilege Use" + "13057": "Non Sensitive Privilege Use" + "13058": "Other Privilege Use Events" + "13312": "Process Creation" + "13313": "Process Termination" + "13314": "DPAPI Activity" + "13315": "RPC Events" + "13316": "Plug and Play Events" + "13317": "Token Right Adjusted Events" + "13568": "Audit Policy Change" + "13569": "Authentication Policy Change" + "13570": "Authorization Policy Change" + "13571": "MPSSVC Rule-Level Policy Change" + "13572": "Filtering Platform Policy Change" + "13573": "Other Policy Change Events" + "13824": "User Account Management" + "13825": "Computer Account Management" + "13826": "Security Group Management" + "13827": "Distribution Group Management" + "13828": "Application Group Management" + "13829": "Other Account Management Events" + "14080": "Directory Service Access" + "14081": "Directory Service Changes" + "14082": "Directory Service Replication" + "14083": "Detailed Directory Service Replication" + "14336": "Credential Validation" + "14337": "Kerberos Service Ticket Operations" + "14338": "Other Account Logon Events" + "14339": "Kerberos Authentication Service" + "14592": "Inbound" + "14593": "Outbound" + "14594": "Forward" + "14595": "Bidirectional" + "14596": "IP Packet" + "14597": "Transport" + "14598": "Forward" + "14599": "Stream" + "14600": "Datagram Data" + "14601": "ICMP Error" + "14602": "MAC 802.3" + "14603": "MAC Native" + "14604": "vSwitch" + "14608": "Resource Assignment" + "14609": "Listen" + "14610": "Receive/Accept" + "14611": "Connect" + "14612": "Flow Established" + "14614": "Resource Release" + "14615": "Endpoint Closure" + "14616": "Connect Redirect" + "14617": "Bind Redirect" + "14624": "Stream Packet" + "14640": "ICMP Echo-Request" + "14641": "vSwitch Ingress" + "14642": "vSwitch Egress" + "14672": "" + "14673": "[NULL]" + "14674": "Value Added" + "14675": "Value Deleted" + "14676": "Active Directory Domain Services" + "14677": "Active Directory Lightweight Directory Services" + "14678": "Yes" + "14679": "No" + "14680": "Value Added With Expiration Time" + "14681": "Value Deleted With Expiration Time" + "14688": "Value Auto Deleted With Expiration Time" + "16384": "Add" + "16385": "Delete" + "16386": "Boot-time" + "16387": "Persistent" + "16388": "Not persistent" + "16389": "Block" + "16390": "Permit" + "16391": "Callout" + "16392": "MD5" + "16393": "SHA-1" + "16394": "SHA-256" + "16395": "AES-GCM 128" + "16396": "AES-GCM 192" + "16397": "AES-GCM 256" + "16398": "DES" + "16399": "3DES" + "16400": "AES-128" + "16401": "AES-192" + "16402": "AES-256" + "16403": "Transport" + "16404": "Tunnel" + "16405": "Responder" + "16406": "Initiator" + "16407": "AES-GMAC 128" + "16408": "AES-GMAC 192" + "16409": "AES-GMAC 256" + "16416": "AuthNoEncap Transport" + "16896": "Enable WMI Account" + "16897": "Execute Method" + "16898": "Full Write" + "16899": "Partial Write" + "16900": "Provider Write" + "16901": "Remote Access" + "16902": "Subscribe" + "16903": "Publish" + AccessMaskDescriptions: + "0x00000001": Create Child + "0x00000002": Delete Child + "0x00000004": List Contents + "0x00000008": SELF + "0x00000010": Read Property + "0x00000020": Write Property + "0x00000040": Delete Treee + "0x00000080": List Object + "0x00000100": Control Access + "0x00010000": DELETE + "0x00020000": READ_CONTROL + "0x00040000": WRITE_DAC + "0x00080000": WRITE_OWNER + "0x00100000": SYNCHRONIZE + "0x00F00000": STANDARD_RIGHTS_REQUIRED + "0x001F0000": STANDARD_RIGHTS_ALL + "0x0000FFFF": SPECIFIC_RIGHTS_ALL + "0x01000000": ADS_RIGHT_ACCESS_SYSTEM_SECURITY + "0x10000000": ADS_RIGHT_GENERIC_ALL + "0x20000000": ADS_RIGHT_GENERIC_EXECUTE + "0x40000000": ADS_RIGHT_GENERIC_WRITE + "0x80000000": ADS_RIGHT_GENERIC_READ + source: |- + if (ctx?.winlog?.event_data?.FailureReason != null) { + def code = ctx.winlog.event_data.FailureReason.replace("%%",""); + if (params.descriptions.containsKey(code)) { + if (ctx?.winlog?.logon == null ) { + HashMap hm = new HashMap(); + ctx.winlog.put("logon", hm); + } + if (ctx?.winlog?.logon?.failure == null) { + HashMap hm = new HashMap(); + ctx.winlog.logon.put("failure", hm); + } + ctx.winlog.logon.failure.put("reason", params.descriptions[code]); + } + } + if (ctx?.winlog?.event_data?.AuditPolicyChanges != null) { + ArrayList results = new ArrayList(); + for (elem in ctx.winlog.event_data.AuditPolicyChanges.splitOnToken(",")) { + def code = elem.replace("%%","").trim(); + if (params.descriptions.containsKey(code)) { + results.add(params.descriptions[code]); + } + } + if (results.length > 0) { + ctx.winlog.event_data.put("AuditPolicyChangesDescription", results); + } + } + if (ctx?.winlog?.event_data?.AccessList != null) { + ArrayList results = new ArrayList(); + for (elem in ctx.winlog.event_data.AccessList.splitOnToken(" ")) { + def code = elem.replace("%%","").trim(); + if (params.descriptions.containsKey(code)) { + results.add(params.descriptions[code]); + } + } + if (results.length > 0) { + ctx.winlog.event_data.put("AccessListDescription", results); + } + } + if (ctx?.winlog?.event_data?.AccessMask != null) { + ArrayList results = new ArrayList(); + Long accessMask = Long.decode(ctx.winlog.event_data.AccessMask); + for (entry in params.AccessMaskDescriptions.entrySet()) { + Long accessFlag = Long.decode(entry.getKey()); + if ((accessMask.longValue() & accessFlag.longValue()) == accessFlag.longValue()) { + results.add(entry.getValue()); + } + } + if (results.length > 0) { + ctx.winlog.event_data.put("AccessMaskDescription", results); + } + } + - script: + lang: painless + ignore_failure: false + tag: 4625 and 4776 Set Status and SubStatus + description: 4625 and 4776 Set Status and SubStatus + # Descriptions of failure status codes. + # https://docs.microsoft.com/en-us/windows/security/threat-protection/auditing/event-4625 + # https://docs.microsoft.com/en-us/windows/security/threat-protection/auditing/event-4776 + params: + "0xc000005e": "There are currently no logon servers available to service the logon request." + "0xc0000064": "User logon with misspelled or bad user account" + "0xc000006a": "User logon with misspelled or bad password" + "0xc000006d": "This is either due to a bad username or authentication information" + "0xc000006e": "Unknown user name or bad password." + "0xc000006f": "User logon outside authorized hours" + "0xc0000070": "User logon from unauthorized workstation" + "0xc0000071": "User logon with expired password" + "0xc0000072": "User logon to account disabled by administrator" + "0xc00000dc": "Indicates the Sam Server was in the wrong state to perform the desired operation." + "0xc0000133": "Clocks between DC and other computer too far out of sync" + "0xc000015b": "The user has not been granted the requested logon type (aka logon right) at this machine" + "0xc000018c": "The logon request failed because the trust relationship between the primary domain and the trusted domain failed." + "0xc0000192": "An attempt was made to logon, but the Netlogon service was not started." + "0xc0000193": "User logon with expired account" + "0xc0000224": "User is required to change password at next logon" + "0xc0000225": "Evidently a bug in Windows and not a risk" + "0xc0000234": "User logon with account locked" + "0xc00002ee": "Failure Reason: An Error occurred during Logon" + "0xc0000413": "Logon Failure: The machine you are logging onto is protected by an authentication firewall. The specified account is not allowed to authenticate to the machine." + "0xc0000371": "The local account store does not contain secret material for the specified account" + "0x0": "Status OK." + source: |- + if (ctx?.winlog?.event_data?.Status == null || + ctx?.event?.code == null || + !["4625", "4776"].contains(ctx.event.code)) { + return; + } + if (params.containsKey(ctx.winlog.event_data.Status)) { + if (ctx?.winlog?.logon == null ) { + HashMap hm = new HashMap(); + ctx.winlog.put("logon", hm); + } + if (ctx?.winlog?.logon?.failure == null) { + HashMap hm = new HashMap(); + ctx.winlog.logon.put("failure", hm); + } + ctx.winlog.logon.failure.put("status", params[ctx.winlog.event_data.Status]); + } + if (ctx?.winlog?.event_data?.SubStatus == null || !params.containsKey(ctx.winlog.event_data.SubStatus)) { + return; + } + if (ctx?.winlog?.logon == null ) { + HashMap hm = new HashMap(); + ctx.winlog.put("logon", hm); + } + if (ctx?.winlog?.logon?.failure == null) { + HashMap hm = new HashMap(); + ctx.winlog.logon.put("failure", hm); + } + ctx.winlog.logon.failure.put("sub_status", params[ctx.winlog.event_data.SubStatus]); + - script: + lang: painless + ignore_failure: false + tag: Set Trust Type + description: Set Trust Type + # Trust Types + # https://docs.microsoft.com/en-us/windows/security/threat-protection/auditing/event-4706 + params: + "1": "TRUST_TYPE_DOWNLEVEL" + "2": "TRUST_TYPE_UPLEVEL" + "3": "TRUST_TYPE_MIT" + "4": "TRUST_TYPE_DCE" + source: |- + if (ctx?.winlog?.event_data?.TdoType == null) { + return; + } + if (!params.containsKey(ctx.winlog.event_data.TdoType)) { + return; + } + ctx.winlog.put("trustType", params[ctx.winlog.event_data.TdoType]); + - script: + lang: painless + ignore_failure: false + tag: Set Trust Direction + description: Set Trust Direction + # Trust Direction + # https://docs.microsoft.com/en-us/windows/security/threat-protection/auditing/event-4706 + params: + "0": "TRUST_DIRECTION_DISABLED" + "1": "TRUST_DIRECTION_INBOUND" + "2": "TRUST_DIRECTION_OUTBOUND" + "3": "TRUST_DIRECTION_BIDIRECTIONAL" + source: |- + if (ctx?.winlog?.event_data?.TdoDirection == null) { + return; + } + if (!params.containsKey(ctx.winlog.event_data.TdoDirection)) { + return; + } + ctx.winlog.put("trustDirection", params[ctx.winlog.event_data.TdoDirection]); + - script: + lang: painless + ignore_failure: false + tag: Set Trust Attributes + description: Set Trust Attributes + # Trust Attributes + # https://docs.microsoft.com/en-us/windows/security/threat-protection/auditing/event-4706 + params: + "0": "UNDEFINED" + "1": "TRUST_ATTRIBUTE_NON_TRANSITIVE" + "2": "TRUST_ATTRIBUTE_UPLEVEL_ONLY" + "4": "TRUST_ATTRIBUTE_QUARANTINED_DOMAIN" + "8": "TRUST_ATTRIBUTE_FOREST_TRANSITIVE" + "16": "TRUST_ATTRIBUTE_CROSS_ORGANIZATION" + "32": "TRUST_ATTRIBUTE_WITHIN_FOREST" + "64": "TRUST_ATTRIBUTE_TREAT_AS_EXTERNAL" + "128": "TRUST_ATTRIBUTE_USES_RC4_ENCRYPTION" + "512": "TRUST_ATTRIBUTE_CROSS_ORGANIZATION_NO_TGT_DELEGATION" + "1024": "TRUST_ATTRIBUTE_PIM_TRUST" + source: |- + if (ctx?.winlog?.event_data?.TdoAttributes == null) { + return; + } + if (!params.containsKey(ctx.winlog.event_data.TdoAttributes)) { + return; + } + ctx.winlog.put("trustAttribute", params[ctx.winlog.event_data.TdoAttributes]); + - script: + lang: painless + ignore_failure: false + tag: Add Session Events + description: Add Session Events + source: |- + if (ctx?.event?.code == null || + !["4778", "4779"].contains(ctx.event.code)) { + return; + } + //AccountName to user.name and related.user + if (ctx?.winlog?.event_data?.AccountName != null) { + if (ctx?.user == null) { + HashMap hm = new HashMap(); + ctx.put("user", hm); + } + if (ctx?.related == null) { + HashMap hm = new HashMap(); + ctx.put("related", hm); + } + if (ctx?.related?.user == null) { + ArrayList al = new ArrayList(); + ctx.related.put("user", al); + } + ctx.user.put("name", ctx.winlog.event_data.AccountName); + if (!ctx.related.user.contains(ctx.winlog.event_data.AccountName)) { + ctx.related.user.add(ctx.winlog.event_data.AccountName); + } + } + + //AccountDomain to user.domain + if (ctx?.winlog?.event_data?.AccountDomain != null) { + if (ctx?.user == null) { + HashMap hm = new HashMap(); + ctx.put("user", hm); + } + ctx.user.put("domain", ctx.winlog.event_data.AccountDomain); + } + + //ClientAddress to source.ip and related.ip + if (ctx?.winlog?.event_data?.ClientAddress != null && + ctx.winlog.event_data.ClientAddress != "-") { + if (ctx?.source == null) { + HashMap hm = new HashMap(); + ctx.put("source", hm); + } + if (ctx?.related == null) { + HashMap hm = new HashMap(); + ctx.put("related", hm); + } + if (ctx?.related?.ip == null) { + ArrayList al = new ArrayList(); + ctx.related.put("ip", al); + } + ctx.source.put("ip", ctx.winlog.event_data.ClientAddress); + if (!ctx.related.ip.contains(ctx.winlog.event_data.ClientAddress)) { + ctx.related.ip.add(ctx.winlog.event_data.ClientAddress); + } + } + + //ClientName to source.domain + if (ctx?.winlog?.event_data?.ClientName != null) { + if (ctx?.source == null) { + HashMap hm = new HashMap(); + ctx.put("source", hm); + } + ctx.source.put("domain", ctx.winlog.event_data.ClientName); + } + + //LogonID to winlog.logon.id + if (ctx?.winlog?.event_data?.LogonID != null) { + if (ctx?.winlog?.logon == null) { + HashMap hm = new HashMap(); + ctx.winlog.put("logon", hm); + } + ctx.winlog.logon.put("id", ctx.winlog.event_data.LogonID); + } + + - script: + lang: painless + ignore_failure: false + tag: Copy Target User + description: Copy Target User + source: |- + if (ctx?.event?.code == null || + !["4624", "4625", "4634", "4647", "4648", "4768", "4769", "4770", + "4771", "4776", "4964"].contains(ctx.event.code)) { + return; + } + + def targetUserId = ctx?.winlog?.event_data?.TargetUserSid; + if (targetUserId == null) { + targetUserId = ctx?.winlog?.event_data?.TargetSid; + } + + //TargetUserSid to user.id or user.target.id + if (targetUserId != null) { + if (ctx?.user == null) { + HashMap hm = new HashMap(); + ctx.put("user", hm); + } + if (ctx?.user?.id == null) { + ctx.user.put("id", targetUserId); + } else { + if (ctx?.user?.target == null) { + HashMap hm = new HashMap(); + ctx.user.put("target", hm); + } + ctx.user.target.put("id", targetUserId); + } + } + + //TargetUserName to related.user and user.name or user.target.name + if (ctx?.winlog?.event_data?.TargetUserName != null) { + def tun = ctx.winlog.event_data.TargetUserName.splitOnToken("@"); + if (ctx?.user == null) { + HashMap hm = new HashMap(); + ctx.put("user", hm); + } + if (ctx?.user?.name == null) { + ctx.user.put("name", tun[0]); + } else { + if (ctx?.user?.target == null) { + HashMap hm = new HashMap(); + ctx.user.put("target", hm); + } + ctx.user.target.put("name", tun[0]); + } + if (ctx?.related == null) { + HashMap hm = new HashMap(); + ctx.put("related", hm); + } + if (ctx?.related?.user == null) { + ArrayList al = new ArrayList(); + ctx.related.put("user", al); + } + if (!ctx.related.user.contains(tun[0])) { + ctx.related.user.add(tun[0]); + } + } + //TargetUserDomain to user.domain or user.target.domain + if (ctx?.winlog?.event_data?.TargetDomainName != null) { + if (ctx?.user == null) { + HashMap hm = new HashMap(); + ctx.put("user", hm); + } + if (ctx?.user?.domain == null) { + ctx.user.put("domain", ctx.winlog.event_data.TargetDomainName); + } else { + if (ctx?.user?.target == null){ + HashMap hm = new HashMap(); + ctx.user.put("target", hm); + } + ctx.user.target.put("domain", ctx.winlog.event_data.TargetDomainName); + } + } + - script: + lang: painless + ignore_failure: false + tag: Copy MemberName to User and User to Group + description: Copy MemberName to User and User to Group + source: |- + if (ctx?.event?.code == null || + !["4727", "4728", "4729", "4730", "4731", "4732", "4733", "4734", "4735", + "4737", "4744", "4745", "4746", "4747", "4748", "4749", "4750", "4751", + "4752", "4753", "4754", "4755", "4756", "4757", "4758", "4759", "4760", + "4761", "4762", "4763", "4764", "4799"].contains(ctx.event.code)) { + return; + } + if (ctx?.winlog?.event_data?.MemberName != null) { + def memberNameParts = ctx.winlog.event_data.MemberName.splitOnToken(","); + def memberName = memberNameParts[0].replace("CN=","").replace("cn=",""); + if (ctx?.related == null) { + HashMap hm = new HashMap(); + ctx.put("related", hm); + } + if (ctx?.related?.user == null) { + ArrayList al = new ArrayList(); + ctx.related.put("user", al); + } + if (ctx?.user == null) { + HashMap hm = new HashMap(); + ctx.put("user", hm); + } + if (ctx?.user?.target == null){ + HashMap hm = new HashMap(); + ctx.user.put("target", hm); + } + ctx.user.target.put("name", memberName); + if (!ctx.related.user.contains(memberName)) { + ctx.related.user.add(memberName); + } + if (memberNameParts.length >= 4) { + def domain = memberNameParts[3].replace("DC=", "").replace("dc=", ""); + ctx.user.target.put("domain", domain); + } + } + if (ctx?.winlog?.event_data?.TargetUserSid != null) { + if (ctx?.group == null) { + HashMap hm = new HashMap(); + ctx.put("group", hm); + } + ctx.group.put("id", ctx.winlog.event_data.TargetUserSid); + } + if (ctx?.winlog?.event_data?.TargetSid != null) { + if (ctx?.group == null) { + HashMap hm = new HashMap(); + ctx.put("group", hm); + } + ctx.group.put("id", ctx.winlog.event_data.TargetSid); + } + if (ctx?.winlog?.event_data?.TargetUserName != null) { + if (ctx?.group == null) { + HashMap hm = new HashMap(); + ctx.put("group", hm); + } + ctx.group.put("name", ctx.winlog.event_data.TargetUserName); + } + if (ctx?.winlog?.event_data?.TargetDomainName != null) { + if (ctx?.group == null) { + HashMap hm = new HashMap(); + ctx.put("group", hm); + } + def domain = ctx.winlog.event_data.TargetDomainName.replace("DC=", "").replace("dc=", ""); + ctx.group.put("domain", domain); + } + if (ctx?.user?.target != null) { + if (ctx?.user?.target?.group == null) { + HashMap hm = new HashMap(); + ctx.user.target.put("group", hm); + } + if (ctx?.group?.id != null) { + ctx.user.target.group.put("id", ctx.group.id); + } + if (ctx?.group?.name != null) { + ctx.user.target.group.put("name", ctx.group.name); + } + if (ctx?.group?.domain != null) { + ctx.user.target.group.put("domain", ctx.group.domain); + } + } + + - script: + lang: painless + ignore_failure: false + tag: Copy Target User to Computer Object + description: Copy Target User to Computer Object + source: |- + if (ctx?.event?.code == null || + !["4741", "4742", "4743"].contains(ctx.event.code)) { + return; + } + if (ctx?.winlog?.event_data?.TargetSid != null) { + if (ctx?.winlog?.computerObject == null) { + HashMap hm = new HashMap(); + ctx.winlog.put("computerObject", hm); + } + ctx.winlog.computerObject.put("id", ctx.winlog.event_data.TargetSid); + } + if (ctx?.winlog?.event_data?.TargetUserName != null) { + if (ctx?.winlog?.computerObject == null) { + HashMap hm = new HashMap(); + ctx.winlog.put("computerObject", hm); + } + ctx.winlog.computerObject.put("name", ctx.winlog.event_data.TargetUserName); + } + if (ctx?.winlog?.event_data?.TargetDomainName != null) { + if (ctx?.winlog?.computerObject == null) { + HashMap hm = new HashMap(); + ctx.winlog.put("computerObject", hm); + } + ctx.winlog.computerObject.put("domain", ctx.winlog.event_data.TargetDomainName); + } + + - set: + field: winlog.logon.id + copy_from: winlog.event_data.TargetLogonId + ignore_failure: false + if: ctx?.event?.code != null && ["4634", "4647", "4964"].contains(ctx.event.code) + + - script: + lang: painless + ignore_failure: false + tag: Copy Subject User from Event Data + description: Copy Subject User from Event Data + source: |- + if (ctx?.event?.code == null || + !["4657", "4670", "4672", "4673", "4674", "4688", "4689", "4697", + "4698", "4699", "4700", "4701", "4702", "4706", "4707", "4713", + "4716", "4717", "4718", "4719", "4720", "4722", "4723", "4724", + "4725", "4726", "4727", "4728", "4729", "4730", "4731", "4732", + "4733", "4734", "4735", "4737", "4738", "4739", "4740", "4741", + "4742", "4743", "4744", "4745", "4746", "4747", "4748", "4749", + "4750", "4751", "4752", "4753", "4754", "4755", "4756", "4757", + "4758", "4759", "4760", "4761", "4762", "4763", "4764", "4767", + "4781", "4798", "4799", "4817", "4904", "4905", "4907", "4912", + "4648"].contains(ctx.event.code)) { + return; + } + if (ctx?.winlog?.event_data?.SubjectUserSid != null) { + if (ctx?.user == null) { + HashMap hm = new HashMap(); + ctx.put("user", hm); + } + ctx.user.put("id", ctx.winlog.event_data.SubjectUserSid); + } + if (ctx?.winlog?.event_data?.SubjectUserName != null) { + if (ctx?.user == null) { + HashMap hm = new HashMap(); + ctx.put("user", hm); + } + if (ctx?.related == null) { + HashMap hm = new HashMap(); + ctx.put("related", hm); + } + if (ctx?.related?.user == null) { + ArrayList al = new ArrayList(); + ctx.related.put("user", al); + } + ctx.user.put("name", ctx.winlog.event_data.SubjectUserName); + if (!ctx.related.user.contains(ctx.winlog.event_data.SubjectUserName)) { + ctx.related.user.add(ctx.winlog.event_data.SubjectUserName); + } + } + if (ctx?.winlog?.event_data?.SubjectDomainName != null) { + if (ctx?.user == null) { + HashMap hm = new HashMap(); + ctx.put("user", hm); + } + ctx.user.put("domain", ctx.winlog.event_data.SubjectDomainName); + } + + - script: + lang: painless + ignore_failure: false + tag: Copy Target User to Target + description: Copy Target User to Target + source: |- + if (ctx?.event?.code == null || + !["4670", "4720", "4722", "4723", "4724", "4725", + "4726", "4738", "4740", "4767", "4798", "4817", + "4907"].contains(ctx.event.code)) { + return; + } + if (ctx?.user == null) { + HashMap hm = new HashMap(); + ctx.put("user", hm); + } + if (ctx?.user?.target == null) { + HashMap hm = new HashMap(); + ctx.user.put("target", hm); + } + def userId = ctx?.winlog?.event_data?.TargetSid; + if (userId != null && userId != "" && userId != "-") ctx.user.target.id = userId; + def userName = ctx?.winlog?.event_data?.TargetUserName; + if (userName != null && userName != "" && userName != "-") { + ctx.user.target.name = userName; + def parts = userName.splitOnToken("@"); + if (parts.length > 1) { + ctx.user.target.name = parts[0]; + } + if (ctx?.related?.user == null) { + ArrayList al = new ArrayList(); + ctx.related.put("user", al); + } + if (!ctx.related.user.contains(ctx.user.target.name)) { + ctx.related.user.add(ctx.user.target.name); + } + } + def userDomain = ctx?.winlog?.event_data?.TargetDomainName; + if (userDomain != null && userDomain != "" && userDomain != "-") ctx.user.target.domain = userDomain; + if (ctx.user?.target != null && ctx.user.target.size() == 0) ctx.user.remove("target"); + + - script: + lang: painless + ignore_failure: false + tag: Copy Target User to Effective + description: Copy Target User to Effective + source: |- + if (ctx?.event?.code == null || + !["4648", "4688"].contains(ctx.event.code)) { + return; + } + if (ctx?.user == null) { + HashMap hm = new HashMap(); + ctx.put("user", hm); + } + if (ctx?.user?.effective == null) { + HashMap hm = new HashMap(); + ctx.user.put("effective", hm); + } + def userId = ctx?.winlog?.event_data?.TargetUserSid; + if (userId != null && userId != "" && userId != "-") ctx.user.effective.id = userId; + def userName = ctx?.winlog?.event_data?.TargetUserName; + if (userName != null && userName != "" && userName != "-") { + ctx.user.effective.name = userName; + def parts = userName.splitOnToken("@"); + if (parts.length > 1) { + ctx.user.effective.name = parts[0]; + } + if (ctx?.related?.user == null) { + ArrayList al = new ArrayList(); + ctx.related.put("user", al); + } + if (!ctx.related.user.contains(ctx.user.effective.name)) { + ctx.related.user.add(ctx.user.effective.name); + } + } + def userDomain = ctx?.winlog?.event_data?.TargetDomainName; + if (userDomain != null && userDomain != "" && userDomain != "-") ctx.user.effective.domain = userDomain; + if (ctx.user?.effective != null && ctx.user.effective.size() == 0) ctx.user.remove("effective"); + + - script: + lang: painless + ignore_failure: false + tag: Copy Subject User from user_data + description: Copy Subject User from user_data + source: |- + if (ctx?.event?.code == null || + !["1102"].contains(ctx.event.code)) { + return; + } + if (ctx?.winlog?.user_data?.SubjectUserSid != null) { + if (ctx?.user == null) { + HashMap hm = new HashMap(); + ctx.put("user", hm); + } + ctx.user.put("id", ctx.winlog.user_data.SubjectUserSid); + } + if (ctx?.winlog?.user_data?.SubjectUserName != null) { + if (ctx?.user == null) { + HashMap hm = new HashMap(); + ctx.put("user", hm); + } + if (ctx?.related == null) { + HashMap hm = new HashMap(); + ctx.put("related", hm); + } + if (ctx?.related?.user == null) { + ArrayList al = new ArrayList(); + ctx.related.put("user", al); + } + ctx.user.put("name", ctx.winlog.user_data.SubjectUserName); + if (!ctx.related.user.contains(ctx.winlog.user_data.SubjectUserName)) { + ctx.related.user.add(ctx.winlog.user_data.SubjectUserName); + } + } + if (ctx?.winlog?.user_data?.SubjectDomainName != null) { + if (ctx?.user == null) { + HashMap hm = new HashMap(); + ctx.put("user", hm); + } + ctx.user.put("domain", ctx.winlog.user_data.SubjectDomainName); + } + + - set: + field: winlog.logon.id + copy_from: winlog.event_data.SubjectLogonId + ignore_failure: true + + - set: + field: winlog.logon.id + copy_from: winlog.user_data.SubjectLogonId + ignore_failure: true + if: |- + ctx?.event?.code != null && + ["1102"].contains(ctx.event.code) + + - script: + lang: painless + ignore_failure: false + tag: Rename Common Auth Fields + description: Rename Common Auth Fields + source: |- + if (ctx?.event?.code == null || + !["1100", "1102", "1104", "1105", "1108", "4624", "4648", "4625", + "4670", "4673", "4674", "4689", "4697", "4719", "4720", "4722", + "4723", "4724", "4725", "4726", "4727", "4728", "4729", "4730", + "4731", "4732", "4733", "4734", "4735", "4737", "4738", "4740", + "4741", "4742", "4743", "4744", "4745", "4746", "4747", "4748", + "4749", "4750", "4751", "4752", "4753", "4754", "4755", "4756", + "4757", "4758", "4759", "4760", "4761", "4762", "4763", "4764", + "4767", "4768", "4769", "4770", "4771", "4798", "4799", "4817", + "4904", "4905", "4907", "4912"].contains(ctx.event.code)) { + return; + } + if (ctx?.winlog?.event_data?.ProcessId != null) { + if (ctx?.process == null) { + HashMap hm = new HashMap(); + ctx.put("process", hm); + } + if (ctx.winlog.event_data.ProcessId instanceof String) { + Long pid = Long.decode(ctx.winlog.event_data.ProcessId); + ctx.process.put("pid", pid.longValue()); + } else { + ctx.process.put("pid", ctx.winlog.event_data.ProcessId); + } + ctx.winlog.event_data.remove("ProcessId"); + } + if (ctx?.winlog?.event_data?.ProcessName != null) { + if (ctx?.process == null) { + HashMap hm = new HashMap(); + ctx.put("process", hm); + } + ctx.process.put("executable", ctx.winlog.event_data.ProcessName); + ctx.winlog.event_data.remove("ProcessName"); + } + if (ctx?.winlog?.event_data?.IpAddress != null && + ctx.winlog.event_data.IpAddress != "-") { + if (ctx?.source == null) { + HashMap hm = new HashMap(); + ctx.put("source", hm); + } + ctx.source.put("ip", ctx.winlog.event_data.IpAddress); + ctx.winlog.event_data.remove("IpAddress"); + } + if (ctx?.winlog?.event_data?.IpPort != null && ctx.winlog.event_data.IpPort != "-") { + if (ctx?.source == null) { + HashMap hm = new HashMap(); + ctx.put("source", hm); + } + ctx.source.put("port", Long.decode(ctx.winlog.event_data.IpPort)); + ctx.winlog.event_data.remove("IpPort"); + } + if (ctx?.winlog?.event_data?.WorkstationName != null) { + if (ctx?.source == null) { + HashMap hm = new HashMap(); + ctx.put("source", hm); + } + ctx.source.put("domain", ctx.winlog.event_data.WorkstationName); + ctx.winlog.event_data.remove("WorkstationName"); + } + if (ctx?.winlog?.event_data?.ClientAddress != null && + ctx.winlog.event_data.ClientAddress != "-") { + if (ctx?.related == null) { + HashMap hm = new HashMap(); + ctx.put("related", hm); + } + ctx.related.put("ip", ctx.winlog.event_data.ClientAddress); + ctx.winlog.event_data.remove("ClientAddress"); + } + if (ctx?.process?.name == null && ctx?.process?.executable != null) { + def parts = ctx.process.executable.splitOnToken("\\"); + ctx.process.put("name", parts[-1]); + } + + - script: + lang: painless + ignore_failure: false + tag: Process Event 4688 + description: Process Event 4688 + source: |- + if (ctx?.event?.code == null || + !["4688"].contains(ctx.event.code)) { + return; + } + if (ctx?.winlog?.event_data?.NewProcessId != null) { + if (ctx?.process == null) { + HashMap hm = new HashMap(); + ctx.put("process", hm); + } + if (ctx.winlog.event_data.NewProcessId instanceof String) { + Long pid = Long.decode(ctx.winlog.event_data.NewProcessId); + ctx.process.put("pid", pid.longValue()); + } else { + ctx.process.put("pid", ctx.winlog.event_data.NewProcessId); + } + ctx.winlog.event_data.remove("NewProcessId"); + } + if (ctx?.winlog?.event_data?.NewProcessName != null) { + if (ctx?.process == null) { + HashMap hm = new HashMap(); + ctx.put("process", hm); + } + ctx.process.put("executable", ctx.winlog.event_data.NewProcessName); + ctx.winlog.event_data.remove("NewProcessName"); + } + if (ctx?.winlog?.event_data?.ParentProcessName != null) { + if (ctx?.process == null) { + HashMap hm = new HashMap(); + ctx.put("process", hm); + } + if (ctx?.process?.parent == null) { + HashMap hm = new HashMap(); + ctx.process.put("parent", hm); + } + ctx.process.parent.put("executable", ctx.winlog.event_data.ParentProcessName); + ctx.winlog.event_data.remove("ParentProcessName"); + } + if (ctx?.process?.name == null && ctx?.process?.executable != null) { + def parts = ctx.process.executable.splitOnToken("\\"); + ctx.process.put("name", parts[-1]); + } + if (ctx?.process?.parent?.name == null && ctx?.process?.parent?.executable != null) { + def parts = ctx.process.parent.executable.splitOnToken("\\"); + ctx.process.parent.put("name", parts[-1]); + } + if (ctx?.winlog?.event_data?.CommandLine != null) { + int start = 0; + int end = 0; + boolean in_quote = false; + ArrayList al = new ArrayList(); + for (int i = 0; i < ctx.winlog.event_data.CommandLine.length(); i++) { + end = i; + if (Character.compare(ctx.winlog.event_data.CommandLine.charAt(i), "\"".charAt(0)) == 0) { + if (in_quote) { + in_quote = false; + } else { + in_quote = true; + } + } + if (Character.isWhitespace(ctx.winlog.event_data.CommandLine.charAt(i)) && !in_quote) { + al.add(ctx.winlog.event_data.CommandLine.substring(start, end)); + start = i + 1; + } + if (i == ctx.winlog.event_data.CommandLine.length() - 1) { + al.add(ctx.winlog.event_data.CommandLine.substring(start, end + 1)); + } + } + if (ctx?.process == null) { + HashMap hm = new HashMap(); + ctx.put("process", hm); + } + ctx.process.put("args", al); + ctx.process.put("command_line", ctx.winlog.event_data.CommandLine); + } + if ((ctx?.winlog?.event_data?.TargetUserName != null) && + (!ctx.winlog.event_data.TargetUserName.equals("-"))) { + if (ctx?.related == null) { + HashMap hm = new HashMap(); + ctx.put("related", hm); + } + if (ctx?.related?.user == null) { + ArrayList al = new ArrayList(); + ctx.related.put("user", al); + } + if (!ctx.related.user.contains(ctx.winlog.event_data.TargetUserName)) { + ctx.related.user.add(ctx.winlog.event_data.TargetUserName); + } + } + + - append: + field: related.user + value: '{{winlog.event_data.SubjectUserName}}' + allow_duplicates: false + if: |- + ctx?.event?.code != null && + ["4624", "4648"].contains(ctx.event.code) && + ctx?.winlog?.event_data?.SubjectUserName != null && + ctx.winlog.event_data.SubjectUserName != "-" + + - append: + field: related.user + value: '{{winlog.event_data.TargetUserName}}' + allow_duplicates: false + if: |- + ctx?.event?.code != null && + ["4688", "4720", "4722", "4723", "4724", "4725", "4726", "4738", + "4740", "4767", "4798"].contains(ctx.event.code) && + ctx?.winlog?.event_data?.TargetUserName != null && + ctx.winlog.event_data.TargetUserName != "-" + + - split: + field: winlog.event_data.PrivilegeList + separator: "\\s+" + if: |- + ctx?.event?.code != null && + ["4672", "4673", "4674", "4741", "4742", "4743"].contains(ctx.event.code) && + ctx?.winlog?.event_data?.PrivilegeList != null + + - set: + field: user.target.name + copy_from: winlog.event_data.OldTargetUserName + ignore_empty_value: true + + - set: + field: user.changes.name + copy_from: winlog.event_data.NewTargetUserName + ignore_empty_value: true + + - append: + field: related.user + value: '{{winlog.event_data.NewTargetUserName}}' + allow_duplicates: false + if: |- + ctx?.winlog?.event_data?.NewTargetUserName != null && + ctx.winlog.event_data.NewTargetUserName != "-" + + - append: + field: related.user + value: '{{winlog.event_data.OldTargetUserName}}' + allow_duplicates: false + if: |- + ctx?.winlog?.event_data?.OldTargetUserName != null && + ctx.winlog.event_data.OldTargetUserName != "-" + + - gsub: + field: source.ip + pattern: "::ffff:" + replacement: "" + ignore_missing: true + + - append: + field: related.ip + value: '{{source.ip}}' + allow_duplicates: false + if: |- + ctx?.source?.ip != null && + ctx.source.ip != "-" + + - script: + lang: painless + ignore_failure: false + tag: Object Policy Change and SidListDesc + description: Object Policy Change and SidListDesc + # SDDL Ace Types + # https://docs.microsoft.com/en-us/windows/security/threat-protection/auditing/event-4715 + # https://docs.microsoft.com/en-us/windows/win32/secauthz/ace-strings + # https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-dtyp/f4296d69-1c0f-491f-9587-a960b292d070 + # SDDL Permissions + # https://docs.microsoft.com/en-us/windows/security/threat-protection/auditing/event-4715 + # https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-dtyp/f4296d69-1c0f-491f-9587-a960b292d070 + # Known SIDs + # https://support.microsoft.com/en-au/help/243330/well-known-security-identifier"S-in-window"S-operating-systems + # https://docs.microsoft.com/en-us/windows/win32/secauthz/sid-strings + # Domain-specific SIDs + # https://support.microsoft.com/en-au/help/243330/well-known-security-identifiers-in-windows-operating-systems + # Object Permission Flags + # https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-dtyp/7a53f60e-e730-4dfe-bbe9-b21b62eb790b + params: + AccountSIDDescription: + AO: Account operators + RU: Alias to allow previous Windows 2000 + AN: Anonymous logon + AU: Authenticated users + BA: Built-in administrators + BG: Built-in guests + BO: Backup operators + BU: Built-in users + CA: Certificate server administrators + CG: Creator group + CO: Creator owner + DA: Domain administrators + DC: Domain computers + DD: Domain controllers + DG: Domain guests + DU: Domain users + EA: Enterprise administrators + ED: Enterprise domain controllers + WD: Everyone + PA: Group Policy administrators + IU: Interactively logged-on user + LA: Local administrator + LG: Local guest + LS: Local service account + SY: Local system + NU: Network logon user + "NO": Network configuration operators + NS: Network service account + PO: Printer operators + PS: Personal self + PU: Power users + RS: RAS servers group + RD: Terminal server users + RE: Replicator + RC: Restricted code + SA: Schema administrators + SO: Server operators + SU: Service logon user + S-1-0: Null Authority + S-1-0-0: Nobody + S-1-1: World Authority + S-1-1-0: Everyone + S-1-16-0: Untrusted Mandatory Level + S-1-16-12288: High Mandatory Level + S-1-16-16384: System Mandatory Level + S-1-16-20480: Protected Process Mandatory Level + S-1-16-28672: Secure Process Mandatory Level + S-1-16-4096: Low Mandatory Level + S-1-16-8192: Medium Mandatory Level + S-1-16-8448: Medium Plus Mandatory Level + S-1-2: Local Authority + S-1-2-0: Local + S-1-2-1: Console Logon + S-1-3: Creator Authority + S-1-3-0: Creator Owner + S-1-3-1: Creator Group + S-1-3-2: Creator Owner Server + S-1-3-3: Creator Group Server + S-1-3-4: Owner Rights + S-1-4: Non-unique Authority + S-1-5: NT Authority + S-1-5-1: Dialup + S-1-5-10: Principal Self + S-1-5-11: Authenticated Users + S-1-5-12: Restricted Code + S-1-5-13: Terminal Server Users + S-1-5-14: Remote Interactive Logon + S-1-5-15: This Organization + S-1-5-17: This Organization + S-1-5-18: Local System + S-1-5-19: NT Authority + S-1-5-2: Network + S-1-5-20: NT Authority + S-1-5-3: Batch + S-1-5-32-544: Administrators + S-1-5-32-545: Users + S-1-5-32-546: Guests + S-1-5-32-547: Power Users + S-1-5-32-548: Account Operators + S-1-5-32-549: Server Operators + S-1-5-32-550: Print Operators + S-1-5-32-551: Backup Operators + S-1-5-32-552: Replicators + S-1-5-32-554: Builtin\Pre-Windows 2000 Compatible Access + S-1-5-32-555: Builtin\Remote Desktop Users + S-1-5-32-556: Builtin\Network Configuration Operators + S-1-5-32-557: Builtin\Incoming Forest Trust Builders + S-1-5-32-558: Builtin\Performance Monitor Users + S-1-5-32-559: Builtin\Performance Log Users + S-1-5-32-560: Builtin\Windows Authorization Access Group + S-1-5-32-561: Builtin\Terminal Server License Servers + S-1-5-32-562: Builtin\Distributed COM Users + S-1-5-32-569: Builtin\Cryptographic Operators + S-1-5-32-573: Builtin\Event Log Readers + S-1-5-32-574: Builtin\Certificate Service DCOM Access + S-1-5-32-575: Builtin\RDS Remote Access Servers + S-1-5-32-576: Builtin\RDS Endpoint Servers + S-1-5-32-577: Builtin\RDS Management Servers + S-1-5-32-578: Builtin\Hyper-V Administrators + S-1-5-32-579: Builtin\Access Control Assistance Operators + S-1-5-32-580: Builtin\Remote Management Users + S-1-5-32-582: Storage Replica Administrators + S-1-5-4: Interactive + S-1-5-5-X-Y: Logon Session + S-1-5-6: Service + S-1-5-64-10: NTLM Authentication + S-1-5-64-14: SChannel Authentication + S-1-5-64-21: Digest Authentication + S-1-5-7: Anonymous + S-1-5-8: Proxy + S-1-5-80: NT Service + S-1-5-80-0: All Services + S-1-5-83-0: NT Virtual Machine\Virtual Machines + S-1-5-9: Enterprise Domain Controllers + S-1-5-90-0: Windows Manager\Windows Manager Group + AceTypes: + A: Access Allowed + D: Access Denied + OA: Object Access Allowed + OD: Object Access Denied + AU: System Audit + AL: System Alarm + OU: System Object Audit + OL: System Object Alarm + ML: System Mandatory Label + SP: Central Policy ID + DomainSpecificSID: + "498": Enterprise Read-only Domain Controllers + "500": Administrator + "501": Guest + "502": KRBTGT + "512": Domain Admins + "513": Domain Users + "514": Domain Guests + "515": Domain Computers + "516": Domain Controllers + "517": Cert Publishers + "518": Schema Admins + "519": Enterprise Admins + "520": Group Policy Creator Owners + "521": Read-only Domain Controllers + "522": Cloneable Domain Controllers + "526": Key Admins + "527": Enterprise Key Admins + "553": RAS and IAS Servers + "571": Allowed RODC Password Replication Group + "572": Denied RODC Password Replication Group + PermissionDescription: + GA: Generic All + GR: Generic Read + GW: Generic Write + GX: Generic Execute + RC: Read Permissions + SD: Delete + WD: Modify Permissions + WO: Modify Owner + RP: Read All Properties + WP: Write All Properties + CC: Create All Child Objects + DC: Delete All Child Objects + LC: List Contents + SW: All Validated + LO: List Object + DT: Delete Subtree + CR: All Extended Rights + FA: File All Access + FR: File Generic Read + FX: FILE GENERIC EXECUTE + FW: FILE GENERIC WRITE + KA: KEY ALL ACCESS + KR: KEY READ + KW: KEY WRITE + KX: KEY EXECUTE + PermsFlags: + "0x80000000": 'Generic Read' + "0x4000000": 'Generic Write' + "0x20000000": 'Generic Execute' + "0x10000000": 'Generic All' + "0x02000000": 'Maximum Allowed' + "0x01000000": 'Access System Security' + "0x00100000": 'Syncronize' + "0x00080000": 'Write Owner' + "0x00040000": 'Write DACL' + "0x00020000": 'Read Control' + "0x00010000": 'Delete' + source: |- + ArrayList translatePermissionMask(def mask, def params) { + ArrayList al = new ArrayList(); + Long permCode = Long.decode(mask); + for (entry in params.PermsFlags.entrySet()) { + Long permFlag = Long.decode(entry.getKey()); + if ((permCode.longValue() & permFlag.longValue()) == permFlag.longValue()) { + al.add(entry.getValue()); + } + } + if (al.length == 0) { + al.add(mask); + } + return al; + } + + HashMap translateACL(def dacl, def params) { + def aceArray = dacl.splitOnToken(";"); + HashMap hm = new HashMap(); + + if (aceArray.length >= 6 ) { + hm.put("grantee", translateSID(aceArray[5], params)); + } + + if (aceArray.length >= 1) { + hm.put("type", params.AceTypes[aceArray[0]]); + } + + if (aceArray.length >= 3) { + if (aceArray[2].startsWith("0x")) { + hm.put("perms", translatePermissionMask(aceArray[2], params)); + } else { + ArrayList al = new ArrayList(); + Pattern permPattern = /.{1,2}/; + Matcher permMatcher = permPattern.matcher(aceArray[2]); + while (permMatcher.find()) { + al.add(params.PermissionDescription[permMatcher.group(0)]); + } + hm.put("perms", al); + } + } + return hm; + } + String translateSID(def sid, def params) { + if (!params.AccountSIDDescription.containsKey(sid)) { + if (sid.startsWith("S-1-5-21")) { + Pattern uidPattern = /[0-9]{1,5}$/; + Matcher uidMatcher = uidPattern.matcher(sid); + if (uidMatcher.find()) { + return params.DomainSpecificSID[uidMatcher.group(0)]; + } + return sid; + } + return sid; + } + return params.AccountSIDDescription[sid]; + } + + void enrichSDDL(def sddlStr, def Sd, def params, def ctx) { + Pattern sdOwnerPattern = /^O\:[A-Z]{2}/; + Matcher sdOwnerMatcher = sdOwnerPattern.matcher(sddlStr); + if (sdOwnerMatcher.find()) { + ctx.winlog.event_data.put(Sd + "Owner", translateSID(sdOwnerMatcher.group(0), params)); + } + + Pattern sdGroupPattern = /^G\:[A-Z]{2}/; + Matcher sdGroupMatcher = sdGroupPattern.matcher(sddlStr); + if (sdGroupMatcher.find()) { + ctx.winlog.event_data.put(Sd + "Group", translateSID(sdGroupMatcher.group(0), params)); + } + + Pattern sdDaclPattern = /(D:([A-Z]*(\(.*\))*))/; + Matcher sdDaclMatcher = sdDaclPattern.matcher(sddlStr); + if (sdDaclMatcher.find()) { + Pattern dacListPattern = /\([^*\)]*\)/; + Matcher dacListMatcher = dacListPattern.matcher(sdDaclMatcher.group(1)); + for (def i = 0; dacListMatcher.find(); i++) { + def newDacl = translateACL(dacListMatcher.group(0).replace("(","").replace(")",""), params); + ctx.winlog.event_data.put(Sd + "Dacl" + i.toString(), newDacl['grantee'] + " :" + newDacl['type'] + " (" + newDacl['perms'] + ")"); + if (["Administrator", "Guest", "KRBTGT"].contains(newDacl['grantee'])) { + if (ctx?.related == null) { + HashMap hm = new HashMap(); + ctx.put("related", hm); + } + if (ctx?.related?.user == null) { + ArrayList al = new ArrayList(); + ctx.related.put("user", al); + } + if (!ctx.related.user.contains(newDacl['grantee'])) { + ctx.related.user.add(newDacl['grantee']); + } + } + } + } + + Pattern sdSaclPattern = /(S:([A-Z]*(\(.*\))*))?$/; + Matcher sdSaclMatcher = sdSaclPattern.matcher(sddlStr); + if (sdSaclMatcher.find()) { + Pattern sacListPattern = /\([^*\)]*\)/; + Matcher sacListMatcher = sacListPattern.matcher(sdSaclMatcher.group(0)); + for (def i = 0; sacListMatcher.find(); i++) { + def newSacl = translateACL(sacListMatcher.group(0).replace("(","").replace(")",""), params); + ctx.winlog.event_data.put(Sd + "Sacl" + i.toString(), newSacl['grantee'] + " :" + newSacl['type'] + " (" + newSacl['perms'] + ")"); + if (["Administrator", "Guest", "KRBTGT"].contains(newSacl['grantee'])) { + if (ctx?.related == null) { + HashMap hm = new HashMap(); + ctx.put("related", hm); + } + if (ctx?.related?.user == null) { + ArrayList al = new ArrayList(); + ctx.related.put("user", al); + } + if (!ctx.related.user.contains(newSacl['grantee'])) { + ctx.related.user.add(newSacl['grantee']); + } + } + } + } + } + + void splitSidList(def sids, def params, def ctx) { + ArrayList al = new ArrayList(); + def sidList = sids.splitOnToken(" "); + ctx.winlog.event_data.put("SidList", sidList); + for (def i = 0; i < sidList.length; i++ ) { + al.add(translateSID(sidList[i].replace("%", "").replace("{", "").replace("}", "").replace(" ",""), params)); + } + ctx.winlog.event_data.put("SidListDesc", al); + } + + if (ctx?.event?.code == null || + !["4670", "4817", "4907", "4908"].contains(ctx.event.code)) { + return; + } + if (ctx?.winlog?.event_data?.OldSd != null) { + enrichSDDL(ctx.winlog.event_data.OldSd, "OldSd", params, ctx); + } + if (ctx?.winlog?.event_data?.NewSd != null) { + enrichSDDL(ctx.winlog.event_data.NewSd, "NewSd", params, ctx); + } + if (ctx?.winlog?.event_data?.SidList != null) { + splitSidList(ctx.winlog.event_data.SidList, params, ctx); + } + + - convert: + field: winlog.record_id + type: string + ignore_missing: true + + - convert: + field: winlog.event_id + type: string + ignore_missing: true + + - set: + field: ecs.version + value: '1.12.0' + + - set: + field: log.level + copy_from: winlog.level + ignore_empty_value: true + ignore_failure: true + if: ctx?.winlog?.level != "" + + - date: + field: winlog.time_created + formats: + - ISO8601 + ignore_failure: true + if: ctx?.winlog?.time_created != null + + - remove: + field: event.original + if: "ctx?.tags == null || !(ctx.tags.contains('preserve_original_event'))" + ignore_failure: true + ignore_missing: true + +on_failure: + - set: + field: error.message + value: |- + Processor "{{ _ingest.on_failure_processor_type }}" with tag "{{ _ingest.on_failure_processor_tag }}" in pipeline "{{ _ingest.on_failure_pipeline }}" failed with message "{{ _ingest.on_failure_message }}" diff --git a/x-pack/winlogbeat/module/security/test/security_windows_test.go b/x-pack/winlogbeat/module/security/test/security_windows_test.go deleted file mode 100644 index 79c8d36cc59..00000000000 --- a/x-pack/winlogbeat/module/security/test/security_windows_test.go +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one -// or more contributor license agreements. Licensed under the Elastic License; -// you may not use this file except in compliance with the Elastic License. - -package test - -import ( - "testing" - - "github.com/elastic/beats/v7/x-pack/winlogbeat/module" - - // Register required processors. - _ "github.com/elastic/beats/v7/libbeat/cmd/instance" - _ "github.com/elastic/beats/v7/libbeat/processors/timestamp" -) - -// Ignore these fields because they can be different on different versions -// of windows. -var ignoreFields = []string{ - "message", -} - -func TestSecurity(t *testing.T) { - module.TestPipeline(t, "testdata/*.evtx", "../config/winlogbeat-security.js", - module.WithFieldFilter(ignoreFields)) -} diff --git a/x-pack/winlogbeat/module/sysmon/config/winlogbeat-sysmon.js b/x-pack/winlogbeat/module/sysmon/config/winlogbeat-sysmon.js deleted file mode 100644 index c91649249f6..00000000000 --- a/x-pack/winlogbeat/module/sysmon/config/winlogbeat-sysmon.js +++ /dev/null @@ -1,1802 +0,0 @@ -// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one -// or more contributor license agreements. Licensed under the Elastic License; -// you may not use this file except in compliance with the Elastic License. - -// Polyfill for String startsWith. -if (!String.prototype.startsWith) { - Object.defineProperty(String.prototype, "startsWith", { - value: function (search, pos) { - pos = !pos || pos < 0 ? 0 : +pos; - return this.substring(pos, pos + search.length) === search; - }, - }); -} - -var sysmon = (function () { - var path = require("path"); - var processor = require("processor"); - var windows = require("windows"); - var net = require("net"); - - // Windows error codes for DNS. This list was generated using - // 'go run gen_dns_error_codes.go'. - var dnsQueryStatusCodes = { - "0": "SUCCESS", - "5": "ERROR_ACCESS_DENIED", - "8": "ERROR_NOT_ENOUGH_MEMORY", - "13": "ERROR_INVALID_DATA", - "14": "ERROR_OUTOFMEMORY", - "123": "ERROR_INVALID_NAME", - "1214": "ERROR_INVALID_NETNAME", - "1223": "ERROR_CANCELLED", - "1460": "ERROR_TIMEOUT", - "4312": "ERROR_OBJECT_NOT_FOUND", - "9001": "DNS_ERROR_RCODE_FORMAT_ERROR", - "9002": "DNS_ERROR_RCODE_SERVER_FAILURE", - "9003": "DNS_ERROR_RCODE_NAME_ERROR", - "9004": "DNS_ERROR_RCODE_NOT_IMPLEMENTED", - "9005": "DNS_ERROR_RCODE_REFUSED", - "9006": "DNS_ERROR_RCODE_YXDOMAIN", - "9007": "DNS_ERROR_RCODE_YXRRSET", - "9008": "DNS_ERROR_RCODE_NXRRSET", - "9009": "DNS_ERROR_RCODE_NOTAUTH", - "9010": "DNS_ERROR_RCODE_NOTZONE", - "9016": "DNS_ERROR_RCODE_BADSIG", - "9017": "DNS_ERROR_RCODE_BADKEY", - "9018": "DNS_ERROR_RCODE_BADTIME", - "9101": "DNS_ERROR_KEYMASTER_REQUIRED", - "9102": "DNS_ERROR_NOT_ALLOWED_ON_SIGNED_ZONE", - "9103": "DNS_ERROR_NSEC3_INCOMPATIBLE_WITH_RSA_SHA1", - "9104": "DNS_ERROR_NOT_ENOUGH_SIGNING_KEY_DESCRIPTORS", - "9105": "DNS_ERROR_UNSUPPORTED_ALGORITHM", - "9106": "DNS_ERROR_INVALID_KEY_SIZE", - "9107": "DNS_ERROR_SIGNING_KEY_NOT_ACCESSIBLE", - "9108": "DNS_ERROR_KSP_DOES_NOT_SUPPORT_PROTECTION", - "9109": "DNS_ERROR_UNEXPECTED_DATA_PROTECTION_ERROR", - "9110": "DNS_ERROR_UNEXPECTED_CNG_ERROR", - "9111": "DNS_ERROR_UNKNOWN_SIGNING_PARAMETER_VERSION", - "9112": "DNS_ERROR_KSP_NOT_ACCESSIBLE", - "9113": "DNS_ERROR_TOO_MANY_SKDS", - "9114": "DNS_ERROR_INVALID_ROLLOVER_PERIOD", - "9115": "DNS_ERROR_INVALID_INITIAL_ROLLOVER_OFFSET", - "9116": "DNS_ERROR_ROLLOVER_IN_PROGRESS", - "9117": "DNS_ERROR_STANDBY_KEY_NOT_PRESENT", - "9118": "DNS_ERROR_NOT_ALLOWED_ON_ZSK", - "9119": "DNS_ERROR_NOT_ALLOWED_ON_ACTIVE_SKD", - "9120": "DNS_ERROR_ROLLOVER_ALREADY_QUEUED", - "9121": "DNS_ERROR_NOT_ALLOWED_ON_UNSIGNED_ZONE", - "9122": "DNS_ERROR_BAD_KEYMASTER", - "9123": "DNS_ERROR_INVALID_SIGNATURE_VALIDITY_PERIOD", - "9124": "DNS_ERROR_INVALID_NSEC3_ITERATION_COUNT", - "9125": "DNS_ERROR_DNSSEC_IS_DISABLED", - "9126": "DNS_ERROR_INVALID_XML", - "9127": "DNS_ERROR_NO_VALID_TRUST_ANCHORS", - "9128": "DNS_ERROR_ROLLOVER_NOT_POKEABLE", - "9129": "DNS_ERROR_NSEC3_NAME_COLLISION", - "9130": "DNS_ERROR_NSEC_INCOMPATIBLE_WITH_NSEC3_RSA_SHA1", - "9501": "DNS_INFO_NO_RECORDS", - "9502": "DNS_ERROR_BAD_PACKET", - "9503": "DNS_ERROR_NO_PACKET", - "9504": "DNS_ERROR_RCODE", - "9505": "DNS_ERROR_UNSECURE_PACKET", - "9506": "DNS_REQUEST_PENDING", - "9551": "DNS_ERROR_INVALID_TYPE", - "9552": "DNS_ERROR_INVALID_IP_ADDRESS", - "9553": "DNS_ERROR_INVALID_PROPERTY", - "9554": "DNS_ERROR_TRY_AGAIN_LATER", - "9555": "DNS_ERROR_NOT_UNIQUE", - "9556": "DNS_ERROR_NON_RFC_NAME", - "9557": "DNS_STATUS_FQDN", - "9558": "DNS_STATUS_DOTTED_NAME", - "9559": "DNS_STATUS_SINGLE_PART_NAME", - "9560": "DNS_ERROR_INVALID_NAME_CHAR", - "9561": "DNS_ERROR_NUMERIC_NAME", - "9562": "DNS_ERROR_NOT_ALLOWED_ON_ROOT_SERVER", - "9563": "DNS_ERROR_NOT_ALLOWED_UNDER_DELEGATION", - "9564": "DNS_ERROR_CANNOT_FIND_ROOT_HINTS", - "9565": "DNS_ERROR_INCONSISTENT_ROOT_HINTS", - "9566": "DNS_ERROR_DWORD_VALUE_TOO_SMALL", - "9567": "DNS_ERROR_DWORD_VALUE_TOO_LARGE", - "9568": "DNS_ERROR_BACKGROUND_LOADING", - "9569": "DNS_ERROR_NOT_ALLOWED_ON_RODC", - "9570": "DNS_ERROR_NOT_ALLOWED_UNDER_DNAME", - "9571": "DNS_ERROR_DELEGATION_REQUIRED", - "9572": "DNS_ERROR_INVALID_POLICY_TABLE", - "9573": "DNS_ERROR_ADDRESS_REQUIRED", - "9601": "DNS_ERROR_ZONE_DOES_NOT_EXIST", - "9602": "DNS_ERROR_NO_ZONE_INFO", - "9603": "DNS_ERROR_INVALID_ZONE_OPERATION", - "9604": "DNS_ERROR_ZONE_CONFIGURATION_ERROR", - "9605": "DNS_ERROR_ZONE_HAS_NO_SOA_RECORD", - "9606": "DNS_ERROR_ZONE_HAS_NO_NS_RECORDS", - "9607": "DNS_ERROR_ZONE_LOCKED", - "9608": "DNS_ERROR_ZONE_CREATION_FAILED", - "9609": "DNS_ERROR_ZONE_ALREADY_EXISTS", - "9610": "DNS_ERROR_AUTOZONE_ALREADY_EXISTS", - "9611": "DNS_ERROR_INVALID_ZONE_TYPE", - "9612": "DNS_ERROR_SECONDARY_REQUIRES_MASTER_IP", - "9613": "DNS_ERROR_ZONE_NOT_SECONDARY", - "9614": "DNS_ERROR_NEED_SECONDARY_ADDRESSES", - "9615": "DNS_ERROR_WINS_INIT_FAILED", - "9616": "DNS_ERROR_NEED_WINS_SERVERS", - "9617": "DNS_ERROR_NBSTAT_INIT_FAILED", - "9618": "DNS_ERROR_SOA_DELETE_INVALID", - "9619": "DNS_ERROR_FORWARDER_ALREADY_EXISTS", - "9620": "DNS_ERROR_ZONE_REQUIRES_MASTER_IP", - "9621": "DNS_ERROR_ZONE_IS_SHUTDOWN", - "9622": "DNS_ERROR_ZONE_LOCKED_FOR_SIGNING", - "9651": "DNS_ERROR_PRIMARY_REQUIRES_DATAFILE", - "9652": "DNS_ERROR_INVALID_DATAFILE_NAME", - "9653": "DNS_ERROR_DATAFILE_OPEN_FAILURE", - "9654": "DNS_ERROR_FILE_WRITEBACK_FAILED", - "9655": "DNS_ERROR_DATAFILE_PARSING", - "9701": "DNS_ERROR_RECORD_DOES_NOT_EXIST", - "9702": "DNS_ERROR_RECORD_FORMAT", - "9703": "DNS_ERROR_NODE_CREATION_FAILED", - "9704": "DNS_ERROR_UNKNOWN_RECORD_TYPE", - "9705": "DNS_ERROR_RECORD_TIMED_OUT", - "9706": "DNS_ERROR_NAME_NOT_IN_ZONE", - "9707": "DNS_ERROR_CNAME_LOOP", - "9708": "DNS_ERROR_NODE_IS_CNAME", - "9709": "DNS_ERROR_CNAME_COLLISION", - "9710": "DNS_ERROR_RECORD_ONLY_AT_ZONE_ROOT", - "9711": "DNS_ERROR_RECORD_ALREADY_EXISTS", - "9712": "DNS_ERROR_SECONDARY_DATA", - "9713": "DNS_ERROR_NO_CREATE_CACHE_DATA", - "9714": "DNS_ERROR_NAME_DOES_NOT_EXIST", - "9715": "DNS_WARNING_PTR_CREATE_FAILED", - "9716": "DNS_WARNING_DOMAIN_UNDELETED", - "9717": "DNS_ERROR_DS_UNAVAILABLE", - "9718": "DNS_ERROR_DS_ZONE_ALREADY_EXISTS", - "9719": "DNS_ERROR_NO_BOOTFILE_IF_DS_ZONE", - "9720": "DNS_ERROR_NODE_IS_DNAME", - "9721": "DNS_ERROR_DNAME_COLLISION", - "9722": "DNS_ERROR_ALIAS_LOOP", - "9751": "DNS_INFO_AXFR_COMPLETE", - "9752": "DNS_ERROR_AXFR", - "9753": "DNS_INFO_ADDED_LOCAL_WINS", - "9801": "DNS_STATUS_CONTINUE_NEEDED", - "9851": "DNS_ERROR_NO_TCPIP", - "9852": "DNS_ERROR_NO_DNS_SERVERS", - "9901": "DNS_ERROR_DP_DOES_NOT_EXIST", - "9902": "DNS_ERROR_DP_ALREADY_EXISTS", - "9903": "DNS_ERROR_DP_NOT_ENLISTED", - "9904": "DNS_ERROR_DP_ALREADY_ENLISTED", - "9905": "DNS_ERROR_DP_NOT_AVAILABLE", - "9906": "DNS_ERROR_DP_FSMO_ERROR", - "9911": "DNS_ERROR_RRL_NOT_ENABLED", - "9912": "DNS_ERROR_RRL_INVALID_WINDOW_SIZE", - "9913": "DNS_ERROR_RRL_INVALID_IPV4_PREFIX", - "9914": "DNS_ERROR_RRL_INVALID_IPV6_PREFIX", - "9915": "DNS_ERROR_RRL_INVALID_TC_RATE", - "9916": "DNS_ERROR_RRL_INVALID_LEAK_RATE", - "9917": "DNS_ERROR_RRL_LEAK_RATE_LESSTHAN_TC_RATE", - "9921": "DNS_ERROR_VIRTUALIZATION_INSTANCE_ALREADY_EXISTS", - "9922": "DNS_ERROR_VIRTUALIZATION_INSTANCE_DOES_NOT_EXIST", - "9923": "DNS_ERROR_VIRTUALIZATION_TREE_LOCKED", - "9924": "DNS_ERROR_INVAILD_VIRTUALIZATION_INSTANCE_NAME", - "9925": "DNS_ERROR_DEFAULT_VIRTUALIZATION_INSTANCE", - "9951": "DNS_ERROR_ZONESCOPE_ALREADY_EXISTS", - "9952": "DNS_ERROR_ZONESCOPE_DOES_NOT_EXIST", - "9953": "DNS_ERROR_DEFAULT_ZONESCOPE", - "9954": "DNS_ERROR_INVALID_ZONESCOPE_NAME", - "9955": "DNS_ERROR_NOT_ALLOWED_WITH_ZONESCOPES", - "9956": "DNS_ERROR_LOAD_ZONESCOPE_FAILED", - "9957": "DNS_ERROR_ZONESCOPE_FILE_WRITEBACK_FAILED", - "9958": "DNS_ERROR_INVALID_SCOPE_NAME", - "9959": "DNS_ERROR_SCOPE_DOES_NOT_EXIST", - "9960": "DNS_ERROR_DEFAULT_SCOPE", - "9961": "DNS_ERROR_INVALID_SCOPE_OPERATION", - "9962": "DNS_ERROR_SCOPE_LOCKED", - "9963": "DNS_ERROR_SCOPE_ALREADY_EXISTS", - "9971": "DNS_ERROR_POLICY_ALREADY_EXISTS", - "9972": "DNS_ERROR_POLICY_DOES_NOT_EXIST", - "9973": "DNS_ERROR_POLICY_INVALID_CRITERIA", - "9974": "DNS_ERROR_POLICY_INVALID_SETTINGS", - "9975": "DNS_ERROR_CLIENT_SUBNET_IS_ACCESSED", - "9976": "DNS_ERROR_CLIENT_SUBNET_DOES_NOT_EXIST", - "9977": "DNS_ERROR_CLIENT_SUBNET_ALREADY_EXISTS", - "9978": "DNS_ERROR_SUBNET_DOES_NOT_EXIST", - "9979": "DNS_ERROR_SUBNET_ALREADY_EXISTS", - "9980": "DNS_ERROR_POLICY_LOCKED", - "9981": "DNS_ERROR_POLICY_INVALID_WEIGHT", - "9982": "DNS_ERROR_POLICY_INVALID_NAME", - "9983": "DNS_ERROR_POLICY_MISSING_CRITERIA", - "9984": "DNS_ERROR_INVALID_CLIENT_SUBNET_NAME", - "9985": "DNS_ERROR_POLICY_PROCESSING_ORDER_INVALID", - "9986": "DNS_ERROR_POLICY_SCOPE_MISSING", - "9987": "DNS_ERROR_POLICY_SCOPE_NOT_ALLOWED", - "9988": "DNS_ERROR_SERVERSCOPE_IS_REFERENCED", - "9989": "DNS_ERROR_ZONESCOPE_IS_REFERENCED", - "9990": "DNS_ERROR_POLICY_INVALID_CRITERIA_CLIENT_SUBNET", - "9991": "DNS_ERROR_POLICY_INVALID_CRITERIA_TRANSPORT_PROTOCOL", - "9992": "DNS_ERROR_POLICY_INVALID_CRITERIA_NETWORK_PROTOCOL", - "9993": "DNS_ERROR_POLICY_INVALID_CRITERIA_INTERFACE", - "9994": "DNS_ERROR_POLICY_INVALID_CRITERIA_FQDN", - "9995": "DNS_ERROR_POLICY_INVALID_CRITERIA_QUERY_TYPE", - "9996": "DNS_ERROR_POLICY_INVALID_CRITERIA_TIME_OF_DAY", - "10054": "WSAECONNRESET", - "10055": "WSAENOBUFS", - "10060": "WSAETIMEDOUT", - }; - - // Windows DNS record type constants. - // https://docs.microsoft.com/en-us/windows/win32/dns/dns-constants - var dnsRecordTypes = { - "1": "A", - "2": "NS", - "3": "MD", - "4": "MF", - "5": "CNAME", - "6": "SOA", - "7": "MB", - "8": "MG", - "9": "MR", - "10": "NULL", - "11": "WKS", - "12": "PTR", - "13": "HINFO", - "14": "MINFO", - "15": "MX", - "16": "TXT", - "17": "RP", - "18": "AFSDB", - "19": "X25", - "20": "ISDN", - "21": "RT", - "22": "NSAP", - "23": "NSAPPTR", - "24": "SIG", - "25": "KEY", - "26": "PX", - "27": "GPOS", - "28": "AAAA", - "29": "LOC", - "30": "NXT", - "31": "EID", - "32": "NIMLOC", - "33": "SRV", - "34": "ATMA", - "35": "NAPTR", - "36": "KX", - "37": "CERT", - "38": "A6", - "39": "DNAME", - "40": "SINK", - "41": "OPT", - "43": "DS", - "46": "RRSIG", - "47": "NSEC", - "48": "DNSKEY", - "49": "DHCID", - "100": "UINFO", - "101": "UID", - "102": "GID", - "103": "UNSPEC", - "248": "ADDRS", - "249": "TKEY", - "250": "TSIG", - "251": "IXFR", - "252": "AXFR", - "253": "MAILB", - "254": "MAILA", - "255": "ANY", - "65281": "WINS", - "65282": "WINSR", - }; - - var setProcessNameUsingExe = function (evt) { - setProcessNameFromPath(evt, "process.executable", "process.name"); - }; - - var setParentProcessNameUsingExe = function (evt) { - setProcessNameFromPath( - evt, - "process.parent.executable", - "process.parent.name" - ); - }; - - var setProcessNameFromPath = function (evt, pathField, nameField) { - var name = evt.Get(nameField); - if (name) { - return; - } - var exe = evt.Get(pathField); - if (!exe) { - return; - } - evt.Put(nameField, path.basename(exe)); - }; - - var splitCommandLine = function (evt, source, target) { - var commandLine = evt.Get(source); - if (!commandLine) { - return; - } - evt.Put(target, windows.splitCommandLine(commandLine)); - }; - - var splitProcessArgs = function (evt) { - splitCommandLine(evt, "process.command_line", "process.args"); - }; - - var splitParentProcessArgs = function (evt) { - splitCommandLine( - evt, - "process.parent.command_line", - "process.parent.args" - ); - }; - - var addUser = function (evt) { - var id = evt.Get("winlog.user.identifier"); - if (id) { - evt.Put("user.id", id); - } - var userParts = evt.Get("winlog.event_data.User"); - if (!userParts) { - return; - } - userParts = userParts.split("\\"); - if (userParts.length === 2) { - evt.Put("user.domain", userParts[0]); - evt.Put("user.name", userParts[1]); - evt.AppendTo("related.user", userParts[1]); - evt.Delete("winlog.event_data.User"); - } - }; - - var setRuleName = function (evt) { - var ruleName = evt.Get("winlog.event_data.RuleName"); - evt.Delete("winlog.event_data.RuleName"); - - if (!ruleName || ruleName === "-") { - return; - } - - evt.Put("rule.name", ruleName); - }; - - var addNetworkDirection = function (evt) { - switch (evt.Get("winlog.event_data.Initiated")) { - case "true": - evt.Put("network.direction", "egress"); - break; - case "false": - evt.Put("network.direction", "ingress"); - break; - } - evt.Delete("winlog.event_data.Initiated"); - }; - - var addNetworkType = function (evt) { - switch (evt.Get("winlog.event_data.SourceIsIpv6")) { - case "true": - evt.Put("network.type", "ipv6"); - break; - case "false": - evt.Put("network.type", "ipv4"); - break; - } - evt.Delete("winlog.event_data.SourceIsIpv6"); - evt.Delete("winlog.event_data.DestinationIsIpv6"); - }; - - var setRelatedIP = function (evt) { - var sourceIP = evt.Get("source.ip"); - if (sourceIP) { - evt.AppendTo("related.ip", sourceIP); - } - - var destIP = evt.Get("destination.ip"); - if (destIP) { - evt.AppendTo("related.ip", destIP); - } - }; - - var getHashPath = function (namespace, hashKey) { - if (hashKey === "imphash") { - return namespace + ".pe.imphash"; - } - - return namespace + ".hash." + hashKey; - }; - - var emptyHashRegex = /^0*$/; - - var hashIsEmpty = function (value) { - if (!value) { - return true; - } - - return emptyHashRegex.test(value); - } - - // Adds hashes from the given hashField in the event to the 'hash' key - // in the specified namespace. It also adds all the hashes to 'related.hash'. - var addHashes = function (evt, namespace, hashField) { - var hashes = evt.Get(hashField); - if (!hashes) { - return; - } - evt.Delete(hashField); - hashes.split(",").forEach(function (hash) { - var parts = hash.split("="); - if (parts.length !== 2) { - return; - } - - var key = parts[0].toLowerCase(); - var value = parts[1].toLowerCase(); - - if (hashIsEmpty(value)) { - return; - } - - var path = getHashPath(namespace, key); - - evt.Put(path, value); - evt.AppendTo("related.hash", value); - }); - }; - - var splitFileHashes = function (evt) { - addHashes(evt, "file", "winlog.event_data.Hashes"); - }; - - var splitFileHash = function (evt) { - addHashes(evt, "file", "winlog.event_data.Hash"); - }; - - var splitProcessHashes = function (evt) { - addHashes(evt, "process", "winlog.event_data.Hashes"); - }; - - var removeEmptyEventData = function (evt) { - var eventData = evt.Get("winlog.event_data"); - if (eventData && Object.keys(eventData).length === 0) { - evt.Delete("winlog.event_data"); - } - }; - - var translateDnsQueryStatus = function (evt) { - var statusCode = evt.Get("sysmon.dns.status"); - if (!statusCode) { - return; - } - var statusName = dnsQueryStatusCodes[statusCode]; - if (statusName === undefined) { - return; - } - evt.Put("sysmon.dns.status", statusName); - }; - - // Splits the QueryResults field that contains the DNS responses. - // Example: "type: 5 f2.taboola.map.fastly.net;::ffff:151.101.66.2;::ffff:151.101.130.2;::ffff:151.101.194.2;::ffff:151.101.2.2;" - var splitDnsQueryResults = function (evt) { - var results = evt.Get("winlog.event_data.QueryResults"); - if (!results) { - return; - } - results = results.split(";"); - - var answers = []; - var ips = []; - for (var i = 0; i < results.length; i++) { - var answer = results[i]; - if (!answer) { - continue; - } - - if (answer.startsWith("type:")) { - var parts = answer.split(/\s+/); - if (parts.length !== 3) { - throw "unexpected QueryResult format"; - } - - answers.push({ - type: dnsRecordTypes[parts[1]], - data: parts[2], - }); - } else { - // Convert V4MAPPED addresses. - answer = answer.replace("::ffff:", ""); - if (net.isIP(answer)) { - ips.push(answer); - - // Synthesize record type based on IP address type. - var type = "A"; - if (answer.indexOf(":") !== -1) { - type = "AAAA"; - } - answers.push({ - type: type, - data: answer, - }); - } - } - } - - if (answers.length > 0) { - evt.Put("dns.answers", answers); - } - if (ips.length > 0) { - evt.Put("dns.resolved_ip", ips); - } - evt.Delete("winlog.event_data.QueryResults"); - }; - - var parseUtcTime = new processor.Timestamp({ - field: "winlog.event_data.UtcTime", - target_field: "winlog.event_data.UtcTime", - timezone: "UTC", - layouts: ["2006-01-02 15:04:05.999"], - tests: ["2019-06-26 21:19:43.237"], - ignore_missing: true, - }); - - var setAdditionalSignatureFields = function (evt) { - var signed = evt.Get("winlog.event_data.Signed"); - if (!signed) { - return; - } - evt.Put("file.code_signature.signed", true); - var signatureStatus = evt.Get("winlog.event_data.SignatureStatus"); - evt.Put("file.code_signature.valid", signatureStatus === "Valid"); - }; - - var setAdditionalFileFieldsFromPath = function (evt) { - var filePath = evt.Get("file.path"); - if (!filePath) { - return; - } - - evt.Put("file.name", path.basename(filePath)); - evt.Put("file.directory", path.dirname(filePath)); - - // path returns extensions with a preceding ., e.g.: .tmp, .png - // according to ecs the expected format is without it, so we need to remove it. - var ext = path.extname(filePath); - if (!ext) { - return; - } - - if (ext.charAt(0) === ".") { - ext = ext.substr(1); - } - evt.Put("file.extension", ext); - }; - - // https://docs.microsoft.com/en-us/windows/win32/sysinfo/registry-hives - var commonRegistryHives = { - HKEY_CLASSES_ROOT: "HKCR", - HKCR: "HKCR", - HKEY_CURRENT_CONFIG: "HKCC", - HKCC: "HKCC", - HKEY_CURRENT_USER: "HKCU", - HKCU: "HKCU", - HKEY_DYN_DATA: "HKDD", - HKDD: "HKDD", - HKEY_LOCAL_MACHINE: "HKLM", - HKLM: "HKLM", - HKEY_PERFORMANCE_DATA: "HKPD", - HKPD: "HKPD", - HKEY_USERS: "HKU", - HKU: "HKU", - }; - - var qwordRegex = new RegExp(/QWORD \(((0x\d{8})-(0x\d{8}))\)/, "i"); - var dwordRegex = new RegExp(/DWORD \((0x\d{8})\)/, "i"); - - var setRegistryFields = function (evt) { - var path = evt.Get("winlog.event_data.TargetObject"); - if (!path) { - return; - } - evt.Put("registry.path", path); - var pathTokens = path.split("\\"); - var hive = commonRegistryHives[pathTokens[0]]; - if (hive) { - evt.Put("registry.hive", hive); - pathTokens.splice(0, 1); - if (pathTokens.length > 0) { - evt.Put("registry.key", pathTokens.join("\\")); - } - } - var value = pathTokens[pathTokens.length - 1]; - evt.Put("registry.value", value); - var data = evt.Get("winlog.event_data.Details"); - if (!data) { - return; - } - // sysmon only returns details of a registry modification - // if it's a qword or dword - var dataType; - var dataValue; - var match = qwordRegex.exec(data); - if (match && match.length > 0) { - var parsedHighByte = parseInt(match[2]); - var parsedLowByte = parseInt(match[3]); - if (!isNaN(parsedHighByte) && !isNaN(parsedLowByte)) { - dataValue = "" + ((parsedHighByte << 8) + parsedLowByte); - dataType = "SZ_QWORD"; - } - } else { - match = dwordRegex.exec(data); - if (match && match.length > 0) { - var parsedValue = parseInt(match[1]); - if (!isNaN(parsedValue)) { - dataType = "SZ_DWORD"; - dataValue = "" + parsedValue; - } - } - } - if (dataType) { - evt.Put("registry.data.strings", [dataValue]); - evt.Put("registry.data.type", dataType); - } - }; - - // Event ID 1 - Process Create. - var event1 = new processor.Chain() - .Add(parseUtcTime) - .AddFields({ - fields: { - category: ["process"], - type: ["start", "process_start"], - }, - target: "event", - }) - .Convert({ - fields: [{ - from: "winlog.event_data.UtcTime", - to: "@timestamp", - }, - { - from: "winlog.event_data.ProcessGuid", - to: "process.entity_id", - }, - { - from: "winlog.event_data.ProcessId", - to: "process.pid", - type: "long", - }, - { - from: "winlog.event_data.Image", - to: "process.executable", - }, - { - from: "winlog.event_data.CommandLine", - to: "process.command_line", - }, - { - from: "winlog.event_data.CurrentDirectory", - to: "process.working_directory", - }, - { - from: "winlog.event_data.ParentProcessGuid", - to: "process.parent.entity_id", - }, - { - from: "winlog.event_data.ParentProcessId", - to: "process.parent.pid", - type: "long", - }, - { - from: "winlog.event_data.ParentImage", - to: "process.parent.executable", - }, - { - from: "winlog.event_data.ParentCommandLine", - to: "process.parent.command_line", - }, - { - from: "winlog.event_data.OriginalFileName", - to: "process.pe.original_file_name", - }, - ], - mode: "rename", - ignore_missing: true, - fail_on_error: false, - }) - .Convert({ - fields: [{ - from: "winlog.event_data.Company", - to: "process.pe.company", - }, - { - from: "winlog.event_data.Description", - to: "process.pe.description", - }, - { - from: "winlog.event_data.FileVersion", - to: "process.pe.file_version", - }, - { - from: "winlog.event_data.Product", - to: "process.pe.product", - }, - ], - mode: "copy", - ignore_missing: true, - fail_on_error: false, - }) - .Add(setRuleName) - .Add(setProcessNameUsingExe) - .Add(splitProcessArgs) - .Add(addUser) - .Add(splitProcessHashes) - .Add(setParentProcessNameUsingExe) - .Add(splitParentProcessArgs) - .Add(removeEmptyEventData) - .Build(); - - // Event ID 2 - File creation time changed. - var event2 = new processor.Chain() - .Add(parseUtcTime) - .AddFields({ - fields: { - category: ["file"], - type: ["change"], - }, - target: "event", - }) - .Convert({ - fields: [{ - from: "winlog.event_data.UtcTime", - to: "@timestamp", - }, - { - from: "winlog.event_data.ProcessGuid", - to: "process.entity_id", - }, - { - from: "winlog.event_data.ProcessId", - to: "process.pid", - type: "long", - }, - { - from: "winlog.event_data.Image", - to: "process.executable", - }, - { - from: "winlog.event_data.TargetFilename", - to: "file.path", - }, - ], - mode: "rename", - ignore_missing: true, - fail_on_error: false, - }) - .Add(setRuleName) - .Add(setAdditionalFileFieldsFromPath) - .Add(setProcessNameUsingExe) - .Add(removeEmptyEventData) - .Build(); - - // Event ID 3 - Network connection detected. - var event3 = new processor.Chain() - .Add(parseUtcTime) - .AddFields({ - fields: { - category: ["network"], - type: ["connection", "start", "protocol"], - }, - target: "event", - }) - .Convert({ - fields: [{ - from: "winlog.event_data.UtcTime", - to: "@timestamp", - }, - { - from: "winlog.event_data.ProcessGuid", - to: "process.entity_id", - }, - { - from: "winlog.event_data.ProcessId", - to: "process.pid", - type: "long", - }, - { - from: "winlog.event_data.Image", - to: "process.executable", - }, - { - from: "winlog.event_data.Protocol", - to: "network.transport", - }, - { - from: "winlog.event_data.SourceIp", - to: "source.ip", - type: "ip", - }, - { - from: "winlog.event_data.SourceHostname", - to: "source.domain", - type: "string", - }, - { - from: "winlog.event_data.SourcePort", - to: "source.port", - type: "long", - }, - { - from: "winlog.event_data.DestinationIp", - to: "destination.ip", - type: "ip", - }, - { - from: "winlog.event_data.DestinationHostname", - to: "destination.domain", - type: "string", - }, - { - from: "winlog.event_data.DestinationPort", - to: "destination.port", - type: "long", - }, - { - from: "winlog.event_data.DestinationPortName", - to: "network.protocol", - }, - ], - mode: "rename", - ignore_missing: true, - fail_on_error: false, - }) - .Add(setRuleName) - .Add(setRelatedIP) - .Add(setProcessNameUsingExe) - .Add(addUser) - .Add(addNetworkDirection) - .Add(addNetworkType) - .CommunityID() - .Add(removeEmptyEventData) - .Build(); - - // Event ID 4 - Sysmon service state changed. - var event4 = new processor.Chain() - .Add(parseUtcTime) - .AddFields({ - fields: { - category: ["process"], - type: ["change"], - }, - target: "event", - }) - .Convert({ - fields: [{ - from: "winlog.event_data.UtcTime", - to: "@timestamp", - }, ], - mode: "rename", - ignore_missing: true, - fail_on_error: false, - }) - .Add(removeEmptyEventData) - .Build(); - - // Event ID 5 - Process terminated. - var event5 = new processor.Chain() - .Add(parseUtcTime) - .AddFields({ - fields: { - category: ["process"], - type: ["end", "process_end"], - }, - target: "event", - }) - .Convert({ - fields: [{ - from: "winlog.event_data.UtcTime", - to: "@timestamp", - }, - { - from: "winlog.event_data.ProcessGuid", - to: "process.entity_id", - }, - { - from: "winlog.event_data.ProcessId", - to: "process.pid", - type: "long", - }, - { - from: "winlog.event_data.Image", - to: "process.executable", - }, - ], - mode: "rename", - ignore_missing: true, - fail_on_error: false, - }) - .Add(setRuleName) - .Add(setProcessNameUsingExe) - .Add(removeEmptyEventData) - .Build(); - - // Event ID 6 - Driver loaded. - var event6 = new processor.Chain() - .Add(parseUtcTime) - .AddFields({ - fields: { - category: ["driver"], - type: ["start"], - }, - target: "event", - }) - .Convert({ - fields: [{ - from: "winlog.event_data.UtcTime", - to: "@timestamp", - }, - { - from: "winlog.event_data.ImageLoaded", - to: "file.path", - }, - ], - mode: "rename", - ignore_missing: true, - fail_on_error: false, - }) - .Convert({ - fields: [{ - from: "winlog.event_data.Signature", - to: "file.code_signature.subject_name", - }, - { - from: "winlog.event_data.SignatureStatus", - to: "file.code_signature.status", - }, - ], - fail_on_error: false, - }) - .Add(setRuleName) - .Add(setAdditionalFileFieldsFromPath) - .Add(setAdditionalSignatureFields) - .Add(splitFileHashes) - .Add(removeEmptyEventData) - .Build(); - - // Event ID 7 - Image loaded. - var event7 = new processor.Chain() - .Add(parseUtcTime) - .AddFields({ - fields: { - category: ["process"], - type: ["change"], - }, - target: "event", - }) - .Convert({ - fields: [{ - from: "winlog.event_data.UtcTime", - to: "@timestamp", - }, - { - from: "winlog.event_data.ProcessGuid", - to: "process.entity_id", - }, - { - from: "winlog.event_data.ProcessId", - to: "process.pid", - type: "long", - }, - { - from: "winlog.event_data.Image", - to: "process.executable", - }, - { - from: "winlog.event_data.ImageLoaded", - to: "file.path", - }, - { - from: "winlog.event_data.OriginalFileName", - to: "file.pe.original_file_name", - }, - - ], - mode: "rename", - ignore_missing: true, - fail_on_error: false, - }) - .Convert({ - fields: [{ - from: "winlog.event_data.Signature", - to: "file.code_signature.subject_name", - }, - { - from: "winlog.event_data.SignatureStatus", - to: "file.code_signature.status", - }, - { - from: "winlog.event_data.Company", - to: "file.pe.company", - }, - { - from: "winlog.event_data.Description", - to: "file.pe.description", - }, - { - from: "winlog.event_data.FileVersion", - to: "file.pe.file_version", - }, - { - from: "winlog.event_data.Product", - to: "file.pe.product", - }, - ], - ignore_missing: true, - fail_on_error: false, - }) - .Add(setRuleName) - .Add(setAdditionalFileFieldsFromPath) - .Add(setAdditionalSignatureFields) - .Add(setProcessNameUsingExe) - .Add(splitFileHashes) - .Add(removeEmptyEventData) - .Build(); - - // Event ID 8 - CreateRemoteThread detected. - var event8 = new processor.Chain() - .Add(parseUtcTime) - .Convert({ - fields: [{ - from: "winlog.event_data.UtcTime", - to: "@timestamp", - }, - { - from: "winlog.event_data.SourceProcessGuid", - to: "process.entity_id", - }, - { - from: "winlog.event_data.SourceProcessId", - to: "process.pid", - type: "long", - }, - { - from: "winlog.event_data.SourceImage", - to: "process.executable", - }, - ], - mode: "rename", - ignore_missing: true, - fail_on_error: false, - }) - .Add(setRuleName) - .Add(setProcessNameUsingExe) - .Add(removeEmptyEventData) - .Build(); - - // Event ID 9 - RawAccessRead detected. - var event9 = new processor.Chain() - .Add(parseUtcTime) - .Convert({ - fields: [{ - from: "winlog.event_data.UtcTime", - to: "@timestamp", - }, - { - from: "winlog.event_data.ProcessGuid", - to: "process.entity_id", - }, - { - from: "winlog.event_data.ProcessId", - to: "process.pid", - type: "long", - }, - { - from: "winlog.event_data.Image", - to: "process.executable", - }, - { - from: "winlog.event_data.Device", - to: "file.path", - }, - ], - mode: "rename", - ignore_missing: true, - fail_on_error: false, - }) - .Add(setRuleName) - .Add(setAdditionalFileFieldsFromPath) - .Add(setProcessNameUsingExe) - .Add(removeEmptyEventData) - .Build(); - - // Event ID 10 - Process accessed. - var event10 = new processor.Chain() - .Add(parseUtcTime) - .AddFields({ - fields: { - category: ["process"], - type: ["access"], - }, - target: "event", - }) - .Convert({ - fields: [{ - from: "winlog.event_data.UtcTime", - to: "@timestamp", - }, - { - from: "winlog.event_data.SourceProcessGUID", - to: "process.entity_id", - }, - { - from: "winlog.event_data.SourceProcessId", - to: "process.pid", - type: "long", - }, - { - from: "winlog.event_data.SourceThreadId", - to: "process.thread.id", - type: "long", - }, - { - from: "winlog.event_data.SourceImage", - to: "process.executable", - }, - ], - mode: "rename", - ignore_missing: true, - fail_on_error: false, - }) - .Add(setRuleName) - .Add(setProcessNameUsingExe) - .Add(removeEmptyEventData) - .Build(); - - // Event ID 11 - File created. - var event11 = new processor.Chain() - .Add(parseUtcTime) - .AddFields({ - fields: { - category: ["file"], - type: ["creation"], - }, - target: "event", - }) - .Convert({ - fields: [{ - from: "winlog.event_data.UtcTime", - to: "@timestamp", - }, - { - from: "winlog.event_data.ProcessGuid", - to: "process.entity_id", - }, - { - from: "winlog.event_data.ProcessId", - to: "process.pid", - type: "long", - }, - { - from: "winlog.event_data.Image", - to: "process.executable", - }, - { - from: "winlog.event_data.TargetFilename", - to: "file.path", - }, - ], - mode: "rename", - ignore_missing: true, - fail_on_error: false, - }) - .Add(setRuleName) - .Add(setAdditionalFileFieldsFromPath) - .Add(setProcessNameUsingExe) - .Add(removeEmptyEventData) - .Build(); - - // Event ID 12 - Registry object added or deleted. - var event12 = new processor.Chain() - .Add(parseUtcTime) - .AddFields({ - fields: { - category: ["configuration", "registry"], - type: ["change"], - }, - target: "event", - }) - .Convert({ - fields: [{ - from: "winlog.event_data.UtcTime", - to: "@timestamp", - }, - { - from: "winlog.event_data.ProcessGuid", - to: "process.entity_id", - }, - { - from: "winlog.event_data.ProcessId", - to: "process.pid", - type: "long", - }, - { - from: "winlog.event_data.Image", - to: "process.executable", - }, - ], - mode: "rename", - ignore_missing: true, - fail_on_error: false, - }) - .Add(setRuleName) - .Add(setRegistryFields) - .Add(setProcessNameUsingExe) - .Add(removeEmptyEventData) - .Build(); - - // Event ID 13 - Registry value set. - var event13 = new processor.Chain() - .Add(parseUtcTime) - .AddFields({ - fields: { - category: ["configuration", "registry"], - type: ["change"], - }, - target: "event", - }) - .Convert({ - fields: [{ - from: "winlog.event_data.UtcTime", - to: "@timestamp", - }, - { - from: "winlog.event_data.ProcessGuid", - to: "process.entity_id", - }, - { - from: "winlog.event_data.ProcessId", - to: "process.pid", - type: "long", - }, - { - from: "winlog.event_data.Image", - to: "process.executable", - }, - ], - mode: "rename", - ignore_missing: true, - fail_on_error: false, - }) - .Add(setRuleName) - .Add(setRegistryFields) - .Add(setProcessNameUsingExe) - .Add(removeEmptyEventData) - .Build(); - - // Event ID 14 - Registry object renamed. - var event14 = new processor.Chain() - .Add(parseUtcTime) - .AddFields({ - fields: { - category: ["configuration", "registry"], - type: ["change"], - }, - target: "event", - }) - .Convert({ - fields: [{ - from: "winlog.event_data.UtcTime", - to: "@timestamp", - }, - { - from: "winlog.event_data.ProcessGuid", - to: "process.entity_id", - }, - { - from: "winlog.event_data.ProcessId", - to: "process.pid", - type: "long", - }, - { - from: "winlog.event_data.Image", - to: "process.executable", - }, - ], - mode: "rename", - ignore_missing: true, - fail_on_error: false, - }) - .Add(setRuleName) - .Add(setRegistryFields) - .Add(setProcessNameUsingExe) - .Add(removeEmptyEventData) - .Build(); - - // Event ID 15 - File stream created. - var event15 = new processor.Chain() - .Add(parseUtcTime) - .AddFields({ - fields: { - category: ["file"], - type: ["access"], - }, - target: "event", - }) - .Convert({ - fields: [{ - from: "winlog.event_data.UtcTime", - to: "@timestamp", - }, - { - from: "winlog.event_data.ProcessGuid", - to: "process.entity_id", - }, - { - from: "winlog.event_data.ProcessId", - to: "process.pid", - type: "long", - }, - { - from: "winlog.event_data.Image", - to: "process.executable", - }, - { - from: "winlog.event_data.TargetFilename", - to: "file.path", - }, - ], - mode: "rename", - ignore_missing: true, - fail_on_error: false, - }) - .Add(setRuleName) - .Add(setAdditionalFileFieldsFromPath) - .Add(setProcessNameUsingExe) - .Add(splitFileHash) - .Add(removeEmptyEventData) - .Build(); - - // Event ID 16 - Sysmon config state changed. - var event16 = new processor.Chain() - .Add(parseUtcTime) - .AddFields({ - fields: { - category: ["configuration"], - type: ["change"], - }, - target: "event", - }) - .Convert({ - fields: [{ - from: "winlog.event_data.UtcTime", - to: "@timestamp", - }, ], - mode: "rename", - ignore_missing: true, - fail_on_error: false, - }) - .Add(removeEmptyEventData) - .Build(); - - // Event ID 17 - Pipe Created. - var event17 = new processor.Chain() - .Add(parseUtcTime) - .AddFields({ - fields: { - category: ["file"], // pipes are files - type: ["creation"], - }, - target: "event", - }) - .Convert({ - fields: [{ - from: "winlog.event_data.UtcTime", - to: "@timestamp", - }, - { - from: "winlog.event_data.ProcessGuid", - to: "process.entity_id", - }, - { - from: "winlog.event_data.ProcessId", - to: "process.pid", - type: "long", - }, - { - from: "winlog.event_data.PipeName", - to: "file.name", - }, - { - from: "winlog.event_data.Image", - to: "process.executable", - }, - ], - mode: "rename", - ignore_missing: true, - fail_on_error: false, - }) - .Add(setRuleName) - .Add(setProcessNameUsingExe) - .Add(removeEmptyEventData) - .Build(); - - // Event ID 18 - Pipe Connected. - var event18 = new processor.Chain() - .Add(parseUtcTime) - .AddFields({ - fields: { - category: ["file"], // pipes are files - type: ["access"], - }, - target: "event", - }) - .Convert({ - fields: [{ - from: "winlog.event_data.UtcTime", - to: "@timestamp", - }, - { - from: "winlog.event_data.ProcessGuid", - to: "process.entity_id", - }, - { - from: "winlog.event_data.ProcessId", - to: "process.pid", - type: "long", - }, - { - from: "winlog.event_data.PipeName", - to: "file.name", - }, - { - from: "winlog.event_data.Image", - to: "process.executable", - }, - ], - mode: "rename", - ignore_missing: true, - fail_on_error: false, - }) - .Add(setRuleName) - .Add(setProcessNameUsingExe) - .Add(removeEmptyEventData) - .Build(); - - // Event ID 19 - WmiEventFilter activity detected. - var event19 = new processor.Chain() - .Add(parseUtcTime) - .Convert({ - fields: [{ - from: "winlog.event_data.UtcTime", - to: "@timestamp", - }, ], - mode: "rename", - ignore_missing: true, - fail_on_error: false, - }) - .Add(setRuleName) - .Add(addUser) - .Add(removeEmptyEventData) - .Build(); - - // Event ID 20 - WmiEventConsumer activity detected. - var event20 = new processor.Chain() - .Add(parseUtcTime) - .Convert({ - fields: [{ - from: "winlog.event_data.UtcTime", - to: "@timestamp", - }, - { - from: "winlog.event_data.Destination", - to: "process.executable", - }, - ], - mode: "rename", - ignore_missing: true, - fail_on_error: false, - }) - .Add(setRuleName) - .Add(addUser) - .Add(setProcessNameUsingExe) - .Add(removeEmptyEventData) - .Build(); - - // Event ID 21 - WmiEventConsumerToFilter activity detected. - var event21 = new processor.Chain() - .Add(parseUtcTime) - .Convert({ - fields: [{ - from: "winlog.event_data.UtcTime", - to: "@timestamp", - }, ], - mode: "rename", - ignore_missing: true, - fail_on_error: false, - }) - .Add(setRuleName) - .Add(addUser) - .Add(removeEmptyEventData) - .Build(); - - // Event ID 22 - DNSEvent (DNS query). - var event22 = new processor.Chain() - .Add(parseUtcTime) - .AddFields({ - fields: { - category: ["network"], - type: ["connection", "protocol", "info"], - }, - target: "event", - }) - .AddFields({ - fields: { - protocol: "dns", - }, - target: "network", - }) - .Convert({ - fields: [{ - from: "winlog.event_data.UtcTime", - to: "@timestamp", - }, - { - from: "winlog.event_data.ProcessGuid", - to: "process.entity_id", - }, - { - from: "winlog.event_data.ProcessId", - to: "process.pid", - type: "long", - }, - { - from: "winlog.event_data.Image", - to: "process.executable", - }, - { - from: "winlog.event_data.QueryName", - to: "dns.question.name", - }, - { - from: "winlog.event_data.QueryStatus", - to: "sysmon.dns.status", - }, - ], - mode: "rename", - ignore_missing: true, - fail_on_error: false, - }) - .RegisteredDomain({ - ignore_failure: true, - ignore_missing: true, - field: "dns.question.name", - target_field: "dns.question.registered_domain", - target_subdomain_field: "dns.question.subdomain", - target_etld_field: "dns.question.top_level_domain", - }) - .Add(setRuleName) - .Add(translateDnsQueryStatus) - .Add(splitDnsQueryResults) - .Add(setProcessNameUsingExe) - .Add(removeEmptyEventData) - .Build(); - - // Event ID 23 - FileDelete (A file delete was detected). - var event23 = new processor.Chain() - .Add(parseUtcTime) - .AddFields({ - fields: { - category: ["file"], // pipes are files - type: ["deletion"], - }, - target: "event", - }) - .Convert({ - fields: [{ - from: "winlog.event_data.UtcTime", - to: "@timestamp", - }, - { - from: "winlog.event_data.ProcessGuid", - to: "process.entity_id", - }, - { - from: "winlog.event_data.ProcessId", - to: "process.pid", - type: "long", - }, - { - from: "winlog.event_data.RuleName", - to: "rule.name", - }, - { - from: "winlog.event_data.TargetFilename", - to: "file.path", - }, - { - from: "winlog.event_data.Image", - to: "process.executable", - }, - { - from: "winlog.event_data.Archived", - to: "sysmon.file.archived", - type: "boolean", - }, - { - from: "winlog.event_data.IsExecutable", - to: "sysmon.file.is_executable", - type: "boolean", - }, - ], - mode: "rename", - ignore_missing: true, - fail_on_error: false, - }) - .Add(setRuleName) - .Add(addUser) - .Add(splitProcessHashes) - .Add(setProcessNameUsingExe) - .Add(setAdditionalFileFieldsFromPath) - .Add(removeEmptyEventData) - .Build(); - - // Event ID 24 - ClipboardChange (New content in the clipboard). - var event24 = new processor.Chain() - .Add(parseUtcTime) - .AddFields({ - fields: { - type: ["change"], - }, - target: "event", - }) - .Convert({ - fields: [{ - from: "winlog.event_data.UtcTime", - to: "@timestamp", - }, - { - from: "winlog.event_data.ProcessGuid", - to: "process.entity_id", - }, - { - from: "winlog.event_data.ProcessId", - to: "process.pid", - type: "long", - }, - { - from: "winlog.event_data.Image", - to: "process.executable", - }, - { - from: "winlog.event_data.Archived", - to: "sysmon.file.archived", - type: "boolean", - }, - { - from: "winlog.event_data.IsExecutable", - to: "sysmon.file.is_executable", - type: "boolean", - }, - ], - mode: "rename", - ignore_missing: true, - fail_on_error: false, - }) - .Add(setRuleName) - .Add(addUser) - .Add(splitProcessHashes) - .Add(setProcessNameUsingExe) - .Add(setAdditionalFileFieldsFromPath) - .Add(removeEmptyEventData) - .Build(); - - // Event ID 25 - ProcessTampering (Process image change). - var event25 = new processor.Chain() - .Add(parseUtcTime) - .AddFields({ - fields: { - category: ["process"], - type: ["change"], - }, - target: "event", - }) - .Convert({ - fields: [{ - from: "winlog.event_data.UtcTime", - to: "@timestamp", - }, - { - from: "winlog.event_data.ProcessGuid", - to: "process.entity_id", - }, - { - from: "winlog.event_data.ProcessId", - to: "process.pid", - type: "long", - }, - { - from: "winlog.event_data.Image", - to: "process.executable", - }, - { - from: "winlog.event_data.Archived", - to: "sysmon.file.archived", - type: "boolean", - }, - { - from: "winlog.event_data.IsExecutable", - to: "sysmon.file.is_executable", - type: "boolean", - }, - ], - mode: "rename", - ignore_missing: true, - fail_on_error: false, - }) - .Add(setRuleName) - .Add(addUser) - .Add(splitProcessHashes) - .Add(setProcessNameUsingExe) - .Add(setAdditionalFileFieldsFromPath) - .Add(removeEmptyEventData) - .Build(); - - // Event ID 255 - Error report. - var event255 = new processor.Chain() - .Add(parseUtcTime) - .Convert({ - fields: [{ - from: "winlog.event_data.UtcTime", - to: "@timestamp", - }, - { - from: "winlog.event_data.ID", - to: "error.code", - }, - ], - mode: "rename", - ignore_missing: true, - fail_on_error: false, - }) - .Add(removeEmptyEventData) - .Build(); - - return { - 1: event1.Run, - 2: event2.Run, - 3: event3.Run, - 4: event4.Run, - 5: event5.Run, - 6: event6.Run, - 7: event7.Run, - 8: event8.Run, - 9: event9.Run, - 10: event10.Run, - 11: event11.Run, - 12: event12.Run, - 13: event13.Run, - 14: event14.Run, - 15: event15.Run, - 16: event16.Run, - 17: event17.Run, - 18: event18.Run, - 19: event19.Run, - 20: event20.Run, - 21: event21.Run, - 22: event22.Run, - 23: event23.Run, - 24: event24.Run, - 25: event25.Run, - 255: event255.Run, - - process: function (evt) { - var event_id = evt.Get("winlog.event_id"); - var processor = this[event_id]; - if (processor === undefined) { - throw "unexpected sysmon event_id"; - } - evt.Put("event.module", "sysmon"); - processor(evt); - }, - }; -})(); - -function process(evt) { - return sysmon.process(evt); -} diff --git a/x-pack/winlogbeat/module/sysmon/ingest/sysmon.yml b/x-pack/winlogbeat/module/sysmon/ingest/sysmon.yml new file mode 100644 index 00000000000..db28eb13cf7 --- /dev/null +++ b/x-pack/winlogbeat/module/sysmon/ingest/sysmon.yml @@ -0,0 +1,1253 @@ +--- +description: Pipeline for Windows Sysmon Event Logs +processors: +## ECS and Event fields. + + - set: + field: ecs.version + value: '1.12.0' + - rename: + field: winlog.level + target_field: log.level + ignore_missing: true + ignore_failure: true + if: ctx?.winlog?.level != "" + - date: + field: winlog.time_created + target_field: event.created + formats: + - ISO8601 + ignore_failure: true + if: ctx?.winlog?.time_created != null + - date: + field: winlog.event_data.UtcTime + formats: + - yyyy-MM-dd HH:mm:ss.SSS + timezone: UTC + ignore_failure: true + if: ctx?.winlog?.event_data?.UtcTime != null + + - set: + field: event.ingested + value: '{{_ingest.timestamp}}' + - set: + field: event.kind + value: event + - set: + field: event.code + value: '{{winlog.event_id}}' + + - script: + description: Set event category and type for all event types. + lang: painless + params: + "1": + category: + - process + type: + - start + "2": + category: + - file + type: + - change + "3": + category: + - network + type: + - start + - connection + - protocol + "4": + category: + - process + type: + - change + "5": + category: + - process + type: + - end + "6": + category: + - driver + type: + - start + "7": + category: + - process + type: + - change + "10": + category: + - process + type: + - access + "11": + category: + - file + type: + - creation + "12": + category: + - configuration + - registry + type: + - change + "13": + category: + - configuration + - registry + type: + - change + "14": + category: + - configuration + - registry + type: + - change + "15": + category: + - file + type: + - access + "16": + category: + - configuration + type: + - change + "17": + category: + - file + type: + - creation + "18": + category: + - file + type: + - access + "22": + category: + - network + type: + - connection + - protocol + - info + "23": + category: + - file + type: + - deletion + "24": + type: + - change + "25": + category: + - process + type: + - change + tag: Add ECS categorization fields + source: |- + if (ctx?.event?.code == null || params.get(ctx.event.code) == null) { + return; + } + def hm = new HashMap(params[ctx.event.code]); + hm.forEach((k, v) -> ctx.event[k] = v); + - convert: + field: winlog.record_id + type: string + ignore_failure: true + ignore_missing: true + + - rename: + field: winlog.event_data.ID + target_field: error.code + ignore_failure: true + ignore_missing: true + if: ctx.event.code == "255" && ctx.winlog?.event_data?.ID != null && ctx.winlog?.event_data?.ID != "" + + - rename: + field: winlog.event_data.RuleName + target_field: rule.name + ignore_missing: true + ignore_failure: true + if: ctx?.winlog?.event_data?.RuleName != null && ctx?.winlog?.event_data?.RuleName != "" && ctx?.winlog?.event_data?.RuleName != "-" + + + - rename: + field: winlog.event_data.Type + target_field: message + ignore_missing: true + ignore_failure: true + if: ctx.event.code == "25" && ctx?.winlog?.event_data?.Type != null && ctx?.winlog?.event_data?.Type != "" + + - rename: + field: winlog.event_data.Hash + target_field: winlog.event_data.Hashes + ignore_missing: true + ignore_failure: true + if: ctx?.winlog?.event_data?.Hash != null && ctx?.winlog?.event_data?.Hash != "" + - kv: + field: winlog.event_data.Hashes + target_field: _temp.hashes + field_split: "," + value_split: "=" + ignore_failure: true + if: ctx?.winlog?.event_data?.Hashes != null + - script: + lang: painless + if: ctx?._temp?.hashes != null + source: |- + def hashIsEmpty(String hash) { + if (hash == "") { + return true; + } + + Pattern emptyHashRegex = /^0*$/; + def matcher = emptyHashRegex.matcher(hash); + + return matcher.matches(); + } + + def hashes = new HashMap(); + def related = [ + "hash": new ArrayList() + ]; + for (entry in ctx._temp.hashes.entrySet()) { + def key = entry.getKey().toString().toLowerCase(); + def value = entry.getValue().toString().toLowerCase(); + + if (hashIsEmpty(value)) { + continue; + } + + hashes[key] = value; + related.hash.add(value); + } + + ctx._temp.hashes = hashes; + if (related.hash.length > 0) { + ctx.related = related; + } + +## Process fields + + - rename: + field: _temp.hashes + target_field: process.hash + if: |- + ctx?._temp?.hashes != null && + ["1", "23", "24", "25"].contains(ctx.event.code) + - rename: + field: process.hash.imphash + target_field: process.pe.imphash + ignore_failure: true + ignore_missing: true + - rename: + field: winlog.event_data.ProcessGuid + target_field: process.entity_id + ignore_missing: true + ignore_failure: true + if: ctx?.winlog?.event_data?.ProcessGuid != null && ctx?.winlog?.event_data?.ProcessGuid != "" + - convert: + field: winlog.event_data.ProcessId + target_field: process.pid + type: long + ignore_failure: true + ignore_missing: true + if: ctx?.winlog?.event_data?.ProcessId != null && ctx?.winlog?.event_data?.ProcessId != "" + - rename: + field: winlog.event_data.Image + target_field: process.executable + ignore_missing: true + ignore_failure: true + if: ctx?.winlog?.event_data?.Image != null && ctx?.winlog?.event_data?.Image != "" + - rename: + field: winlog.event_data.SourceProcessGuid + target_field: process.entity_id + ignore_missing: true + ignore_failure: true + if: ctx?.winlog?.event_data?.SourceProcessGuid != null && ctx?.winlog?.event_data?.SourceProcessGuid != "" + - rename: + field: winlog.event_data.SourceProcessGUID + target_field: process.entity_id + ignore_missing: true + ignore_failure: true + if: ctx?.winlog?.event_data?.SourceProcessGUID != null && ctx?.winlog?.event_data?.SourceProcessGUID != "" + - convert: + field: winlog.event_data.SourceProcessId + target_field: process.pid + type: long + ignore_failure: true + ignore_missing: true + if: ctx?.winlog?.event_data?.SourceProcessId != null && ctx?.winlog?.event_data?.SourceProcessId != "" + - convert: + field: winlog.event_data.SourceThreadId + target_field: process.thread.id + type: long + ignore_failure: true + ignore_missing: true + if: ctx?.winlog?.event_data?.SourceThreadId != null && ctx?.winlog?.event_data?.SourceThreadId != "" + - rename: + field: winlog.event_data.SourceImage + target_field: process.executable + ignore_missing: true + ignore_failure: true + if: ctx?.winlog?.event_data?.SourceImage != null && ctx?.winlog?.event_data?.SourceImage != "" + - rename: + field: winlog.event_data.Destination + target_field: process.executable + ignore_missing: true + ignore_failure: true + if: ctx?.winlog?.event_data?.Destination != null && ctx?.winlog?.event_data?.Destination != "" + - rename: + field: winlog.event_data.CommandLine + target_field: process.command_line + ignore_missing: true + ignore_failure: true + if: ctx?.winlog?.event_data?.CommandLine != null && ctx?.winlog?.event_data?.CommandLine != "" + - rename: + field: winlog.event_data.CurrentDirectory + target_field: process.working_directory + ignore_missing: true + ignore_failure: true + if: ctx?.winlog?.event_data?.CurrentDirectory != null && ctx?.winlog?.event_data?.CurrentDirectory != "" + - rename: + field: winlog.event_data.ParentProcessGuid + target_field: process.parent.entity_id + ignore_missing: true + ignore_failure: true + if: ctx?.winlog?.event_data?.ParentProcessGuid != null && ctx?.winlog?.event_data?.ParentProcessGuid != "" + - convert: + field: winlog.event_data.ParentProcessId + target_field: process.parent.pid + type: long + ignore_failure: true + ignore_missing: true + if: ctx?.winlog?.event_data?.ParentProcessId != null && ctx?.winlog?.event_data?.ParentProcessId != "" + - rename: + field: winlog.event_data.ParentImage + target_field: process.parent.executable + ignore_missing: true + ignore_failure: true + if: ctx?.winlog?.event_data?.ParentImage != null && ctx?.winlog?.event_data?.ParentImage != "" + - rename: + field: winlog.event_data.ParentCommandLine + target_field: process.parent.command_line + ignore_missing: true + ignore_failure: true + if: ctx?.winlog?.event_data?.ParentCommandLine != null && ctx?.winlog?.event_data?.ParentCommandLine != "" + - rename: + field: winlog.event_data.OriginalFileName + target_field: process.pe.original_file_name + ignore_missing: true + ignore_failure: true + if: ctx.event.code != "7" && ctx?.winlog?.event_data?.OriginalFileName != null && ctx?.winlog?.event_data?.OriginalFileName != "" + - set: + field: process.pe.company + copy_from: winlog.event_data.Company + ignore_empty_value: true + ignore_failure: true + if: ctx.event.code != "7" + - set: + field: process.pe.description + copy_from: winlog.event_data.Description + ignore_empty_value: true + ignore_failure: true + if: ctx.event.code != "7" + - set: + field: process.pe.file_version + copy_from: winlog.event_data.FileVersion + ignore_empty_value: true + ignore_failure: true + if: ctx.event.code != "7" + - set: + field: process.pe.product + copy_from: winlog.event_data.Product + ignore_empty_value: true + ignore_failure: true + if: ctx.event.code != "7" + + - script: + description: Implements Windows-like SplitCommandLine + lang: painless + if: |- + (ctx?.process?.command_line != null && ctx.process.command_line != "") || + (ctx?.process?.parent?.command_line != null && ctx.process.parent.command_line != "") + source: |- + // appendBSBytes appends n '\\' bytes to b and returns the resulting slice. + def appendBSBytes(StringBuilder b, int n) { + for (; n > 0; n--) { + b.append('\\'); + } + return b; + } + + // readNextArg splits command line string cmd into next + // argument and command line remainder. + def readNextArg(String cmd) { + def b = new StringBuilder(); + boolean inquote; + int nslash; + for (; cmd.length() > 0; cmd = cmd.substring(1)) { + def c = cmd.charAt(0); + if (c == (char)' ' || c == (char)0x09) { + if (!inquote) { + return [ + "arg": appendBSBytes(b, nslash).toString(), + "rest": cmd.substring(1) + ]; + } + } else if (c == (char)'"') { + b = appendBSBytes(b, nslash/2); + if (nslash%2 == 0) { + // use "Prior to 2008" rule from + // http://daviddeley.com/autohotkey/parameters/parameters.htm + // section 5.2 to deal with double double quotes + if (inquote && cmd.length() > 1 && cmd.charAt(1) == (char)'"') { + b.append(c); + cmd = cmd.substring(1); + } + inquote = !inquote; + } else { + b.append(c); + } + nslash = 0; + continue; + } else if (c == (char)'\\') { + nslash++; + continue; + } + b = appendBSBytes(b, nslash); + nslash = 0; + b.append(c); + } + return [ + "arg": appendBSBytes(b, nslash).toString(), + "rest": '' + ]; + } + + // commandLineToArgv splits a command line into individual argument + // strings, following the Windows conventions documented + // at http://daviddeley.com/autohotkey/parameters/parameters.htm#WINARGV + // Original implementation found at: https://github.com/golang/go/commit/39c8d2b7faed06b0e91a1ad7906231f53aab45d1 + def commandLineToArgv(String cmd) { + def args = new ArrayList(); + while (cmd.length() > 0) { + if (cmd.charAt(0) == (char)' ' || cmd.charAt(0) == (char)0x09) { + cmd = cmd.substring(1); + continue; + } + def next = readNextArg(cmd); + cmd = next.rest; + args.add(next.arg); + } + return args; + } + + def cmd = ctx?.process?.command_line; + if (cmd != null && cmd != "") { + ctx.process.args = commandLineToArgv(cmd); + ctx.process.args_count = ctx.process.args.length; + } + + def parentCmd = ctx?.process?.parent?.command_line; + if (parentCmd != null && parentCmd != "") { + ctx.process.parent.args = commandLineToArgv(parentCmd); + ctx.process.parent.args_count = ctx.process.parent.args.length; + } + + - script: + description: Adds process name information. + lang: painless + if: |- + (ctx?.process?.executable != null && ctx.process.executable.length() > 1) || + (ctx?.process?.parent?.executable != null && ctx.process.parent.executable.length() > 1) + source: |- + def getProcessName(def path) { + def idx = path.lastIndexOf("\\"); + if (idx > -1) { + return path.substring(idx+1); + } + return ""; + } + + def cmd = ctx?.process?.executable; + if (cmd != null && cmd != "" && ctx?.process?.name == null) { + def name = getProcessName(cmd); + if (name != "") { + ctx.process.name = name; + } + } + + def parentCmd = ctx?.process?.parent?.executable; + if (parentCmd != null && parentCmd != "" && ctx?.process?.parent?.name == null) { + def name = getProcessName(parentCmd); + if (name != "") { + ctx.process.parent.name = name; + } + } + +## File fields + + - rename: + field: _temp.hashes + target_field: file.hash + if: |- + ctx?._temp?.hashes != null && + ["6", "7", "15"].contains(ctx.event.code) + - rename: + field: file.hash.imphash + target_field: file.pe.imphash + ignore_failure: true + ignore_missing: true + - rename: + field: winlog.event_data.TargetFilename + target_field: file.path + ignore_missing: true + ignore_failure: true + if: ctx?.winlog?.event_data?.TargetFilename != null && ctx?.winlog?.event_data?.TargetFilename != "" + - rename: + field: winlog.event_data.Device + target_field: file.path + ignore_missing: true + ignore_failure: true + if: ctx?.winlog?.event_data?.Device != null && ctx?.winlog?.event_data?.Device != "" + - rename: + field: winlog.event_data.PipeName + target_field: file.name + ignore_missing: true + ignore_failure: true + if: ctx?.winlog?.event_data?.PipeName != null && ctx?.winlog?.event_data?.PipeName != "" + - rename: + field: winlog.event_data.ImageLoaded + target_field: file.path + ignore_missing: true + ignore_failure: true + if: ctx?.winlog?.event_data?.ImageLoaded != null && ctx?.winlog?.event_data?.ImageLoaded != "" + - set: + field: file.code_signature.subject_name + copy_from: winlog.event_data.Signature + ignore_failure: true + ignore_empty_value: true + - set: + field: file.code_signature.status + copy_from: winlog.event_data.SignatureStatus + ignore_failure: true + ignore_empty_value: true + - rename: + field: winlog.event_data.OriginalFileName + target_field: file.pe.original_file_name + ignore_missing: true + ignore_failure: true + if: ctx.event.code == "7" && ctx?.winlog?.event_data?.OriginalFileName != null && ctx?.winlog?.event_data?.OriginalFileName != "" + - set: + field: file.pe.company + copy_from: winlog.event_data.Company + ignore_failure: true + ignore_empty_value: true + if: ctx.event.code == "7" + - set: + field: file.pe.description + copy_from: winlog.event_data.Description + ignore_failure: true + ignore_empty_value: true + if: ctx.event.code == "7" + - set: + field: file.pe.file_version + copy_from: winlog.event_data.FileVersion + ignore_failure: true + ignore_empty_value: true + if: ctx.event.code == "7" + - set: + field: file.pe.product + copy_from: winlog.event_data.Product + ignore_failure: true + ignore_empty_value: true + if: ctx.event.code == "7" + - set: + field: file.code_signature.signed + value: true + if: ctx?.winlog?.event_data?.Signed != null && ctx.winlog.event_data.Signed == true + - set: + field: file.code_signature.valid + value: true + if: ctx?.winlog?.event_data?.SignatureStatus != null && ctx?.winlog?.event_data?.SignatureStatus == "Valid" + + - script: + description: Adds file information. + lang: painless + if: ctx?.file?.path != null && ctx.file.path.length() > 1 + source: |- + def path = ctx.file.path; + def idx = path.lastIndexOf("\\"); + if (idx > -1) { + if (ctx?.file == null) { + ctx.file = new HashMap(); + } + ctx.file.name = path.substring(idx+1); + ctx.file.directory = path.substring(0, idx); + + def extIdx = path.lastIndexOf("."); + if (extIdx > -1) { + ctx.file.extension = path.substring(extIdx+1); + } + } + +## Network, Destination, and Source fields + + - rename: + field: winlog.event_data.Protocol + target_field: network.transport + ignore_missing: true + ignore_failure: true + if: ctx?.winlog?.event_data?.Protocol != null && ctx?.winlog?.event_data?.Protocol != "" + - rename: + field: winlog.event_data.DestinationPortName + target_field: network.protocol + ignore_missing: true + ignore_failure: true + if: ctx.event.code != "22" && ctx?.winlog?.event_data?.DestinationPortName != null && ctx?.winlog?.event_data?.DestinationPortName != "" + - rename: + field: winlog.event_data.SourcePortName + target_field: network.protocol + ignore_missing: true + ignore_failure: true + if: ctx.event.code != "22" && ctx?.winlog?.event_data?.SourcePortName != null && ctx?.winlog?.event_data?.SourcePortName != "" + - set: + field: network.protocol + value: dns + if: ctx.event.code == "22" + - convert: + field: winlog.event_data.SourceIp + target_field: source.ip + type: ip + ignore_failure: true + ignore_missing: true + if: ctx?.winlog?.event_data?.SourceIp != null && ctx?.winlog?.event_data?.SourceIp != "" + - rename: + field: winlog.event_data.SourceHostname + target_field: source.domain + ignore_missing: true + ignore_failure: true + if: ctx?.winlog?.event_data?.SourceHostname != null && ctx?.winlog?.event_data?.SourceHostname != "" + - convert: + field: winlog.event_data.SourcePort + target_field: source.port + type: long + ignore_failure: true + ignore_missing: true + if: ctx?.winlog?.event_data?.SourcePort != null && ctx?.winlog?.event_data?.SourcePort != "" + - convert: + field: winlog.event_data.DestinationIp + target_field: destination.ip + type: ip + ignore_failure: true + ignore_missing: true + if: ctx?.winlog?.event_data?.DestinationIp != null && ctx?.winlog?.event_data?.DestinationIp != "" + - rename: + field: winlog.event_data.DestinationHostname + target_field: destination.domain + ignore_missing: true + ignore_failure: true + if: ctx?.winlog?.event_data?.DestinationHostname != null && ctx?.winlog?.event_data?.DestinationHostname != "" + - convert: + field: winlog.event_data.DestinationPort + target_field: destination.port + type: long + ignore_failure: true + ignore_missing: true + if: ctx?.winlog?.event_data?.DestinationPort != null && ctx?.winlog?.event_data?.DestinationPort != "" + - rename: + field: winlog.event_data.QueryName + target_field: dns.question.name + ignore_missing: true + ignore_failure: true + if: ctx?.winlog?.event_data?.QueryName != null && ctx?.winlog?.event_data?.QueryName != "" + - set: + field: network.direction + value: egress + if: ctx?.winlog?.event_data?.Initiated != null && ctx?.winlog?.event_data?.Initiated == "true" + - set: + field: network.direction + value: ingress + if: ctx?.winlog?.event_data?.Initiated != null && ctx?.winlog?.event_data?.Initiated == "false" + - set: + field: network.type + value: ipv4 + if: ctx?.winlog?.event_data?.SourceIsIpv6 != null && ctx?.winlog?.event_data?.SourceIsIpv6 == "false" + - set: + field: network.type + value: ipv6 + if: ctx?.winlog?.event_data?.SourceIsIpv6 != null && ctx?.winlog?.event_data?.SourceIsIpv6 == "true" + - script: + description: | + Splits the QueryResults field that contains the DNS responses. + Example: "type: 5 f2.taboola.map.fastly.net;::ffff:151.101.66.2;::ffff:151.101.130.2;::ffff:151.101.194.2;::ffff:151.101.2.2;" + lang: painless + if: ctx?.winlog?.event_data?.QueryResults != null && ctx?.winlog?.event_data?.QueryResults != "" + params: + "1": "A" + "2": "NS" + "3": "MD" + "4": "MF" + "5": "CNAME" + "6": "SOA" + "7": "MB" + "8": "MG" + "9": "MR" + "10": "NULL" + "11": "WKS" + "12": "PTR" + "13": "HINFO" + "14": "MINFO" + "15": "MX" + "16": "TXT" + "17": "RP" + "18": "AFSDB" + "19": "X25" + "20": "ISDN" + "21": "RT" + "22": "NSAP" + "23": "NSAPPTR" + "24": "SIG" + "25": "KEY" + "26": "PX" + "27": "GPOS" + "28": "AAAA" + "29": "LOC" + "30": "NXT" + "31": "EID" + "32": "NIMLOC" + "33": "SRV" + "34": "ATMA" + "35": "NAPTR" + "36": "KX" + "37": "CERT" + "38": "A6" + "39": "DNAME" + "40": "SINK" + "41": "OPT" + "43": "DS" + "46": "RRSIG" + "47": "NSEC" + "48": "DNSKEY" + "49": "DHCID" + "100": "UINFO" + "101": "UID" + "102": "GID" + "103": "UNSPEC" + "248": "ADDRS" + "249": "TKEY" + "250": "TSIG" + "251": "IXFR" + "252": "AXFR" + "253": "MAILB" + "254": "MAILA" + "255": "ANY" + "65281": "WINS" + "65282": "WINSR" + source: |- + def results = /;/.split(ctx.winlog.event_data.QueryResults); + def answers = new ArrayList(); + def ips = new ArrayList(); + def relatedHosts = new ArrayList(); + for (def i = 0; i < results.length; i++) { + def answer = results[i]; + if (answer == "") { + continue; + } + + if (answer.startsWith("type:")) { + def parts = /\s+/.split(answer); + if (parts.length != 3) { + throw new Exception("unexpected QueryResult format"); + } + + answers.add([ + "type": params[parts[1]], + "data": parts[2] + ]); + relatedHosts.add(parts[2]); + } else { + answer = answer.replace("::ffff:", ""); + ips.add(answer); + } + } + + if (answers.length > 0) { + ctx.dns.answers = answers; + } + if (ips.length > 0) { + ctx.dns.resolved_ip = ips; + } + if (relatedHosts.length > 0) { + if (ctx?.related == null) { + ctx.related = new HashMap(); + } + ctx.related.hosts = relatedHosts; + } + - foreach: + field: dns.resolved_ip + ignore_missing: true + processor: + convert: + field: _ingest._value + type: ip + on_failure: + - remove: + field: _ingest._value + - script: + description: Convert V4MAPPED addresses. + lang: painless + if: ctx?.dns?.resolved_ip != null + source: |- + if (ctx.dns.answers == null) { + ctx.dns.answers = new ArrayList(); + } + for (def i = 0; i < ctx.dns.resolved_ip.length; i++) { + def ip = ctx.dns.resolved_ip[i]; + if (ip == null) { + ctx.dns.resolved_ip.remove(i); + continue; + } + + // Synthesize record type based on IP address type. + def type = "A"; + if (ip.indexOf(":") != -1) { + type = "AAAA"; + } + ctx.dns.answers.add([ + "type": type, + "data": ip + ]); + } + - registered_domain: + field: dns.question.name + target_field: dns.question + ignore_failure: true + ignore_missing: true + - append: + field: related.hosts + value: "{{dns.question.name}}" + allow_duplicates: false + if: ctx?.dns?.question?.name != null && ctx?.dns?.question?.name != "" + - remove: + description: Remove dns.question.domain because it is not part of ECS and is redundant with dns.question.name. + field: dns.question.domain + ignore_missing: true + ignore_failure: true + - foreach: + field: dns.resolved_ip + ignore_missing: true + processor: + append: + field: related.ip + value: "{{_ingest._value}}" + allow_duplicates: false + ignore_failure: true + - community_id: + ignore_failure: true + ignore_missing: false + +## User fields + + - set: + field: user.id + copy_from: winlog.user.identifier + ignore_empty_value: true + ignore_failure: true + - split: + field: winlog.event_data.User + target_field: "_temp.user_parts" + separator: '\\' + if: ctx?.winlog?.event_data?.User != null + - set: + field: user.domain + value: "{{_temp.user_parts.0}}" + ignore_failure: true + ignore_empty_value: true + if: ctx?._temp?.user_parts != null && ctx._temp.user_parts.size() == 2 + - set: + field: user.name + value: "{{_temp.user_parts.1}}" + ignore_failure: true + ignore_empty_value: true + if: ctx?._temp?.user_parts != null && ctx._temp.user_parts.size() == 2 + +## Sysmon fields + + - rename: + field: winlog.event_data.QueryStatus + target_field: sysmon.dns.status + ignore_missing: true + ignore_failure: true + if: ctx?.winlog?.event_data?.QueryStatus != null && ctx?.winlog?.event_data?.QueryStatus != "" + - script: + description: Translate DNS Query status. + lang: painless + params: + "5": "ERROR_ACCESS_DENIED" + "0": "SUCCESS" + "8": "ERROR_NOT_ENOUGH_MEMORY" + "13": "ERROR_INVALID_DATA" + "14": "ERROR_OUTOFMEMORY" + "123": "ERROR_INVALID_NAME" + "1214": "ERROR_INVALID_NETNAME" + "1223": "ERROR_CANCELLED" + "1460": "ERROR_TIMEOUT" + "4312": "ERROR_OBJECT_NOT_FOUND" + "9001": "DNS_ERROR_RCODE_FORMAT_ERROR" + "9002": "DNS_ERROR_RCODE_SERVER_FAILURE" + "9003": "DNS_ERROR_RCODE_NAME_ERROR" + "9004": "DNS_ERROR_RCODE_NOT_IMPLEMENTED" + "9005": "DNS_ERROR_RCODE_REFUSED" + "9006": "DNS_ERROR_RCODE_YXDOMAIN" + "9007": "DNS_ERROR_RCODE_YXRRSET" + "9008": "DNS_ERROR_RCODE_NXRRSET" + "9009": "DNS_ERROR_RCODE_NOTAUTH" + "9010": "DNS_ERROR_RCODE_NOTZONE" + "9016": "DNS_ERROR_RCODE_BADSIG" + "9017": "DNS_ERROR_RCODE_BADKEY" + "9018": "DNS_ERROR_RCODE_BADTIME" + "9101": "DNS_ERROR_KEYMASTER_REQUIRED" + "9102": "DNS_ERROR_NOT_ALLOWED_ON_SIGNED_ZONE" + "9103": "DNS_ERROR_NSEC3_INCOMPATIBLE_WITH_RSA_SHA1" + "9104": "DNS_ERROR_NOT_ENOUGH_SIGNING_KEY_DESCRIPTORS" + "9105": "DNS_ERROR_UNSUPPORTED_ALGORITHM" + "9106": "DNS_ERROR_INVALID_KEY_SIZE" + "9107": "DNS_ERROR_SIGNING_KEY_NOT_ACCESSIBLE" + "9108": "DNS_ERROR_KSP_DOES_NOT_SUPPORT_PROTECTION" + "9109": "DNS_ERROR_UNEXPECTED_DATA_PROTECTION_ERROR" + "9110": "DNS_ERROR_UNEXPECTED_CNG_ERROR" + "9111": "DNS_ERROR_UNKNOWN_SIGNING_PARAMETER_VERSION" + "9112": "DNS_ERROR_KSP_NOT_ACCESSIBLE" + "9113": "DNS_ERROR_TOO_MANY_SKDS" + "9114": "DNS_ERROR_INVALID_ROLLOVER_PERIOD" + "9115": "DNS_ERROR_INVALID_INITIAL_ROLLOVER_OFFSET" + "9116": "DNS_ERROR_ROLLOVER_IN_PROGRESS" + "9117": "DNS_ERROR_STANDBY_KEY_NOT_PRESENT" + "9118": "DNS_ERROR_NOT_ALLOWED_ON_ZSK" + "9119": "DNS_ERROR_NOT_ALLOWED_ON_ACTIVE_SKD" + "9120": "DNS_ERROR_ROLLOVER_ALREADY_QUEUED" + "9121": "DNS_ERROR_NOT_ALLOWED_ON_UNSIGNED_ZONE" + "9122": "DNS_ERROR_BAD_KEYMASTER" + "9123": "DNS_ERROR_INVALID_SIGNATURE_VALIDITY_PERIOD" + "9124": "DNS_ERROR_INVALID_NSEC3_ITERATION_COUNT" + "9125": "DNS_ERROR_DNSSEC_IS_DISABLED" + "9126": "DNS_ERROR_INVALID_XML" + "9127": "DNS_ERROR_NO_VALID_TRUST_ANCHORS" + "9128": "DNS_ERROR_ROLLOVER_NOT_POKEABLE" + "9129": "DNS_ERROR_NSEC3_NAME_COLLISION" + "9130": "DNS_ERROR_NSEC_INCOMPATIBLE_WITH_NSEC3_RSA_SHA1" + "9501": "DNS_INFO_NO_RECORDS" + "9502": "DNS_ERROR_BAD_PACKET" + "9503": "DNS_ERROR_NO_PACKET" + "9504": "DNS_ERROR_RCODE" + "9505": "DNS_ERROR_UNSECURE_PACKET" + "9506": "DNS_REQUEST_PENDING" + "9551": "DNS_ERROR_INVALID_TYPE" + "9552": "DNS_ERROR_INVALID_IP_ADDRESS" + "9553": "DNS_ERROR_INVALID_PROPERTY" + "9554": "DNS_ERROR_TRY_AGAIN_LATER" + "9555": "DNS_ERROR_NOT_UNIQUE" + "9556": "DNS_ERROR_NON_RFC_NAME" + "9557": "DNS_STATUS_FQDN" + "9558": "DNS_STATUS_DOTTED_NAME" + "9559": "DNS_STATUS_SINGLE_PART_NAME" + "9560": "DNS_ERROR_INVALID_NAME_CHAR" + "9561": "DNS_ERROR_NUMERIC_NAME" + "9562": "DNS_ERROR_NOT_ALLOWED_ON_ROOT_SERVER" + "9563": "DNS_ERROR_NOT_ALLOWED_UNDER_DELEGATION" + "9564": "DNS_ERROR_CANNOT_FIND_ROOT_HINTS" + "9565": "DNS_ERROR_INCONSISTENT_ROOT_HINTS" + "9566": "DNS_ERROR_DWORD_VALUE_TOO_SMALL" + "9567": "DNS_ERROR_DWORD_VALUE_TOO_LARGE" + "9568": "DNS_ERROR_BACKGROUND_LOADING" + "9569": "DNS_ERROR_NOT_ALLOWED_ON_RODC" + "9570": "DNS_ERROR_NOT_ALLOWED_UNDER_DNAME" + "9571": "DNS_ERROR_DELEGATION_REQUIRED" + "9572": "DNS_ERROR_INVALID_POLICY_TABLE" + "9573": "DNS_ERROR_ADDRESS_REQUIRED" + "9601": "DNS_ERROR_ZONE_DOES_NOT_EXIST" + "9602": "DNS_ERROR_NO_ZONE_INFO" + "9603": "DNS_ERROR_INVALID_ZONE_OPERATION" + "9604": "DNS_ERROR_ZONE_CONFIGURATION_ERROR" + "9605": "DNS_ERROR_ZONE_HAS_NO_SOA_RECORD" + "9606": "DNS_ERROR_ZONE_HAS_NO_NS_RECORDS" + "9607": "DNS_ERROR_ZONE_LOCKED" + "9608": "DNS_ERROR_ZONE_CREATION_FAILED" + "9609": "DNS_ERROR_ZONE_ALREADY_EXISTS" + "9610": "DNS_ERROR_AUTOZONE_ALREADY_EXISTS" + "9611": "DNS_ERROR_INVALID_ZONE_TYPE" + "9612": "DNS_ERROR_SECONDARY_REQUIRES_MASTER_IP" + "9613": "DNS_ERROR_ZONE_NOT_SECONDARY" + "9614": "DNS_ERROR_NEED_SECONDARY_ADDRESSES" + "9615": "DNS_ERROR_WINS_INIT_FAILED" + "9616": "DNS_ERROR_NEED_WINS_SERVERS" + "9617": "DNS_ERROR_NBSTAT_INIT_FAILED" + "9618": "DNS_ERROR_SOA_DELETE_INVALID" + "9619": "DNS_ERROR_FORWARDER_ALREADY_EXISTS" + "9620": "DNS_ERROR_ZONE_REQUIRES_MASTER_IP" + "9621": "DNS_ERROR_ZONE_IS_SHUTDOWN" + "9622": "DNS_ERROR_ZONE_LOCKED_FOR_SIGNING" + "9651": "DNS_ERROR_PRIMARY_REQUIRES_DATAFILE" + "9652": "DNS_ERROR_INVALID_DATAFILE_NAME" + "9653": "DNS_ERROR_DATAFILE_OPEN_FAILURE" + "9654": "DNS_ERROR_FILE_WRITEBACK_FAILED" + "9655": "DNS_ERROR_DATAFILE_PARSING" + "9701": "DNS_ERROR_RECORD_DOES_NOT_EXIST" + "9702": "DNS_ERROR_RECORD_FORMAT" + "9703": "DNS_ERROR_NODE_CREATION_FAILED" + "9704": "DNS_ERROR_UNKNOWN_RECORD_TYPE" + "9705": "DNS_ERROR_RECORD_TIMED_OUT" + "9706": "DNS_ERROR_NAME_NOT_IN_ZONE" + "9707": "DNS_ERROR_CNAME_LOOP" + "9708": "DNS_ERROR_NODE_IS_CNAME" + "9709": "DNS_ERROR_CNAME_COLLISION" + "9710": "DNS_ERROR_RECORD_ONLY_AT_ZONE_ROOT" + "9711": "DNS_ERROR_RECORD_ALREADY_EXISTS" + "9712": "DNS_ERROR_SECONDARY_DATA" + "9713": "DNS_ERROR_NO_CREATE_CACHE_DATA" + "9714": "DNS_ERROR_NAME_DOES_NOT_EXIST" + "9715": "DNS_WARNING_PTR_CREATE_FAILED" + "9716": "DNS_WARNING_DOMAIN_UNDELETED" + "9717": "DNS_ERROR_DS_UNAVAILABLE" + "9718": "DNS_ERROR_DS_ZONE_ALREADY_EXISTS" + "9719": "DNS_ERROR_NO_BOOTFILE_IF_DS_ZONE" + "9720": "DNS_ERROR_NODE_IS_DNAME" + "9721": "DNS_ERROR_DNAME_COLLISION" + "9722": "DNS_ERROR_ALIAS_LOOP" + "9751": "DNS_INFO_AXFR_COMPLETE" + "9752": "DNS_ERROR_AXFR" + "9753": "DNS_INFO_ADDED_LOCAL_WINS" + "9801": "DNS_STATUS_CONTINUE_NEEDED" + "9851": "DNS_ERROR_NO_TCPIP" + "9852": "DNS_ERROR_NO_DNS_SERVERS" + "9901": "DNS_ERROR_DP_DOES_NOT_EXIST" + "9902": "DNS_ERROR_DP_ALREADY_EXISTS" + "9903": "DNS_ERROR_DP_NOT_ENLISTED" + "9904": "DNS_ERROR_DP_ALREADY_ENLISTED" + "9905": "DNS_ERROR_DP_NOT_AVAILABLE" + "9906": "DNS_ERROR_DP_FSMO_ERROR" + "9911": "DNS_ERROR_RRL_NOT_ENABLED" + "9912": "DNS_ERROR_RRL_INVALID_WINDOW_SIZE" + "9913": "DNS_ERROR_RRL_INVALID_IPV4_PREFIX" + "9914": "DNS_ERROR_RRL_INVALID_IPV6_PREFIX" + "9915": "DNS_ERROR_RRL_INVALID_TC_RATE" + "9916": "DNS_ERROR_RRL_INVALID_LEAK_RATE" + "9917": "DNS_ERROR_RRL_LEAK_RATE_LESSTHAN_TC_RATE" + "9921": "DNS_ERROR_VIRTUALIZATION_INSTANCE_ALREADY_EXISTS" + "9922": "DNS_ERROR_VIRTUALIZATION_INSTANCE_DOES_NOT_EXIST" + "9923": "DNS_ERROR_VIRTUALIZATION_TREE_LOCKED" + "9924": "DNS_ERROR_INVAILD_VIRTUALIZATION_INSTANCE_NAME" + "9925": "DNS_ERROR_DEFAULT_VIRTUALIZATION_INSTANCE" + "9951": "DNS_ERROR_ZONESCOPE_ALREADY_EXISTS" + "9952": "DNS_ERROR_ZONESCOPE_DOES_NOT_EXIST" + "9953": "DNS_ERROR_DEFAULT_ZONESCOPE" + "9954": "DNS_ERROR_INVALID_ZONESCOPE_NAME" + "9955": "DNS_ERROR_NOT_ALLOWED_WITH_ZONESCOPES" + "9956": "DNS_ERROR_LOAD_ZONESCOPE_FAILED" + "9957": "DNS_ERROR_ZONESCOPE_FILE_WRITEBACK_FAILED" + "9958": "DNS_ERROR_INVALID_SCOPE_NAME" + "9959": "DNS_ERROR_SCOPE_DOES_NOT_EXIST" + "9960": "DNS_ERROR_DEFAULT_SCOPE" + "9961": "DNS_ERROR_INVALID_SCOPE_OPERATION" + "9962": "DNS_ERROR_SCOPE_LOCKED" + "9963": "DNS_ERROR_SCOPE_ALREADY_EXISTS" + "9971": "DNS_ERROR_POLICY_ALREADY_EXISTS" + "9972": "DNS_ERROR_POLICY_DOES_NOT_EXIST" + "9973": "DNS_ERROR_POLICY_INVALID_CRITERIA" + "9974": "DNS_ERROR_POLICY_INVALID_SETTINGS" + "9975": "DNS_ERROR_CLIENT_SUBNET_IS_ACCESSED" + "9976": "DNS_ERROR_CLIENT_SUBNET_DOES_NOT_EXIST" + "9977": "DNS_ERROR_CLIENT_SUBNET_ALREADY_EXISTS" + "9978": "DNS_ERROR_SUBNET_DOES_NOT_EXIST" + "9979": "DNS_ERROR_SUBNET_ALREADY_EXISTS" + "9980": "DNS_ERROR_POLICY_LOCKED" + "9981": "DNS_ERROR_POLICY_INVALID_WEIGHT" + "9982": "DNS_ERROR_POLICY_INVALID_NAME" + "9983": "DNS_ERROR_POLICY_MISSING_CRITERIA" + "9984": "DNS_ERROR_INVALID_CLIENT_SUBNET_NAME" + "9985": "DNS_ERROR_POLICY_PROCESSING_ORDER_INVALID" + "9986": "DNS_ERROR_POLICY_SCOPE_MISSING" + "9987": "DNS_ERROR_POLICY_SCOPE_NOT_ALLOWED" + "9988": "DNS_ERROR_SERVERSCOPE_IS_REFERENCED" + "9989": "DNS_ERROR_ZONESCOPE_IS_REFERENCED" + "9990": "DNS_ERROR_POLICY_INVALID_CRITERIA_CLIENT_SUBNET" + "9991": "DNS_ERROR_POLICY_INVALID_CRITERIA_TRANSPORT_PROTOCOL" + "9992": "DNS_ERROR_POLICY_INVALID_CRITERIA_NETWORK_PROTOCOL" + "9993": "DNS_ERROR_POLICY_INVALID_CRITERIA_INTERFACE" + "9994": "DNS_ERROR_POLICY_INVALID_CRITERIA_FQDN" + "9995": "DNS_ERROR_POLICY_INVALID_CRITERIA_QUERY_TYPE" + "9996": "DNS_ERROR_POLICY_INVALID_CRITERIA_TIME_OF_DAY" + "10054": "WSAECONNRESET" + "10055": "WSAENOBUFS" + "10060": "WSAETIMEDOUT" + if: ctx?.sysmon?.dns?.status != null && ctx?.sysmon?.dns?.status != "" + source: |- + def status = params[ctx.sysmon.dns.status]; + if (status != null) { + ctx.sysmon.dns.status = status; + } + - convert: + field: winlog.event_data.Archived + target_field: sysmon.file.archived + type: boolean + ignore_missing: true + ignore_failure: true + if: ctx?.winlog?.event_data?.Archived != null && ctx?.winlog?.event_data?.Archived != "" + - convert: + field: winlog.event_data.IsExecutable + target_field: sysmon.file.is_executable + type: boolean + ignore_missing: true + ignore_failure: true + if: ctx?.winlog?.event_data?.IsExecutable != null && ctx?.winlog?.event_data?.IsExecutable != "" + +## Related fields + + - append: + field: related.user + value: "{{user.name}}" + ignore_failure: true + allow_duplicates: false + if: ctx?.user?.name != null && ctx.user.name != "" + - append: + field: related.ip + value: "{{source.ip}}" + ignore_failure: true + allow_duplicates: false + if: ctx?.source?.ip != null && ctx.source.ip != "" + - append: + field: related.ip + value: "{{destination.ip}}" + ignore_failure: true + allow_duplicates: false + if: ctx?.destination?.ip != null && ctx.destination.ip != "" + +## Registry fields + + - script: + description: Set registry fields. + lang: painless + if: |- + ctx?.winlog?.event_data?.TargetObject != null && ctx?.winlog?.event_data?.TargetObject != "" && + ["12", "13", "14"].contains(ctx.event.code) + params: + HKEY_CLASSES_ROOT: "HKCR" + HKCR: "HKCR" + HKEY_CURRENT_CONFIG: "HKCC" + HKCC: "HKCC" + HKEY_CURRENT_USER: "HKCU" + HKCU: "HKCU" + HKEY_DYN_DATA: "HKDD" + HKDD: "HKDD" + HKEY_LOCAL_MACHINE: "HKLM" + HKLM: "HKLM" + HKEY_PERFORMANCE_DATA: "HKPD" + HKPD: "HKPD" + HKEY_USERS: "HKU" + HKU: "HKU" + source: |- + ctx.registry = new HashMap(); + Pattern qwordRegex = /(?i)QWORD \(((0x\d{8})-(0x\d{8}))\)/; + Pattern dwordRegex = /(?i)DWORD \((0x\d{8})\)/; + + def path = ctx.winlog.event_data.TargetObject; + ctx.registry.path = path; + + def pathTokens = Arrays.asList(/\\/.split(path)); + def hive = params[pathTokens[0]]; + if (hive != null) { + ctx.registry.hive = hive; + if (pathTokens.length > 1) { + ctx.registry.key = pathTokens.subList(1, pathTokens.length).join("\\"); + } + } + + def value = pathTokens[pathTokens.length - 1]; + ctx.registry.value = value; + + def data = ctx?.winlog?.event_data?.Details; + if (data != null && data != "") { + def prefixLen = 2; // to remove 0x prefix + def dataValue = ""; + def dataType = ""; + def matcher = qwordRegex.matcher(data); + if (matcher.matches()) { + def parsedHighByte = Long.parseLong(matcher.group(2).substring(prefixLen), 16); + def parsedLowByte = Long.parseLong(matcher.group(3).substring(prefixLen), 16); + if (!Double.isNaN(parsedHighByte) && !Double.isNaN(parsedLowByte)) { + dataType = "SZ_QWORD"; + dataValue = Long.toString(((parsedHighByte << 8) + parsedLowByte)); + } + } else { + matcher = dwordRegex.matcher(data); + if (matcher.matches()) { + def parsedValue = Long.parseLong(matcher.group(1).substring(prefixLen), 16); + if (!Double.isNaN(parsedValue)) { + dataType = "SZ_DWORD"; + dataValue = matcher.group(1); + } + } + } + + if (dataType != "") { + ctx.registry.data = [ + "strings": [dataValue], + "type": dataType + ]; + } + } + +## Cleanup + + - remove: + field: + - _temp + - winlog.event_data.ProcessId + - winlog.event_data.ParentProcessId + - winlog.event_data.SourceProcessId + - winlog.event_data.SourceThreadId + - winlog.event_data.SourceIp + - winlog.event_data.SourcePort + - winlog.event_data.SourcePortName + - winlog.event_data.DestinationIp + - winlog.event_data.DestinationPort + - winlog.event_data.DestinationPortName + - winlog.event_data.RuleName + - winlog.event_data.User + - winlog.event_data.Initiated + - winlog.event_data.SourceIsIpv6 + - winlog.event_data.DestinationIsIpv6 + - winlog.event_data.QueryStatus + - winlog.event_data.Archived + - winlog.event_data.IsExecutable + - winlog.event_data.QueryResults + - winlog.event_data.UtcTime + - winlog.event_data.Hash + - winlog.event_data.Hashes + - winlog.event_data.TargetObject + - winlog.event_data.Details + - winlog.time_created + - winlog.level + ignore_failure: true + ignore_missing: true + - script: + description: Remove all empty values from event_data. + lang: painless + source: ctx?.winlog?.event_data?.entrySet().removeIf(entry -> entry.getValue() == null || entry.getValue().equals("") || entry.getValue().equals("-")); + - remove: + description: Remove empty event data. + field: winlog.event_data + ignore_missing: true + ignore_failure: true + if: ctx?.winlog?.event_data != null && ctx.winlog.event_data.size() == 0 + +on_failure: + - set: + field: "error.message" + value: |- + Processor "{{ _ingest.on_failure_processor_type }}" with tag "{{ _ingest.on_failure_processor_tag }}" in pipeline "{{ _ingest.on_failure_pipeline }}" failed with message "{{ _ingest.on_failure_message }}" diff --git a/x-pack/winlogbeat/module/sysmon/test/sysmon_windows_test.go b/x-pack/winlogbeat/module/sysmon/test/sysmon_windows_test.go deleted file mode 100644 index 1f4d78ad017..00000000000 --- a/x-pack/winlogbeat/module/sysmon/test/sysmon_windows_test.go +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one -// or more contributor license agreements. Licensed under the Elastic License; -// you may not use this file except in compliance with the Elastic License. - -package test - -import ( - "testing" - - "github.com/elastic/beats/v7/x-pack/winlogbeat/module" - - // Register required processors. - _ "github.com/elastic/beats/v7/libbeat/cmd/instance" - _ "github.com/elastic/beats/v7/libbeat/processors/timestamp" -) - -// Ignore these fields so that the tests will pass if Sysmon is not installed. -var ignoreFields = []string{ - "event.action", - "message", - "winlog.opcode", - "winlog.task", - - // Ignore these fields as under some circumstances they are not populated. - // (observed under Windows 7). - "winlog.user.type", - "winlog.user.name", - "winlog.user.domain", -} - -func TestSysmon(t *testing.T) { - module.TestPipeline(t, "testdata/*.evtx", "../config/winlogbeat-sysmon.js", - module.WithFieldFilter(ignoreFields)) -} diff --git a/x-pack/winlogbeat/winlogbeat.reference.yml b/x-pack/winlogbeat/winlogbeat.reference.yml index 09afd2e6208..0868d8c8027 100644 --- a/x-pack/winlogbeat/winlogbeat.reference.yml +++ b/x-pack/winlogbeat/winlogbeat.reference.yml @@ -14,13 +14,26 @@ # directory in which it was started. #winlogbeat.registry_file: .winlogbeat.yml +# The timeout value that controls when registry entries are written to disk +# (flushed). When an unwritten update exceeds this value, it triggers a write +# to disk. When flush is set to 0s, the registry is written to disk after each +# batch of events has been published successfully. The default value is 5s. +#winlogbeat.registry_flush: 5s + +# By default Ingest pipelines are not updated if a pipeline with the same ID +# already exists. If this option is enabled Winlogbeat overwrites pipelines +# every time a new Elasticsearch connection is established. +#winlogbeat.overwrite_pipelines: false + # event_logs specifies a list of event logs to monitor as well as any # accompanying options. The YAML data type of event_logs is a list of # dictionaries. # -# The supported keys are name (required), tags, fields, fields_under_root, -# forwarded, ignore_older, level, event_id, provider, and include_xml. Please -# visit the documentation for the complete details of each option. +# The supported keys are name, id, xml_query, tags, fields, fields_under_root, +# forwarded, ignore_older, level, event_id, provider, and include_xml. +# The xml_query key requires an id and must not be used with the name, +# ignore_older, level, event_id, or provider keys. Please visit the +# documentation for the complete details of each option. # https://go.es.io/WinlogbeatConfig winlogbeat.event_logs: @@ -30,58 +43,17 @@ winlogbeat.event_logs: - name: System - name: Security - processors: - - script: - lang: javascript - id: security - file: ${path.home}/module/security/config/winlogbeat-security.js - name: Microsoft-Windows-Sysmon/Operational - processors: - - script: - lang: javascript - id: sysmon - file: ${path.home}/module/sysmon/config/winlogbeat-sysmon.js - name: Windows PowerShell event_id: 400, 403, 600, 800 - processors: - - script: - lang: javascript - id: powershell - file: ${path.home}/module/powershell/config/winlogbeat-powershell.js - name: Microsoft-Windows-PowerShell/Operational event_id: 4103, 4104, 4105, 4106 - processors: - - script: - lang: javascript - id: powershell - file: ${path.home}/module/powershell/config/winlogbeat-powershell.js - name: ForwardedEvents tags: [forwarded] - processors: - - script: - when.equals.winlog.channel: Security - lang: javascript - id: security - file: ${path.home}/module/security/config/winlogbeat-security.js - - script: - when.equals.winlog.channel: Microsoft-Windows-Sysmon/Operational - lang: javascript - id: sysmon - file: ${path.home}/module/sysmon/config/winlogbeat-sysmon.js - - script: - when.equals.winlog.channel: Windows PowerShell - lang: javascript - id: powershell - file: ${path.home}/module/powershell/config/winlogbeat-powershell.js - - script: - when.equals.winlog.channel: Microsoft-Windows-PowerShell/Operational - lang: javascript - id: powershell - file: ${path.home}/module/powershell/config/winlogbeat-powershell.js # ================================== General =================================== @@ -163,66 +135,6 @@ winlogbeat.event_logs: # length of its retry interval each time, up to this maximum. #max_retry_interval: 30s - # The spool queue will store events in a local spool file, before - # forwarding the events to the outputs. - # Note: the spool queue is deprecated and will be removed in the future. - # Use the disk queue instead. - # - # The spool file is a circular buffer, which blocks once the file/buffer is full. - # Events are put into a write buffer and flushed once the write buffer - # is full or the flush_timeout is triggered. - # Once ACKed by the output, events are removed immediately from the queue, - # making space for new events to be persisted. - #spool: - # The file namespace configures the file path and the file creation settings. - # Once the file exists, the `size`, `page_size` and `prealloc` settings - # will have no more effect. - #file: - # Location of spool file. The default value is ${path.data}/spool.dat. - #path: "${path.data}/spool.dat" - - # Configure file permissions if file is created. The default value is 0600. - #permissions: 0600 - - # File size hint. The spool blocks, once this limit is reached. The default value is 100 MiB. - #size: 100MiB - - # The files page size. A file is split into multiple pages of the same size. The default value is 4KiB. - #page_size: 4KiB - - # If prealloc is set, the required space for the file is reserved using - # truncate. The default value is true. - #prealloc: true - - # Spool writer settings - # Events are serialized into a write buffer. The write buffer is flushed if: - # - The buffer limit has been reached. - # - The configured limit of buffered events is reached. - # - The flush timeout is triggered. - #write: - # Sets the write buffer size. - #buffer_size: 1MiB - - # Maximum duration after which events are flushed if the write buffer - # is not full yet. The default value is 1s. - #flush.timeout: 1s - - # Number of maximum buffered events. The write buffer is flushed once the - # limit is reached. - #flush.events: 16384 - - # Configure the on-disk event encoding. The encoding can be changed - # between restarts. - # Valid encodings are: json, ubjson, and cbor. - #codec: cbor - #read: - # Reader flush timeout, waiting for more events to become available, so - # to fill a complete batch as required by the outputs. - # If flush_timeout is 0, all available events are forwarded to the - # outputs immediately. - # The default value is 0s. - #flush.timeout: 0s - # Sets the maximum number of CPUs that can be executing simultaneously. The # default is the number of logical CPUs available in the system. #max_procs: @@ -539,6 +451,13 @@ output.elasticsearch: # The pin is a base64 encoded string of the SHA-256 fingerprint. #ssl.ca_sha256: "" + # A root CA HEX encoded fingerprint. During the SSL handshake if the + # fingerprint matches the root CA certificate, it will be added to + # the provided list of root CAs (`certificate_authorities`), if the + # list is empty or not defined, the matching certificate will be the + # only one in the list. Then the normal SSL validation happens. + #ssl.ca_trusted_fingerprint: "" + # Enable Kerberos support. Kerberos is automatically enabled if any Kerberos setting is set. #kerberos.enabled: true @@ -671,6 +590,13 @@ output.elasticsearch: # The pin is a base64 encoded string of the SHA-256 fingerprint. #ssl.ca_sha256: "" + # A root CA HEX encoded fingerprint. During the SSL handshake if the + # fingerprint matches the root CA certificate, it will be added to + # the provided list of root CAs (`certificate_authorities`), if the + # list is empty or not defined, the matching certificate will be the + # only one in the list. Then the normal SSL validation happens. + #ssl.ca_trusted_fingerprint: "" + # The number of times to retry publishing an event after a publishing failure. # After the specified number of retries, the events are typically dropped. # Some Beats, such as Filebeat and Winlogbeat, ignore the max_retries setting @@ -872,6 +798,13 @@ output.elasticsearch: # The pin is a base64 encoded string of the SHA-256 fingerprint. #ssl.ca_sha256: "" + # A root CA HEX encoded fingerprint. During the SSL handshake if the + # fingerprint matches the root CA certificate, it will be added to + # the provided list of root CAs (`certificate_authorities`), if the + # list is empty or not defined, the matching certificate will be the + # only one in the list. Then the normal SSL validation happens. + #ssl.ca_trusted_fingerprint: "" + # Enable Kerberos support. Kerberos is automatically enabled if any Kerberos setting is set. #kerberos.enabled: true @@ -1036,6 +969,13 @@ output.elasticsearch: # The pin is a base64 encoded string of the SHA-256 fingerprint. #ssl.ca_sha256: "" + # A root CA HEX encoded fingerprint. During the SSL handshake if the + # fingerprint matches the root CA certificate, it will be added to + # the provided list of root CAs (`certificate_authorities`), if the + # list is empty or not defined, the matching certificate will be the + # only one in the list. Then the normal SSL validation happens. + #ssl.ca_trusted_fingerprint: "" + # -------------------------------- File Output --------------------------------- #output.file: @@ -1055,7 +995,7 @@ output.elasticsearch: #path: "/tmp/winlogbeat" # Name of the generated files. The default is `winlogbeat` and it generates - # files: `winlogbeat`, `winlogbeat.1`, `winlogbeat.2`, etc. + # files: `winlogbeat-{datetime}.ndjson`, `winlogbeat-{datetime}-1.ndjson`, etc. #filename: winlogbeat # Maximum size in kilobytes of each file. When this size is reached, and on @@ -1073,6 +1013,7 @@ output.elasticsearch: # Configure automatic file rotation on every startup. The default is true. #rotate_on_startup: true + # ------------------------------- Console Output ------------------------------- #output.console: # Boolean flag to enable or disable the output module. @@ -1171,19 +1112,13 @@ output.elasticsearch: # Set to false to disable template loading. #setup.template.enabled: true -# Select the kind of index template. From Elasticsearch 7.8, it is possible to -# use component templates. Available options: legacy, component, index. -# By default winlogbeat uses the legacy index templates. -#setup.template.type: legacy - # Template name. By default the template name is "winlogbeat-%{[agent.version]}" # The template name and pattern has to be set in case the Elasticsearch index pattern is modified. #setup.template.name: "winlogbeat-%{[agent.version]}" -# Template pattern. By default the template pattern is "-%{[agent.version]}-*" to apply to the default index settings. -# The first part is the version of the beat and then -* is used to match all daily indices. +# Template pattern. By default the template pattern is "winlogbeat-%{[agent.version]}" to apply to the default index settings. # The template name and pattern has to be set in case the Elasticsearch index pattern is modified. -#setup.template.pattern: "winlogbeat-%{[agent.version]}-*" +#setup.template.pattern: "winlogbeat-%{[agent.version]}" # Path to fields.yml file to generate the template #setup.template.fields: "${path.config}/fields.yml" @@ -1230,17 +1165,8 @@ setup.template.settings: # output.elasticsearch.index is ignored, and the write alias is used to set the # index name. -# Enable ILM support. Valid values are true, false, and auto. When set to auto -# (the default), the Beat uses index lifecycle management when it connects to a -# cluster that supports ILM; otherwise, it creates daily indices. -#setup.ilm.enabled: auto - -# Set the prefix used in the index lifecycle write alias name. The default alias -# name is 'winlogbeat-%{[agent.version]}'. -#setup.ilm.rollover_alias: 'winlogbeat' - -# Set the rollover index pattern. The default is "%{now/d}-000001". -#setup.ilm.pattern: "{now/d}-000001" +# Enable ILM support. Valid values are true, false. +#setup.ilm.enabled: true # Set the lifecycle policy name. The default policy name is # 'beatname'. @@ -1338,6 +1264,13 @@ setup.kibana: # The pin is a base64 encoded string of the SHA-256 fingerprint. #ssl.ca_sha256: "" + # A root CA HEX encoded fingerprint. During the SSL handshake if the + # fingerprint matches the root CA certificate, it will be added to + # the provided list of root CAs (`certificate_authorities`), if the + # list is empty or not defined, the matching certificate will be the + # only one in the list. Then the normal SSL validation happens. + #ssl.ca_trusted_fingerprint: "" + # ================================== Logging =================================== @@ -1409,11 +1342,6 @@ logging.files: # file. Defaults to true. # rotateonstartup: true - # Rotated files are either suffixed with a number e.g. winlogbeat.1 when - # renamed during rotation. Or when set to date, the date is added to - # the end of the file. On rotation a new file is created, older files are untouched. - #suffix: count - # ============================= X-Pack Monitoring ============================== # Winlogbeat can export internal metrics to a central Elasticsearch monitoring # cluster. This requires xpack monitoring to be enabled in Elasticsearch. The @@ -1541,6 +1469,13 @@ logging.files: # The pin is a base64 encoded string of the SHA-256 fingerprint. #ssl.ca_sha256: "" + # A root CA HEX encoded fingerprint. During the SSL handshake if the + # fingerprint matches the root CA certificate, it will be added to + # the provided list of root CAs (`certificate_authorities`), if the + # list is empty or not defined, the matching certificate will be the + # only one in the list. Then the normal SSL validation happens. + #ssl.ca_trusted_fingerprint: "" + # Enable Kerberos support. Kerberos is automatically enabled if any Kerberos setting is set. #kerberos.enabled: true diff --git a/x-pack/winlogbeat/winlogbeat.yml b/x-pack/winlogbeat/winlogbeat.yml index c0c01d2ceea..6ae52cd3f3a 100644 --- a/x-pack/winlogbeat/winlogbeat.yml +++ b/x-pack/winlogbeat/winlogbeat.yml @@ -13,9 +13,11 @@ # accompanying options. The YAML data type of event_logs is a list of # dictionaries. # -# The supported keys are name (required), tags, fields, fields_under_root, -# forwarded, ignore_older, level, event_id, provider, and include_xml. Please -# visit the documentation for the complete details of each option. +# The supported keys are name, id, xml_query, tags, fields, fields_under_root, +# forwarded, ignore_older, level, event_id, provider, and include_xml. +# The xml_query key requires an id and must not be used with the name, +# ignore_older, level, event_id, or provider keys. Please visit the +# documentation for the complete details of each option. # https://go.es.io/WinlogbeatConfig winlogbeat.event_logs: @@ -25,58 +27,17 @@ winlogbeat.event_logs: - name: System - name: Security - processors: - - script: - lang: javascript - id: security - file: ${path.home}/module/security/config/winlogbeat-security.js - name: Microsoft-Windows-Sysmon/Operational - processors: - - script: - lang: javascript - id: sysmon - file: ${path.home}/module/sysmon/config/winlogbeat-sysmon.js - name: Windows PowerShell event_id: 400, 403, 600, 800 - processors: - - script: - lang: javascript - id: powershell - file: ${path.home}/module/powershell/config/winlogbeat-powershell.js - name: Microsoft-Windows-PowerShell/Operational event_id: 4103, 4104, 4105, 4106 - processors: - - script: - lang: javascript - id: powershell - file: ${path.home}/module/powershell/config/winlogbeat-powershell.js - name: ForwardedEvents tags: [forwarded] - processors: - - script: - when.equals.winlog.channel: Security - lang: javascript - id: security - file: ${path.home}/module/security/config/winlogbeat-security.js - - script: - when.equals.winlog.channel: Microsoft-Windows-Sysmon/Operational - lang: javascript - id: sysmon - file: ${path.home}/module/sysmon/config/winlogbeat-sysmon.js - - script: - when.equals.winlog.channel: Windows PowerShell - lang: javascript - id: powershell - file: ${path.home}/module/powershell/config/winlogbeat-powershell.js - - script: - when.equals.winlog.channel: Microsoft-Windows-PowerShell/Operational - lang: javascript - id: powershell - file: ${path.home}/module/powershell/config/winlogbeat-powershell.js # ====================== Elasticsearch template settings ======================= @@ -160,6 +121,9 @@ output.elasticsearch: #username: "elastic" #password: "changeme" + # Pipeline to route events to security, sysmon, or powershell pipelines. + pipeline: "winlogbeat-%{[agent.version]}-routing" + # ------------------------------ Logstash Output ------------------------------- #output.logstash: # The Logstash hosts