Friday, December 23, 2016

Just Enough (Temporary Remote) Administration - (Part 1)

11:50 AM Posted by Adam Dzak , No comments

Scenario/poll: Show of hands administrators - how many of you have an environment wherein individual user accounts are granted remote desktop access, to specific machines, and still have them even when they don't need those rights?

Keep your hands up - how many of you would like to know who those accounts are? When they got that permission? Who gave them the permission? etc.

The above scenario I'm sure is a common one that most departments will either deny or have no idea to the extent that it's happening. Even still, should the question be posed of "Well how bad is it in our environment?" who can answer this question quickly? I mean truly quickly. I mean in under 1 minute quickly!

Service Manager to the Rescue...
In the days before SCSM and SCO/SMA I found myself in this situation all too often. Whether it be places I was working full time or consulting at, there was always a degree of this one-off and non-auditable behavior. In the time since a lot (and I mean a lot) of single purpose tools have been created to address this incredibly specific situation. But with those tools come some rather high price tags.

I am a huge fan of less tools, more standards, and leveraging what I have before committing to something wholly new (and so wildly specific in this case). So with System Center in your environment, could we address this issue?


To solve this, we're going to leverage native Service Manager and Orchestrator functionality. 1 Service Request and 2 really tiny runbooks. Depending on your experience with the ecosystem the following is either going to incredibly obvious making this post a waste of your time OR perhaps you're just getting started and looking for ideas to impress your colleagues. So if it's the second one...let's impress your colleagues!

So just what exactly are we going to build?
  • Reduce privileged access in the environment through SCO
  • Provide instant auditable and reportable data through SCSM
  • Prevent members of your organization from "gaming" this request through SCO/SCSM
Enough teasing your respective IT security teams. Let's get to building.

It's not backwards, it's Orchestrator first...
We're going to create two runbooks within Orchestrator as our first steps. If you followed my "New Employee" and HR processes series of blogs OR you're just getting started with System Center this approach may seem entirely backwards but I assure you it'll work out.

As a preface to this, whatever SCO account you choose to accomplish this will absolutely need to be a Local Admin on the machine(s) you are going to perform this against. While I originally thought to myself "Ugh, I don't want to grant admin access to another account. That's the thing I'm trying to solve!" But again - we're adding a single automated account that no one controls (except Orchestrator) to invoke these actions on our behalf.

  • UPDATE: I wanted to expand a bit more on the above paragraph with respect to "whatever SCO account you choose..." as it always seems to prompt the question "Well how could I chose?" By default the "Run .NET Script" activity will be run with the SCO service account. Since you probably don't want to distribute the Orchestrator service account to machines in your environment it would make much more sense to create a dedicated account to perform this function. Then save it's username and password as Global Variables in SCO. Then use an invoke-command with the scripts found below and leverage the credentials there. That way SCO is the thing spinning up the script, but it gets executed with an entirely different set of credentials on the remote machine. If you're unfamiliar with how to call credentials in PowerShell this is the most straightforward post on the matter. Just wanted to add this as I was writing this post in conjunction with deving this in a dev environment and as such not thinking this through as much as I should have for a post trying to be so security focused.

Runbook 1 - Grant x Permission on y Machine
High Level: We're going to obtain the Affected User of a Service Request, take the Windows Computer they selected on our request offering page, take the time they needed on this machine and then add them to some local security group on a machine. For the purpose of this post, I'm going to hardcode "Administrators" into the PowerShell script that grants permissions. However I'm confident that after walking through this, you could easily see how to alter this to either change the local group in the PowerShell script or allow the requesting user to select which group they would want to be in and then pass it into this runbook.

Finally, we'll have this (aforementioned) runbook execute a child runbook so they get removed from this group when the time they selected is up. To prevent the requesting person from keeping the permission, we're going to make sure this child runbook is not dependent on finishing based on the Parent Runbook's status (which will be "Complete"). By doing this it means once the first runbook finishes, the Service Request will be marked as Completed even though this second, non-dependent runbook is silently counting away to remove permissions at the selected time.

Initialize Data: We'll create one parameter and call it "ActivityGUID"

Get Relationship (RB to SR): We'll move from the SCO Runbook object and get the related (parent) Service Request

Get SR: We'll get the Service Request object

Get Relationship (SR to AU): We'll move from the Service Request and obtained the Affected User

Get Affected User: We'll get the related object from the previous Get Relationship step and obtain the Affected User object

Get Relationship (RB to Windows Computer): We'll get the Windows Computer that was selected on the request offering and mapped to the Runbook.

Get Computer: We'll get the Windows Computer object

Grant Access on Computer: We'll take all the objects we fetched from our previous steps and use it to drive a PowerShell script that adds the Affected User to the Local Administrators group on the selected Windows Computer. The good news is this PowerShell script will work with PowerShell 2.0 functionality, so you won't have to pull your hair out dealing with workarounds for getting PS 3+ working here. We'll use Ed Wilson's "The Scripting Guy's" two liner and just substitute the variables with our variables from the SCO databus. We'll also add a few lines for some simple datetime math. I've also put the script in here so you can quickly copy and past.

Don't forget that you'll have to head over to the "Published Data" tab on this Run .NET Script activity and make sure you publish the variable "timeToWaitInSeconds" so you can consume this data downstream in the second runbook. As far as datatype, a string will do.

[datetime]$currentTime = get-date
[datetime]$srScheduledEndTime = "srSCHEDULEDENDTIME"
$timeToWait = $srScheduledEndTime - $currentTime
$timeToWaitInSeconds = $timeToWait.TotalSeconds

$computer = "COMPUTERHERE"
$group = "Administrators"
$domain = "DOMAINNAME"
$user = "USERNAME"
$de = [ADSI]“WinNT://$computer/$Group,group”

So why the whole $currentTime thing? Why not just use the Service Request's created date, or the Runbook's Created Date?

The request process I'm showing only addressing the technical backend of this whole thing. That said, it would make sense that in your Service Request template to perhaps place a Review Activity before this activity or any other series of internal organization processes before this runbook invokes itself. But whether you do or do not when this runbook invokes it will grab the current datetime so that when the calculation runs to determine "how long to grant access" it will be the most accurate reflection of time that was requested.

02 - Revoke Permissions on Computer: Finally we'll pass all those previously obtained objects and the requested time into a non-dependent (i.e. "Wait for Completion" is unchecked on this Invoke Runbook activity) child runbook that start-sleeps for the selected period of time before removing the permissions. But before we can pass these variables from the SCO databus, we'll need to construct the 2nd runbook and create some parameters first. This one is super simple:

Runbook 2 - Remove x Permission on y Machine after z Period of Time (glad I only need three variables in this lead in)
High Level: We're going to take the Affected User, computer, and period of time in seconds from the parent runbook and pause this runbook until the timer expires.

Pause? How are we going to pause? Orchestrator and even SMA (PowerShell) don't really pause, they sort of just go and do their thing.

Quite simply we're just going to leverage the "start-sleep" cmd-let of PowerShell for the time the user selected on the Service Request.

Oh. Yeah...that. Nevermind.

We're also going to allow concurrent executions of this runbook so multiple people can make the request at the same time in addition to getting their rights revoked at the time selected as opposed to letting runbook jobs get queued up thus breaking the thing we're trying to setup here. But how are we going to remove the user that originally requested this? Good news, it's the almost identical script used in the adding of permissions, we're just going to change a few things. See if you can spot the differences.

Also the published data used in the screenshot here is the Parameters you'll have to create for your Initialize Data activity that proceeds this. To be perfectly clear those are:

  • endTimeInSeconds
  • computerName
  • userDomain
  • username
As for the script:

start-sleep -seconds "TIMEINSECONDS"
$computer = "COMPUTERHERE"
$group = "Administrators"
$domain = "DOMAINNAME"
$user = "USERNAME"

$de = [ADSI]“WinNT://$computer/$Group,group”

This completes the Orchestrator part of this request. Next thing we'll do is head over to SCSM, sync these runbooks, create their respective activity templates, create the Service Request template, add the runbook activities into the SR template, then finally create the Request Offering.

If you made it this far then the "hard part" is over! I hope this provides a framework which you can build off.
  • Maybe call a script to delete local user profiles after the timer expires?
  • Maybe send the Affected User that their time is going to expire soon?

I'm sure there are any number of organizational processes you could incorporate into this! In the next post, we'll do all of the SCSM work.

Until next time. Make On!


Post a Comment