Overview
Rambling
One of my favorite things about events like the PowerShell + DevOps Global Summit is the opportunity to chat with so many folks in the PowerShell community. Invariably, you end up bringing back a wealth of fun ideas.
This year, Brandon Olin gave an awesome lightning demo on PoshBot, a PowerShell-based bot framework. It’s not quite as mature as Errbot or Hubot, but it’s a super quick way to get a bot up and running for folks using PowerShell!
Why ChatOps? Why Bots?
I’ll let someone more well versed in the topic handle this - Jason Hand has a great beginners guide to ChatOps. Long story short?
- Communication - avoid certain folks monopolizing discussions, allow quiet folks to get important details out, keep everything in a searchable medium for new and existing team members
- Transparency - information isn’t hidden in e-mail threads that new or excluded folks will never see - everything is searchable, and ideally you do work in open channels
- Sharing - tools and ideas can be shared in a single spot
- Learning - find details on old topics that never made it into docs, see how people solve things with bots
- Automated communication - changes to code, deployments, alerts, etc. can be sent to chat
- Security - Guardrails and other safeguards can reduce risk (consider what JEA provides)
- Incident response - keep incident communication in central, searchable location, not a bunch of incomprehensible e-mail threads
- Provide an interesting balance between creating a web interface or GUI for a PowerShell script, and forcing folks to use PowerShell
- Share gifs
I could be off base, but I also see this as a prerequisite for effective remote work.
So! Hopefully you’re interested in checking this out. It helps if your team is already using something like Slack.
Let’s dive in and start using PoshBot!
PoshBot
We’re going to cover the basics to get up and running with PoshBot:
- Create a Slack bot
- Create a PoshBot configuration
- Run PoshBot as a service
- Write a PoshBot plugin
- Use PoshBot
This might seem like a lot of work, but the configuration and service are a one time thing - Writing plugins is just like writing PowerShell functions and modules!
Create a Slack bot user
This assumes you have admin privileges to your Slack team:
- Add a new bot integration:
https://YOUR-TEAM-HERE.slack.com/services/new/bot
- Name the bot - we’ll use
testbot
- Optionally, pick an icon
- Copy the resulting token for the bot config. Keep this safe!
We have our token, let’s get a bot configured!
Configuring PoshBot
There’s more you can configure, but we’ll start with the basics. Keep in mind you might abstract this into your configuration management system, use infrastructure as code, etc.
That’s it! We can quickly test this interactively: Start-PoshBot -Configuration $pbc -Verbose
We should see the bot load up and start listening:
VERBOSE: Creating new Slack backend instance
VERBOSE: Creating bot instance with name [testbot]
...
VERBOSE: [SlackBackend:LoadUsers] Adding user: REDACTED:wframe
...
VERBOSE: [Group: AddUser] Adding user [REDACTED] to [Admin]
If we look in Slack, we’ll see the bot in the list of users, but we still need to invite it to any channel we want to use it in - /invite @testbot
. You can also DM the bot.
That’s it, we have a bot! Let’s set it up to run as a service.
Run PoshBot as a service
There are several ways to run PowerShell as a service; We’re going to use nssm - it’s a bit simpler than some of the alternatives.
First things first - we need the script that will run as a service - C:\poshbot\start-poshbot.ps1
. This is pretty bare bones, you could do more:
Basically, read the config, run Start-Poshbot. Forever. Okay! Let’s run this as a service:
If all went well, in a few seconds we should see testbot
online in our Slack team again!
Now for the fun part. Let’s write a quick PoshBot plugin!
Write a PoshBot plugin
A PoshBot plugin is basically a PowerShell module with a few PoshBot bits. We’ll skip the typical module scaffolding to keep our example simple.
We’ll create our poshbot.example module in our plugins directory:
$null = mkdir C:\poshbot\plugins\poshbot.example -force
Next, we’ll create a quick module manifest, Poshbot.Example.psd1
:
The key bits are to require PoshBot, and while not mandatory, describing the permissions can be helpful.
Finally, we’ll draft a quick module script, Poshbot.Example.psm1
:
Whew!
The key bit here is the [PoshBot.BotCommand()]
custom attribute - we use this to tell PoshBot what the command name is (if different from function name), permissions required to run this, and aliases that will also call this command.
So, that !user
command is pretty ugly. Unfortunately, we’re no longer in PowerShell land, where we write commands that do one thing and do it well, using the pipeline to connect things together.
Some things you might consider:
- Add different format options. A table is pretty and easy to digest, but won’t always cut it
- Provide PowerShell-esque Verb-Noun names, but add aliases for everything. Short commands and parameter names are important, when you don’t have tab completion or intellisense
- If it makes sense, add the ability to specify what properties to output, and pick a sane default
- If it makes sense, consider writing a file and uploading it to Slack (e.g. a graph png, a spreadsheet), or linking to external URLs
- Publish your module to the PowerShell gallery with a name starting
Poshbot.
- PoshBot will automatically find these when you use!Find-Plugin
We’ve written a PoshBot plugin - how do we use it?
Using PoshBot
So! We have a bot, it’s running as a service, and we’ve started writing some custom commands - let’s play!
install-plugin poshbot.example
!user wframe
Oh. We have to deal with access controls first!
PoshBot Access Controls
We’ll create a group and role, tie the group to the role, tie permissions to the role, and add users to the group:
!New-Group sysadmins
!New-Role sysadmins
!Add-GroupRole sysadmins sysadmins
!Add-RolePermission sysadmins poshbot.example:read
!Add-GroupUser sysadmins wframe
And finally: !user wframe
Getting Help
How did we know how to do that? Mostly reading docs, but you can also use the !help
command if you ever forget a command name or syntax:
!help
!help example:user
Note that we need to specify enough of a command for it to be unique before we get the full help, we can’t just use user
.
Running Commands
We’re ready to go! Some quick examples using our functions:
- Use an arbitrary LDAP filter, and specify some specific properties to return:
!user --l '(mail=wframe*)' --p samaccountname, displayname, enabled
- Check out what variables are available when in a PoshBot function:
!var
That’s about it! Now you know how to start up your own PoshBot in Slack, and write custom commands.
What’s Next?
Many folks start with read-only commands until they get comfortable with things. Some example tasks you might write commands for:
- Get stuff from AD - groups, group membership, users, etc.
- Do stuff in AD - disable or unlock accounts, kick off replication
- Get stuff and do stuff from a variety of other systems!
- Tickets
- Configuration management systems
- CMDBs or other inventory sources
- IPAM systems
- Monitoring systems
- Databases
- etc.
- Restart services and servers
- Kill stuck sessions
- Query log data, performance data, etc. - this can be text, graph based, anything else (you can create and upload arbitrary files!)
- Provide quick shortcuts to common docs
For all of these, you’ll need to consider a way to provide access to your service account. Some common approaches:
- If possible, use a password manager, or serialize credentials via DPAPI so that your service account can read them and use them in commands
- You might create delegated, constrained endpoints, or use JEA
- You might run the service as an account that has delegated access (be extra cautious here), etc.
Consider read-only accounts, or delegating only the privileges needed for any approach you take. Also, you might classify your system appropriately to ensure appropriate security controls are in place : )
Unfortunately, some folks are apprehensive about bots. What if something breaks? What if someone breaks in?
We Don’t Trust Bots
I’ve heard this. I’m sure others will hear it as well. Boiled down, PoshBot is pretty secure:
- There’s no opportunity for injection. PoshBot doesn’t execute text, it uses the AST to validate commands and parameters
- Only commands PoshBot knows about can run
- PoshBot enforces access controls via groups, roles, and permissions
- If an author considers what could go wrong, guardrails and other safeguards can make a command more safe than running natively - think about the benefits of using JEA. Maybe I provide access to restart services, but only a subset of services that make sense
There are still a few risks. What if Slack itself is compromised? What if an account is compromised? A few things to consider that would mitigate this a bit:
- Use two-factor auth
- Limit the extent of what your commands can do. Maybe don’t write
delete datacenter
, or allowadd innocent-looking-backup-account to domain admins
Keep in mind security is about risk management, otherwise we would throw all our equipment into the sea and be done with computing. For most, the value of ChatOps will far outweigh the risks.
References
There’s plenty of other reading material out there on ChatOps, consider checking these out:
- Jason Hand on a Beginners Guide to ChatOps
- Matt Hodgkins on ChatOps on Windows with Hubot and PowerShell
- Matt Hodgkins on ChatOps with PowerShell
What about PoshBot itself?
Poshbot is quite new, compared to bots like Hubot or Errbot - there’s not much out there yet!
Brandon is doing an awesome job, but help is always welcome - found a bug? Want to help with docs? Have a feature request? Want to learn Pester and write some tests? Open an issue or a pull request!
Cheers!