Exploring Python Libraries for Handling BigFix Client Relevances

I wanted to reach out regarding an exciting development in our toolset. As some of you may know, we’ve been utilizing a PowerShell module to manage client relevances efficiently. However, to enhance compatibility and expand our capabilities, we’ve been exploring the possibility of replicating this functionality in Python.

$expressions = @('if (exists folder ((value "EnterpriseClientFolder" of keys "HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\BigFix\EnterpriseClient" of native registry) as string & "DEX")) then ((not exists (file of folder ((value "EnterpriseClientFolder" of keys "HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\BigFix\EnterpriseClient" of native registry) as string & "DEX")) whose ((name of it = "LastArchivalTime.txt"))) or (exists (file of folder ((value "EnterpriseClientFolder" of keys "HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\BigFix\EnterpriseClient" of native registry) as string & "DEX")) whose ((name of it = "LastArchivalTime.txt") and (now - modification time of it > 24*hour)))) else false', 'if (exists folder ((value "EnterpriseClientFolder" of keys "HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\BigFix\EnterpriseClient" of native registry) as string & "DEX\Results")) then (number of files of folder ((value "EnterpriseClientFolder" of keys "HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\BigFix\EnterpriseClient" of native registry) as string & "DEX\Results") > 0) else false', '(name of it, version of it) of operating system')
 
foreach ($expression in $expressions){
 
    $relevance = Invoke-EvaluateClientRelevance $expression
 
    $relevance.Answer
 
}

True
True
Win11, 10.0.22621.3155

Is there anything availabe in python also ?

@JasonWalker Need your support here…

I’m not familiar with that PowerShell module. I don’t think I’ve seen anything in Python to call the client relevance evaluator, but I could envision something that either uses the Client Compliance API, or calls the QNA.exe binary and reads the stdin/stdout from it to evaluate relevance

used the client query to achive this in python:

import requests
import xml.etree.ElementTree as ET
import time

url = "https://Server:52311/api/clientquery"

payload = """<BESAPI>
<ClientQuery>
    <ApplicabilityRelevance>true</ApplicabilityRelevance>
    <QueryText>name of operating system</QueryText>
    <Target>
        <ComputerName>target server</ComputerName>
    </Target>
</ClientQuery>
</BESAPI>"""

headers = {
    'Content-Type': 'text/plain',
    'Authorization': 'Basic key'
}

try:
    # Make POST request
    response = requests.post(url, headers=headers, data=payload, verify=False)
    response.raise_for_status()  

    print("POST Response:", response.text)

    # Parse XML response
    root = ET.fromstring(response.content)
    id_element = root.find(".//ID")
    if id_element is not None:
        id_value = id_element.text
        print("ID:", id_value)
        try:
            id_value_int = int(id_value)
            print("ID (Integer):", id_value_int)
            time.sleep(6)

            # Make GET request to retrieve the result
            url_result = f"https://Server:52311/api/clientqueryresults/{id_value_int}"
            response_get = requests.get(url_result, headers=headers, verify=False)
            response_get.raise_for_status() 
            prnt("GET Response:", response_get.text)
            

            root_get = ET.fromstring(response_get.content)
            if root_get.find(".//Result") is None:
                print("No results found.")
        except ValueError:
            print("ID is not an integer")
    else:
        print("ID not found in response.")

except requests.exceptions.RequestException as e:
    print("Error:", e)
1 Like

There is a Python Module that can be installed with PIP for interacting with the BigFix REST API which I would highly recommend using for many reasons:

Here is a working example that uses clientquery:

There is also a python script for evaluating relevance locally on a system, which is less useful in many ways, but this actually seems like what you are trying to accomplish:

I also have scripts for running QNA relevance locally WITHOUT installing the agent: ( to validate relevance in docker for instance )

2 Likes

I added an example to besapi to use it to do clientquery:

It has some enhancements.

Worked like a magic !!!

1 Like

Glad to hear it.

The example could use enhancements, like the ability to accept the client relevance as file text, or command line arg, stdin, or a string within the script if neither are provided. File text is one of the better options to not have to deal with character escaping, which can become a big pain.

It would also be handy if it could pick 10 target computer ids that have UDP notifications or persistent connections working, which would be more specific than what it currently does.

Would also be interesting to accept a list of computer ids as input somewhere to target, but the default is to target 10 recently reported computers, which is a pretty good option without having a specific target in mind.

It would also be useful to incorporate some of these capabilities as functions within the besapi module itself, and then provide a way to do it within bescmd interactive command prompt.

Originally the besapi python module was as thin as possible wrapper around the BigFix REST API with functions to make it easier to work with in python, but over time I have created more and more helper functions to provide actual outcomes in smart ways, including migrating example functionality from the bescmd interactive command to actual besapi module functions that are then called by bescmd instead.

Now, when implementing a new capability, I generally start with a script here:

Then implement the same as a bescmd interactive option:

Then move that same function into besapi itself:

1 Like