Building on my last post on stateful-process-command-executor this post will cover how you can leverage that node.js module to expose the capabilities of Powershell cmdlets over a REST api presented through an AngularJS interface. Why would one want to do this you ask? Well I’ve covered this in my last post but I will briefly explain it here.
(Note, what is described below could just as easily be built for Bash processes as well as the underlying module supports it)
The use case came out of the need to automate certain calls to manage various objects within Microsoft o365’s environment. Unfortunately Microsoft’s GraphAPI, does not expose all of the functionality that is available via its suite of various Powershell cmdlets for o365 services. Secondly when you need to do these operations via Powershell, its requires a per-established remote PSSession to o365…. and establishing (and tearing down) a new remote PSSession whenever you need to invoke a cmdlet against a remote resource (remote server, or o365 endpoint) is expensive. Lastly, who wants to actually sit there and manually run these commands when they could be automated and invoked on demand via other means… such as via a web-service etc. Hence this is how stateful-process-command-proxy came to be… it provides the building block bridge between node.js and a pool of pre-established Powershell consoles. Once you have node.js talking to stateful-process-command-proxy, you can build whatever you want on top of that in node.js to mediate the calls.
The first higher level NPM module that builds on stateful-process-command-proxy is powershell-command-executor
What this adds on top of stateful-process-command-proxy is probably best described by this diagram:
So the main thing to understand is that the module provides the PSCommandService class which takes a registry of pre-defined “named” commands and respective permissible arguments. The registry is nothing more than a object full of configuration and is easy to define. You can see an example here in the project which defines a bunch of named “commands” and their arguments usable for o365 to manipulate users, groups etc. PSCommandService is intended to serve as a decoupling point between the caller and the StatefulProcessCommandProxy… in other words a place where you can restrict and limit the types of commands, and arguments (sanitized) that can ever reach the Powershell processes that are pooled within StatefulProcessCommandProxy.
It is PSCommandService‘s responsibility to lookup the named command you want to execute, sanitize the arguments and generate a literal Powershell command string that is then sent to the StatefulProcessCommandProxy to be execute. StatefulProcessCommandProxy, once the command is received is responsible for checking that the command passes its command whitelist and blacklist before executing it. The sample o365Utils.js config file provides a set of pre-canned (usable) examples of init/destroy commands, auto-invalidation commands and whitelist/blacklist configs that you can use when constructing the StatefulProcessCommandProxy that the PSCommandService will use internally.
The next logic step is to expose some sort of access to invoking these pre-canned “commands” to callers. One way to do this is via exposing it via a web-service.
WARNING: doing such a thing, without much thought can expose you to serious security risks. You need to really think about how you will secure access to this layer, the types of commands you expose, your argument sanitiziation and filtering of permissible commands via whitelists and blacklists etc for injection protection. Another precaution you may want to take is running it only on Localhost for experimental purposes only. READ OWASPs article on command injection.
Ok with that obvious warning out of the way here is the next little example project which provides this kind of layer that builds on top of the latter: powershell-command-executor-ui
This project is a simple Node.js ExpressJS app that provides a simple set of REST services that allows the caller to:
- get all available named commands in the PSCommandService registry
- get an individual command configuration from the registry
- generate a command from a set of arguments
- execute the command via a set of arguments and get the result
- obtain the “status” of the underlying StatefulProcessCommandProxy and its history of commands
Given the above set of services, one can easily build a user-interface which dynamically lets the user invoke any command in the registry and see the results… and this is exactly what this project does via an AngularJS interface (albeit a bit crude…). See diagrams below.
Hopefully this will be useful to others out there, enjoy.
Ahhh, love it! So you need to configure a Windows box to be able to utilize DOS, sorry PowerShell, to remotely manage your Azure AD / o365 / Exchange online services via “cmdlets”. You do some searching online and come across a ton of seemingly loosely connected Technet articles, forum questions etc.
Well I hope to summarize it up for you in this single blog post and I’ll try to keep it short without a lot of “why this needs to be done” explanations. You can read up on that on your own w/ the reference links below.
#1: The first thing we need to do is setup a separate user account that we will use when connecting via PowerShell to the remote services we want to manage with it:
- Using an account with administrative privileges, login to your Azure account/tenant at https://manage.windowsazure.com
- Once logged in click on “Active Directory” and select the instance you want to add the new user account too
- Click on “Add user”, fill out the details. Be sure to select “Global Administrator” as the role (or a lesser one, if need be depending on what you will be doing with PowerShell)
- Click create and it will generate a temporary password and email it to that user + the user listed for the secondary email that you filled out
- Logout of the Azure management portal
- Login again at https://manage.windowsazure.com, however this time login as the new user you just created with the temporary password. Once logged in, reset the password to a better one, click next.
- You should now be logged in as the new user you just created and on the main Azure management dashboard screen
- Find the link for managing “Exchange” and click on it
- You will now be redirected to the o365 Exchange admin center
- Click on “Permissions”, you will now see a bunch of groups/roles, the one we care about is Organization Management.
- Highlight the “Organization Management” role/group and ensure that the user you are logged in as (the new user you just created) is a member of this group directly or indirectly. You need to be a member of this group in order to get the “Remote Shell” permission that lets you download the Exchange cmdlets and manage exchange remotely via PowerShell. (See here for info on this group and the Remote Shell permission)
#2: Now that our special admin user is created with all the needed permissions, we can now get our PowerShell environment ready:
- Get on the Windows box that you intend to run the PowerShell commands from
- Download and install the “Microsoft Online Services Sign-In Assistant for IT Professionals” (its ok even if you are not a “professional”)
- Its 2014… you need to reboot after the last step…
- Download and install the “Azure AD Module for Windows PowerShell 64 bit”
#3: Ok, lets verify basic Azure AD PowerShell cmdlet capabilities
- Now on your Desktop RIGHT click on “Windows Azure Active Directory Module for Windows PowerShell” and “Run as Administrator”
- In PowerShell run this command “Set-ExecutionPolicy Unrestricted”
- In PowerShell run this command “Connect-MsolService” a nice dialog will prompt you for your credentials (use the creds that you setup above)
- In PowerShell run this command “Get-Msoluser”, get data back?? Great you are good to go for basic connectivity
#4: Finally…. lets verify o365 Exchange PowerShell cmdlet capabilities
- In the same PowerShell as you started above…
- Type: “$UserCredential = Get-Credential”… again enter your user credentials
$Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://outlook.office365.com/powershell-liveid/ -Credential $UserCredential -Authentication Basic -AllowRedirection
- Type: “Import-PSSession $Session”
- At this point you should see some activity at the top of your PowerShell window as 300+ Exchange online cmdlets are downloaded to your system for use
- Quickly verify the Exchange Online Remote Shell permission with: “Get-User YOUR_UPN | Format-List RemotePowerShellEnabled”
- You should get back “RemotePowerShellEnabled: true”
DONE, proceed to the next quagmire…
Managing Azure AD Using PowerShell:
o365 Exchange online: Remote Shell Permission and Organization Management
Connect to Exchange Online using Remote PowerShell:
Series: Using remote PowerShell to manage o365