Endpoint Visibility: Azure Functions

Most of our endpoint management has now shifted to the cloud. With this often comes easy and great API access. Having this API access can really help you automate tedious tasks or increase your visibility.

If you manage multiple agents on your endpoints, you often have teams managing at the source. You may also have the teams split, managing each agent differently. Regardless of how it’s setup, both teams will have the same goal of having 100% compliance with agent health/coverage.

This is where solutions such as Azure Functions can help. Sure, local Powershell, bash or python scripts can do the job, but they can often expose API keys. There is nothing wrong with this method, as I do run it myself however using this method does bring certain challenges…

With Azure Functions, you centralize the “script” and have the options to combine multiple APIs behind closed doors. This is due to only needing to share 1, or none which isn’t specific to the agents. For example, the key shared is for the Function, not Qualys, Defender or CrowdStrike. This allows you to easy rotate, if stolen. That being said, Azure functions do give the options to restrict using multiple methods; which I will briefly cover.

If you don’t have an Azure tenant and you do want to try this out, I do recommend spinning one up. The trail/free account does come with money, which can allow you to create such resource. Most of this, is also included in the free tier, so you don’t have to worry about those charges $$$.

Once you have your tenant, create a resource group and your Azure Function App. For this, I’ve created func-xstag0

You don’t have to do these next steps, but I do, just for Security or usage purposes.

Go to configuration:

· Change the version to Powershell 7.0.
· Disable FTP state.
· Change the HTTP version to 2.0.

If you want to secure or limit to your own Public IP, or network, clicking Networking and select Access restrictions or App assigned address. The App Assigned Address allows you to force HTTPs and set certificates, and the Access restrictions will allow you to remove the Internet and expose only to your networks.

If you did want the logs, remember that they are never enabled by default (Unless you have policy), so do enable (Diagnostic settings):

During creation, you can also tick App insight, which offers additional logs. Entirely up to you.

One final point. If you do choose to use the keys within the HTTP requests, they can be found under App Keys. If compromised, remember to rotate. You could also create custom keys and share these out with the different teams. For instance, you may give the Security team one key and ServiceDesk another. This allows you to filter out certain requests later down the line.

Once you are good to go, click Functions and hit Create. Select HTTP Trigger, and then select how you are going to develop. For this, I’ve chosen to develop in portal:

Once you’ve created, go into the Function and select Integration. Once in, Select your Trigger “HTTP (Request)”. As stated earlier, this is where you can choose how your users will interact. If you are wanting to use keys, by default it will be on Function. If you are wanting to do no keys, select Anonymous.

Now, onto the code…

This is where you can do as much as you like and get creative. I’ll run through a simple example, just to show.

To begin with, you want to accept the inputs.

Using the Test/Run, we can see that with this, the function app can receive the request either via the Query or Body of the request.

On the right, we can test this by passing it a value. As you can see, I’ve called this hostn2s, so this is the attribute that I have to pass. If this passed as {“name”: “Example”}, it would fail.

Once you have this value, you can use with your APIs to get the necessary data. For example, if your checking the status of an agent, run each API using the value passed ($hostn2s) and combine the result. You could use a foreach loop for example.

The above is a simple example of getting the data of an endpoint within CrowdStrike. Here, we get the token, we get the AID and then get the current data of the endpoint.

Once we have that, we set it as the $body variable. If you’re running multiple, you may want to create an object and build on it. For example:

Create the object first and add the value of Hostname. Then run through each API and update the status.

Once you have this, you can return it within Body. Using local Powershell as an example, it will look similar to:

For me, I like to convert to JSON, as later on we can parse the data better.

Once we are happy, we need to test. The quickest method would be to use Test/Run again:

Here we can see the output returned. If we are wanting to run it on our local host, or CLI, we can click Get Function URL and do the following:

First, we select the method. Once you know your keys, you don’t have to come here each time, as you can just modify the keys in the URL you share. Again, for this example, I’ve used anonymous.

I can now either run CLI or view in Browser (Depending how you’ve set it up):

Just think, if you integrate with multiple clouds (Agents), you can have a single source to check the health of that endpoint quickly. This can be used during gap analysis or during an incident/detection.

If fancy, you could even include the URL within an Adaptive Card or Share/Generate the URL as part of the response alert.

I will cover more on this in part 2 and will show you how to extend this further by using Logic Apps…


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Create a website or blog at WordPress.com

%d bloggers like this: