Skip to main content

Homotechsual Discord NinjaOne Discord GitHub contributors Azure DevOps Pipeline Status Azure DevOps Code Coverage License GitHub Sponsors

This is a work in progress

NinjaGet and it's documentation are a work in progress and may not be 100% feature complete. Work continues with the expectation being that it'll be at our minimum viable product (MVP) stage by the 15th October 2023. At this stage consider this alpha quality and use for testing and feedback only!

During this period you'll need to look at the dev branch on GitHub for the NinjaGet code. GitHub's docs explain how to view other branches.

About

NinjaGet is the evolution of a script we developed in-house to automate our third-party patching using, whereever possible, the Microsoft WinGet package manager - part of our continuing drive to reduce additional attack surface and third-party dependencies on our endpoints.

Windows includes a package manager, we thought, so why not use it.

In various discussions in the NinjaOne users community I mentioned this and was asked to share it. I was quick to say "sure" and started looking at what it'd take to polish it up and make it a bit more "consumable" for the wider community. I quickly realised that it was going to be a lot more work than I'd anticipated.

So, I decided to start from scratch and build something that was more "community friendly" from the ground up. NinjaGet is the result of that effort, around 12 months of work and morphing into something which isn't easily comparable to the original script that inspired it.

Installing

Installing NinjaGet is basically as simple as putting the contents of the GitHub Repository somewhere on your endpoints and running the NinjaGetEntryPoint.ps1 file in Setup mode. Setup mode will create the required folders and files and then exit. Read the note below about security before you do this though and then checkout the Example Install Script section for an example of how you might do this.

Forking Review it!

In the interests of security, I strongly recommend that you fork the repository and review the code before installing it. I'm not saying that we're doing anything malicious, but I am saying that you should be careful about what you install on your endpoints. I'm not responsible for any damage caused by the use of this tool.

The code is available on GitHub and contributions and feedback are welcomed. Code is all plain-text PowerShell and should be easy to review. If you find any issues, please raise them on the GitHub Issues page.

In the interests of making testing the development version easier - you shouldn't fork the dev branch and instead when testing the development version you should use the main repository. The example install script for dev below reflects this.

Installing the Dev Branch

If you're installing the dev branch there's a couple of extra steps since a lot of the setup logic assumes it'll run as SYSTEM. You'll need to run the install script as SYSTEM using PSExec or NinjaOne. Unfortunately getting PSExec is a bit of a pain (it's not on WinGet yet!).

You can download PSExec from Microsoft's Sysinternals site.

You can then invoke the install script using:

C:\path\to\psexec -s -i powershell.exe -File .\ExampleInstallScript.ps1

Or if you want an interactive session:

C:\path\to\psexec -s -i powershell.exe

You might need to adjust your execution policy to allow the script to run. You can do this using:

Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope Process

Example Install Script

You'll need to run the below as SYSTEM. Use NinjaOne or PSExec

# URL to your fork of the repository
$NinjaGetRepo = 'https://github.com/YOURUSERNAME/ninjaget' # Note the lack of trailing `/` please.
$NinjaGetPath = (Join-Path -Path $ENV:ProgramData -ChildPath 'NinjaGet')
$NinjaGetTempExtractionPath = (Join-Path -Path $ENV:Temp -ChildPath 'NinjaGet')

# Download the repository
$NinjaGetDownloadZip = ('{0}/archive/main.zip' -f $NinjaGetRepo)
$NinjaGetDownloadFile = ('{0}\NinjaGet.zip' -f $ENV:Temp)

# Create the NinjaGet folder
if (-not (Test-Path -Path $NinjaGetPath)) {
New-Item -Path $NinjaGetPath -ItemType Directory -Force
}

# Download the repository
Invoke-WebRequest -Uri $NinjaGetDownloadZip -OutFile $NinjaGetDownloadFile

# Extract the zip file to temp.
Expand-Archive -Path $NinjaGetDownloadFile -DestinationPath $NinjaGetTempExtractionPath -Force

# Copy the contents of the extracted folder to the NinjaGet folder

Copy-Item -Path ('{0}\ninjaget-main\*' -f $NinjaGetTempExtractionPath) -Destination $NinjaGetPath -Force -Verbose -Recurse

# Remove the downloaded zip file
Remove-Item -Path $NinjaGetDownloadFile -Force

# Remove the extracted folder
Remove-Item -Path $NinjaGetTempExtractionPath -Force -Recurse

# Confirm that we have the `NinjaGetEntryPoint.ps1` file
if (-not (Test-Path -Path ('{0}\NinjaGetEntryPoint.ps1' -f $NinjaGetPath))) {
throw 'Unable to find the NinjaGetEntryPoint.ps1 file. Please check the installation.'
}

# Setup parameters
$SetupParameters = @{
Operation = 'Setup'
InstallPath = $NinjaGetPath
}

# Run the entry point in setup mode

Set-Location -Path $NinjaGetPath
.\NinjaGetEntryPoint.ps1 @SetupParameters

This example downloads the ZIP containing the NinjaGet source to $ENV:Temp and then extracts the contents to C:\ProgramData\NinjaGet\.

Project Structure

The project splits functions over various files grouped, broadly, by theme - e.g NinjaGet.Functions.RMM.ps1 holds RMM related functions.

Full documentation of the functions is available in the Functions section of the documentation.

ToDo: Write functions documentation.

Settings

The NinjaGetEntryPoint.ps1 file allows you to configure a number of settings, generally used alongside the Setup operation and written to the registry at HKLM:\SOFTWARE\NinjaGet. These settings are used by the various functions to control their behaviour. The settings are documented in the Settings section of the documentation.

Getting Started

This section has outgrown this page and has been moved to it's own Getting Started section.

Still To Come

There's a bunch of functionality that exists in theory but hasn't been 'wired up' yet, so things to look forward to are:

  1. Invoke the app install and uninstall methods separately from the process loop.
  2. Uninstall NinjaGet from devices - exists but the entry point hasn't been wired up yet.
  3. Reporting to NinjaOne, so you can see what's been installed and uninstalled. This will be in your script run activities anyway but it'll be nice to have it in the UI as well - might need changes on the NinjaOne side for this.
  4. Logic to close apps before updating or uninstalling them with the ability for users to defer the update or uninstall if they're busy (longer term goal - at the moment using the update at login option via Task Scheduler or NinjaOne automation scheduling is probably the best way to handle this).
  5. Logic to handle apps that require a reboot after install, update or uninstall.
  6. Feature requests from the community.