Creation of Custom Activity Actions

Overview

Thanks to all the snow my area got, I had some time inside to play around in my test environment. During this time, I dug into the guts of the NPS application, with no set goal in mind besides the curiosity of wondering how everything works under the hood. As someone who has had to work with support on resolving a few separate issues within the database, that seemed like a good place to start. In this exploration of the database schema and structure, I discovered something exciting, the structure and functionality for creating custom activity actions is already in place! Hopefully I’m not spoiling a big reveal from the Netwrix team, but below I will show you how to manually add entries to the database to create your very own custom activity action complete with it’s own custom parameters, as shown here!

Description

First off, lets get a big warning/disclaimer out there that you shouldn’t be directly messing with your production database just because I showed you this.

DISCLAIMER: DO NOT DO THIS IN YOUR PRODUCTION ENVIRONMENT. THERE IS NO TELLING WHAT ISSUES MAY ARISE FOR YOU, IF UPDATES WILL OVERWRITE THIS DATA, OR IF YOU WILL BREAK SOMETHING. THIS IS JUST A PROOF OF CONCEPT TO SHOW OFF THE CAPABILITY ALREADY WITHIN THE PRODUCT.

With that out of the way, lets talk about this cool functionality! To start, lets discuss a bit about the NPS database and version. In my test lab here, NPS is running version 25.12.00001 on a single node with the postgres16 database on the same box, and I will be assuming you are running in the same way. Additionally, I have modified my pg_hba.conf to allow connections to the DB without a password from the localhost; don’t do this if it isn’t in a test lab. Once connected to the database (see changing NPS default postgresql user if you need to change the DB credential), we can see the list of tables . The ones we are most interested in are related to actions, specifically the action_template and action_template_parameter tables (also notice the action_parameter table for possible future post if there’s interest):

SELECT table_name FROM information_schema.tables WHERE table_name LIKE '%action%';

If we query the data within the action_template table, we can see some familiar actions, the built-ins! Interestingly, all the built-in actions are doing, are calling scripts from within the SbPAMScriptDirectory and passing along parameters. This means we can hook in our own custom scripts or really anything. I’ve limited the output of this command for readability.

SELECT id,display_name,icon,definition FROM action_template LIMIT 20;

If we want to create our own custom action, we can simply run the below command adjusting the values as necessary. The node_id is required, so the below command is pulling it from the node table for you, but if you have multiple instances it might make a difference. I don’t know for sure what the node is really referencing. You can change the icon to specific values per the chart below, and feel free to change the definition, or command you want to run, as you see fit. The current command definition will simply create a file named test in the ActionServiceWorker directory with the SbPamScriptDirectory value in it.

icon values
groups
add
file
sync
arrow-up
terminal
protection
server
user
host
domain
arrow-down
INSERT INTO action_template (display_name,description,icon,definition,user_defined,node_id)
SELECT 'Community Post','Congrats on your custom action!','terminal','Invoke-Expression ''Set-Content -Path "C:\Program Files\Stealthbits\PAM\ActionServiceWorker\test" -Value "We did it! - $SbPAmScriptDirectory"''',FALSE,node.id
FROM node
LIMIT 1;

Once ran, we need to restart the NPS Proxy service, this will restart all required services alongside it. Once restarted, lets see our new action!

If we run an activity using this action, we can see that we get a file output in the directory showing we successfully got code to execute!

But how do we add in those fancy parameters that things like the built-in actions can do? Well that’s where the action_template_parameter table comes in! Lets go ahead and add a custom text field, a restricted dropdown list and a checkbox to our action. Running the below commands will create them all. To define what kind of parameter these will be is a bit tricky as it depends a bit on the type column, but also the value_set column. Unfortunately, besides trial and error I don’t see references to what each type are specifically supposed to be/do.

--Text field
INSERT INTO action_template_parameter (name,display_name,description,required,action_template_id,type,limit_to_value_set)
SELECT 'CustomParameter','Custom Parameter','A custom text parameter for the community!',FALSE,action_template.id,5,FALSE
FROM action_template
WHERE display_name LIKE 'Community Post'
LIMIT 1;

--Dropdown with required fields
INSERT INTO action_template_parameter (name,display_name,description,required,action_template_id,type,limit_to_value_set,value_set)
SELECT 'CustomParameter2','Custom Parameter2','Another custom parameter for the community?!',FALSE,action_template.id,5,TRUE,'["Option1","Option2"]'
FROM action_template
WHERE display_name LIKE 'Community Post'
LIMIT 1;

--Checkbox
INSERT INTO action_template_parameter (name,display_name,description,required,action_template_id,type,limit_to_value_set)
SELECT 'CustomParameter3','Custom Parameter3 Checkbox','A custom text parameter for the community!',FALSE,action_template.id,17,FALSE
FROM action_template
WHERE display_name LIKE 'Community Post'
LIMIT 1;

Now, restarting our NPS proxy service again, we can refresh the web UI. Looking at our action now, we can see our parameters are added!

Closing Notes

Now I know this was a somewhat pointless endeavor since this is 100% unsupported in any production environment; however, the fact that the structure is already present for this ability has me hopeful that we will have custom actions coming in the future as it seems to just need web UI elements. Additionally, I enjoyed diving into the NPS database and seeing how things tick. These custom actions are just one of the few things I discovered and plan to write up if people are interested in these types of posts. Specifically regarding these custom actions, besides simply executing the code, our custom parameters are also created as PowerShell variables and can be directly referenced by their name (not their display_name), IE: $CustomParameter can be called from our example to retrieve that data! The potential to build very powerful third party actions is very exciting. If you’re still reading this far, I hope you enjoyed the read and gained at least something from it. If you have any questions/concerns/interest in this topic, feel free to reply or message me, there is a decent bit of other information around this I gathered from testing that doesn’t fit into this post without dragging it out too much.

This is awesome @DavidHenry! :snowflake: :rocket: