Work

Reinstalling Connectwise Automate (Labtech) on Linux machine after cloning a disk in Azure

Connectwise Automate / Labtech agent icon

This is a pretty basic post and doesn’t go into the requirements to do a Linux version of sysprep, but I needed to temporarily clone a RedHat server in Azure that had the Connectwise Automate agent on it this morning. After a reboot, the server was showing up in Automate as the same id as the previous server which is not what we needed.

The documentation for the Linux agent is pretty lacking and restarting agents did not seem to fix the issue.

By changing into the location of the Automate agent, you can run the uninstaller.sh app and then reinstall with a new installer.sh that is typically going to be already downloaded to your home/ltechagent directory. Poking around it was easiest to remove and readd as a new agent.

Documenting as I’m sure I or other people will need this again.

cd /usr/local/ltechagent
sudo ./uninstaller.sh
cd ..
ls  -al
#No lttechagent directory should exist anymore

#change to location where labtech installer was downloaded, typically in the home directory and already unzipped.
cd ~/ltechagent
chmod +x install.sh
sudo ./install.sh
ps -ef | grep ltech
#Should see two results of the agent running
#View results of install
cat /tmp/ltech_install_log.txt
#refresh Automate console to see machine showing up correctly

Using Microsoft Graph Update-MgGroup with Certificate Based Authentication as a working alternative for Set-UnifiedGroup

Yesterday I had a fun time converting a PowerShell script that used the set-unifiedgroup powershell command that was originally running with basic authentication, to a script that would run using certificate based authentication so it can run against a tenant that uses Modern Authentication for office365.

There were quite a few hurdles to overcome so hopefully this helps other people.

Step 1 – Fix Office365 logins

Blank browser page that loads when attempting to log into Office365

The computer was initially generating a blank white page on the screen when attempting to log into the Office365 or Azure portal. This was resolved by resetting the browser settings in Control Panel / Internet Options. Clearing cookies and temporary internet files did not help for this step.

Step2 – Connect to Office365.

The ExchangeOnline module was already installed on the computer, but needed to be updated with

 update-Module -Name ExchangeOnlineManagement

The rest of this phase reduced the previous 5+ lines of code to log into Office365 to a one liner. There are quite a few steps involved in this, but App-only authentication in Exchange Online PowerShell and Security & Compliance PowerShell | Microsoft Learn is a good document to follow. Make sure that the SSL certificate is documented somewhere so that you get a reminder *before* the certificate expires. Once the certificate is uploaded to Azure and permissions are set it is possible to connect with

connect-exchangeonline -CertificateThumbprint "1a2b3c4d5e6f....." -appid "123abc-456def...." -organization "companyname.onmicrosoft.com"

Initially I thought that would be it, but after running the script I discovered the next big snag –

Step3 – Converting set-unifiedgroup to MS Graph module equivalent

The script gathered a list of Microsoft 365 distribution groups (or UnifiedGroups) in Office365 that had their access level not set to private and changed them to be private. The previous code was this

Get-UnifiedGroup -ResultSize Unlimited | Where-Object { $_.primarySmtpAddress -match 'companyname.onmicrosoft.com' -and $_.accesstype -ne 'Private' -and $_.HiddenFromAddressListsEnabled -ne 'true' } | Set-UnifiedGroup -AccessType Private -HiddenFromAddressListsEnabled $true -verbose

However, set-unifiedgroup is one of a few commands that cannot be used with Certificate Based Authentication and the msgraph module has to be used instead. The Microsoft documentation points this out but does not provide helpful information on how to actually get this accomplished. The linked information refers to api calls rather than using actual Microsoft Graph PowerShell commands and there were several gotchas in this process (hence this blog post).

First the Microsoft graph module needs to be installed on the computer with

Install-Module Microsoft.Graph

Step3a – Importing Microsoft.Graph.Groups

When importing the Microsoft.Graph module on the machine into PowerShell , not only did it take over 10 minutes to import, an error message is generated stating

Import-Module : Function Get-MgUserContactFolderChildFolderContactMultiValueExtendedProperty cannot be created because<br>function capacity 4096 has been exceeded for this scope.
Screenshot error stating Import-Module : Function Get-MgUserContactFolderChildFolderContactMultiValueExtendedProperty cannot be created because
function capacity 4096 has been exceeded for this scope.

This is due to the sheer number of commands available in the module and PowerShell 5.1 has a limit to the number of commands that can be used. Using PowerShell 7 is one way of fixing that issue but I was trying to reduce the amount of changes being made to this pc. By importing a subsection of the module with import-module microsoft.graph.groups the number of commands that are available is greatly reduced and the import is also a lot quicker. 10 seconds to run instead of over 10 minutes from above.

Step3b – Filter left

The original search returned all groups in Office365 and then filtered them locally. In this large organization, there are a significant number of groups returned and the lookup took several minutes to run. By passing a filter parameter I was able to reduce the number of groups significantly.

Unfortunately the filter parameter does not support accesstype or the primarysmtpaddress so these have to be filtered out by piping the groups to a select-object statement.

Get-UnifiedGroup -ResultSize Unlimited | Where-Object { $_.primarySmtpAddress -match 'companyname.onmicrosoft.com' -and $_.accesstype -ne 'Private' -and $_.HiddenFromAddressListsEnabled -ne 'true' }

becomes

$groups=get-unifiedgroup -filter {(hiddenfromaddresslistsenabled -ne $true)} | where-object {$_.primarysmtpaddress -match 'companyname.onmicrosoft.com' -and $_.accesstype -ne 'Private'} 

After making this change, the groups were returned in less than a minute.

Step3c – Changing from set-unifiedgroup to Update-MgGroup

The new command to modify the group is update-mggroup but the standard command does not have the ability to change the access type as per the documentation at Update-MgGroup (Microsoft.Graph.Groups) | Microsoft Learn

Screenshot for the update-MgGroup command that is missing the AccessType parameter

However, after switching the document to the Beta version of the api in the dropdown menu on the left, the accesstype parameter becomes available. The above screenshot shows AccessType is missing vs the screenshot below that includes this option.

Screenshot of the update-MgGroup beta command that includes the AccessType parameter

We therefore end up with the following commands to set the profile to Beta, load the Microsft.Graph.Groups subset of the module and then connect to Microsoft. Graph

Select-MgProfile -Name "beta"
import-module microsoft.graph.groups
connect-mggraph -clientid "1a2b3c4d5e-1234-1a2c3-a1aa-aa12b3456c7d" -tenantid companyname.onmicrosoft.com -certificatethumbprint "0a4f....fe"

I had issues with the next bit of code and ended up using my Exchange online connections to retrieve the groups that matched the criteria of not being hidden from the address list and where the access type was not private, and then using the ExternalDirectoryObjectID from those groups in the update-mggroup command from the graph module.

In theory I should have been able to search using the get-mggroup command but I was having issues getting the filters and search to work correctly. I could not get any results to come back for searches that included the companyname.onmicrosoft.com email address. As soon as I added that to the criteria the results came back empty. Due to time constraints I used the (admittedly) messy option of using Exchange to grab the groups and graph to update them.

$groups=get-unifiedgroup -filter {(hiddenfromaddresslistsenabled -ne $true)} | where-object {$_.primarysmtpaddress -match ‘companyname.onmicrosoft.com’ -and $_.accesstype -ne ‘Private’}

foreach ($group in $groups) {
update-mggroup -groupid $group.ExternalDirectoryObjectId -accesstype "Private" -HideFromAddressLists
}

Finally, the script was completed by disconnecting the Graph and the Exchange connections

get-pssession | Remove-PSSession
Disconnect-MgGraph
Stop-Transcript

Using the transcript option at the beginning of the script really helped in debugging this code as it’s meant to run from a scheduled task and viewing the transcript enabled me to see what the issue was and then decide to test further in an interactive session.

SQL, dbatools and Webroot

I have been busy working on a SQL server migration, and have come across a couple of issues.

Firstly, attempting to install or upgrade an SQL instance with Webroot on the machine generates an unauthorized action on the machine. Reviewing the error logs provides the following error

Exception type: Microsoft.SqlServer.Configuration.Sco.ScoException
Message: 
Attempted to perform an unauthorized operation.
HResult : 0x84bb0001
FacilityCode : 1211 (4bb)
ErrorCode : 1 (0001)
Data: 
WatsonData = Uninstall@{145996FC-8E6B-47AB-BEA5-A84F12B72AF5}

Navigating to HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall registry shows the value {14599…..} is Webroot. Set server into unmanaged mode and then removing Webroot then enabled me to install SQL service packs.

I’ve also run into the same issue on new installs which leads me to the second issue.

I’m using dbatools to install with notes taken from the newly printed dbatools in a month of lunches. A book I purchased pre-pandemic and promptly forgot about but I finally got my hands on the book.

dbatools is a fantastic resource for SQL admins who want to automate everything and a common task is installing SQL.

Unfortunately there’s a typo in Listing 13.6 and 13.7 The parameter SQLUSERDBDATADIR that is coded into the sql config.ini file should actually be SQLUSERDBDIR

It took me a while to figure that one out. I then went to check out the books online only to find someone had found and reported the same error – yesterday!

The moral of the story is to check the books online first.

Also, whilst looking at my Manning books – I have a Powershell problem (or maybe with all these books I don’t!

Listing of Powershell books from Manning Publications

Fixed: 161008 The source virtual machine doesn’t have a network interface or all the network interfaces were deleted when using Azure Migrate

I’ve been working on an Azure Migrate project at work this week and had an interesting issue after attempting to start a replication of the source servers. The configurations were brought in from the Azure Migrate assessment tool but I received an odd error that there was no connected network interface on the source server.

This is a very strange error as all the source servers do have network interfaces otherwise there would not be much point in migrating them up to Azure! The error id 161008 and messages of “No connected network interface is configured for the virtual machine” and “The source virtual machine doesn’t have a network interface or all the network interfaces were deleted” did not make much sense, however the recommendation of “If there is no network interface on the source machine, add one and then go to Computer and Network settings of the virtual machine to configure the network interface” was a slight clue.

error id 161008 and messages of No connected network interface is configured for the virtual machine" and The source virtual machine doesn't have a network interface or all the network interfaces were deleted

Part of the solution steps imply that you create a nic on the server, but as the server has not actually been created in Azure yet, this step is not possible and the source server obviously has nic’s already setup so no change can be made on that server.

After getting a second pair of eyes on the issue (Thanks A!) , we had an Aha moment in the Compute and Network section of the server setup. The Assessment had set the nic’s on the machine to Do not Create and Secondary Network. As there was no primary nic configured on this page, the error message above is generated. Setting the Secondary nic to Primary rather than Secondary enabled the replication to start successfully.

Screenshot of configuring Compute and Network for an Azure migrate server

2 lessons from this – Always ensure you have a primary nic configured when using Azure Migrate. Get a second pair of eyes for that fresh look at the problem as sometimes you just can’t see the wood for the trees.

Fixed: Powershell prompts to run scripts when importing sessions – change %temp%

Powershell Security warning

My new work computer has had issues attempting to run Office365 commands for a while. After successfully connecting to Office365, using connect-exchangeonline (as an example), I would get a security warning – “Run only scripts that you trust. While scripts from the internet can be useful, this script can potentially harm your computer. If you trust this script, use the Unblock-File cmdlet to allow the script to run without this warning message. Do you want to run c:\temp\temp\tmp_rnncyvj4.v10\tmp_rnncyvj4.v10.format.ps1xml?
[D] Do not run [R] Run once [S] Suspend [?] Help (default is “D”):

And this would repeat with the appropriate .psm1 file too.

The usual solution is to use unblock-file or set-executionpolicy -remotesigned.

However, in this case the files are dynamically downloaded and will have a different filename everytime and setting the execution policy did not make any difference.

I ended up changing my temp folder from c:\temp\temp to c:\andy\temp and now I no longer get prompted.

Very odd behaviour that is not too annoying until you run scripts across all the office365 tenants!

Fixed: ScreenConnect / Control missing from Labtech / Automate

Automate screenshot

For the past two days my Automate window was missing all of the Screenconnect plugins that allow one click remote access to client machines. Both the one that shows at the top of the computer list and also when the machine window is launched. (Screenshot below shows how it should look)

Screenshot showing the control icon in Automate for computers

A reinstall of the software (including renaming the left over Labtech files in Program files and Program Data after removing the software) did not fix the issue.

However, reviewing the C:\ProgramData\LabTech Client\Logs\yyyymmdd_LTcErrors.txt showed lots of plugin exceptions including the following:-

An attempt was made to load an assembly from a network location which would have caused the assembly to be sandboxed in previous versions of the .NET Framework. This release of the .NET Framework does not enable CAS policy by default, so this load may be dangerous. If this load is not intended to sandbox the assembly, please enable the loadFromRemoteSources switch. See http://go.microsoft.com/fwlink/?LinkId=155569 for more information

Following that link provided the hint that loadFromRemoteSources needs to be enabled.

Editing “C:\Program Files (x86)\LabTech Client\LTClient.exe.config” and adding <loadFromRemoteSources enabled=”true”/> just before the /runtime> line, Automate now includes the control button.

LTClient config file showing the loadfromremotesources element

Fixed: Lastpass seems to randomly add incorrect data to Forms.

We use a web based documentation system at work and have had a couple of instances where data for companies (ie Company X) seems to have been randomly edited in forms to include data from another form (ie Company Y) in the system. In a form that had a username, password, url and notes field we discovered that a tech could go in and edit the notes (and only the notes field) and without realising it, the username and password were also being updated in the form. The tech would hit save and now the saved password was incorrect.
Thankfully the documentation system has revision histories to allow us to revert back to the previous settings. but it is still a painful process to go back and review recent changes to see which ones were genuine edits and which were changed incorrectly.

We initially blamed it on LastPass filling out data as the issue would not occur if we disabled LastPass, however a search in LastPass would not return the data that was being added to the form. It took us a while to track down, but Chris, one of our techs worked out what was going on.

Sample lastpass password screen with extra field button highlighted

LastPass has additional fields that don’t show up when you browse (and apparently search) and the data from these extra fields were automatically being filled in for some reason. Click the wrench, highlighted in the above screenshot to see the extra hidden fields.

Our solution was to delete these extra fields, save the record in LastPass and we no longer have LastPass corrupting our data.

Happy Anniversary Absoblogginlutely!

16 years ago today I registered Absoblogginlutely.net and started to blog at this location. I totally missed the fact that back in March, helsby.net became 20 years old, a domain that I registered as an early birthday present to myself and is now used as my main email service.
This means I’ve been blogging on or off for about 20 years – how time flies!
Unfortunately I’ve not been updating this blog as often as I’d like as a lot of the tweaks and discoveries that I would normally blog about have become more work related and therefore more confidential.
However I would like to get back into the habit of documenting more so watch this space.
I’m heading to the Columbus Infosec Summit on Thursday and Friday this week which has always been full of interesting talks and demonstrations. It is sold out, but the twitter tag is .

Paula Januszkiewicz is one of the keynotes this year and her presentations are always valuable with a lot of takeaways and simultaneously manages to impress and scare me with the state of IT Security nowadays.

Fixed – Screenconnect blocked by Windows Smartscreen

Due to an expired code sign certificate, the version of Screenconnect that is launched from Connectwise Automate (aka Labtech) fails to run on 2 of my Windows 10 machines but works fine on the rest of the machines. The error message “Your administrator has blocked this application because it potentially poses a security risk to your computer”. The ones that fail are running Windows 1809 and 1903 so I suspect that there is some of the new features of SmartScreen are enabled and older versions do not have these settings.

Your administrator has blocked this application because it potentially poses a security risk to your computer

Checking out the file used for Screenconnect, I saw that the certificate used to sign the exe file expired on February 1st this year, but I’m not sure why my machines suddenly started to refuse to run it the last few days of March.

The Screenconnect.WindowsClient.exe is downloaded to a random subdirectory of appdata\local\apps\2.0 so I recommend you navigate to this directory and then search for *.exe and check the correct screenconnect file as per the screenshot below which shows the certificate expiring on the 1st February

ScreenConnect certificate expiry dates

After searching around and contacting Connectwise Support they advised me this would be fixed in an upcoming version. In the meantime setting the registry value HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft.NETFramework\Security\TrustManager\PromptingLevel\Internet to a string type of Enabled will allow the ClickOnce application to popup and this allows the dialog box to give an option as to whether the file should be run or not (the previous setting was Disabled). This then allows the user to select yes to install and run the file overriding the invalid SSL certificate.

Obviously this is not a great idea but it does allow you to run Screenconnect from within the Automate window. (The other alternative is to use the Screenconnect website itself to connect).

Fixed: PDF’s will not load over insecure http but will on secure https (if you have a Meraki firewall)

Had a weird issue this morning where pdf files that were served over http were getting blocked and would not load. Some sites also have https so we were able to just change the url to https and the file would then download.

After checking various browser settings I checked the Meraki firewall. By Disabling the Advanced Malware Protection (AMP) under Security/Threat Protection the files were downloaded successfully.
Instead of leaving AMP off, I then put a whitelist url of http://*.pdf and now pdf files load successfully with AMP still protecting the network.

Whitelisting pdf files in Meraki
Meraki pdf whitelisting

The frustrating thing is that AMP does not seem to be logged anywhere so it was not obvious that this was the cause of the problem. It also turns out that this has been a problem with AMP in the past as this 2 year old thread on Reddit shows!