Professional Documents
Culture Documents
Sans Continuous Diagnostics and Mitigation Evolving Federal Defenses With Cost Effective and Maintainable Data Integration Solutions
Sans Continuous Diagnostics and Mitigation Evolving Federal Defenses With Cost Effective and Maintainable Data Integration Solutions
Abstract
Civilian federal agencies have struggled to implement the Continuous Diagnostics and
Mitigation program over the past decade. Billions of dollars have been spent, and the
cybersecurity tools have been deployed. Yet, there are challenges in getting the data from
those tools into the new CDM Dashboard powered by Elasticsearch and Kibana. Filebeat
and Logstash can solve this problem. The data from two CDM tools, HCL BigFix and
Tenable.sc were collected using Filebeat and Logstash and stored in Elasticsearch. This
approach is simple, maintainable, feasible, and cost-effective.
CDM: DON’T MISS A BEAT 2
1. Introduction
Americans have reportedly lost over six point nine billion dollars in the last
calendar year due to cybercrime (FBI, 2021). Over the past five years, the combined
losses have been $18.7 billion, with 2.76 million complaints to the Internet Crime
Complaint Center (FBI, 2021). Criminal attacks like fraud, scams, and theft have become
commonplace as “…the threats in the digital world mirror the threats in the physical
world” (Schneier, 2015). The real-world ramifications of events in cyberspace can be
devastating and far-reaching.
In May 2021, a ransomware attack shut down an oil pipeline that supplied 45% of
fuel to the U.S. East Coast (Committee on Homeland Security, 2021). Cyberspace has
even been recognized as the fifth domain of war, permeating land, sea, air, and space
(Welch, 2011). So, it should not be a surprise that people are waging cyber war on the
world’s biggest and most powerful organization, the U.S. Government.
The government impacts nearly all aspects of American lives, from ensuring the
food they eat is safe to the money they use to pay for it. Like all organizations, the
government depends on information systems to successfully carry out its missions and
functions at scale. The results could be dire if the confidentiality, integrity, or availability
of federal information systems are compromised. But just how do these attacks occur?
A little over a year after 9/11 shook the nation, the E-Government Act of 2002
was signed into law (E-Government Act, 2002). It recognized that computer systems and
networks would play a critical part in the government’s public services and missions.
Moreover, it enacted the need to address cybersecurity risks at federal agencies not a
moment too soon: “With our great reliance on computers and the numerous flaws found
in most systems, this is the Golden Age of Hacking” (Skoudis & Liston, 2006).
In the RMF, information systems undergo a risk assessment where the potential
threats, known vulnerabilities, and the impact of an incident are measured. This informs
how the information system is categorized. Based on the risk assessment and
categorization, a baseline of security controls can be applied and tailored to the specific
risks. After the initial security control assessment, the system must be authorized to
operate. Finally, the system must be continually assessed since risks, the information
system, and its environment can change over time. These entire processes can be repeated
as necessary.
it; and (4) a risk scoring and analysis subsystem with predefined views that can drive
operational decisions. The CAESARS FE report also foresaw a challenge with
implementing a CM program: different federal civilian agencies had purchased various
products from various vendors, and not all those vendors had adopted standards for
shipping the data into another system like a CM repository. The paper advised working
closely with the vendor community to adopt specific standards that would enhance their
products and benefit their customers by integrating their tools with continuous
monitoring solutions.
One of the biggest roadblocks was that the cybersecurity tools (CM data sources)
do not integrate easily with the integration layer components (CM repositories), where
risk scores were calculated: “[The] disjointed collection and use of data inhibits effective
governance, decision-making, and action” (Otto, 2017). This led to gaps in the
fundamental data source domain necessary for any continuous monitoring program. In
fact, they’re the same cautions expressed in the 2011 CAESARS FE report.
Corroborating these failures, the Government Accountability Office (GAO) found that:
“The 23 civilian agencies covered by the Chief Financial Officers Act of 1990
(CFO Act) have often not effectively implemented the federal government’s
A plan was already in motion to help address these failures. The CDM Dynamic
and Evolving Federal Enterprise Network Defense (DEFEND) contracts awarded
potentially billions of dollars to private sector companies to fix the gaps (Cordell, 2018).
Also, in 2018, a new child agency was formed under DHS, the Cybersecurity and
Infrastructure Security Agency (CISA; CISA Act, 2018). CISA assumed leadership over
the CDM program and decided to pivot the CDM dashboard to a technology called
Elastic Stack (Wiltshire, 2019). The plan to address the CDM program failures sounded
promising: new funding, new leadership, and new technology.
The stack’s roots are in being free and open-source (Elastic, n.d.-g). In 2021,
Elastic moved the source code of Elasticsearch and Kibana from the Apache 2.0 license
to either the Elastic License or the Server Side Public License to protect the company’s
investments from non-reciprocal cloud service providers (Elastic, 2021a). “This license
change ensures our community and customers have free and open access to use, modify,
redistribute, and collaborate on the code” (Elastic, 2021a). To this day, the code remains
open, being housed in public repositories so that customers can adapt it for their own use
cases (Elastic, n.d.-g). This is key for solving the challenges of today and tomorrow in
the CDM program. Even though all the products are free, features required in the CDM
program cost money, like advanced security controls, advanced features, and service
level agreements (Elastic, n.d.-h).
1.5.1. Beats
Beats are free, open, agent-based data shippers. They’re lightweight and do not
require root privileges to run. One of the Beats, called Filebeat, has generic inputs that
can be configured to collect data (e.g., filestream, HTTP JSON, log, TCP, and UDP), and
it has 70 pre-built modules to simplify data retrieval from specific tools (Elastic, 2022b).
In a use case like CDM, Beats have tremendous potential to solve the problem of
retrieving data from the CDM tools.
1.5.2. Logstash
“Logstash is an open source data collection engine with real-time pipelining
capabilities” (Elastic, 2022c). It’s all about collecting, parsing, transforming, and
shipping data. First, Logstash input plugins are used to read from data sources like Beats,
shell commands, files, databases, and network protocols, to name a few (Elastic, n.d.-f).
Second, the data can be sent through numerous pipelines that can transform it from one
data type to another and parse the data’s content to normalize it. Filter plugins can be
conditionally applied in the pipeline to perform arbitrary data processing operations. Last,
the data can be shipped off to where it needs to go. In the CDM program, Logstash can
replace the integration layer components.
1.5.3. Elasticsearch
Elasticsearch is a free and open search engine that a Wired article once called
“Your own private Google” (Finley, 2012). It stores data as documents consisting of
field-value pairs that can have various data types. It is fast, scalable, and resilient. The
CDM Dashboard will require some of the paid features like document-level security for
granular access controls in multi-tenant environments or users scoped to assets in a
particular FISMA group (Wiltshire, 2019). The CDM Dashboard will also use cross-
cluster search (CCS; Harmon, 2021), which allows remote Elasticsearch clusters to be
queried. CCS is perfect for the FISMA reporting requirements in CDM and for quickly
responding to new threats or vulnerabilities.
1.5.4. Kibana
Kibana is the free and open front end to Elasticsearch that presents the data.
Whether it’s a dashboard, a map, a bar chart, or a search interface, Kibana has it covered.
Kibana makes it easy to craft search queries and visualize the data. This is where the
CDM Dashboard is built. The customizability of Kibana allows the CDM Dashboard to
implement the government’s Agency-Wide Adaptive Risk Enumeration (AWARE)
algorithm (CISA, 2020). The AWARE scoring methodology helps defenders prioritize
which problems to fix first.
Since the CDM program’s inception in 2013, CDM contractors have developed
custom solutions to bring the data into the CDM Dashboard (U.S. Government, n.d.-b)
with varying degrees of success. Some solutions are riddled with unnecessary
complexities, redundancies, and inefficiencies. The Federal government has paid a total
estimated cost of $10.9 billion dollars (GAO, 2020) to get the CDM program up and
running. Take a moment to imagine what a cybersecurity tool integration might look like
if it was built by one group of contractors with hundreds of millions of dollars starting in
2013 (U.S. Government, n.d.-a) and then, in many cases, rebuilt by a new group of CDM
DEFEND contractors with hundreds of millions of dollars starting in 2018 (U.S.
Government, n.d.-b). It begs the question of whether anyone other than the contractors
that built the solution will be able to maintain the integration layer, compelling the
government to rely on them. The integration layer will inevitably break, need to be
patched, or need to be adapted for a new use case. Future funding for a legion of
developers is not guaranteed. Federal teams need an integration layer that is maintainable,
cost-effective, and feasible. And they need something they can implement in days, not
decades.
The researcher hypothesized that the capabilities already present in Elastic Stack
can be used to collect the data from CDM tools, perform arbitrary transformations on said
data, and ship the results off to Elasticsearch. Such a solution, if successful, would save
hundreds of millions of dollars in integration costs. Further cost savings would be
realized by eliminating redundant data aggregators, databases, or CM repositories in the
integration layer. This would reduce the overall complexity of the system to a single suite
of tools that are designed to work together (Elastic, n.d.-a), thereby providing a more
maintainable solution.
2. Research Method
The research began by identifying two CDM tools (GSA, 2022a, 2022b) that had
no existing Filebeat modules or Logstash plugins. Tenable.sc and HCL BigFix were
chosen, which have a combined federal investment of over a quarter of a billion dollars
(U.S. Government, n.d.-c, n.d.-d), indicating that if the experiment is successful, it would
have an immediate impact that matters.
interact with the server from the BigFix console or WebUI, which allows them to
perform system administration tasks. For example, an operator could create a fixlet (i.e.,
an action) that checks if a computer is missing a particular patch, then conditionally
download, install, and report if the patch was installed successfully. BigFix has an
application called Web Reports, which provides a read-only view of the console and
makes building reports very easy. Web Reports was used to create a hardware asset
management (HWAM) report and a CSM report based on the CIS checklists. Another
application called BigFix Inventory (BFI) was deployed to collect software asset
management (SWAM) data. All available software scan types were issued on the lab
hosts daily (HCL, n.d.-c).
Experimenting and testing began by reading the vendor documentation on how data could
be retrieved from the CDM tool. This was then compared to the available inputs for
Filebeat and Logstash. Once data could be retrieved from the tool, Logstash filters were
applied to transform, parse, and ship the data to Elasticsearch.
The APIs were used to collect data from Tenable.sc and BigFix. This involved
reading the official documentation, crafting test queries, and then implementing the
queries in the input configurations. During initial testing, the output was sent to the
console’s standard output. This displays the events collected directly in the terminal
running Logstash or Filebeat.
Once the Filebeat HTTP JSON input filter was selected as the primary way to
retrieve the data from the Tenable.sc, the researcher iteratively built a Filebeat
configuration. The configuration leveraged the HTTP JSON capabilities for retrieving the
data at a configurable interval, retrieving the data in chunks (pagination), retries, rate
limiting, request transformations, and response transformations.
Logstash filter plugins were used to process the event data into JSON field-value
pairs. The Elastic Common Schema Version 8.2 (Elastic, n.d.-b) was used for field
naming conventions. Commonly used filters include the mutate filter, the date filter, and
the JSON filter.
The Elasticsearch output plugin was used to send the data from Logstash to
Elasticsearch during the development process. Numerous test indices were used to
compare the results of Logstash configuration changes and conveniently view the data of
interest using queries in Kibana.
The Filebeat HTTP JSON input supports numerous authentication options, data
retrieval at configurable intervals, pagination, request transformations, response
transformations, and more (Elastic, n.d.-d). The configuration may be tuned to mitigate
the impact on a production environment or optimized for available resources. For
example, it could be configured to retrieve 5,000 records at a time, waiting 15 to 30
seconds between requests for records created in the last 24 hours. Settings like these and
many more may be tuned to meet reporting and performance requirements lending
credence to the feasibility of Filebeat data retrieval. Filebeat was configured to ship the
retrieved data over to Logstash.
Logstash was able to parse and transform the Tenable.sc data using filter plugins.
The default filter plugins were able to handle the vast majority of the data. Conditional if-
else statements were used to handle cases. Trickier situations like the vulnerability
priority rating context were handled using the ruby plugin filter, which gives free rein to
the Ruby programming language. See Appendix E, H, and K for the Tenable.sc Logstash
pipeline configurations for asset, plugin, and vulnerability data.
The Filebeat and Logstash configurations were built and tested on Elastic Stack
version 7.17.4, and no changes were needed when compared against version 7.17.5. This
was assessed by adding tags on plugin failures in the Logstash pipelines for errors.
Events with errors were sent to a separate Elasticsearch index for analysis and
remediation.
A one-month trial license for HCL BigFix was used for developing the
integration. BigFix Web Reports was used for creating an HWAM report, as depicted in
Figure 1. The 42 fields composing the HWAM report were selected from the default
content packaged with every BigFix deployment to be applicable to a wide audience. The
full list of fields is listed in Appendix S. A portable XML version of the report is
available in Appendix T that can be imported into Web Reports.
Relevance language subject matter expert was needed to create an integration, which
pulverized the prospects of a feasible and maintainable solution.
The researcher investigated how Web Reports was displaying its reports by using
the network panel in Google Chrome’s developer tools to inspect network activity. This
revealed a POST request to /post/shortentext with a URL encoded payload composed of
the column names, the number of results to retrieve, a start index, the column to sort by,
the sort direction, and the filters to apply. An example payload is shown in Figure 3.
Once in the Logstash pipeline, all retrieved results were parsed and transformed in
accordance with the Elastic Common Schema naming conventions. All fields in the
HWAM, CSM, and SWAM reports were successfully ingested into Elasticsearch. A
sample Elasticsearch document from each report is shown in Appendix W. The Logstash
configurations are shown in Appendices M, O, and Q for HWAM, CSM, and SWAM,
respectively, with corresponding Elasticsearch mappings in Appendices N, P, and R.
3.2. Discussion
Filebeat and Logstash have advanced data ingestion and transformation
capabilities. They are free, open, and extendable to add new features. When retrieving
and transforming data, there are myriad options and tool-specific integrations built by
Elastic and the community. The Filebeat and Logstash configurations created in this
research are easily adaptable for adding new fields to either CDM tool.
When used in the CDM program, Filebeat and Logstash should be configured for
continuous monitoring as opposed to interval monitoring. The current CDM requirement
is to retrieve data once every 72 hours (CISA, 2021). Logstash is capable of retrieving
mountains of data, and mitigations can be configured for spikes in events per second. In a
dynamic and evolving threat landscape, cyber defenders need today’s information today.
True continuous ingestion may be facilitated by the deployment architecture, which also
plays into how resilient the system is and how agency needs can be met. An example
deployment scenario is discussed in Appendix V.
An alternative to using Filebeat to collect data is Elastic Agent. Elastic Agent has
an HTTP JSON input and a generally available Tenable.sc version 5.18 integration
(Elastic, 2022b). Whether to use one or the other depends on numerous factors, given that
they have many of the same capabilities (Elastic, n.d.-e). At the moment, Filebeat has
specific features that may be favored by federal agencies, such as a locally managed
secrets keystore for secure settings (Elastic, n.d.-e).
Once the data is finally in Elasticsearch, Kibana may be used to build queries and
visualizations. Figure 5 demonstrates how fields are aggregable by computing the sums
of CPU cores and total RAM. The pie chart shows the distribution of operating systems
in the lab. A chart depicting the counts of hosts in various subnets is shown as well. If an
analyst clicked on the Linux Ubuntu 20.04 slice of the pie chart, a filter would be applied,
and all of the visualizations would update to reflect only that OS. The actual CDM
Dashboard would show the aggregated AWARE score and could be similarly filtered by
FISMA groups (CISA, 2020).
robust, and easy to maintain. If an agency has the data that can help make federal
networks safer but is struggling to get it in a risk management dashboard, they should use
the Elastic Stack’s capabilities to get the data. Filebeat has pre-built modules for many
tools on the CDM-approved product list (GSA, 2022a), such as Bluecoat, Check Point,
Cisco, Crowdstrike, and Cyberark (GSA, 2022b) chosen from the first five alphabetically
ascending. If a Filebeat module or Logstash input doesn’t exist, this research
demonstrates how one can be built. Filebeat and Logstash can fulfill the requirements of
the integration layer, and they are completely free.
This research shows that there is a simpler way that can be expanded upon to
meet the CDM mission requirements. Filebeat and Logstash are extendable to fulfill
needs not present in the hundreds of existing integrations. Filebeat, Logstash,
Elasticsearch, and Kibana are well documented. And they are cost-effective.
images of the Tenable.sc data in Kibana were not shown in the findings. Future research
could test the Tenable.sc Filebeat and Logstash configurations on other versions.
For BigFix, cURL was used to retrieve the HWAM, CSM, and VUL reports.
Future research could retrieve these reports with the Filebeat HTTP JSON input by
adding (a) the ability to change the “request.method” from an initial POST to a GET for
BFI, and (b) the ability to store a session-based cookie for Web Reports.
Seneca once said, “Our lack of confidence is not the result of difficulty; the
difficulty comes from our lack of confidence” (Seneca, 65). As daunting as reshaping a
multi-billion dollar government cybersecurity program is, this research provides evidence
that Elastic Stack is a cost-effective, maintainable, and feasible solution to the integration
layer challenges. Others can expand upon this research by building Elastic Stack
integrations for CDM tools that don’t exist yet. Additional research can also show others
how to use some of the more advanced capabilities of Logstash.
5. Conclusion
Civilian federal agencies over the past decade have struggled to implement a risk-
based continuous monitoring dashboard with data sourced from cybersecurity tools.
Elastic Stack can solve this problem at a fraction of the cost. The research presented here
shows that it is entirely feasible to bring data from CDM tools into Elastic Stack without
the need for costly and complicated solutions. Since BigFix and Tenable.sc data can be
retrieved in JSON format, the Logstash pipelines essentially just rename the fields. While
events are in the pipeline, they can be enriched with data from numerous external
sources, such as a CSV plugin to append FISMA information, the DNS plugin to perform
reverse lookups on events that are missing a hostname, or the HTTP plugin to retrieve
asset information from an asset management REST API. Alternatively, post hoc
enrichment can occur by using Logstash to query Elasticsearch for missing fields.
The CDM program’s present level of funding will not last forever. The solutions
being built by DEFEND contractors must be maintainable by federal teams in the future.
The Filebeat and Logstash configurations developed in this research are compatible
across numerous versions of Elastic Stack and the CDM tools, meaning that no changes
were needed to retrieve all of the data. If a change is needed, making an adjustment is
easy. Say a new field is desired from BigFix. It’s as simple as adding the URL encoded
column or criteria to the input and then renaming that field in Logstash.
References
BigFix Developer. (n.d.-c). Session Relevance Guide. Retrieved August 4, 2022, from
https://developer.bigfix.com/relevance/guide/session/
BigFix Developer. (n.d.-b). The BigFix SOAP API. Retrieved July 4, 2022, from
https://developer.bigfix.com/other/soap-api/
BigFix Developer. (n.d.-a). The BigFix REST API. Retrieved July 4, 2022, from
https://developer.bigfix.com/rest-api/
Committee on Homeland Security. (2021, June 9). Cyber threats in the pipeline: Using
lessons from the colonial ransomware attack to defend critical infrastructure.
GovInfo | U.S. Government Publishing Office.
https://www.govinfo.gov/content/pkg/CHRG-117hhrg45085/html/CHRG-
117hhrg45085.htm
Cordell, C. (2018, August 22). Booz Allen Hamilton snags $1b cdm defend task order.
FedScoop. https://www.fedscoop.com/booz-allen-hamilton-snags-1b-cdm-defend-
task-order/
Cybersecurity and Infrastructure Security Agency Act of 2018, Pub. L. No. 115-278
(2018). https://www.govinfo.gov/content/pkg/PLAW-115publ278/pdf/PLAW-
115publ278.pdf
Cybersecurity and Infrastructure Security Agency. (2020, September 20). Continuous
diagnostics and mitigation program: aware scoring.
https://www.cisa.gov/sites/default/files/publications/cdm-program-aware-scoring-
fact-sheet-092020-508.pdf
Cybersecurity and Infrastructure Security Agency. (2022). Continuous diagnostics and
mitigation program. Retrieved June 16, 2022, from https://www.cisa.gov/cdm
Cybersecurity and Infrastructure Security Agency. (2021, August 8). Continuous
diagnostics and mitigation program technical capabilities volume two:
requirements catalog version 2.4. General Services Administration.
https://www.gsa.gov/cdnstatic/Integrated_Technology_Services/CDM-PROG-
2021-CDM%20Technical%20Volume%202_v24.pdf
Page 13
Meyering, J., & Eggert, P. (2021, August 1). GNU Diffutils. The GNU Operating System
and the Free Software Movement. https://www.gnu.org/software/diffutils/
Microsoft. (n.d.). Maximum URL length is 2,083 characters in internet explorer.
Microsoft Support. https://support.microsoft.com/en-us/topic/maximum-url-
length-is-2-083-characters-in-internet-explorer-174e7c8a-6666-f4e0-6fd6-
908b53c12246
Office of Inspector General. (2021, June 1). DHS has made limited progress
implementing the continuous diagnostics and mitigation program. Department of
Homeland Security. https://www.oig.dhs.gov/sites/default/files/assets/2021-
06/OIG-21-38-Jun21.pdf
Otto, D. (2017, October, 31). Managing risk against cyber uncertainties: using the
dashboard. DHS Federal Network Resilience Division.
https://www.cisa.gov/uscert/sites/default/files/cdm_files/FNR_CGB_TRNG_OCT
2017_Webinar_Slide_Presentation.pdf
Quinn, J. (2016, October 13). CDM: Transition to Phase Two and Beyond. CISA.
https://www.cisa.gov/uscert/sites/default/files/cdm_files/FNR_CPM_OTH_Webi
nar_October.pdf
Ross, R., Katzke, S., Johnson, L., Swanson, M., Stoneburner, G., Rogers, G., & Lee, A.
(2005, February 2). Recommended security controls for federal information
systems. NIST Special Publication (SP) 800-53.
https://csrc.nist.gov/publications/detail/sp/800-53/archive/2005-02-28
Robinson, A. (2018, April 30). Did Einstein really say that? Nature.
https://www.nature.com/articles/d41586-018-05004-4
Scott. (2018a, February 5). Interesting and useful JSON restful APIs in web reports.
BigFix Forum. Retrieved July 5, 2022, from
https://forum.bigfix.com/t/interesting-and-useful-json-restful-apis-in-web-
reports/24441
Scott. (2018b, February 5). DoubleDeuceBuddha/bfwr_api. GitHub. Retrieved July 5,
2022, from https://github.com/DoubleDeuceBuddha/bfwr_api
Seneca, L. A. (65). Moral letters to lucilius/Letter 104. Wikisource, the free library.
Retrieved August 15, 2022, from
https://en.wikisource.org/wiki/Moral_letters_to_Lucilius/Letter_104
Schneier, B. (2015). Secrets and lies: Digital security in a networked world. John Wiley
& Sons.
Skoudis, E., & Liston, T. (2006). Counter hack reloaded: A step-by-step guide to
computer attacks and effective defenses (2nd ed.). Pearson. p. 2
Stenberg, Daniel. (2022, June 27). curl. Retrieved July 12, 2022, from https://curl.se/
Stewart, J. (2015a, June 18). The way Bigfix session relevance statements are written
matters (part1). https://www.jgstew.com/bigfix/2015/06/18/The-way-BigFix-
Session-Relevance-statements-are-written-matters-(part1).html
Stewart, J. (2015b, September 14). The way Bigfix session relevance statements are
written matters (part2) computer names.
https://www.jgstew.com/bigfix/2015/09/14/The-way-BigFix-Session-Relevance-
statements-are-written-matters-(Part2)-Computer-Names.html
Stewart, J. (2016, October 11). The way Bigfix session relevance statements are written
matters (part3) whose. https://www.jgstew.com/bigfix/2016/10/11/The-way-
BigFix-Session-Relevance-statements-are-written-matters-(Part3)-Whose.html
Sullivan, T. (2017, June 21). The meaning of Kibana. Discuss the Elastic Stack.
https://discuss.elastic.co/t/the-meaning-of-kibana/89828
Talbert, J. (2020, January 1). Efficient session relevance query for computer properties.
BigFix Forum. Retrieved July 6, 2022, from https://forum.bigfix.com/t/efficient-
session-relevance-query-for-computer-properties/32820
Tenable. (n.d.-b). Tenable.sc API: Overview. Retrieved July 15, 2022, from
https://docs.tenable.com/tenablesc/api/index.htm
Tenable. (n.d.-a). Tenable.sc. Retrieved August 14, 2022, from
https://www.tenable.com/products/tenable-sc
The MITRE Corporation. (n.d.). Glossary. CVE. Retrieved June 12, 2022, from
https://www.cve.org/ResourcesSupport/Glossary?activeTerm=glossaryVulnerabil
ity
Appendix B: Software
Author Name Version Link
Chance VS Code 0.0.4 https://github.com/randomchance/vscode-
Carroll extension: logstash-configuration-syntax
randomchance.l
ogstash
Meyering Diffutils https://www.gnu.org/software/diffutils/
& Eggert
Elastic Elasticsearch 7.17.4 https://www.elastic.co/downloads/past-
releases/elasticsearch-7-17-4
Elastic Elasticsearch 7.17.5 https://www.elastic.co/downloads/past-
releases/elasticsearch-7-17-5
Elastic Elasticsearch 8.1.2 https://www.elastic.co/downloads/past-
releases/elasticsearch-8-1-2
Elastic Elasticsearch 8.2.2 https://www.elastic.co/downloads/past-
releases/elasticsearch-8-2-2
Elastic Elasticsearch 8.3.2 https://www.elastic.co/downloads/past-
releases/elasticsearch-8-3-2
Elastic Filebeat 7.17.4 https://www.elastic.co/downloads/past-
releases/filebeat-7-17-4
Elastic Filebeat 7.17.5 https://www.elastic.co/downloads/past-
releases/filebeat-7-17-5
Elastic Filebeat 8.1.2 https://www.elastic.co/downloads/past-
releases/filebeat-8-1-2
Elastic Filebeat 8.2.2 https://www.elastic.co/downloads/past-
releases/filebeat-8-2-2
Elastic Filebeat 8.3.2 https://www.elastic.co/downloads/past-
releases/filebeat-8-3-2
Elastic Kibana 7.17.4 https://www.elastic.co/downloads/past-
releases/kibana-7-17-4
Elastic Kibana 7.17.5 https://www.elastic.co/downloads/past-
releases/kibana-7-17-5
Elastic Kibana 8.1.2 https://www.elastic.co/downloads/past-
releases/kibana-8-1-2
Elastic Kibana 8.2.2 https://www.elastic.co/downloads/past-
releases/kibana-8-2-2
Elastic Kibana 8.3.2 https://www.elastic.co/downloads/past-
releases/kibana-8-3-2
Elastic Logstash 7.17.4 https://www.elastic.co/downloads/past-
releases/logstash-7-17-4
Elastic Logstash 7.17.5 https://www.elastic.co/downloads/past-
releases/logstash-7-17-5
https://www.microsoft.com/en-
Microsoft Windows Server 2019
us/evalcenter/download-windows-server-2019
filebeat.inputs:
- type: httpjson
config_version: 2
interval: 60s
request.url: ${tenable_url}/rest/analysis
request.method: POST
request.ssl:
certificate_authorities:
- "${ca_cert}"
verification_mode: certificate
#request.retry.wait_min:
#request.retry.wait_max:
#request.retry.max_attempts:
request.transforms:
- delete:
target: header.User-Agent
- set:
target: header.User-Agent
value: 'Integration/1.0 (Elastic; Tenable.sc Beat; Build/7.17.4)'
- set:
target: header.x-apikey
value: "accesskey=${tenable_access_key}; secretkey=${tenable_secret_key}"
- set:
target: header.Accept
value: "application/json"
- set:
target: body.type
value: 'vuln'
- set:
target: body.query.type
value: 'vuln'
- set:
target: body.query.tool
value: 'sumip'
- append:
target: body.query.filters
value: |-
{
"filterName":"lastSeen",
"operator":"=",
"value": '[[.cursor.last_event_ts]]-[[(now).Unix]]'
}
default: |-
{
"filterName":"lastSeen",
"operator":"=",
"value": '[[(parseDate now (parseDuration "-168h")).Unix]]-[[(now).Unix]]'
}
value_type: json
- set:
target: body.sourceType
value: 'cumulative'
- set:
target: body.startOffset
value: 0
- set:
target: body.endOffset
value: 2000
response.split:
target: body.response.results
response.pagination:
- set:
target: body.startOffset
value: '[[toInt .last_response.body.response.endOffset]]'
fail_on_template_error: true
- set:
target: body.endOffset
value: '[[add (toInt .last_response.body.response.endOffset) 5000]]'
fail_on_template_error: true
cursor:
last_event_ts:
value: '[[if (ge (toInt .last_response.body.response.endOffset) (toInt
.last_response.body.response.totalRecords))]][[toInt
.last_response.body.timestamp]][[end]]'
output.logstash:
hosts: ["${logstash_url}"]
input {
beats {
port => 5044
}
}
filter {
mutate {
rename => {
"[message]" => "[event][original]"
}
}
json {
source => "[event][original]"
target => "[json]"
skip_on_invalid_json => true
}
date {
match => ["[json][@timestamp]", "ISO8601"]
tag_on_failure => ["_dateparsefailure"]
}
mutate {
add_field => {
"[event][category]" => "host"
"[event][type]" => "info"
"[event][kind]" => "state"
}
}
if [json][uniqueness] {
mutate {
split => {
"[json][uniqueness]" => ","
}
tag_on_failure => "_mutate_error"
}
ruby {
code => '
a = event.get("[json][uniqueness]")
uniqueKey = ""
a.each { |a|
if a == "repositoryID"
uniqueKey += event.get("[json][repository][id]")
else
uniqueKey += event.get("[json][#{a}]")
end
}
uniqueKey += "_"
event.set("[tenable_sc][asset][custom_hash]", uniqueKey)
'
tag_on_exception => "_rubyexception"
}
}
# Fingerprint custom SHA256 hash. Concatenates the names and values of all fields
given in the source option into one string before doing the fingerprint computation.
fingerprint {
method => "SHA256"
concatenate_sources => true
source => ["[tenable_sc][asset][custom_hash]"]
target => ["[tenable_sc][asset][custom_hash]"]
}
if [json][ip] {
mutate {
add_field => {
"[related][ip]" => "%{[json][ip]}"
"[host][ip]" => "%{[json][ip]}"
}
}
mutate {
rename => {
"[json][ip]" => "[tenable_sc][asset][ip]"
}
}
}
if [json][dnsName] {
# Dissect the dnsName into two new fields if it contains a dot "." into host.name
(everything up to first period) and host.domain.name (everything after)
if [json][dnsName] =~ /\./ {
dissect {
mapping => {
"[json][dnsName]" => "%{[host][name]}.%{[host][domain][name]}"
}
tag_on_failure => ["_dissectfailure"]
}
mutate {
add_field => {
"[related][hosts]" => "%{[host][name]}"
}
}
mutate {
copy => {
"[json][dnsName]" => "[host][hostname]"
}
}
mutate {
rename => {
"[json][dnsName]" => "[tenable_sc][asset][dns][name]"
}
}
} else {
mutate {
add_field => {
"[related][hosts]" => "[json][dnsName]}"
}
}
mutate {
copy => {
"[json][dnsName]" => "[host][hostname]"
}
}
# Technically only the host.name and not the host.name plus host.domain.name
mutate {
rename => {
"[json][dnsName]" => "[tenable_sc][asset][dns][name]"
}
}
}
}
mutate {
rename => {
"[json][uuid]" => "[tenable_sc][asset][uuid]"
"[json][score]" => "[tenable_sc][asset][score]"
"[json][total]" => "[tenable_sc][asset][total]"
"[json][severityInfo]" => "[tenable_sc][asset][severity][info]"
"[json][severityLow]" => "[tenable_sc][asset][severity][low]"
"[json][severityMedium]" => "[tenable_sc][asset][severity][medium]"
"[json][severityHigh]" => "[tenable_sc][asset][severity][high]"
rename => {
"[json][netbiosName]" => "[tenable_sc][asset][netbios][name]"
}
}
}
mutate {
remove_field => ["[json]"]
}
output {
if "_dateparsefailure" in [tags] or "_mutate_error" in [tags] or "_rubyexception" in
[tags] or "_dissectfailure" in [tags] {
stdout {
codec => rubydebug {
metadata => true
}
}
}
elasticsearch {
hosts => ["${es_url}"]
index => "asset"
user => "${logstash_es_user}"
password => "${logstash_es_user_pw}"
cacert => "${cacert_path}"
# truststore => "${truststore_path}"
# truststore_password => "${truststore_pw}"
}
}
"fields" : {
"text" : {
"type" : "text"
}
}
},
"type" : {
"type" : "keyword",
"ignore_above" : 256,
"fields" : {
"text" : {
"type" : "text"
}
}
},
"version" : {
"type" : "keyword",
"ignore_above" : 256,
"fields" : {
"text" : {
"type" : "text"
}
}
}
}
},
"ecs" : {
"properties" : {
"version" : {
"type" : "keyword",
"ignore_above" : 256,
"fields" : {
"text" : {
"type" : "text"
}
}
}
}
},
"event" : {
"properties" : {
"category" : {
"type" : "keyword",
"ignore_above" : 256,
"fields" : {
"text" : {
"type" : "text"
}
}
},
"created" : {
"type" : "date"
},
"kind" : {
"type" : "keyword",
"ignore_above" : 256,
"fields" : {
"text" : {
"type" : "text"
}
}
},
"type" : {
"type" : "keyword",
"ignore_above" : 256,
"fields" : {
"text" : {
"type" : "text"
}
}
}
}
},
"host" : {
"properties" : {
"domain" : {
"properties" : {
"name" : {
"type" : "keyword",
"ignore_above" : 256,
"fields" : {
"text" : {
"type" : "text"
}
}
}
}
},
"hostname" : {
"type" : "keyword",
"ignore_above" : 256,
"fields" : {
"text" : {
"type" : "text"
}
}
},
"ip" : {
"type" : "keyword",
"ignore_above" : 256,
"fields" : {
"text" : {
"type" : "ip"
}
}
},
"mac" : {
"type" : "keyword",
"ignore_above" : 256,
"fields" : {
"text" : {
"type" : "text"
}
}
},
"name" : {
"type" : "keyword",
"ignore_above" : 256,
"fields" : {
"text" : {
"type" : "text"
}
}
}
}
},
"input" : {
"properties" : {
"type" : {
"type" : "keyword",
"ignore_above" : 256,
"fields" : {
"text" : {
"type" : "text"
}
}
}
}
},
"related" : {
"properties" : {
"hosts" : {
"type" : "keyword",
"ignore_above" : 256,
"fields" : {
"text" : {
"type" : "text"
}
}
},
"ip" : {
"type" : "keyword",
"ignore_above" : 256,
"fields" : {
"text" : {
"type" : "text"
}
}
}
}
},
"tags" : {
"type" : "keyword",
"ignore_above" : 256,
"fields" : {
"text" : {
"type" : "text"
}
}
},
"tenable_sc" : {
"properties" : {
"asset" : {
"properties" : {
"bios" : {
"properties" : {
"guid" : {
"type" : "keyword",
"ignore_above" : 256,
"fields" : {
"text" : {
"type" : "text"
}
}
}
}
},
"custom_hash" : {
"type" : "keyword",
"ignore_above" : 256,
"fields" : {
"text" : {
"type" : "text"
}
}
},
"dns" : {
"properties" : {
"name" : {
"type" : "keyword",
"ignore_above" : 256,
"fields" : {
"text" : {
"type" : "text"
}
}
}
}
},
"host_uniqueness" : {
"type" : "keyword",
"ignore_above" : 256,
"fields" : {
"text" : {
"type" : "text"
}
}
},
"ip" : {
"type" : "keyword",
"ignore_above" : 256,
"fields" : {
"text" : {
"type" : "text"
}
}
},
"last_auth_run" : {
"type" : "keyword",
"ignore_above" : 256,
"fields" : {
"text" : {
"type" : "text"
}
}
},
"last_unauth_run" : {
"type" : "keyword",
"ignore_above" : 256,
"fields" : {
"text" : {
"type" : "text"
}
}
},
"mac" : {
"type" : "keyword",
"ignore_above" : 256,
"fields" : {
"text" : {
"type" : "text"
}
}
},
"mcafee" : {
"properties" : {
"guid" : {
"type" : "keyword",
"ignore_above" : 256,
"fields" : {
"text" : {
"type" : "text"
}
}
}
}
},
"netbios" : {
"properties" : {
"name" : {
"type" : "keyword",
"ignore_above" : 256,
"fields" : {
"text" : {
"type" : "text"
}
}
}
}
},
"os_cpe" : {
"type" : "keyword",
"ignore_above" : 256,
"fields" : {
"text" : {
"type" : "text"
}
}
},
"plugin_set" : {
"type" : "keyword",
"ignore_above" : 256,
"fields" : {
"text" : {
"type" : "text"
}
}
},
"policy" : {
"properties" : {
"name" : {
"type" : "keyword",
"ignore_above" : 256,
"fields" : {
"text" : {
"type" : "text"
}
}
}
}
},
"repository" : {
"properties" : {
"dataFormat" : {
"type" : "keyword",
"ignore_above" : 256,
"fields" : {
"text" : {
"type" : "text"
}
}
},
"description" : {
"type" : "keyword",
"ignore_above" : 256,
"fields" : {
"text" : {
"type" : "text"
}
}
},
"id" : {
"type" : "keyword",
"ignore_above" : 256,
"fields" : {
"text" : {
"type" : "text"
}
}
},
"name" : {
"type" : "keyword",
"ignore_above" : 256,
"fields" : {
"text" : {
"type" : "text"
}
}
}
}
},
"score" : {
"type" : "keyword",
"ignore_above" : 256,
"fields" : {
"text" : {
"type" : "text"
},
"long" : {
"type" : "long"
}
}
},
"severity" : {
"properties" : {
"critical" : {
"type" : "keyword",
"ignore_above" : 256,
"fields" : {
"text" : {
"type" : "text"
},
"long" : {
"type" : "long"
}
}
},
"high" : {
"type" : "keyword",
"ignore_above" : 256,
"fields" : {
"text" : {
"type" : "text"
},
"long" : {
"type" : "long"
}
}
},
"info" : {
"type" : "keyword",
"ignore_above" : 256,
"fields" : {
"text" : {
"type" : "text"
},
"long" : {
"type" : "long"
}
}
},
"low" : {
"type" : "keyword",
"ignore_above" : 256,
"fields" : {
"text" : {
"type" : "text"
},
"long" : {
"type" : "long"
}
}
},
"medium" : {
"type" : "keyword",
"ignore_above" : 256,
"fields" : {
"text" : {
"type" : "text"
},
"long" : {
"type" : "long"
}
}
}
}
},
"total" : {
"type" : "keyword",
"ignore_above" : 256,
"fields" : {
"text" : {
"type" : "text"
},
"long" : {
"type" : "long"
}
}
},
"tpm" : {
"properties" : {
"id" : {
"type" : "keyword",
"ignore_above" : 256,
"fields" : {
"text" : {
"type" : "text"
}
}
}
}
},
"uniqueness" : {
"type" : "keyword",
"ignore_above" : 256,
"fields" : {
"text" : {
"type" : "text"
}
}
},
"uuid" : {
"type" : "keyword",
"ignore_above" : 256,
"fields" : {
"text" : {
"type" : "text"
}
}
}
}
}
}
}
}
}
}
}
filebeat.inputs:
- type: httpjson
config_version: 2
interval: 15m
request.url: ${tenable_url}/rest/plugin
request.method: GET
request.timeout: 60s
request.ssl:
certificate_authorities:
- "${ca_cert}"
verification_mode: certificate
#request.retry.wait_min:
#request.retry.wait_max:
#request.retry.max_attempts:
request.transforms:
- delete:
target: header.User-Agent
- set:
target: header.User-Agent
value: 'Integration/1.0 (Elastic; Tenable.sc Beat; Build/7.17.4)'
- set:
target: header.x-apikey
value: "accesskey=${tenable_access_key}; secretkey=${tenable_secret_key}"
# Fields to test: agent
# The following parameters must be passed in as query string (as opposed to JSON) in
the format of: /plugin?filterField=id&op=eq&value=1&...
# family,vprContext,xrefs
- set:
target: url.params.fields
value:
id,name,description,type,copyright,version,sourceFile,dependencies,requiredPorts,require
dUDPPorts,cpe,srcPort,dstPort,protocol,riskFactor,solution,seeAlso,synopsis,checkType,
exploitEase,exploitAvailable,exploitFrameworks,cvssVector,cvssVectorBF,baseScore,te
mporalScore,cvssV3Vector,cvssV3VectorBF,cvssV3BaseScore,cvssV3TemporalScore,v
prScore,stigSeverity,pluginPubDate,pluginModDate,patchPubDate,patchModDate,vulnP
ubDate,modifiedTime,md5
- set:
target: url.params.filterField
value: pluginModDate
- set:
target: url.params.op
value: gt
- set:
target: url.params.value
value: '[[.cursor.last_event_ts]]'
default: '[[(now (parseDuration "-720h")).Unix]]'
- set:
target: url.params.sortField
value: modifiedTime
- set:
target: url.params.sortDirection
value: ASC
- set:
target: url.params.startOffset
value: 0
- set:
target: url.params.endOffset
value: 50
response.pagination:
- set:
target: url.params.startOffset
value: '[[toInt (.last_response.url.params.Get "endOffset")]]'
fail_on_template_error: true
- set:
target: url.params.endOffset
value: '[[add (toInt (.last_response.url.params.Get "endOffset")) 50]]'
fail_on_template_error: true
response.split:
target: body.response
cursor:
last_event_ts:
value: '[[if (lt (len .last_response.body.response)
50)]][[.last_event.pluginModDate]][[end]]'
output.logstash:
hosts: ["localhost:5044"]
input {
beats {
port => 5044
}
}
filter {
mutate {
rename => {
"[message]" => "[event][original]"
}
}
json {
source => "[event][original]"
target => "[json]"
skip_on_invalid_json => true
}
date {
match => ["[json][modifiedTime]", "UNIX"]
tag_on_failure => ["_dateparsefailure"]
}
# Fingerprint. Sets the indexed document's _id to a SHA-256 hash. Concatenates the
names and values of all fields given in the source option into one string before doing the
fingerprint computation.
fingerprint {
method => "SHA256"
concatenate_sources => true
source => [
"[json][modifiedTime]",
"[json][id]",
"[json][name]",
"[json][type]",
"[json][description]",
"[json][version]",
"[json][sourceFile]",
"[json][cpe]",
"[json][dependencies]",
"[json][riskFactor]",
"[json][vprContext]",
"[json][vprScore]",
"[json][baseScore]",
"[json][temporalScore]",
"[json][cvssVector]",
"[json][cvssV3Vector]",
"[json][pluginModDate]",
"[json][patchPubDate]",
"[json][vulnPubDate]",
"[json][family]"
]
target => "[@metadata][_id]"
}
# ECS event fields
mutate {
add_field => {
"[event][category]" => "configuration"
"[event][type]" => "info"
"[event][kind]" => "event"
}
}
# Rename fields
mutate {
rename => {
"[json][agent]" => "[tenable_sc][plugin][agent]"
"[json][id]" => "[tenable_sc][plugin][id]"
"[json][name]" => "[tenable_sc][plugin][name]"
"[json][description]" => "[tenable_sc][plugin][description]"
"[json][type]" => "[tenable_sc][plugin][type]"
"[json][copyright]" => "[tenable_sc][plugin][copyright]"
"[json][version]" => "[tenable_sc][plugin][version]"
"[json][sourceFile]" => "[tenable_sc][plugin][source_file]"
"[json][requiredPorts]" => "[tenable_sc][plugin][required_ports]"
"[json][requiredUDPPorts]" => "[tenable_sc][plugin][required_udp_ports]"
"[json][srcPort]" => "[tenable_sc][plugin][src_port]"
"[json][dstPort]" => "[tenable_sc][plugin][dst_port]"
"[json][protocol]" => "[tenable_sc][plugin][protocol]"
"[json][riskFactor]" => "[tenable_sc][plugin][risk_factor]"
"[json][solution]" => "[tenable_sc][plugin][solution]"
"[json][synopsis]" => "[tenable_sc][plugin][synopsis]"
"[json][checkType]" => "[tenable_sc][plugin][check_type]"
"[json][exploitEase]" => "[tenable_sc][plugin][exploit][ease]"
mutate {
add_field => {
"[tenable_sc][plugin][is_plugin_published]" => "false"
}
}
}
else {
mutate {
add_field => {
"[tenable_sc][plugin][is_plugin_published]" => "true"
}
}
date {
match => ["[json][pluginPubDate]", "UNIX"]
target => "[tenable_sc][plugin][plugin_pub_date]"
tag_on_failure => ["_dateparsefailure_plugin_pub_date"]
}
}
}
# If the pluginModDate is "-1" set it to false, else set it to true and parse the
modification date into a new field
if [json][pluginModDate] {
if [json][pluginModDate] == "-1" {
mutate {
add_field => {
"[tenable_sc][plugin][is_plugin_modified]" => "false"
}
}
}
else {
mutate {
add_field => {
"[tenable_sc][plugin][is_plugin_modified]" => "true"
}
}
date {
match => ["[json][pluginModDate]", "UNIX"]
target => "[tenable_sc][plugin][plugin_mod_date]"
tag_on_failure => ["_dateparsefailure_plugin_mod_date"]
}
}
}
# If the patchPubDate is "-1" set it to false, else set it to true and parse the modification
date into a new field
if [json][patchPubDate] {
if [json][patchPubDate] == "-1" {
mutate {
add_field => {
"[tenable_sc][plugin][is_patch_published]" => "false"
}
}
}
else {
mutate {
add_field => {
"[tenable_sc][plugin][is_patch_published]" => "true"
}
}
date {
match => ["[json][patchPubDate]", "UNIX"]
target => "[tenable_sc][plugin][patch_pub_date]"
tag_on_failure => ["_dateparsefailure_patch_pub_date"]
}
}
}
# If the patchModDate is "-1" set it to false, else set it to true and parse the
modification date into a new field
if [json][patchModDate] {
if [json][patchModDate] == "-1" {
mutate {
add_field => {
"[tenable_sc][plugin][is_patch_published]" => "false"
}
}
}
else {
mutate {
add_field => {
"[tenable_sc][plugin][is_patch_published]" => "true"
}
}
date {
match => ["[json][patchModDate]", "UNIX"]
target => "[tenable_sc][plugin][patch_mod_date]"
tag_on_failure => ["_dateparsefailure_patch_mod_date"]
}
}
}
# If the vulnPubDate is "-1" set it to false, else set it to true and parse the modification
date into a new field
if [json][vulnPubDate] {
if [json][vulnPubDate] == "-1" {
mutate {
add_field => {
"[tenable_sc][plugin][is_vulnerability_published]" => "false"
}
}
}
else {
mutate {
add_field => {
"[tenable_sc][plugin][is_vulnerability_published]" => "true"
}
}
date {
match => ["[json][vulnPubDate]", "UNIX"]
target => "[tenable_sc][plugin][vuln_pub_date]"
tag_on_failure => ["_dateparsefailure_vuln_pub_date"]
}
}
}
date {
match => ["[json][modifiedTime]", "UNIX"]
target => "[tenable_sc][plugin][modified_time]"
tag_on_failure => ["_dateparsefailure_modified_time"]
}
# Split the xref field into an array using a comma delimiter
if [json][xrefs] {
mutate {
split => {
"[json][xrefs]" => ","
}
}
mutate {
rename => {
"[json][xrefs]" => "[tenable_sc][vulnerability][xrefs]"
}
}
}
mutate {
remove_field => ["[json]"]
}
if "preserve_original_event" not in [tags] {
mutate {
remove_field => ["[event][original]"]
}
}
output {
elasticsearch {
hosts => ["${es_url}"]
index => "plugin"
#document_id => "%{[@metadata][_id]}"
user => "${logstash_es_user}"
password => "${logstash_es_user_pw}"
cacert => "${cacert_path}"
#truststore => "${truststore_path}"
#truststore_password => "${truststore_pw}"
}
}
"type" : "keyword",
"ignore_above" : 256,
"fields" : {
"text" : {
"type" : "text"
}
}
}
}
},
"ecs" : {
"properties" : {
"version" : {
"type" : "keyword",
"ignore_above" : 256,
"fields" : {
"text" : {
"type" : "text"
}
}
}
}
},
"event" : {
"properties" : {
"category" : {
"type" : "keyword",
"ignore_above" : 256,
"fields" : {
"text" : {
"type" : "text"
}
}
},
"created" : {
"type" : "date"
},
"kind" : {
"type" : "keyword",
"ignore_above" : 256,
"fields" : {
"text" : {
"type" : "text"
}
}
},
"type" : {
"type" : "keyword",
"ignore_above" : 256,
"fields" : {
"text" : {
"type" : "text"
}
}
}
}
},
"input" : {
"properties" : {
"type" : {
"type" : "keyword",
"ignore_above" : 256,
"fields" : {
"text" : {
"type" : "text"
}
}
}
}
},
"tags" : {
"type" : "keyword",
"ignore_above" : 256,
"fields" : {
"text" : {
"type" : "text"
}
}
},
"tenable_sc" : {
"properties" : {
"plugin" : {
"properties" : {
"agent" : {
"type" : "keyword",
"ignore_above" : 256,
"fields" : {
"text" : {
"type" : "text"
}
}
},
"base_score" : {
"type" : "keyword",
"ignore_above" : 256,
"fields" : {
"text" : {
"type" : "text"
},
"long" : {
"type" : "long"
}
}
},
"check_type" : {
"type" : "keyword",
"ignore_above" : 256,
"fields" : {
"text" : {
"type" : "text"
}
}
},
"copyright" : {
"type" : "keyword",
"ignore_above" : 256,
"fields" : {
"text" : {
"type" : "text"
}
}
},
"cpe" : {
"type" : "keyword",
"ignore_above" : 256,
"fields" : {
"text" : {
"type" : "text"
}
}
},
"cvss_vector" : {
"type" : "keyword",
"ignore_above" : 256,
"fields" : {
"text" : {
"type" : "text"
}
}
},
"cvss_vector_bf" : {
"type" : "keyword",
"ignore_above" : 256,
"fields" : {
"text" : {
"type" : "text"
}
}
},
"cvssv3_base_score" : {
"type" : "keyword",
"ignore_above" : 256,
"fields" : {
"text" : {
"type" : "text"
},
"long" : {
"type" : "long"
}
}
},
"cvssv3_temporal_score" : {
"type" : "keyword",
"ignore_above" : 256,
"fields" : {
"text" : {
"type" : "text"
},
"long" : {
"type" : "long"
}
}
},
"cvssv3_vector" : {
"type" : "keyword",
"ignore_above" : 256,
"fields" : {
"text" : {
"type" : "text"
}
}
},
"cvssv3_vector_bf" : {
"type" : "keyword",
"ignore_above" : 256,
"fields" : {
"text" : {
"type" : "text"
}
}
},
"dependencies" : {
"type" : "keyword",
"ignore_above" : 256,
"fields" : {
"text" : {
"type" : "text"
}
}
},
"description" : {
"type" : "keyword",
"ignore_above" : 256,
"fields" : {
"text" : {
"type" : "text"
}
}
},
"dst_port" : {
"type" : "keyword",
"ignore_above" : 256,
"fields" : {
"text" : {
"type" : "text"
},
"long" : {
"type" : "long"
}
}
},
"exploit" : {
"properties" : {
"ease" : {
"type" : "keyword",
"ignore_above" : 256,
"fields" : {
"text" : {
"type" : "text"
}
}
},
"frameworks" : {
"type" : "keyword",
"ignore_above" : 256,
"fields" : {
"text" : {
"type" : "text"
}
}
},
"is_available" : {
"type" : "keyword",
"ignore_above" : 256,
"fields" : {
"text" : {
"type" : "text"
},
"boolean" : {
"type" : "boolean"
}
}
}
}
},
"family" : {
"properties" : {
"id" : {
"type" : "keyword",
"ignore_above" : 256,
"fields" : {
"text" : {
"type" : "text"
}
}
},
"name" : {
"type" : "keyword",
"ignore_above" : 256,
"fields" : {
"text" : {
"type" : "text"
}
}
},
"type" : {
"type" : "keyword",
"ignore_above" : 256,
"fields" : {
"text" : {
"type" : "text"
}
}
}
}
},
"id" : {
"type" : "keyword",
"ignore_above" : 256,
"fields" : {
"text" : {
"type" : "text"
}
}
},
"is_patch_published" : {
"type" : "keyword",
"ignore_above" : 256,
"fields" : {
"text" : {
"type" : "text"
},
"boolean" : {
"type" : "boolean"
}
}
},
"is_patch_modified" : {
"type" : "keyword",
"ignore_above" : 256,
"fields" : {
"text" : {
"type" : "text"
},
"boolean" : {
"type" : "boolean"
}
}
},
"is_plugin_modified" : {
"type" : "keyword",
"ignore_above" : 256,
"fields" : {
"text" : {
"type" : "text"
},
"boolean" : {
"type" : "boolean"
}
}
},
"is_plugin_published" : {
"type" : "keyword",
"ignore_above" : 256,
"fields" : {
"text" : {
"type" : "text"
},
"boolean" : {
"type" : "boolean"
}
}
},
"is_vulnerability_published" : {
"type" : "keyword",
"ignore_above" : 256,
"fields" : {
"text" : {
"type" : "text"
},
"boolean" : {
"type" : "boolean"
}
}
},
"md5" : {
"type" : "keyword",
"ignore_above" : 256,
"fields" : {
"text" : {
"type" : "text"
}
}
},
"modified_time" : {
"type" : "date"
},
"name" : {
"type" : "keyword",
"ignore_above" : 256,
"fields" : {
"text" : {
"type" : "text"
}
}
},
"patch_pub_date" : {
"type" : "date"
},
"plugin_mod_date" : {
"type" : "date"
},
"plugin_pub_date" : {
"type" : "date"
},
"protocol" : {
"type" : "keyword",
"ignore_above" : 256,
"fields" : {
"text" : {
"type" : "text"
}
}
},
"required_ports" : {
"type" : "keyword",
"ignore_above" : 256,
"fields" : {
"text" : {
"type" : "text"
}
}
},
"required_udp_ports" : {
"type" : "keyword",
"ignore_above" : 256,
"fields" : {
"text" : {
"type" : "text"
}
}
},
"risk_factor" : {
"type" : "keyword",
"ignore_above" : 256,
"fields" : {
"text" : {
"type" : "text"
}
}
},
"see_also" : {
"type" : "keyword",
"ignore_above" : 256,
"fields" : {
"text" : {
"type" : "text"
}
}
},
"solution" : {
"type" : "keyword",
"ignore_above" : 256,
"fields" : {
"text" : {
"type" : "text"
}
}
},
"source" : {
"type" : "keyword",
"ignore_above" : 256,
"fields" : {
"text" : {
"type" : "text"
}
}
},
"source_file" : {
"type" : "keyword",
"ignore_above" : 256,
"fields" : {
"text" : {
"type" : "text"
}
}
},
"src_port" : {
"type" : "keyword",
"ignore_above" : 256,
"fields" : {
"text" : {
"type" : "text"
},
"long" : {
"type" : "long"
}
}
},
"stig_severity" : {
"type" : "keyword",
"ignore_above" : 256,
"fields" : {
"text" : {
"type" : "text"
}
}
},
"synopsis" : {
"type" : "keyword",
"ignore_above" : 256,
"fields" : {
"text" : {
"type" : "text"
}
}
},
"temporal_score" : {
"type" : "keyword",
"ignore_above" : 256,
"fields" : {
"text" : {
"type" : "text"
},
"long" : {
"type" : "long"
}
}
},
"type" : {
"type" : "keyword",
"ignore_above" : 256,
"fields" : {
"text" : {
"type" : "text"
}
}
},
"version" : {
"type" : "keyword",
"ignore_above" : 256,
"fields" : {
"text" : {
"type" : "text"
}
}
},
"vpr" : {
"properties" : {
"score" : {
"type" : "keyword",
"ignore_above" : 256,
"fields" : {
"text" : {
"type" : "text"
},
"long" : {
"type" : "long"
}
}
},
"context": {
"properties": {
"age_of_vuln": {
"type": "keyword",
"ignore_above": 256,
"fields": {
"text": {
"type": "text"
}
}
},
"cvssV3_impactScore": {
"type": "keyword",
"ignore_above": 256,
"fields": {
"text": {
"type": "text"
},
"float" : {
"type" : "float"
}
}
},
"exploit_code_maturity": {
"type": "keyword",
"ignore_above": 256,
"fields": {
"text": {
"type": "text"
}
}
},
"product_coverage": {
"type": "keyword",
"ignore_above": 256,
"fields": {
"text": {
"type": "text"
}
}
},
"threat_intensity_last_28": {
"type": "keyword",
"ignore_above": 256,
"fields": {
"text": {
"type": "text"
}
}
},
"threat_recency": {
"type": "keyword",
"ignore_above": 256,
"fields": {
"text": {
"type": "text"
}
}
},
"threat_sources_last_28": {
"type": "keyword",
"ignore_above": 256,
"fields": {
"text": {
"type": "text"
}
}
}
}
}
}
},
"vuln_pub_date" : {
"type" : "date"
},
"xrefs" : {
"type" : "keyword",
"ignore_above" : 256,
"fields" : {
"text" : {
"type" : "text"
}
}
}
}
}
}
}
}
}
}
}
filebeat.inputs:
- type: httpjson
config_version: 2
interval: 15m
request.url: ${tenable_url}/rest/analysis
request.method: POST
request.ssl:
certificate_authorities:
- "${ca_cert}"
verification_mode: certificate
request.transforms:
- set:
target: header.User-Agent
value: 'Integration/1.0 (Elastic; Tenable.sc Beat; Build/7.17.4)'
- set:
target: header.x-apikey
value: "accesskey=${tenable_access_key}; secretkey=${tenable_secret_key}"
- set:
target: header.Accept
value: "application/json"
- set:
target: body.type
value: 'vuln'
- set:
target: body.query.type
value: 'vuln'
- set:
target: body.query.tool
value: 'vulndetails'
- set:
target: body.query.filters
value: |-
{
"filterName":"lastSeen",
"operator":"=",
"value": '[[.cursor.last_event_ts]]-[[(now).Unix]]'
}
default: |-
{
"filterName":"lastSeen",
"operator":"=",
"value": '[[(now (parseDuration "-24h")).Unix]]-[[(now).Unix]]'
}
- set:
target: body.sortDir
value: 'DESC'
- set:
target: body.sourceType
value: 'cumulative'
- set:
target: body.sortField
value: 'lastSeen'
- set:
target: body.startOffset
value: 0
- set:
target: body.endOffset
value: 1000
response.split:
target: body.response.results
response.pagination:
- set:
target: body.startOffset
value: '[[toInt .last_response.body.response.endOffset]]'
fail_on_template_error: true
- set:
target: body.endOffset
value: '[[add (toInt .last_response.body.response.endOffset) 1000]]'
fail_on_template_error: true
cursor:
last_event_ts:
value: '[[if (ge (toInt .last_response.body.response.endOffset) (toInt
.last_response.body.response.totalRecords))]][[.last_event.lastSeen]][[end]]'
output.logstash:
hosts: ["${logstash_url}"]
input {
beats {
port => 5044
}
}
filter {
mutate {
rename => {
"[message]" => "[event][original]"
}
}
# JSON conversion of the event
json {
source => "[event][original]"
target => "[json]"
skip_on_invalid_json => true
}
# Fingerprint. Sets the indexed document's _id to a SHA-256 hash. Concatenates the
names and values of all fields given in the source option into one string before doing the
fingerprint computation.
fingerprint {
method => "SHA256"
concatenate_sources => true
source => [
"[json][pluginID]",
"[json][ip]",
"[json][uuid]",
"[json][firstSeen]",
"[json][lastSeen]",
"[json][exploitAvailable]",
"[json][vulnPubDate]",
"[json][patchPubDate]",
"[json][pluginPubDate]",
"[json][pluginModDate]",
"[json][pluginText]",
"[json][dnsName]",
"[json][macAddress]",
"[json][operatingSystem]",
"[json][pluginInfo]"
]
target => "[@metadata][_id]"
}
# Copy the @timestamp of the document back to the lastSeen value (when the scan
occurred)
date {
match => ["[json][lastSeen]", "UNIX"]
tag_on_failure => ["_dateparsefailure_timestamp"]
}
# Copy the formatted @timestamp into [tenable_sc][vulnerability][last_seen]
mutate {
copy => {
"[@timestamp]" => "[tenable_sc][vulnerability][last_seen]"
}
}
# Add fields for the event category, type, and kind
mutate {
add_field => {
"[event][category]" => "threat"
"[event][type]" => "info"
"[event][kind]" => "event"
}
}
# Vendor set to Tenable
mutate {
add_field => {
"[vulnerability][scanner][vendor]" => "Tenable"
}
}
# CVSS Version 3. If there's a value in the CVSS version 3 field [cvssV3*] fields, set
the vulnerability.score.version to 3
if [json][cvssV3BaseScore] or [json][cvssV3TemporalScore] {
mutate {
add_field => {
"[vulnerability][score][version]" => "3.0"
"[vulnerability][classification]" => "CVSS"
}
}
# CVSS Version 3. Rename the fields to ECS. The filter ignores if they don't exist.
mutate {
rename => {
"[json][cvssV3BaseScore]" => "[vulnerability][score][base]"
"[json][cvssV3TemporalScore]" => "[vulnerability][score][temporal]"
}
}
}
# Change \n to a space then split into an array on the space
if [json][seeAlso] {
mutate {
gsub => ["[json][seeAlso]", "\n", " "]
tag_on_failure => "_mutate_error_seeAlso"
}
mutate {
split => {
"[json][seeAlso]" => " "
}
tag_on_failure => "_mutate_error_seeAlso"
}
mutate {
rename => {
"[json][seeAlso]" => "[vulnerability][reference]"
}
}
}
# CVE. List of CVEs separated by a comma. If it's not empty, this builds an array of
CVE reference links and sets the appropriate fields
if [json][cve] {
mutate {
add_field => {
"[vulnerability][enumeration]" => "CVE"
}
}
mutate {
split => {
"[json][cve]" => ","
}
}
mutate {
copy => {
"[json][cve]" => "[vulnerability][id]"
}
}
mutate {
copy => {
"[json][cve]" => "[vulnerability][reference]"
}
}
# This builds the vulnerability.reference field by prepending the Mitre URL to the
list of CVEs
# The regex pattern (?<=^) identifies the start of a newline.
mutate {
gsub => ["[vulnerability][reference]", "(?<=^)", "https://cve.mitre.org/cgi-
bin/cvename.cgi?name="]
tag_on_failure => "_mutate_error_gsub_vulnref"
}
}
# Rename fields using ECS
mutate {
rename => {
"[json][description]" => "[vulnerability][description]"
"[json][severity][name]" => "[vulnerability][severity]"
"[json][severity][id]" => "[tenable_sc][vulnerability][id]"
}
}
# Set tenable_sc.vulnerability.id to the values of the fields listed in uniqueness
if [json][uniqueness] {
# Replaces the string "repositoryID" with the string value of the numeric repository
ID
# For example, if {[json][uniqueness] : "repositoryID,IP,dns"} and if
{[json][repository][id] : "5"} then {[json][uniqueness] : "5,IP,dns"}
mutate {
split => {
"[json][uniqueness]" => ","
}
}
ruby {
code => '
a = event.get("[json][uniqueness]")
uniqueKey = ""
a.each { |a|
if a == "repositoryID"
uniqueKey += event.get("[json][repository][id]")
else
uniqueKey += event.get("[json][#{a}]")
end
}
uniqueKey += "_"
event.set("[tenable_sc][vulnerability][id]", uniqueKey)
'
tag_on_exception => "_rubyexception"
}
}
# Fingerprint custom SHA256 hash. Concatenates the names and values of all fields
given in the source option into one string before doing the fingerprint computation.
fingerprint {
method => "SHA256"
concatenate_sources => true
source => [
"[json][pluginID]",
"[json][port]",
"[json][protocol]",
"[tenable_sc][vulnerability][id]"
]
target => "[tenable_sc][vulnerability][custom_hash]"
}
# Rename plugin fields
mutate {
rename => {
"[json][pluginID]" => "[tenable_sc][vulnerability][plugin][id]"
"[json][pluginName]" => "[tenable_sc][vulnerability][plugin][name]"
"[json][pluginText]" => "[tenable_sc][vulnerability][plugin][text]"
}
}
# Rename risk fields
mutate {
rename => {
"[json][severity][description]" =>
"[tenable_sc][vulnerability][severity][description]"
"[json][acceptRisk]" => "[tenable_sc][vulnerability][accept_risk]"
"[json][recastRisk]" => "[tenable_sc][vulnerability][recast_risk]"
}
}
# If hasBeenMitigated is 0, set the field to false; if it is 1 set the field to true
if [json][hasBeenMitigated] == "0" {
mutate {
add_field => {
"[tenable_sc][vulnerability][has_been_mitigated]" => "false"
}
}
}
else if [json][hasBeenMitigated] == "1" {
mutate {
add_field => {
"[tenable_sc][vulnerability][has_been_mitigated]" => "true"
}
}
}
else {
mutate {
add_tag => ["preserve_original_event", "_has_been_mitigated"]
}
}
# Rename vprScore
if [json][vprScore] {
mutate {
rename => {
"[json][vprScore]" => "[tenable_sc][vulnerability][vpr][score]"
}
}
}
# Sets the vprContext "id" field's value to the new field's name
# Sets the vprContext "value" field's value to that the new field's value
if [json][vprContext] {
json {
source => "[json][vprContext]"
target => "[json][vprContext]"
tag_on_failure => ["_jsonparsefailure_vprContext"]
}
ruby {
code => '
a = event.get("[json][vprContext]")
a.each { |a|
event.set("[tenable_sc][vulnerability][vpr][context][#{a["id"]}]", a["value"])
}
'
tag_on_exception => "_rubyexception_vprContext"
}
}
# IP fields
if [json][ip] {
mutate {
add_field => {
"[related][ip]" => "%{[json][ip]}"
"[host][ip]" => "%{[json][ip]}"
}
}
mutate {
rename => {
"[json][ip]" => "[tenable_sc][vulnerability][ip]"
}
}
}
# Port and Proto fields
mutate {
rename => {
"[json][port]" => "[tenable_sc][vulnerability][port]"
"[json][protocol]" => "[tenable_sc][vulnerability][protocol]"
}
}
# Parse the firstSeen date and rename
date {
match => ["[json][firstSeen]", "UNIX"]
target => "[tenable_sc][vulnerability][first_seen]"
}
# If an exploit is available set to true, else if an exploit is not available set to false
if [json][exploitAvailable] == "Yes" {
mutate {
add_field => {
"[tenable_sc][vulnerability][exploit][is_available]" => "true"
}
}
}
else if [json][exploitAvailable] == "No" {
mutate {
add_field => {
"[tenable_sc][vulnerability][exploit][is_available]" => "false"
}
}
}
else {
mutate {
add_tag => ["preserve_original_event", "_exploit_is_available"]
}
}
# Rename fields
mutate {
rename => {
"[json][exploitEase]" => "[tenable_sc][vulnerability][exploit][ease]"
"[json][exploitFrameworks]" =>
"[tenable_sc][vulnerability][exploit][frameworks]"
"[json][solution]" => "[tenable_sc][vulnerability][solution]"
"[json][synopsis]" => "[tenable_sc][vulnerability][synopsis]"
"[json][riskFactor]" => "[tenable_sc][vulnerability][risk_factor]"
"[json][stigSeverity]" => "[tenable_sc][vulnerability][stig_severity]"
"[json][baseScore]" => "[tenable_sc][vulnerability][base_score]"
"[json][temporalScore]" => "[tenable_sc][vulnerability][temporal_score]"
"[json][cvssVector]" => "[tenable_sc][vulnerability][cvss_vector]"
"[json][cvssV3Vector]" => "[tenable_sc][vulnerability][cvss_v3_vector]"
}
}
}
}
date {
match => ["[json][patchPubDate]", "UNIX"]
target => "[tenable_sc][vulnerability][patch][pub_date]"
tag_on_failure => ["_dateparsefailure_patch_pub_date"]
}
}
# If the plugin is not modified set this to false, else set it to true and parse the
modification date into a new field
if [json][pluginModDate] == "-1" {
mutate {
add_field => {
"[tenable_sc][vulnerability][plugin][is_modified]" => "false"
}
}
}
else {
mutate {
add_field => {
"[tenable_sc][vulnerability][plugin][is_modified]" => "true"
}
}
date {
match => ["[json][pluginModDate]", "UNIX"]
target => "[tenable_sc][vulnerability][plugin][mod_date]"
tag_on_failure => ["_dateparsefailure_plugin_mod_date"]
}
}
# If the plugin is not published set this to false, else set it to true and parse the publish
date into a new field
if [json][pluginPubDate] == "-1" {
mutate {
add_field => {
"[tenable_sc][vulnerability][plugin][is_published]" => "false"
}
}
}
else {
mutate {
add_field => {
"[tenable_sc][vulnerability][plugin][is_published]" => "true"
}
}
date {
match => ["[json][pluginPubDate]", "UNIX"]
}
mutate {
rename => {
"[json][dnsName]" => "[tenable_sc][vulnerability][dns][name]"
}
}
} else {
mutate {
add_field => {
"[related][hosts]" => "[json][dnsName]}"
}
}
mutate {
copy => {
"[json][dnsName]" => "[host][hostname]"
}
}
mutate {
rename => {
"[json][dnsName]" => "[tenable_sc][vulnerability][dns][name]"
}
}
}
}
# netbios field
if [json][netbiosName] {
# If it's not in related.hosts, add it
if [json][netbiosName] not in [related][hosts] {
mutate {
add_field => {
"[related][hosts]" => "%{[json][netbiosName]}"
}
}
}
mutate {
rename => {
"[json][netbiosName]" => "[tenable_sc][vulnerability][netbios][name]"
}
}
}
# MAC address
if [json][macAddress] {
# substitute the regex set "[-:.]" with "-"
mutate {
gsub => ["[json][macAddress]", "[-:.]", "-"]
tag_on_failure => "_mutate_error_gsub_mac_address"
}
mutate {
uppercase => ["[json][macAddress]"]
}
mutate {
add_field => {
"[host][mac]" => "%{[json][macAddress]}"
}
}
mutate {
rename => {
"[json][macAddress]" => "[tenable_sc][vulnerability][mac]"
}
}
}
mutate {
add_field => {
"[host][os][full]" => "%{[json][operatingSystem]}"
}
}
mutate {
rename => {
"[json][operatingSystem]" => "[tenable_sc][vulnerability][operating_system]"
}
}
mutate {
rename => {
"[json][uniqueness]" => "[tenable_sc][vulnerability][uniqueness]"
}
}
mutate {
rename => {
"[json][hostUniqueness]" => "[tenable_sc][vulnerability][host_uniqueness]"
}
}
mutate {
rename => {
"[json][family][id]" => "[tenable_sc][vulnerability][family][id]"
}
}
if [json][family][name] {
mutate {
add_field => {
"[vulnerability][category]" => "%{[json][family][name]}"
}
}
mutate {
rename => {
"[json][family][name]" => "[tenable_sc][vulnerability][family][name]"
}
}
}
mutate {
rename => {
"[json][family][type]" => "[tenable_sc][vulnerability][family][type]"
}
}
# Rename fields
mutate {
rename => {
"[json][repository][id]" => "[tenable_sc][vulnerability][repository][id]"
"[json][repository][name]" => "[tenable_sc][vulnerability][repository][name]"
"[json][repository][description]" =>
"[tenable_sc][vulnerability][repository][description]"
"[json][repository][sciID]" => "[tenable_sc][vulnerability][repository][sci_id]"
"[json][repository][dataFormat]" =>
"[tenable_sc][vulnerability][repository][data_format]"
}
}
# Remove the left over JSON conversion of the event
mutate {
remove_field => ["[json]"]
}
if "preserve_original_event" not in [tags] {
mutate {
remove_field => ["[event][original]"]
}
}
}
output {
elasticsearch {
hosts => ["${es_url}"]
index => "vuln"
document_id => "%{[@metadata][_id]}"
user => "${logstash_es_user}"
password => "${logstash_es_user_pw}"
cacert => "${cacert_path}"
#truststore => "${truststore_path}"
#truststore_password => "${truststore_pw}"
}
}
"text": {
"type": "text"
}
}
},
"os": {
"properties": {
"full": {
"type": "keyword",
"fields": {
"text": {
"type": "text"
}
}
}
}
}
}
},
"related": {
"properties": {
"hosts": {
"type": "keyword",
"fields": {
"text": {
"type": "text"
}
}
},
"ip" : {
"type" : "keyword",
"fields" : {
"text" : {
"type" : "ip"
}
}
}
}
},
"tenable_sc": {
"properties": {
"vulnerability": {
"properties": {
"accept_risk": {
"type": "keyword"
},
"base_score": {
"type": "keyword"
},
"bid": {
"type": "keyword"
},
"check_type": {
"type": "keyword"
},
"cpe": {
"type": "keyword"
},
"custom_hash": {
"type": "keyword"
},
"cvss_v3_vector": {
"type": "keyword"
},
"cvss_vector": {
"type": "keyword"
},
"dns": {
"properties": {
"name": {
"type": "keyword"
}
}
},
"exploit": {
"properties": {
"ease": {
"type": "keyword"
},
"frameworks": {
"type": "keyword"
},
"is_available": {
"type": "boolean"
}
}
},
"family": {
"properties": {
"id": {
"type": "keyword"
},
"name": {
"type": "keyword"
},
"type": {
"type": "keyword"
}
}
},
"first_seen": {
"type": "date"
},
"has_been_mitigated": {
"type": "boolean"
},
"host_uniqueness": {
"type": "keyword"
},
"id": {
"type": "keyword"
},
"ip" : {
"type" : "keyword",
"fields" : {
"text" : {
"type" : "ip"
}
}
},
"is_vulnerability_published": {
"type": "boolean"
},
"last_seen": {
"type": "date"
},
"mac": {
"type": "keyword"
},
"netbios": {
"properties": {
"name": {
"type": "keyword"
}
}
},
"operating_system": {
"type": "keyword"
},
"patch": {
"properties": {
"is_published": {
"type": "boolean"
},
"pub_date": {
"type": "date"
}
}
},
"plugin": {
"properties": {
"id": {
"type": "keyword"
},
"is_published": {
"type": "boolean"
},
"is_modified": {
"type": "boolean"
},
"mod_date": {
"type": "date"
},
"name": {
"type": "keyword"
},
"pub_date": {
"type": "date"
},
"text": {
"type": "text"
}
}
},
"port": {
"type": "keyword",
"fields": {
"integer": {
"type": "integer"
}
}
},
"protocol": {
"type": "keyword"
},
"recast_risk": {
"type": "keyword"
},
"repository": {
"properties": {
"data_format": {
"type": "keyword"
},
"description": {
"type": "keyword",
"ignore_above": 256,
"fields": {
"text": {
"type": "text"
}
}
},
"id": {
"type": "keyword"
},
"name": {
"type": "keyword"
},
"sci_id": {
"type": "keyword"
}
}
},
"risk_factor": {
"type": "keyword"
},
"severity": {
"properties": {
"description": {
"type": "keyword"
},
"id": {
"type": "keyword"
}
}
},
"solution": {
"type": "text"
},
"stig_severity": {
"type": "keyword"
},
"synopsis": {
"type": "keyword",
"ignore_above": 256,
"fields": {
"text": {
"type": "text"
}
}
},
"temporal_score": {
"type": "keyword"
},
"uniqueness": {
"type": "keyword"
},
"uuid": {
"type": "keyword"
},
"version": {
"type": "keyword"
},
"vpr": {
"properties": {
"context": {
"properties": {
"age_of_vuln": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
},
"cvssV3_impactScore": {
"type": "float"
},
"exploit_code_maturity": {
"type": "keyword"
},
"product_coverage": {
"type": "keyword"
},
"threat_intensity_last_28": {
"type": "keyword"
},
"threat_recency": {
"type": "keyword"
},
"threat_sources_last_28": {
"type": "keyword"
}
}
},
"score": {
"type": "float"
}
}
},
"vuln_pub_date": {
"type": "date"
},
"xref": {
"type": "keyword",
"ignore_above": 256,
"fields": {
"text": {
"type": "text"
}
}
}
}
}
}
},
"vulnerability": {
"properties": {
"category": {
"type": "keyword"
},
"classification": {
"type": "keyword"
},
"description": {
"type": "text"
},
"enumeration": {
"type": "keyword"
},
"id": {
"type": "keyword",
"ignore_above": 256
},
"reference": {
"type": "keyword",
"ignore_above": 256,
"fields": {
"text": {
"type": "text"
}
}
},
"scanner": {
"properties": {
"vendor": {
"type": "keyword"
}
}
},
"score": {
"properties": {
"base": {
"type": "float"
},
"temporal": {
"type": "float"
},
"version": {
"type": "keyword"
}
}
},
"severity": {
"type": "keyword"
}
}
}
}
}
}
input {
exec {
command => "sh -c /home/student/get-hwam.sh"
interval => 900
ecs_compatibility => "v8"
}
}
filter {
mutate {
rename => {
"[message]" => "[event][original]"
}
}
json {
source => "[event][original]"
target => "[json]"
tag_on_failure => ["preserve_original_event"]
}
if "preserve_original_event" not in [tags] {
mutate {
remove_field => ["[event][original]"]
}
}
mutate {
remove_field => ["[process]", "[host]"]
}
split {
field => "[json][results]"
}
date {
match => ["[json][results][properties][R-Last Report Time][result]", "E, d MMM yyyy
HH:mm:ss Z",
"E, dd MMM yyyy HH:mm:ss Z"]
}
mutate {
add_field => {
"[agent][type]" => "bes client"
}
}
mutate {
add_field => {
"[event][category]" => "host"
"[event][type]" => "info"
"[event][kind]" => "state"
"[ecs][version]" => "8.2"
"[event][provider]" => "BigFix"
}
}
mutate {
rename => {
"[json][results][computerHref]" => "[event][url]"
"[json][results][properties][R-Computer Name][result]" => "[host][name]"
"[json][results][properties][R-ID][result]" => "[host][id]"
"[json][results][properties][R-OS][result]" => "[host][os][full]"
"[json][results][properties][O-3093-35-18][result]" => "[host][cpu][cores]"
"[json][results][properties][O-3093-305-16][result]" => "[host][cpu][cores]"
"[json][results][properties][O-3093-35-6][result]" => "[host][cpu][processors]"
"[json][results][properties][O-3093-305-4][result]" => "[host][cpu][processors]"
"[json][results][properties][R-MAC Address][result]" => "[host][mac]"
"[json][results][properties][R-CPU][result]" => "[host][cpu][name]"
"[json][results][properties][O-13014-19-2][result]" => "[agent][scanner][version]"
"[json][results][properties][O-1-205-3][result]" => "[agent][relay][name]"
"[json][results][properties][D/Subnet%20Address/TjwTe57B3z9HXSvUiuNLLO8eV%2
bg][result]" => "[host][subnet]"
"[json][results][properties][O-3093-305-11][result]" => "[host][network][adapters]"
"[json][results][properties][O-3093-35-11][result]" => "[host][network][adapters]"
"[json][results][properties][O-3093-35-8][result]" => "[host][drive][count]"
"[json][results][properties][O-9307-34-2][result]" => "[host][model]"
"[json][results][properties][O-3093-33-3][result]" => "[host][model]"
"[json][results][properties][O-1-204-1][result]" => "[agent][version]"
"[json][results][properties][O-3093-33-1][result]" => "[host][dhcp_server]"
"[json][results][properties][O-3093-35-2][result]" => "[host][model]"
"[json][results][properties][O-3093-305-5][result]" => "[host][drive][names]"
"[json][results][properties][O-3093-35-9][result]" => "[host][drive][names]"
"[json][results][properties][O-3093-35-4][result]" => "[host][is_laptop]"
"[json][results][properties][O-3093-305-2][result]" => "[host][is_laptop]"
"[json][results][properties][O-3093-35-1][result]" => "[host][manufacturer]"
if [json][results][properties][R-DNS Name][result] {
# Dissect the DNS Name into two new fields if it contains a dot
if [json][results][properties][R-DNS Name][result] =~ /\./ {
dissect {
mapping => {
"[json][results][properties][R-DNS Name][result]" =>
"%{[host][name]}.%{[host][domain][name]}"
}
tag_on_failure => ["_dissectfailure_DNS"]
}
mutate {
add_field => {
"[related][hosts]" => "%{[host][name]}"
}
}
mutate {
rename => {
"[json][results][properties][R-DNS Name][result]" => "[host][hostname]"
}
}
}
}
else {
mutate {
add_field => {
"[related][hosts]" => "%{[json][results][properties][R-DNS Name][result]}"
}
}
mutate {
rename => {
"[json][results][properties][R-DNS Name][result]" => "[host][name]"
}
}
}
if [json][results][properties][R-IP Address][result] {
mutate {
rename => {
"[json][results][properties][R-IP Address][result]" => "[host][ip]"
}
}
mutate {
add_field => {
"[related][ip]" => "%{[host][ip]}"
}
}
}
if [json][results][properties][R-IPv6 Address][result] {
mutate {
rename => {
"[json][results][properties][R-IPv6 Address][result]" => "[host][ipv6]"
}
}
mutate {
add_field => {
"[related][ip]" => "%{[host][ipv6]}"
}
}
}
mutate {
copy => {
"[host][os][full]" => "[os][full]"
}
}
mutate {
lowercase => ["[host][is_laptop]"]
}
if
[json][results][properties][D/Total%20Size%20of%20System%20Drive/tmutWa7NR%2
bcxoW%2bcZJir9U7itaU][result] =~ /^[0-9]* MB$/ {
dissect {
mapping => {
"[json][results][properties][D/Total%20Size%20of%20System%20Drive/tmutWa7NR%2
bcxoW%2bcZJir9U7itaU][result]" => "%{[host][drive][system][size_megabytes]}
%{?MB}"
}
}
}
else {
mutate {
rename => {
"[json][results][properties][D/Total%20Size%20of%20System%20Drive/tmutWa7NR%2
bcxoW%2bcZJir9U7itaU][result]" => "[host][drive][system][size]"
}
}
}
if
[json][results][properties][D/Free%20Space%20on%20System%20Drive/8cqlsJBnBvC8
%2f%2f9KBo23Mzq6jts][result] =~ /^[0-9]* MB$/ {
dissect {
mapping => {
"[json][results][properties][D/Free%20Space%20on%20System%20Drive/8cqlsJBnBvC
8%2f%2f9KBo23Mzq6jts][result]" =>
"%{[host][drive][system][free_space_megabytes]} %{?MB}"
}
}
}
else {
mutate {
rename => {
"[json][results][properties][D/Free%20Space%20on%20System%20Drive/8cqlsJBnBvC
8%2f%2f9KBo23Mzq6jts][result]" => "[host][drive][system][free_space]"
}
}
}
if [json][results][properties][D/RAM/2pGqHiqzzkoNb6Lqh0XDPFnISwg][result] =~
/^[0-9]* MB$/ {
dissect {
mapping => {
"[json][results][properties][D/RAM/2pGqHiqzzkoNb6Lqh0XDPFnISwg][result]"
=> "%{[host][ram][total_megabytes]} %{?MB}"
}
}
}
else {
mutate {
rename => {
"[json][results][properties][D/RAM/2pGqHiqzzkoNb6Lqh0XDPFnISwg][result]"
=> "[host][ram][total]"
}
}
}
mutate {
remove_field => ["[json]"]
}
}
output {
elasticsearch {
hosts => ["${es_url}"]
index => "bigfix-hwam"
#document_id => "%{[host][id]}"
user => "${logstash_es_user}"
password => "${logstash_es_user_pw}"
cacert => "${cacert_path}"
}
}
"type": "keyword",
"ignore_above": 256,
"fields": {
"text": {
"type": "text"
}
}
},
"version": {
"type": "keyword",
"ignore_above": 256,
"fields": {
"text": {
"type": "text"
},
"version": {
"type": "version"
}
}
}
}
},
"ecs": {
"properties": {
"version": {
"type": "keyword",
"ignore_above": 256,
"fields": {
"text": {
"type": "text"
}
}
}
}
},
"event": {
"properties": {
"category": {
"type": "keyword"
},
"kind": {
"type": "keyword"
},
"provider": {
"type": "keyword"
},
"type": {
"type": "keyword"
},
"url": {
"type": "keyword"
}
}
},
"host": {
"properties": {
"cpu": {
"properties": {
"brand": {
"type": "keyword",
"ignore_above": 256,
"fields": {
"text": {
"type": "text"
}
}
},
"cores": {
"type": "keyword",
"ignore_above": 256,
"fields": {
"text": {
"type": "text"
},
"integer": {
"type": "integer"
}
}
},
"name": {
"type": "keyword",
"ignore_above": 256,
"fields": {
"text": {
"type": "text"
}
}
},
"processors": {
"type": "keyword",
"ignore_above": 256,
"fields": {
"text": {
"type": "text"
},
"integer": {
"type": "integer"
}
}
}
}
},
"dhcp_server": {
"type": "keyword",
"ignore_above": 256,
"fields": {
"text": {
"type": "text"
},
"ip": {
"type": "ip"
}
}
},
"dns": {
"properties": {
"servers": {
"type": "keyword",
"ignore_above": 256,
"fields": {
"text": {
"type": "text"
},
"ip": {
"type": "ip"
}
}
}
}
},
"domain": {
"properties": {
"name": {
"type": "keyword",
"ignore_above": 256,
"fields": {
"text": {
"type": "text"
}
}
}
}
},
"drive": {
"properties": {
"count": {
"type": "keyword",
"ignore_above": 256,
"fields": {
"text": {
"type": "text"
}
}
},
"names": {
"type": "keyword",
"ignore_above": 256,
"fields": {
"text": {
"type": "text"
}
}
},
"system": {
"properties": {
"free_space": {
"type": "keyword",
"ignore_above": 256,
"fields": {
"text": {
"type": "text"
}
}
},
"free_space_megabytes": {
"type": "keyword",
"ignore_above": 256,
"fields": {
"long": {
"type": "long"
}
}
},
"size": {
"type": "keyword",
"ignore_above": 256,
"fields": {
"text": {
"type": "text"
}
}
},
"size_megabytes": {
"type": "keyword",
"ignore_above": 256,
"fields": {
"long": {
"type": "long"
}
}
}
}
}
}
},
"hostname": {
"type": "keyword",
"ignore_above": 256,
"fields": {
"text": {
"type": "text"
}
}
},
"id": {
"type": "keyword",
"ignore_above": 256,
"fields": {
"text": {
"type": "text"
}
}
},
"ip": {
"type": "keyword",
"ignore_above": 256,
"fields": {
"text": {
"type": "text"
},
"ip": {
"type": "ip"
}
}
},
"ipv6": {
"type": "keyword",
"ignore_above": 256,
"fields": {
"text": {
"type": "text"
},
"ip": {
"type": "ip"
}
}
},
"is_laptop": {
"type": "boolean"
},
"mac": {
"type": "keyword",
"ignore_above": 256,
"fields": {
"text": {
"type": "text"
}
}
},
"make": {
"type": "keyword",
"ignore_above": 256,
"fields": {
"text": {
"type": "text"
}
}
},
"manufacturer": {
"type": "keyword",
"ignore_above": 256,
"fields": {
"text": {
"type": "text"
}
}
},
"model": {
"type": "keyword",
"ignore_above": 256,
"fields": {
"text": {
"type": "text"
}
}
},
"name": {
"type": "keyword",
"ignore_above": 256,
"fields": {
"text": {
"type": "text"
}
}
},
"network": {
"properties": {
"adapters": {
"type": "keyword",
"ignore_above": 256,
"fields": {
"text": {
"type": "text"
}
}
}
}
},
"os": {
"properties": {
"full": {
"type": "keyword",
"ignore_above": 256,
"fields": {
"text": {
"type": "text"
}
}
}
}
},
"ram": {
"properties": {
"total": {
"type": "keyword",
"ignore_above": 256,
"fields": {
"text": {
"type": "text"
}
}
},
"total_megabytes": {
"type": "keyword",
"ignore_above": 256,
"fields": {
"long": {
"type": "long"
}
}
}
}
},
"subnet": {
"type": "keyword",
"ignore_above": 256,
"fields": {
"text": {
"type": "text"
},
"ip": {
"type": "ip"
}
}
},
"type": {
"type": "keyword",
"ignore_above": 256,
"fields": {
"text": {
"type": "text"
}
}
}
}
},
"os": {
"properties": {
"full": {
"type": "keyword",
"ignore_above": 256,
"fields": {
"text": {
"type": "text"
}
}
}
}
},
"process": {
"type": "object"
},
"related": {
"properties": {
"hosts": {
"type": "keyword",
"ignore_above": 256,
"fields": {
"text": {
"type": "text"
}
}
},
"ip": {
"type": "keyword",
"ignore_above": 256,
"fields": {
"text": {
"type": "text"
}
}
}
}
}
}
}
}
}
input {
exec {
command => "sh -c /home/student/get-csm-win2019.sh"
interval => 900
ecs_compatibility => "v8"
}
}
filter {
mutate {
rename => {
"[message]" => "[event][original]"
}
}
json {
source => "[event][original]"
target => "[json]"
tag_on_failure => ["preserve_original_event"]
}
if "preserve_original_event" not in [tags] {
mutate {
remove_field => ["[event][original]"]
}
}
mutate {
remove_field => ["[json][columns]", "[process]", "[host]"]
}
mutate {
add_field => {
"[event][category]" => "host"
"[event][type]" => "info"
"[event][kind]" => "state"
"[ecs][version]" => "8.2"
"[event][provider]" => "BigFix"
}
}
split {
field => "[json][results]"
}
mutate {
rename => {
"[json][results][fixletHref]" => "[bigfix][csm][fixlet][reference]"
}
}
mutate {
copy => {
"[bigfix][csm][fixlet][reference]" => "[event][url]"
}
}
mutate {
rename => {
"[json][results][computerHref]" => "[bigfix][csm][computer][reference]"
}
}
mutate {
rename => {
"[json][results][dbid]" => "[bigfix][csm][dbid]"
}
}
if [json][results][properties][Relevance][result] == "Applicable" {
mutate {
add_field => {
"[bigfix][csm][is_applicable]" => "true"
}
}
}
else {
mutate {
add_field => {
"[bigfix][csm][is_applicable]" => "false"
}
}
}
# 11/5/2019, 5/18/2021, Month (no leading zero)/day (no leading zero)/YEAR
date {
match => ["[json][results][properties][Source Release Date][result]", "M/d/YYYY"]
target => "[bigfix][csm][source][release_date]"
}
mutate {
rename => {
"[json][results][properties][Source][result]" => "[bigfix][csm][source][name]"
}
}
mutate {
rename => {
"[json][results][properties][Source Severity][result]" =>
"[bigfix][csm][source][severity]"
}
}
mutate {
rename => {
"[json][results][properties][Source ID][result]" => "[bigfix][csm][source][id]"
}
}
if [json][results][properties][Computer][result] {
mutate {
rename => {
"[json][results][properties][Computer][result]" => "[bigfix][csm][computer][name]"
}
}
mutate {
copy => {
"[bigfix][csm][computer][name]" => "[host][name]"
}
}
}
mutate {
rename => {
"[json][results][properties][Type][result]" => "[bigfix][csm][type]"
}
}
mutate {
rename => {
"[json][results][properties][Applicable Computer Count][result]" =>
"[bigfix][csm][applicable_computer_count]"
}
}
mutate {
rename => {
"[json][results][properties][Remediated Computer Count][result]" =>
"[bigfix][csm][remediated_computer_count]"
}
}
mutate {
rename => {
mutate {
rename => {
"[json][results][properties][Progress][result]" => "[bigfix][csm][progress]"
}
}
if [json][results][properties][Visibility][result] == "Visible" {
mutate {
add_field => {
"[bigfix][csm][is_visible]" => "true"
}
}
}
else {
mutate {
add_field => {
"[bigfix][csm][is_visible]" => "false"
}
}
}
mutate {
rename => {
"[json][results][properties][Comments][result]" => "[bigfix][csm][comments]"
}
}
# TODO confirm date format matches, missing from lab sample
date {
match => ["[json][results][properties][Activation Time (Analysis)][result]",
"M/d/YYYY", "ISO8601"]
target => "[bigfix][csm][analysis][activated_time]"
tag_on_failure => ["_dateparsefailure_activated_time"]
}
mutate {
rename => {
"[json][results][properties][Activated By (Analysis)][result]" =>
"[bigfix][csm][analysis][activated_by]"
}
}
mutate {
rename => {
"[json][results][properties][Mean Time to Remediate][result]" =>
"[bigfix][csm][mean_time_to_remediate]"
}
}
mutate {
rename => {
"[json][results][properties][Unlocked Computer Count][result]" =>
"[bigfix][csm][unlocked_computer_count]"
}
}
mutate {
remove_field => ["[json]"]
}
}
output {
elasticsearch {
hosts => ["${es_url}"]
index => "bigfix-csm"
#document_id => "%{[host][id]}"
user => "${logstash_es_user}"
password => "${logstash_es_user_pw}"
cacert => "${cacert_path}"
}
}
"ignore_above" : 256,
"fields" : {
"text" : {
"type" : "text"
}
}
}
}
},
"dbid" : {
"type" : "keyword"
},
"download_size" : {
"type" : "keyword",
"ignore_above" : 256,
"fields" : {
"text" : {
"type" : "text"
}
}
},
"fixlet" : {
"properties" : {
"reference" : {
"type" : "keyword",
"ignore_above" : 256,
"fields" : {
"text" : {
"type" : "text"
}
}
}
}
},
"id" : {
"type" : "keyword"
},
"is_applicable" : {
"type" : "boolean"
},
"is_visible" : {
"type" : "boolean"
},
"mean_time_to_remediate" : {
"type" : "keyword",
"ignore_above" : 256
},
"name" : {
"type" : "keyword",
"ignore_above" : 256,
"fields" : {
"text" : {
"type" : "text"
}
}
},
"open_action_count" : {
"type" : "long"
},
"progress" : {
"type" : "keyword",
"ignore_above" : 256
},
"remediated_computer_count" : {
"type" : "long"
},
"sitename" : {
"type" : "keyword",
"ignore_above" : 256,
"fields" : {
"text" : {
"type" : "text"
}
}
},
"source" : {
"properties" : {
"id" : {
"type" : "keyword",
"ignore_above" : 256,
"fields" : {
"text" : {
"type" : "text"
}
}
},
"name" : {
"type" : "keyword",
"ignore_above" : 256,
"fields" : {
"text" : {
"type" : "text"
}
}
},
"release_date" : {
"type" : "date"
},
"severity" : {
"type" : "keyword",
"ignore_above" : 256,
"fields" : {
"text" : {
"type" : "text"
}
}
}
}
},
"type" : {
"type" : "keyword",
"ignore_above" : 256,
"fields" : {
"text" : {
"type" : "text"
}
}
},
"unlocked_computer_count" : {
"type" : "long"
}
}
}
}
},
"ecs" : {
"properties" : {
"version" : {
"type" : "keyword",
"ignore_above" : 256
}
}
},
"event" : {
"properties" : {
"category" : {
"type" : "keyword"
},
"kind" : {
"type" : "keyword"
},
"provider" : {
"type" : "keyword"
},
"type" : {
"type" : "keyword"
},
"url" : {
"type" : "keyword"
}
}
},
"json" : {
"properties" : {
"dir" : {
"type" : "keyword",
"ignore_above" : 256,
"fields" : {
"text" : {
"type" : "text"
}
}
},
"pageSize" : {
"type" : "long"
},
"recordsReturned" : {
"type" : "long"
},
"results" : {
"properties" : {
"properties" : {
"properties" : {
"Activated By (Analysis)" : {
"properties" : {
"name" : {
"type" : "keyword",
"ignore_above" : 256,
"fields" : {
"text" : {
"type" : "text"
}
}
},
"plural" : {
"type" : "boolean"
}
}
},
"Activation Time (Analysis)" : {
"properties" : {
"name" : {
"type" : "keyword",
"ignore_above" : 256,
"fields" : {
"text" : {
"type" : "text"
}
}
},
"plural" : {
"type" : "boolean"
}
}
},
"Applicable Computer Count" : {
"properties" : {
"name" : {
"type" : "keyword",
"ignore_above" : 256,
"fields" : {
"text" : {
"type" : "text"
}
}
},
"plural" : {
"type" : "boolean"
}
}
},
"CVE" : {
"properties" : {
"name" : {
"type" : "keyword",
"ignore_above" : 256,
"fields" : {
"text" : {
"type" : "text"
}
}
},
"plural" : {
"type" : "boolean"
}
}
},
"Category" : {
"properties" : {
"name" : {
"type" : "keyword",
"ignore_above" : 256,
"fields" : {
"text" : {
"type" : "text"
}
}
},
"plural" : {
"type" : "boolean"
}
}
},
"Comments" : {
"properties" : {
"name" : {
"type" : "keyword",
"ignore_above" : 256,
"fields" : {
"text" : {
"type" : "text"
}
}
},
"plural" : {
"type" : "boolean"
}
}
},
"Deployed Action Count" : {
"properties" : {
"name" : {
"type" : "keyword",
"ignore_above" : 256,
"fields" : {
"text" : {
"type" : "text"
}
}
},
"plural" : {
"type" : "boolean"
},
"result" : {
"type" : "keyword",
"ignore_above" : 256,
"fields" : {
"text" : {
"type" : "text"
}
}
}
}
},
"Download Size" : {
"properties" : {
"name" : {
"type" : "keyword",
"ignore_above" : 256,
"fields" : {
"text" : {
"type" : "text"
}
}
},
"plural" : {
"type" : "boolean"
}
}
},
"ID" : {
"properties" : {
"name" : {
"type" : "keyword",
"ignore_above" : 256,
"fields" : {
"text" : {
"type" : "text"
}
}
},
"plural" : {
"type" : "boolean"
}
}
},
"Mean Time to Remediate" : {
"properties" : {
"name" : {
"type" : "keyword",
"ignore_above" : 256,
"fields" : {
"text" : {
"type" : "text"
}
}
},
"plural" : {
"type" : "boolean"
}
}
},
"Name" : {
"properties" : {
"name" : {
"type" : "keyword",
"ignore_above" : 256,
"fields" : {
"text" : {
"type" : "text"
}
}
},
"plural" : {
"type" : "boolean"
}
}
},
"Open Action Count" : {
"properties" : {
"name" : {
"type" : "keyword",
"ignore_above" : 256,
"fields" : {
"text" : {
"type" : "text"
}
}
},
"plural" : {
"type" : "boolean"
}
}
},
"Progress" : {
"properties" : {
"name" : {
"type" : "keyword",
"ignore_above" : 256,
"fields" : {
"text" : {
"type" : "text"
}
}
},
"plural" : {
"type" : "boolean"
}
}
},
"Remediated Computer Count" : {
"properties" : {
"name" : {
"type" : "keyword",
"ignore_above" : 256,
"fields" : {
"text" : {
"type" : "text"
}
}
},
"plural" : {
"type" : "boolean"
}
}
},
"SANS" : {
"properties" : {
"name" : {
"type" : "keyword",
"ignore_above" : 256,
"fields" : {
"text" : {
"type" : "text"
}
}
},
"plural" : {
"type" : "boolean"
}
}
},
"Sitename" : {
"properties" : {
"name" : {
"type" : "keyword",
"ignore_above" : 256,
"fields" : {
"text" : {
"type" : "text"
}
}
},
"plural" : {
"type" : "boolean"
}
}
},
"Source" : {
"properties" : {
"name" : {
"type" : "keyword",
"ignore_above" : 256,
"fields" : {
"text" : {
"type" : "text"
}
}
},
"plural" : {
"type" : "boolean"
}
}
},
"Source ID" : {
"properties" : {
"name" : {
"type" : "keyword",
"ignore_above" : 256,
"fields" : {
"text" : {
"type" : "text"
}
}
},
"plural" : {
"type" : "boolean"
}
}
},
"Source Release Date" : {
"properties" : {
"name" : {
"type" : "keyword",
"ignore_above" : 256,
"fields" : {
"text" : {
"type" : "text"
}
}
},
"plural" : {
"type" : "boolean"
},
"result" : {
"type" : "keyword",
"ignore_above" : 256,
"fields" : {
"text" : {
"type" : "text"
}
}
}
}
},
"Source Severity" : {
"properties" : {
"name" : {
"type" : "keyword",
"ignore_above" : 256,
"fields" : {
"text" : {
"type" : "text"
}
}
},
"plural" : {
"type" : "boolean"
}
}
},
"Type" : {
"properties" : {
"name" : {
"type" : "keyword",
"ignore_above" : 256,
"fields" : {
"text" : {
"type" : "text"
}
}
},
"plural" : {
"type" : "boolean"
}
}
},
"Unlocked Computer Count" : {
"properties" : {
"name" : {
"type" : "keyword",
"ignore_above" : 256,
"fields" : {
"text" : {
"type" : "text"
}
}
},
"plural" : {
"type" : "boolean"
}
}
},
"Visibility" : {
"properties" : {
"name" : {
"type" : "keyword",
"ignore_above" : 256,
"fields" : {
"text" : {
"type" : "text"
}
}
},
"plural" : {
"type" : "boolean"
},
"result" : {
"type" : "keyword",
"ignore_above" : 256,
"fields" : {
"text" : {
"type" : "text"
}
}
}
}
}
}
}
}
},
"sort" : {
"type" : "keyword",
"ignore_above" : 256,
"fields" : {
"text" : {
"type" : "text"
}
}
},
"startIndex" : {
"type" : "long"
},
"totalRecords" : {
"type" : "long"
},
"totalRecordsUnknown" : {
"type" : "boolean"
}
}
},
"tags" : {
"type" : "keyword",
"ignore_above" : 256,
"fields" : {
"text" : {
"type" : "text"
}
}
}
}
}
}
}
}
input {
exec {
command => "sh -c /home/student/get-swam.sh"
interval => 3600
ecs_compatibility => "v8"
}
}
filter {
mutate {
rename => {
"[message]" => "[event][original]"
}
}
json {
source => "[event][original]"
target => "[json]"
tag_on_failure => ["preserve_original_event"]
}
if "preserve_original_event" not in [tags] {
mutate {
remove_field => ["[event][original]"]
}
}
mutate {
remove_field => ["[process]", "[host]"]
}
mutate {
add_field => {
"[event][category]" => "host"
}
}
mutate {
rename => {
"[json][rows][path][path]" => "[bigfix][inventory][component][path]"
}
}
mutate {
rename => {
"[json][rows][component_id]" => "[bigfix][inventory][component][id]"
}
}
mutate {
rename => {
"[json][rows][max_cve][name]" => "[bigfix][inventory][component][max_cve]"
}
}
mutate {
rename => {
"[json][rows][catalog_dimension][created_at]" =>
"[bigfix][inventory][component][creation]"
}
}
mutate {
rename => {
"[json][rows][catalog_dimension][edited_at]" =>
"[bigfix][inventory][component][modification]"
}
}
mutate {
rename => {
"[json][rows][catalog_dimension][publisher_id]" =>
"[bigfix][inventory][component][publisher_id]"
}
}
mutate {
remove_field => ["[json]"]
}
}
output {
stdout {
codec => rubydebug
}
elasticsearch {
hosts => ["${es_url}"]
"version": {
"type": "version"
}
}
},
"id": {
"type": "keyword",
"ignore_above": 256,
"fields": {
"text": {
"type": "text"
}
}
},
"max_cve": {
"type": "keyword",
"ignore_above": 256,
"fields": {
"text": {
"type": "text"
}
}
},
"modification": {
"type": "date"
},
"name": {
"type": "keyword",
"ignore_above": 256,
"fields": {
"text": {
"type": "text"
}
}
},
"path": {
"type": "keyword",
"ignore_above": 256,
"fields": {
"text": {
"type": "text"
}
}
},
"publisher_id": {
"type": "keyword",
"ignore_above": 256,
"fields": {
"text": {
"type": "text"
}
}
},
"version": {
"type": "keyword",
"ignore_above": 256,
"fields": {
"text": {
"type": "text"
},
"version": {
"type": "version"
}
}
}
}
},
"computer": {
"properties": {
"id": {
"type": "keyword",
"ignore_above": 256,
"fields": {
"text": {
"type": "text"
}
}
},
"is_current": {
"type": "boolean"
},
"last_scan_attempt": {
"type": "date"
},
"last_seen": {
"type": "date"
},
"name": {
"type": "keyword",
"ignore_above": 256,
"fields": {
"text": {
"type": "text"
}
}
},
"remote_id": {
"type": "keyword",
"ignore_above": 256,
"fields": {
"text": {
"type": "text"
}
}
},
"valid_to": {
"type": "date"
}
}
},
"publisher": {
"properties": {
"name": {
"type": "keyword",
"ignore_above": 256,
"fields": {
"text": {
"type": "text"
}
}
}
}
}
}
}
}
},
"event": {
"properties": {
"category": {
"type": "keyword"
},
"kind": {
"type": "keyword"
},
"provider": {
"type": "keyword"
},
"type": {
"type": "keyword"
},
"url": {
"type": "keyword"
}
}
},
"host": {
"properties": {
"id": {
"type": "keyword",
"ignore_above": 256,
"fields": {
"text": {
"type": "text"
}
}
},
"name": {
"type": "keyword",
"ignore_above": 256,
"fields": {
"text": {
"type": "text"
}
}
}
}
},
"process": {
"properties": {
"command_line": {
"type": "keyword",
"ignore_above": 256,
"fields": {
"text": {
"type": "text"
}
}
}
}
}
}
}
}
}
2%22%3A27%2C%22O-3093-35-5%22%3A28%2C%22O-3093-305-
3%22%3A29%2C%22O-3093-305-
5%22%3A30%2C%22D%2FFree%2520Space%2520on%2520System%2520Drive%2F8
cqlsJBnBvC8%252f%252f9KBo23Mzq6jts%22%3A31%2C%22D%2FTotal%2520Size
%2520of%2520System%2520Drive%2FtmutWa7NR%252bcxoW%252bcZJir9U7itaU%
22%3A32%2C%22O-3093-35-9%22%3A33%2C%22R-
Computer%20Type%22%3A34%2C%22O-3093-35-2%22%3A35%2C%22O-3093-35-
1%22%3A36%2C%22O-3093-33-3%22%3A37%2C%22O-3093-35-
8%22%3A38%2C%22R-CPU%22%3A39%2C%22O-3093-35-6%22%3A40%2C%22O-
3093-305-4%22%3A41%2C%22O-3093-35-18%22%3A42%2C%22O-3093-305-
16%22%3A43%2C%22R-OS%22%3A44%2C%22R-
Last%20Report%20Time%22%3A45%7D%22</URLParameters>
<SourcePage>ExploreComputers</SourcePage>
</BESWebReport>
#!/bin/bash
# Filename: get-hwam.sh
# Purpose: Retrieve a custom hardware-based report.
COLUMNS="c%3DR-Computer%2520Name%26c%3DO-3093-44-7%26c%3DO-3093-
44-9%26c%3DO-3093-45-7%26c%3DO-3093-44-5%26c%3DO-3093-44-6%26c%3DO-
3093-45-1%26c%3DO-3093-44-8%26c%3DO-3093-45-6%26c%3DR-ID%26c%3DO-1-
204-1%26c%3DO-1-205-3%26c%3DO-13014-19-2%26c%3DR-
DNS%2520Name%26c%3DO-3093-33-2%26c%3DO-3093-33-1%26c%3DR-
IP%2520Address%26c%3DR-
IPv6%2520Address%26c%3DD%252FSubnet%252520Address%252FTjwTe57B3z9HX
SvUiuNLLO8eV%25252bg%26c%3DO-3093-305-11%26c%3DO-3093-35-
11%26c%3DR-
MAC%2520Address%26c%3DD%252FRAM%252F2pGqHiqzzkoNb6Lqh0XDPFnISw
g%26c%3DO-3093-305-2%26c%3DO-3093-35-4%26c%3DO-9307-34-1%26c%3DO-
9307-34-2%26c%3DO-3093-35-5%26c%3DO-3093-305-3%26c%3DO-3093-305-
5%26c%3DD%252FFree%252520Space%252520on%252520System%252520Drive%25
2F8cqlsJBnBvC8%25252f%25252f9KBo23Mzq6jts%26c%3DD%252FTotal%252520Si
ze%252520of%252520System%252520Drive%252FtmutWa7NR%25252bcxoW%25252
bcZJir9U7itaU%26c%3DO-3093-35-9%26c%3DR-Computer%2520Type%26c%3DO-
3093-35-2%26c%3DO-3093-35-1%26c%3DO-3093-33-3%26c%3DO-3093-35-
8%26c%3DR-CPU%26c%3DO-3093-35-6%26c%3DO-3093-305-4%26c%3DO-3093-
35-18%26c%3DO-3093-305-16%26c%3DR-OS%26c%3DR-
Last%2520Report%2520Time%26"
#Additional variables: columnOrder, sort, dir
# The following variables may be used to filter Web Reports: filterName, filterID,
filterDescription, matchType, conditionList, selectedContentTypeName, selectorList,
selectedOperatorName, selectedOperatorValue, selectedProperty, type, id, name,
displayName
#!/bin/bash
# Filename: get-csm.sh
# Purpose: Retrieve all CIS benchmarks from BigFix Web Reports, with with all
available columns and applicable computers expanded.
FILTER="%7B%22matchType%22%3A%22all%22%2C%22conditionList%22%3A%5
B%7B%22selectedContentTypeName%22%3A%22Fixlet%22%2C%22selectorList%22
%3A%5B%7B%22selectedOperatorName%22%3A%22is%22%2C%22selectedOperator
Value%22%3A%22Visible%22%7D%5D%2C%22selectedProperty%22%3A%7B%22n
ame%22%3A%22Visibility%22%2C%22id%22%3A%22Visibility%22%7D%7D%2C%
7B%22selectedContentTypeName%22%3A%22Fixlet%22%2C%22selectorList%22%3
A%5B%7B%22selectedOperatorName%22%3A%22is%22%2C%22selectedOperatorVal
ue%22%3A%22%7B%5C%22BESSiteID%5C%22%3A%7B%5C%22DatabaseSiteID%
5C%22%3A15426%7D%7D%22%7D%2C%7B%22selectedOperatorName%22%3A%2
2is%22%2C%22selectedOperatorValue%22%3A%22%7B%5C%22BESSiteID%5C%22
%3A%7B%5C%22DatabaseSiteID%5C%22%3A15394%7D%7D%22%7D%2C%7B%2
2selectedOperatorName%22%3A%22is%22%2C%22selectedOperatorValue%22%3A%
22%7B%5C%22BESSiteID%5C%22%3A%7B%5C%22DatabaseSiteID%5C%22%3A1
5483%7D%7D%22%7D%2C%7B%22selectedOperatorName%22%3A%22is%22%2C
%22selectedOperatorValue%22%3A%22%7B%5C%22BESSiteID%5C%22%3A%7B%
5C%22DatabaseSiteID%5C%22%3A11366%7D%7D%22%7D%2C%7B%22selectedOp
eratorName%22%3A%22is%22%2C%22selectedOperatorValue%22%3A%22%7B%5C
%22BESSiteID%5C%22%3A%7B%5C%22DatabaseSiteID%5C%22%3A12181%7D%
7D%22%7D%2C%7B%22selectedOperatorName%22%3A%22is%22%2C%22selected
OperatorValue%22%3A%22%7B%5C%22BESSiteID%5C%22%3A%7B%5C%22Data
baseSiteID%5C%22%3A15515%7D%7D%22%7D%2C%7B%22selectedOperatorName
%22%3A%22is%22%2C%22selectedOperatorValue%22%3A%22%7B%5C%22BESSit
eID%5C%22%3A%7B%5C%22DatabaseSiteID%5C%22%3A15736%7D%7D%22%7D
%2C%7B%22selectedOperatorName%22%3A%22is%22%2C%22selectedOperatorValu
e%22%3A%22%7B%5C%22BESSiteID%5C%22%3A%7B%5C%22DatabaseSiteID%5
C%22%3A15464%7D%7D%22%7D%5D%2C%22selectedProperty%22%3A%7B%22n
ame%22%3A%22Site%22%2C%22id%22%3A%22Site%22%7D%7D%5D%7D"
COLUMNS="c=Name&c=Visibility&c=Unlocked%20Computer%20Count&c=Source
%20Severity&c=Source%20ID&c=Sitename&c=SANS&c=Progress&c=Open%20Actio
n%20Count&c=Mean%20Time%20to%20Remediate&c=Download%20Size&c=Deploy
ed%20Action%20Count&c=CVE&c=Comments&c=Activation%20Time%20(Analysis)
&c=Activated%20By%20(Analysis)&c=ID&c=Category&c=Applicable%20Computer%
20Count&c=Remediated%20Computer%20Count&c=Type&c=Source&c=Source%20R
elease%20Date"
#NEWFILTER="true"
RESPONSE_PAGINATION=$(curl -k
"${VAR_BF_WR_URL}/json/fixletproperties?results=$RESULTS&startIndex=$STAR
TINDEX&$COLUMNS" -s -b cookies.txt)
echo "$RESPONSE_PAGINATION"
RETURNED_RESULTS=$(echo "$RESPONSE_PAGINATION" | sed
's/.*recordsReturned"://' | cut -d ',' -f 1)
if [ $RETURNED_RESULTS != $RESULTS ]; then
break
fi
((STARTINDEX+=RESULTS))
done
Figure U2. A bash script used to retrieve the CSM report during development.
Finally, a Bash script to retrieve a software instances report from BigFix Inventory is
shown in Figure U3. The number of rows to pull is configurable, and pagination will
occur until all results are retrieved.
#!/bin/bash
# Filename: get-swam.sh
# Purpose: Retrieve all software instances from BigFix Inventory
COLUMNS="columns%5B%5D=computer.id&columns%5B%5D=computer.name&col
umns%5B%5D=computer.valid_to&columns%5B%5D=prod_inv_id&columns%5B%5D
=is_shared&columns%5B%5D=is_suppressed&columns%5B%5D=component_id&colu
mns%5B%5D=product_metric_id&columns%5B%5D=catalog_dimension.discoverable_
name&columns%5B%5D=catalog_dimension.version&columns%5B%5D=bundle_name
&columns%5B%5D=processor.computer_type&columns%5B%5D=computer.last_seen
&columns%5B%5D=catalog_dimension.publisher_id&columns%5B%5D=catalog_dime
nsion.publisher_name&columns%5B%5D=component_version&columns%5B%5D=path
.path&columns%5B%5D=is_current&columns%5B%5D=max_cve.name&columns%5B
%5D=cve_rank.is_one&columns%5B%5D=catalog_dimension.created_at&columns%5
B%5D=catalog_dimension.edited_at&columns%5B%5D=computer.remote_id&columns
%5B%5D=computer_health.agent_version&columns%5B%5D=computer_health.last_sc
an_attempt"
LIMIT="50"
OFFSET="0"
CRITERIA="%7B%22and%22%3A+%5B%5B%22is_current%22%2C+%22%3D%22
%2C+%221%22%5D%2C+%5B%22is_suppressed%22%2C+%22%3D%22%2C+%220
%22%5D%5D%7D"
and performance requirements. The Logstash pipeline is configured to look at certain key
fields, and if they’re missing, it will query for them, as shown by the dashed line to DNS
and Asset Inventory. Child Agency A also has a requirement to send its data to a security
information and event management (SIEM) product, so Logstash is configured to
perform parsing on the data destined for the SIEM and sends the CDM data to the parent
agency.
Child Agency B is shown sending data from numerous systems in addition to the
CDM tools that may aid analysts. In this case, Logstash acts solely as an aggregator and
sends all the events to the parent for parsing. In this scenario, a message broker was
chosen by the parent agency as a temporary storage system. The advantage of the
message broker is that it allows the parent agency’s Logstash instance to retrieves the
logs as resources become available in the pipeline. It also adds data resiliency on top of
Logstash capabilities like the persistent queues and dead letter queues.
Appendix Y. A CVE search with fields of interest added as columns to the view