Inventory rules (also known as detection rules) are used on Managed Deliveries to ensure a software release (or SP or update) is applicable or installed.
The feature was introduce in the 6.2 version of Patch Management and allowed Altiris to ensure Windows Updates were installed via Patch and still applied on a computer. It was then extended to Managed Deliveries in 7.0 whilst in 7.1 Patch switched to another detection engine.
Although this mechanism has been in the product for a number of year its operations are not so well explained in public documentation, so we'll try to fill this gap in this article.
So, let's start naming the different components that we have in play there:
- Inventory Rules: an xml string detailing the checks that make up the rule itself
- Inventory Rule Agent: the agent that takes the rule as input, run the detection check and returns a boolean result
- Inventory Rule Cache: a SQLLite file that contains the list of inventory rules and other information related
- Inventory Rule Web-Service: the server interface that is used to deliver rules to the inventory rule agent
The rules, agent and cache will not be detailed here, as their operation can be understood from documenting the web-service interfaces or from working with them in the SMP console (rules).
So, what does the Inventory Rule Web Service expose and how is it used by the agent? Before we go into the interface in detail here is a look at the inventory rule document hierarchy:
At the top we have the DataClass. The dataclass in effect is a Result Data Class, and it pertains to a specific platform. Windows dataclass result is a null guid, most likely for simplicity (other platforms where not considered in Patch Management 6.2 - so that could be the historical explanation).
All inventory rule for a platform will share the same dataclassresult, so the data class hash is a hash of the entire inventory rule tree for a given platform. This allows the agent to detect from the highest level whether it's cache is clean or dirty using a request of type DataClassHash. Once the response is received we can check against the cache if the hash matches: a match means the cache is clean, a mis-match means the cache is dirty.
If we have a dirty hash it can be because of one of two cases:
- The cache is empty because the agent just got installed (or the cache file was deleted)
- The cache is dirty because one or more detection rules have changed or were added or removed
If the cache is empty, the task at hand is very simple: request the entire rule set for the dataclass from the server using a request of type DataClassRules. This is a single http request that will return the entire set of inventory rules that will then be inserted in the cache and used by the inventory rule agent.
If the cache is dirty the task is only a little more complex: we get a list of inventory rule hashes using a request of type DataClassRuleSummaryfrom the server and decide what to do from there (this allows the Inventory Rule Agent to check if rules should be removed from the cache, added or modified and to act accordingly).
Depending on the number of rules that have changed the agent may decide to refresh the entire rule set (discarding the entire cache and downloading all the rules in a request) or it can request each rule xml string from the server (in case of insertion / update) using a request of type Rules. Deletion of rules is a very simple operation as it does not require communication with the server.
As you can see the interface as a lot of granularity and allows the agent to ensure all the inventory rules are in synch with a reduced amount of client-server communication (with one massive caveat in 7.1 [1]).
Now here are the details of each http interface with sample input and output from a 7.1 SP2 MP1.1 server (some changes were introduced in 7.5 but the overall interface and its operations remain very similar).
Inventory Rule Management :: Agent Rule Data interfaces
Interface rule = /Altiris/InventoryRuleManagement/AgentRuleData.ashx
Interface parameters = DataClassHash | DataClassRuleSummary | DataClassRules | Rules
Currently supported dataclass guids:
Windows inventory rule = {00000000-0000-0000-0000-000000000000}
Linux inventory rules = {155B4553-8BEB-4579-8855-6AAE47A4AFC0}
Request Type = DataClassHash
Input = Xml Dataclass list with Guid in DataClasses root element
Output = Xml <DataClassGuid, Hash> list in dataClasses root element
Sample request xml post:
<dataClasses> <dataClass guid=’00000000-0000-0000-0000-000000000000’/> <dataClass guid=’55b4553-8beb-4579-8855-6aae47a4afc0’> </dataClasses>
Sample response xml:
<?xml version="1.0" encoding="utf-8"?> <dataClasses> <dataClass guid="{00000000-0000-0000-0000-000000000000}" hash="9CBgmnpo7BKGyVz4Tk9Yao4yG4g=" /> <dataClass guid="{155b4553-8beb-4579-8855-6aae47a4afc0}" hash="y+xkQUJ4VpmQb2eKUHBKmKROfhQ=" /> </dataClasses>
Request Type = DataClassRuleSummary
Input = Query parameter DataClassGuid
Output: Xml <DataClassGuid, Hash> list in inventoryRuleSummary root element
Sample request query parameter:
?DataType=DataClassRuleSummary&DataClassGuid=00000000-0000-0000-0000-000000000000
Sample response xml:
<?xml version="1.0" encoding="utf-8"?> <inventoryRuleSummary> <dataClass guid="{00000000-0000-0000-0000-000000000000}" hash="9CBgmnpo7BKGyVz4Tk9Yao4yG4g="> <rule guid="{75af027a-33ca-4f1e-832c-024b367ac64c}" hash="ROKkxfSz31BIdRCHQ/Z43Ro1qFs=" /> <rule guid="{3f3b4b0c-5218-4350-a589-02af2cdff41c}" hash="oPS/kgVq8vn7IdA6Y62O1LdSFxc=" /> </dataClass> </inventoryRuleSummary>
Request Type = DataClassRules
Input = Query parameter DataClassGuid
Output = Xml inventoryRule list in inventoryRules root element
Sample request query parameter:
?DataType=DataClassRules&DataClassGuid=00000000-0000-0000-0000-000000000000
Sample response xml:
<?xml version="1.0" encoding="utf-8"?> <inventoryRules guid="{00000000-0000-0000-0000-000000000000}" hash="9CBgmnpo7BKGyVz4Tk9Yao4yG4g="> <inventoryRule guid="{75af027a-33ca-4f1e-832c-024b367ac64c}" dataClass="{00000000-0000-0000-0000-000000000000}" hash="ROKkxfSz31BIdRCHQ/Z43Ro1qFs=" softwareComponentGuid="{d6d1a4b8-c330-43d7-9b3b-c127b6463700}"> <rule ruleEngineCLSID="{df407668-ec52-4582-8c1d-0c4d73e9530e}"> <ruleset type="Smart"> <Prereqs></Prereqs> <and> <rule engine="{dc9b3e4c-7273-4e88-981a-f27826ce8aee}"> <detection version="7.0" legacy62RuleProvider="standard"> <installed> <expression> <msiProductInstalled productCode="{4f117e37-a44e-4afc-ae28-7eb93c8b2436}" impersonateInteractiveUser="False" /> </expression> </installed> </detection> </rule> </and> </ruleset> </rule> </inventoryRule> <inventoryRules>
Request Type = Rules
Input = Xml Rules Guids list in root element Rules
Output =Xml Rule list in Rules element
Sample request xml post:
<rules> <rule guid = '005A7AFB-2D13-41F3-B828-023C4BD3AD47' /> <rule guid = '15A24CC2-FECC-4044-9DA7-0282AC32E0FA' /> <rule guid = '764D748D-19B9-46D1-ABFA-07347A20DF64' /> </rules>
Sample response xml:
<?xml version="1.0" encoding="utf-8"?> <inventoryRules> <inventoryRule guid="{005a7afb-2d13-41f3-b828-023c4bd3ad47}" dataClass="{155b4553-8beb-4579-8855-6aae47a4afc0}" hash="zSk7NBs/iQkoo5xLpTt/vqvm1BA=" softwareComponentGuid="{95895f28-bafd-4aed-88bd-4487428fd7db}"> <rule ruleEngineCLSID="{47d519a3-4ae7-4523-95fd-b669151be5c4}"> <os platform="Linux" arch="x86" name="SUSE Linux Enterprise Desktop" major_version="10" /> </rule> </inventoryRule> <inventoryRule guid="{15a24cc2-fecc-4044-9da7-0282ac32e0fa}"> <error> <message><![CDATA[Rule (15a24cc2-fecc-4044-9da7-0282ac32e0fa) does not exist in the database]]></message> </error> </inventoryRule> <inventoryRule guid="{764d748d-19b9-46d1-abfa-07347a20df64}" dataClass="{00000000-0000-0000-0000-000000000000}" hash="BZ6NRmcK4MJlWBQ/SA/pvlD/gmE=" softwareComponentGuid="{8f95edab-ea4f-40b9-894a-5888d2753927}"> <rule ruleEngineCLSID="{df407668-ec52-4582-8c1d-0c4d73e9530e}"> <ruleset type="Smart"><and> <rule engine="{dc9b3e4c-7273-4e88-981a-f27826ce8aee}"> <detection version="7.0" legacy62RuleProvider="standard"> <installed><expression><msiProductInstalled productCode="{a6b9b503-fa90-4512-9410-ad5a8cad43fc}" impersonateInteractiveUser="True"/></expression></installed> </detection> </rule></and> </ruleset> </rule> </inventoryRule> </inventoryRules>