vRA SaltStack Config - Salt Project - Header

A debugging example of Salt Win-Repo issues

The Issue

I was hitting issues when trying to use the Salt Win-Repo to install software. Below is a copy of my state file.

ensure_malwarebytes_installed:
  pkg.installed:
    - pkgs:
      - malwarebytes

It would fail with the below helpful error messages. But most importantly, I’d check the minion, to find the software was actually installed.

  {
    "return": {
      "pkg_|-ensure_malwarebytes_installed_|-ensure_malwarebytes_installed_|-installed": {
        "name": "ensure_malwarebytes_installed",
        "__id__": "ensure_malwarebytes_installed",
        "result": false,
        "__sls__": "Windows.software-install.malwarebytes",
        "changes": {
          "malwarebytes": "Unable to locate package malwarebytes"
        },
        "comment": "The following packages failed to install/update: malwarebytes",
        "duration": 343.731,
        "start_time": "13:07:43.183808",
        "__run_num__": 0
      }

If I instead ran the command from my salt master, it would be successful with no error outputs:

salt {minion_name} pkg.install malwarebytes -l debug
The Debugging Effort

Because the software is installed on the minion, I run the “pkg.list_pkgs” command, so I can detail exactly what the system returns.

C:\Users\Administrator>salt-call pkg.list_pkgs
local:
    ----------
...
    Malwarebytes version 4.5.12.204:
        4.5.12.204
...

Next, I want to remove the package, before I continue to debug, however I hit another issue.

C:\Users\Administrator>salt-call pkg.remove malwarebytes -l info
local:
    ----------
    malwarebytes:
        ----------
        current:
            not installed
 
C:\Users\Administrator>salt-call pkg.remove malwarebytes -l info
[INFO    ] Executing command '"C:\Windows\system32\cmd.exe"' in directory 'C:\Users\Administrator'
[ERROR   ] Command '"C:\Windows\system32\cmd.exe"' failed with return code: 1
[ERROR   ] stdout: The system cannot find the path specified.
[ERROR   ] retcode: 1
[ERROR   ] Failed to remove malwarebytes; retcode: 1; uninstaller output: The system cannot find the path specified.
[WARNING ] Expected changes for package removal may not have occurred
local:
    ----------
    malwarebytes:
        ----------
        uninstall status:
            failed
The Cause

Now to the debugging effort. I render the SLS file on my minion, so I can understand exactly what values are computed and used on the system to install and remove the package.

C:\Users\Administrator>salt-call slsutil.renderer salt://win/repo-ng/salt-winrepo-ng/malwarebytes.sls default_template=jinja
local:
    ----------
    malwarebytes:
        ----------
        4.3.0.210:
            ----------
            full_name:
                Malwarebytes Anti-Malware version 4.3.0.210
            installer:
                https://data-cdn.mbamupdates.com/web/mb4-setup-consumer/MBSetup.exe
            install_flags:
                /SP- /VERYSILENT /SUPPRESSMSGBOXES /NORESTART
            uninstaller:
                %ProgramFiles(x86)%\Malwarebytes Anti-Malware\unins000.exe
            uninstall_flags:
                /SP- /VERYSILENT /SUPPRESSMSGBOXES /NORESTART
            msiexec:
                False
            locale:
                en_US
            reboot:
                False

First, the name provided in the “pkg.list_pkgs” command, doesn’t match the name provided in the win-repo malware bytes file, after the software is installed (despite the error when running the state file).

This is the probable cause of the inital error in my state file, it cannot return the expected software is installed, due to the name mismatch.

salt win-repo - debug - slsutil.renderer compare to pkg.list_pkgs

However, we also have the uninstall issue to dive into as well. The second step is to validate the path used for the uninstall file and its arguments.

The first obvious thing, is that the new Malware bytes version is installed into the “Program Files” folder on 64bit Operating Systems now, and not the x86 folder. The other issue is that there is no longer a unins000.exe file.

This explains the error message when running “pkg.remove malwarebytes” returning “system cannot find the path specified”.

salt win-repo - debug - slsutil.renderer - compare uninstall path to system

The Fix

Ok, so let’s check the file in question that Salt is using.

# cat /srv/salt/win/repo-ng/salt-winrepo-ng/malwarebytes.sls

# just 32-bit x86 installer available
{% if grains['cpuarch'] == 'AMD64' %}
    {% set PROGRAM_FILES = "%ProgramFiles(x86)%" %}
{% else %}
    {% set PROGRAM_FILES = "%ProgramFiles%" %}
{% endif %}
# Source: http://www.malwarebytes.org
malwarebytes:
#  {% for version in ['4.3.0.210'] %}
#  '{{ version }}':
#    full_name: 'Malwarebytes Anti-Malware version {{ version }}'
#    installer: 'https://data-cdn.mbamupdates.com/web/mb4-setup-consumer/MBSetup.exe'
#    install_flags: '/SP- /VERYSILENT /SUPPRESSMSGBOXES /NORESTART'
#    uninstaller: '{{ PROGRAM_FILES }}\Malwarebytes Anti-Malware\unins000.exe'
#    uninstall_flags: '/SP- /VERYSILENT /SUPPRESSMSGBOXES /NORESTART'
#    msiexec: False
#    locale: en_US
#    reboot: False
#  {% endfor %}
#
  '4.3.0.210':
    full_name: 'Malwarebytes Anti-Malware version 4.3.0.210'
    installer: 'https://data-cdn.mbamupdates.com/web/mb4-setup-consumer/MBSetup.exe'
    install_flags: '/SP- /VERYSILENT /SUPPRESSMSGBOXES /NORESTART'
    uninstaller: '{{ PROGRAM_FILES }}\Malwarebytes Anti-Malware\unins000.exe'
    uninstall_flags: '/SP- /VERYSILENT /SUPPRESSMSGBOXES /NORESTART'
    msiexec: False
    locale: en_US
    reboot: False
#

Now to break down the items in the file that are problematic.

  • If Statement
    • This sets the Program Files location to be used for computing the uninstall location based on the Operating Systems CPU Architecture, defined by looking up the grain information for the minion.
    • The issue here is that it sets a 64Bit system to use the “Program Files x86” folder, which as we uncovered in the above analysis, is the wrong location.
  • Uninstaller
    • This uses the wrong program folder, as the structure has now changed not only into the “Program Files” folder, but also from “\Malwarebytes Anti-Malware\” to “\Malwarebytes\Anti-Malware\
    • The uninstall file itself has now changed.
      • After a bit of digging, I found it in the program folder now called “mbuns.exe”
  • Installer
    • MalwareBytes unfortunately only provides a public generic link which has no version attached. This is fantastic, as you always get the latest version. But terrible, as you don’t know the version number upfront.
    • MalwareBytes doesn’t provide any links to older versions.
    • This causes issues in how best to define the win-repo file going forward to differentiate between versions and ensuring salt acts in the correct manor when it encounters an installed version of MalwareBytes already.
  • The commented-out code
    • Just makes the file look a bit messier, I assume it was left there for testing by the previous creator.

Ok, so fixing this is a few small changes, but also a bit of a pain of the fact you cannot 100% resolve this. Thanks to the lack of previous versions from the vendor in their software download.

First let’s ditch the commented-out code. And replicate the version block of code.

  • Create a version for the existing code (4.3.0.210)
  • Create a version for the latest file install available (4.5.12.204)

For both versions, add at the start and end of each version block a “for/endfor” statement, which references the version number as the string.

Change the version numbering at the start of the block to the variable {{ version}}. This will now be populated by the “for” statement that precedes it.

For the “full_name” property, remove the static version number and add in the variable.

  • Update the newer version code block to match that as seen when we ran pkg.list_pkgs

Focusing on just the changes needed in the new version block

  • Remove the “If” statement that sets the “Program Files” variable
    • Add in a “set” statement to configure the variable to the correct location.
  • Update the “uninstaller” location to the correct location and file
  • Update the “uninstall_flags” to use the correct ones
    • There’s no documentation from MalwareBytes on this, so it was some googling and trial and error running the commands manually to find the right ones.

And that’s it and done. Giving you the code below.

# Source: http://www.malwarebytes.org
malwarebytes:
  {% for version in ['4.3.0.210'] %}
  # just 32-bit x86 installer available
  {% if grains['cpuarch'] == 'AMD64' %}
      {% set PROGRAM_FILES = "%ProgramFiles(x86)%" %}
  {% else %}
      {% set PROGRAM_FILES = "%ProgramFiles%" %}
  {% endif %}
  '{{ version }}':
    full_name: 'Malwarebytes Anti-Malware version {{ version }}'
    installer: 'https://data-cdn.mbamupdates.com/web/mb4-setup-consumer/MBSetup.exe'
    install_flags: '/SP- /VERYSILENT /SUPPRESSMSGBOXES /NORESTART'
    uninstaller: '{{ PROGRAM_FILES }}\Malwarebytes Anti-Malware\unins000.exe'
    uninstall_flags: '/SP- /VERYSILENT /SUPPRESSMSGBOXES /NORESTART'
    msiexec: False
    locale: en_US
    reboot: False
  {% endfor %}

  {% for version in ['4.5.12.204'] %}
  {% set PROGRAM_FILES = "%ProgramFiles%" %}
  '{{ version }}':
    full_name: 'Malwarebytes version {{ version }}'
    installer: 'https://data-cdn.mbamupdates.com/web/mb4-setup-consumer/MBSetup.exe'
    install_flags: '/SP- /VERYSILENT /SUPPRESSMSGBOXES /NORESTART'
    uninstaller: '{{ PROGRAM_FILES }}\Malwarebytes\Anti-Malware\mbuns.exe'
    uninstall_flags: '/SP- /VERYSILENT /SUPPRESSMSGBOXES /NORESTART'
    msiexec: False
    locale: en_US
    reboot: False
  {% endfor %}

Now that’s all that’s left to do is update our minions with the new file on our system. And apply the state file again.

First we can run the “slsutil.renderer” on my test machine to make sure my new file renders correctly.

salt win-repo - debug - slsutil.renderer - test new SLS file

And finally applying the state file.

"return": {
      "pkg_|-ensure_malwarebytes_installed_|-ensure_malwarebytes_installed_|-installed": {
        "name": "ensure_malwarebytes_installed",
        "__id__": "ensure_malwarebytes_installed",
        "result": true,
        "__sls__": "Windows.software-install.malwarebytes",
        "changes": {
          "malwarebytes": {
            "new": "4.5.12.204",
            "old": ""
          }
        },
        "comment": "The following packages were installed/updated: malwarebytes",
        "duration": 127472.689,
        "start_time": "17:45:28.779065",
        "__run_num__": 0

 

Regards

Dean Lewis

Leave a Reply

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

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