Feeding Your SIEM: Integrating Cisco AMP for Endpoints via Event Streams

Modern IT infrastructure generates a massive amount of log data, and today, we’re going to talk about piping even more of it into your SIEM.

While it’s relatively easy to log into individual servers to hunt for specific logs, achieving a true 360-degree view of your environment is a completely different challenge. Your SIEM is the ideal engine for correlating this multi-source data and investigating incidents—but are your endpoints fully part of that equation? Cisco AMP for Endpoints offers incredible flexibility, allowing you to integrate its telemetry with virtually any SIEM or third-party software stack.

Three-panel comic showing an IT analyst overwhelmed by log data and SIEM alerts. In the first panel, a pipe labeled “More Logs” dumps paper logs into a SIEM while a coworker cheerfully announces more logs are being added. In the second panel, the analyst searches through individual servers with a magnifying glass, surrounded by tangled cables and data sources like firewalls, cloud apps, identity, email, databases, and endpoints. In the third panel, Cisco AMP for Endpoints telemetry flows into the SIEM, which acts like a detective engine correlating clues from endpoint devices and helping the analyst connect the dots.
More logs are only useful when your SIEM can actually make sense of them. With endpoint telemetry in the mix, the story gets a lot easier to solve.

Before We Start

Disclaimer: This article is an independent weekend project. It is not sponsored, endorsed, or administered by my employer, and the opinions expressed here are entirely my own.

While the activities outlined below are generally safe, tinkering with infrastructure always carries some inherent risk. Keep in mind that certain security best practices (like peer hostname verification) have been bypassed for the sake of simplicity in this tutorial. If you aren’t completely comfortable with these steps, please seek professional support. This guide is provided “as is,” without warranties, support, or liability for any data loss, security breaches, or other IT calamities.

Three-panel comic showing a weekend IT side project about Cisco AMP for Endpoints and SIEM telemetry. In the first panel, an excited IT hobbyist holds a large disclaimer sheet listing “Independent project,” “Opinions my own,” “As is,” “No warranties,” and “Not my employer’s fault,” while a skeptical observer says the disclaimer is longer than the tutorial. In the second panel, the hobbyist nervously works on a server rack beside a large lever labeled “Peer Hostname Verification,” flipped to “Bypassed for Simplicity,” while warning signs and safety notes surround the lab. In the third panel, Cisco AMP for Endpoints collects activity from laptops, servers, files, network connections, and workstations, then sends colorful telemetry streams into a happy SIEM dashboard showing prevent, detect, respond, and telemetry data.
Every weekend project starts with a disclaimer, a coffee, and one questionable shortcut. The win comes when AMP for Endpoints turns all that endpoint activity into rich telemetry your SIEM can actually use.

What is AMP for Endpoints?

If you’ve found your way to this article, you probably already know. But for the sake of completeness: Cisco AMP for Endpoints (AMP4EP) is a next-generation endpoint security solution designed to prevent, detect, and respond to advanced threats.

Beyond its core protective features, AMP4EP acts as a massive telemetry-gathering tool. It collects a wealth of security data about the endpoints themselves, alongside their interactions with other devices, servers, files, and network connections. It is exactly this rich, relational data that we want to extract and share with our SIEM.

Three-panel comic about setting up an AMP for Endpoints to SIEM integration through APIs. In the first panel, a nerdy IT analyst points at a “Setup Options” board and chooses the “API Route,” with notes about picking the correct region, US, APJC, or EU, and choosing v1 APIs. A skeptical coworker jokes that he picked the nerdy option. In the second panel, the analyst looks exhausted while operating a machine labeled “Polling,” repeatedly checking for new data, surrounded by clocks, calendars, API resource lists, and warning notes. The coworker compares polling to a woodpecker with Wi-Fi. In the third panel, a glowing “Event Stream” flows smoothly from AMP for Endpoints into a happy SIEM client, carrying event bubbles such as process started, file changed, connection made, and alert. The analyst relaxes while the coworker admits the event stream approach is much better.
Polling keeps asking, “Anything new yet?” Event Streams simply connect once and listen. Much better for your SIEM, your script, and your sanity.

How Do We Set It Up?

There are a few ways to achieve this integration. Some methods work out-of-the-box, while others rely on the AMP4EP APIs. Today, we will be focusing on the API route.

  • Step 1: Head over to the API documentation page and select the region that corresponds to your cloud instance (US, APJC, or EU).
  • Step 2: On the following page, select the v1 APIs.

Most of the API resources listed here require on-demand polling—meaning your custom script or software has to continuously ask the server if there is new data. However, Event Streams are the perfect exception.

Instead of forcing you to write a scheduled script to constantly check for updates, Event Streams provide a continuous, real-time flow of information from AMP4EP directly to your client. By initiating a single connection to the stream, your setup can simply sit back and listen for new messages as they roll in, making the integration far more efficient and elegant.

Activating the APIs

Before we can start pulling data, we need to generate a dedicated username and password to access the API resources. It’s important to note that these are separate from the credentials you normally use to log into the AMP4EP web portal.

Here is how to set them up:

  1. Log into your AMP4EP console using your standard credentials.
  2. Navigate to Accounts > API Credentials (you can reference the official documentation if you get stuck).
  3. Create a new set of credentials with Read & Write access.
  4. Optional but recommended: Tick the Enable Command Line option.

Note: You may be prompted to activate Two-Step Verification if you haven’t already done so.

Before moving on, a quick heads-up: I will be using Microsoft Windows for this tutorial to quickly test the Event Stream API. However, if you are using Linux or macOS, don’t worry—the fundamental concepts and API calls are essentially identical across operating systems.

Creating the AMQP Messaging Resource

The AMP4EP Event Streamer relies on the AMQP (Advanced Message Queuing Protocol) standard. In this step, we are going to create the resource that allows us to receive data streams from AMP4EP.

As always, make sure you are referencing the API documentation specific to your cloud instance (US, APJC, or EU).

To interact with the API, we need an API client. For this guide, we will use Postman, a popular and free API development environment available for multiple operating systems.

  • Download and install Postman. (You can skip creating an account by clicking “Take me straight to the app” at the bottom of the window).
  • Close any introductory pop-ups to get to the main workspace.

We are almost ready to connect to the Event Streamer, but we have one crucial step left: we need to tell AMP4EP which events we actually care about.

Finding Your Event IDs

AMP4EP tracks a massive variety of events, such as Threat Quarantined, Threat Detected, and Cloud Recall Restore from Quarantine. To filter our stream, we need to locate the specific ID numbers associated with the events we want to receive.

For this test, I recommend tracking Threat Quarantined and Threat Detected.

To find their corresponding IDs, we will use the GET /v1/event_types API call:

  1. Open Postman and set the request type to GET.
  2. Enter the Request URL for your region’s API (e.g., https://api.amp.cisco.com/v1/event_types).
  3. Under the Authorization tab, set the type to Basic Auth.
  4. Enter the API Username and Password you generated in the first step.
  5. Click Send.

Once the request completes, you will see a JSON response populated in the text area at the bottom of your Postman window. Scroll through this data to find the IDs for your target events.

In my environment, the ID for Threat Quarantined is 553648143, and Threat Detected is 1090519054. Take a look at your JSON output—what are yours? (They will likely be the exact same).

Creating the AMQP Resource

Now that we have our Event IDs, our next step is to create the actual queue—the streaming resource itself.

While the technical specifics are outlined in the AMP4EP documentation, the goal of this step is straightforward: we need to generate a new, distinct set of credentials (a separate username and password) that will be used exclusively to connect to this AMQP stream.

To get this set up, let’s fire up Postman once more.

The setup here is very similar to our previous API call, but with a few critical changes.

Most importantly, you need to change the request type in Postman from a GET to a POST. This is because we are actively creating the queue on the server. Keep in mind that this is a one-time operation—once the queue is created, we can connect to it as many times as we need to without having to recreate it.

Here is how to configure your Postman request:

  1. Change the request method from GET to POST.
  2. Ensure your API Basic Auth credentials are still applied under the Authorization tab.
  3. Pass your parameters to the API. You can do this by clicking the Params button in Postman and adding them line by line, or you can skip that and simply paste a fully constructed URL directly into the address bar.

You will need to include the Event IDs we found in the previous step, as well as a custom name for your queue. I named my queue DQrbpudi2, but you can name yours whatever makes the most sense for your environment.

For your convenience, here is the complete URL I used to build my request: https://api.amp.cisco.com/v1/event_streams?event_type[]=553648143&event_type[]=1090519054&name=DQrbpudi2

If you look under the Body section of your successful Postman request, you will see the returned JSON response. This payload is exactly what we were looking for—it contains all the essential connection details for your new AMQP resource, including the queue name, username, password, host, port, and protocol.

Now it’s time to actually retrieve events from this newly minted queue.

In a real-world production environment, this is the stage where you would implement a script or middleware to capture these events and route them to your SIEM, dump them into a database, or write them to a secure log file. The possibilities are virtually endless. You can build this integration using your favorite programming language and a variety of third-party libraries. If you are looking to build a highly scalable pipeline, integrating a robust message broker like RabbitMQ is an excellent architectural choice to explore.

For the scope of this tutorial, however, we are going to keep things simple. Instead of building a complex middleware pipeline, we will just focus on successfully pulling these incoming messages and displaying them directly in a command-line console.

Installing Ruby

Cisco’s official documentation uses Ruby to demonstrate how to capture incoming messages from the queue, so we will follow suit for this tutorial.

  1. Head over to Ruby Installer and download the appropriate installer for your operating system (x86 or x64). I used the “Ruby+Devkit” package.
  2. Run the installer. You can safely accept all the default settings, with two minor exceptions: uncheck the “MSYS2 development toolchain” and the “ridk install” options. We won’t need those components for this project.

Writing and Running the Ruby Client

To interact with our AMQP stream, we will be relying on the popular Bunny library for Ruby.

Our next step is to create the actual Ruby script that will connect to the queue and print the incoming messages. Open your favorite text editor, paste the code snippet below, and save the file into your Ruby directory (e.g., C:\Ruby25-x64 or wherever you installed it) as test.rb.

Ruby

require 'bunny'

# Replace with your unique connection string
connection_url = "amqps://531-c3f9f207XXXXXXXXXXXX:7522e7c03f4217155dXXXXXXXXXXXXXXXXXXXXXX@export-streaming.amp.cisco.com:443"

conn = Bunny.new(connection_url)
conn.start

ch = conn.create_channel

# Replace 'event_stream_531' with your specific queue name
q  = ch.queue('event_stream_531', :passive => true, :durable => true)

x  = ch.default_exchange

q.subscribe(:block => true) do |delivery_info, metadata, payload|
  puts "Received #{payload}"
end

Customizing Your Variables

Before running the script, you must update the placeholder values with the JSON data you received from your Postman POST request in the previous step:

The Queue Name: In the Ruby line that defines the queue, replace event_stream_531 with the queue_name value returned in the JSON response under amqp_credentials. Do not use the custom name you passed in the POST request, such as DQrbpudi2, unless that exact value is returned as queue_name in your own JSON response.

The Ruby line should look like this, using the queue_name from your JSON response:

q = ch.queue('event_stream_531', :passive => true, :durable => true)

The Connection URL: Notice how the connection_url string is formatted. It follows the structure: amqps://[username]:[password]@[host]:[port].

In the example above, 531-c3f9f207XXXXXXXXXXXX is the generated username, and the string immediately following the colon, 7522e7c…, is the password. Plug your specific username, password, host, and port into this format.

With your script customized and saved, it is finally time to see it in action.

Open up your command line interface, navigate to the directory where you saved your file (for example, C:\Ruby25-x64), and execute the script by typing the following command:

ruby test.rb

If everything is configured correctly, your console will establish a connection to your AMP4EP AMQP resource and begin actively listening. As soon as a relevant event (like a threat being detected or quarantined) occurs in your environment, you will see the JSON payload populate live right there in your command shell!

At this point, your Ruby client is officially connected and actively listening to your AMP4EP events. (If you don’t believe me, move on to the next section and we will prove it! 🙂)

Testing the Queue

I can’t speak to how much organic activity is currently happening in your specific AMP4EP instance. Because I am using a controlled demo environment for this tutorial, there isn’t a massive amount of background data automatically flowing through.

To generate some live activity, I am going to do two things:

  1. Refresh the demo data: Log into your AMP4EP console and navigate to Accounts > Demo Data > Refresh Demo Data.
  2. Download a test file: I am going to download the EICAR test file. If you aren’t familiar with it, EICAR is a harmless, industry-standard “fake” virus designed specifically to safely trigger antivirus alerts. Downloading this will force AMP4EP to generate a live event.

If you are following along, head over to the EICAR website to grab the test file. I recommend using the specific download link highlighted in the image below:

Depending on your endpoint’s configuration, AMP4EP (or your local built-in antivirus) might not automatically snatch up the file the second it downloads. If it slipped through the initial net, we just need to force a manual scan to generate our alert.

Since I am using Windows for this tutorial, I can simply trigger the scan directly from Windows File Explorer, as shown in the example below.

As expected, the system will immediately recognize the test file as a threat, flag it as malicious, and swiftly remove it.

While it is always satisfying to see your endpoint protection doing its job locally, the real magic is happening behind the scenes. If you switch back over to your command-line interface where your Ruby script is running, you should immediately see the fruit of our labor.

Verifying in the Console

To confirm everything is working as expected, head back over to your AMP4EP web console and verify that the EICAR threat event registered correctly.

For reference, here is a look at how that alert populates in my own environment:

The Moment of Truth

Now, let’s check back in on our Ruby script. If everything is wired up correctly, we should expect to see the exact same EICAR event that just triggered in the AMP4EP web console reflected live in our command-line interface…

…and there it is!

Because the test file was immediately removed by the system rather than quarantined, our script captured the exact Threat Detected event we were expecting to see.

Conclusion

I hope you enjoyed this hands-on example!

Keep in mind that while this Ruby script is a great proof of concept, you will want to build something significantly more robust for a production environment. The ultimate goal is to take this continuous stream of messages and systematically route them to your SIEM, where you can correlate the data, trigger alerts, and take meaningful action.

As mentioned earlier, integrating a message broker like RabbitMQ alongside your preferred programming language is an excellent way to process these payloads reliably at scale.

Consider this tutorial the starting line for your AMP4EP API journey. Best of luck building out your integrations, and happy coding!

Additional Resources

Looking to dive deeper? Here are a few helpful resources to keep you going:

  • Cisco AMP for Endpoints API Documentation: Official API reference documentation.
  • Cisco AMP for Endpoints API Tutorial: A broader overview of working with the AMP for Endpoints API.
  • Python Event Stream Examples: Python-based Event Stream examples are available in the walbit and QuiLoxx repositories.

Originally published on LinkedIn on May 6, 2018.

Leave a Reply

Your email address will not be published. Required fields are marked *