Configuration Manager Application Request: Sample Notification and Approval Automation Solution

Update: I have released an installed, configuration instruction, as well as source code for an application similar to the one demonstrated in this blog. Find the information at the folloing site - https://blogs.technet.com/b/neilp/archive/2014/09/10/cmaae.aspx


Introduction -

During my last blog post I detailed some of the internal components of the System Center 2012 Application Request and Approval system. Included was a look into the views created in the CM Database, WMI specific data and methods, and finally I’ve shown how to approve or deny an application request using PowerShell. In this post I will be walking through a sample end-to-end application request notification and approval system. This solution is only a sample of what is possible. This blog post is meant to generate ideas and provide sample code that may help fulfill those ideas. There may be items included in this solution that would not work well in your environment. However as you will see, the sample Runbooks are easily modifiable and can be used as a starting point and can be crafted into just about any environment.

The sample solution detailed in this post consists of three Orchestrator Runbooks, a simple custom ASP.NET application, and many of the elements (PowerShell and Data) previously discussed. The goal of this solution is quite simply to provide an email alert to the appropriate approver each time a new application request has been entered into the Configuration Manager system. With this email, the approver will have the ability to approve or deny the application request without having access or the need to access the Configuration Manager console.

All Reference Material for this Blog (Orchestrator Runbook Exports) can be found at the following location – Download

Solution High Level Overview –

  • An Orchestrator Runbooks monitors the application approval system (WMI) checking for new requests every two minutes.
  • When a new request is detected, information about the request including the Request UID is placed into an email. Included in this email is a link to the ASP.NET application page on which the application can be approved or denied. This email is sent to the requesting users Manager as defined in Active Directory.
  • Once received, the approver can follow the embedded URL to the approval tool. In this tool the application request can be approved or denied.
  • Once the application has been approved or denied, an email is generated and sent to the requesting user with the approval/denial details.
  • Additionally there is workflow in the solution that will send a follow up email in the event an application request has not been acted upon in a configurable amount days. The solution will also auto deny any request that has not been acted upon in a configurable amount of days.

As you can see, this is a very simple solution in terms of what is being performed, however very nicely builds onto the new Configuration Manager Application Approval System. Without a solution such as this, Configuration Manager provides no email notification of pending application approvals and likewise requires access to the console for all approval activity. 

Solution In Action –

Before digging into the Runbooks and application code, let me show the full end-to-end execution of this solution. This will provide context as we look at the Orchestrator Runbooks, scripts, and .NET code.

Client Side logged in as user –

User navigates to the application portal and selects an application to request.

 

 Comments are added to the request and the request is submitted.

On the Application Approvers side –

An email alert is auto generated and sent to the requesting user’s manager –

 

The manager can then follow the embedded URL to the approval application. From this application the approver can approve or deny the request and also add a comment.

 

Back on the requesting user's end an email will be received notifying of the approval decision. If the application has been approved the installation will begin momentarily .

 

Additionally if the application request has not been acted upon in a specified number of days a second email (not shown) will be sent to the requesting user’s manager. This email is almost identical to the first however indicates that the request is ageing. Finally if the application request is not acted upon after a configurable amount of days, the request will be auto denied due to inactivity and an email will be sent to the user indicating this (also not shown).

 

Sample Solution Deep Dive –

Components –

  • Data Manipulation and Active Directory Integration Packs (thes must deployed to the Runbook Designer before importing the Runbook samples).
  • Application Request Gather Runbook.
  • Application Request Action Runbook.
  • Get Email Address Runbook.
  • Approval ASP Application.

Application Request Gather Runbook -

Monitor Date/Time – is configured to execute this Runbook every two minutes.

Get All Application Requests – PowerShell that gathers each application request with a CurrentState of 1 (See Previous Blog for explination of Current State), publishes the Requests GUID.

 $a=@()

$app = Get-WmiObject -Class SMS_UserApplicationRequest -Namespace root/SMS/site_ <Published Data Site Code > -ComputerName <Published Data Computer Name> | where-object -FilterScript {$_.CurrentState -eq "1"}

foreach ($appr in $app)

{

$a += $appr.RequestGuid

}

Gather Data for Each Request – PowerShell that loops through each application request (CurrentState = 1) by Request ID and pulls back information to be placed into the email and also does math on the last modified date in order to determine the next move (First Email, Second Email, Cancel, etc.).

$app = Get-WmiObject -Class SMS_UserApplicationRequest -Namespace root/SMS/site_ <Published Data Site Code> -ComputerName <Published Data Site Server> | where-object -FilterScript {$_.RequestGuid -eq “ <Published Data Request UID> ”}

foreach ($appr in $app) {$comment = $appr.Comments; $user = $appr.User; $appName = $appr.Application; $date = $appr.ConvertToDateTime($appr.LastModifiedDate)}

$today = get-date

$diffd = ($today - $date).days

$diffh = ($today - $date).hours

$diffm = ($today - $date).minutes

if ($diffd -gt 2)

{

$action = "Cancel"

}

if ($diffd -lt 1 -and $diffh -lt 1 -and $diffm -lt 2)

{

$action = "FirstEmail"

}

if ($diffd -eq 1 -and $diffh -gt 1 -and $diffm -lt 2 )

{

$action = "SecondEmail"

}

Get Email Address 1 and 2 – This calls a Runbook that will run a series of data manipulation and Get AD User lookups against the requesting user name. The outcome is an email address for both the requesting user and the user’s manager. I will not detail this Runbook in this blog posting, but the Runbook is provided at the download link.

First Email and Second Email – These two activities send out a very basic email. The content of these emails is made of data from the previous activity. Included in this email is a URL to the application request approve / deny application. This URL is made up of the name of the website plus a parameter of the Application Request UID (Notice the ?UID=) . We will discuss how this application works and the significance of the Request UID later in this post.

Email Body section of the send email activities.

Auto Deny the Application Request – this activity calls the Application Request Action Runbook (See next group for an explanation).

 

Application Request Action Runbook –

Initialize Data – consumes the Request UID, The approval or denial decision, and comments from the ASP.Net Application or from the Request Gather Runbook (in the event of an auto deny).

Approve / Deny – this activity triggers the WMI method to approve or deny each application request. This script was detailed in my last blog posting.

$wmi = Get-WmiObject -Class sms_userapplicationrequest -Filter 'requestguid = " <Published Data Request UID> "' -ComputerName " <Published Data Site Server> " -Namespace "root\sms\site_ <Published Data Site Code> "

if ($wmi)

{

$rtn = $wmi. <Published Data Approve/Deny> (‘ <Published Data Description> ’);

}

Gather Data for Each Request – this is more or less similar to the gather activity of the same name in the first Runbook. Here we are re-gathering the data for the end user Approve/Deny email. I will not paste the code in here, refer back to the last section or download the sample Runbooks and inspect there for more information.

Get Email Address – Gets email address for both requesting user and users manager.

Send Email – Finally once the application has been approved or Denied an email is sent to the requesting user with request status.

 

Approval ASP.NET Application -

The final piece to this sample solution is the ASP.NET application. There is nothing fancy happening with this application. It quite simply performs the following tasks

  • Consumes the Request UID from the passed URL (recall this was constructed from the Orchestrator Send Email Activity).
  • Queries WMI on the site server for information about the request and displays this on the Web APP.
  • Takes the Approved/Denied value and the entered comments, executes the Application Request Action Runbook, passing to it these two values as parameters.

So putting it even more simply, the application is basically a ‘fancy’ Runbook interface. This application could easily be replaced with a script, SharePoint, or many other types of interfaces. The value in this form is that it is dynamic (based on the Request UID). Because of this we do not have to store any additional data anywhere. If you think through the process, between the time a user requests access to an application and the time it takes an approval administrator to actually perform the approval, the request is in an idle state. How do we store the request in a format that can be accessible at any time? In this solution it is stored in the form of a URL embedded inside of an email and a dynamic application that consumes the Request ID from the embedded URL.

I will not be providing an installer for this application at this time, however here is some sample code. If there is interest in having an installer package please let me know. Given enough interest I will complete a few remaining items and make it available for download.

App Approval Code

  1. using System;
  2. using System.Management;
  3. using System.Text;
  4. using AppApproval.SCOService;
  5. using System.Data.Services.Client;
  6. using System.Linq;
  7. using System.Configuration;
  8.  
  9. namespace AppApproval
  10. {
  11.     public partial class _Default : System.Web.UI.Page
  12.     {
  13.  
  14.         string strUser;
  15.         string strAppR;
  16.         string strAppC;
  17.         
  18.         string sSiteServer = ConfigurationManager.AppSettings["SiteSever"];
  19.         string sSiteCode = ConfigurationManager.AppSettings["SiteCode"];
  20.         string sSCORCH = ConfigurationManager.AppSettings["SCORCHWS"];
  21.         string sRBUID = ConfigurationManager.AppSettings["RBUID"];
  22.  
  23.         string sUID;
  24.      
  25.         protected void Page_Load(object sender, EventArgs e)
  26.         {
  27.  
  28.             Uri MyUrl = Request.Url;
  29.             string URL = MyUrl.AbsoluteUri.ToString();
  30.             sUID = Request.QueryString.Get("UID");
  31.  
  32.             ConnectionOptions options = new ConnectionOptions();
  33.  
  34.             ManagementScope scope = new ManagementScope("\\\\" + sSiteServer + "\\root\\sms\\Site_" + sSiteCode);
  35.             
  36.             scope.Connect();
  37.  
  38.             ObjectQuery query = new ObjectQuery("SELECT * FROM SMS_UserApplicationRequest WHERE RequestGuid ='" + sUID + "'");
  39.             ManagementObjectSearcher search = new ManagementObjectSearcher(scope, query);
  40.  
  41.             ManagementObjectCollection queryCollection = search.Get();
  42.             
  43.             foreach (ManagementObject User in search.Get())
  44.             {
  45.                 strUser = User["User"].ToString();
  46.                 strAppR = User["Application"].ToString();
  47.                 strAppC = User["Comments"].ToString();
  48.             }
  49.  
  50.             lblUser.Text = strUser;
  51.             lblApplication.Text = strAppR;
  52.             lblComment.Text = strAppC;
  53.  
  54.         }
  55.  
  56.         protected void btnSubmit_Click(object sender, EventArgs e)
  57.         {
  58.             string approve = ddlApprove.SelectedItem.ToString();
  59.  
  60.             Guid runbookId = new Guid(sRBUID);
  61.             string serviceRoot = sSCORCH;
  62.  
  63.             SCOService.OrchestratorContext context = new SCOService.OrchestratorContext(new Uri(serviceRoot));
  64.  
  65.             context.Credentials = System.Net.CredentialCache.DefaultCredentials;
  66.  
  67.             var runbookParams = context.RunbookParameters.Where(runbookParam => runbookParam.RunbookId == runbookId && runbookParam.Direction == "In");
  68.  
  69.             // Configure the XML for the parameters
  70.             StringBuilder parametersXml = new StringBuilder();
  71.             if (runbookParams != null && runbookParams.Count() > 0)
  72.             {
  73.  
  74.                 parametersXml.Append("<Data>");
  75.                 foreach (var param in runbookParams)
  76.                 {
  77.                     if (param.Name == "RUID:")
  78.                     {
  79.                         parametersXml.AppendFormat("<Parameter><ID>{0}</ID><Value>{1}</Value></Parameter>", param.Id.ToString("B"), sUID);
  80.                     }
  81.  
  82.                     if (param.Name == "Approve/Deny:")
  83.                     {
  84.                         parametersXml.AppendFormat("<Parameter><ID>{0}</ID><Value>{1}</Value></Parameter>", param.Id.ToString("B"), approve);
  85.                     }
  86.  
  87.                     if (param.Name == "Description:")
  88.                     {
  89.                         parametersXml.AppendFormat("<Parameter><ID>{0}</ID><Value>{1}</Value></Parameter>", param.Id.ToString("B"), txtComments.Text);
  90.                     }
  91.                   
  92.                 }
  93.                 parametersXml.Append("</Data>");
  94.             }
  95.  
  96.             try
  97.             {
  98.                 // Create new job and assign runbook Id and parameters.
  99.                 Job job = new Job();
  100.                 job.RunbookId = runbookId;
  101.                 job.Parameters = parametersXml.ToString();
  102.  
  103.                 // Add newly created job.
  104.                 context.AddToJobs(job);
  105.                 context.SaveChanges();
  106.  
  107.             }
  108.  
  109.             catch (DataServiceQueryException ex)
  110.             {
  111.                 throw new ApplicationException("Error starting runbook.", ex);
  112.             }
  113.             
  114.         }
  115.  
  116.         protected void ddlApprove_SelectedIndexChanged(object sender, EventArgs e)
  117.         {
  118.  
  119.         }
  120.  
  121.     }
  122. }

Additionally the following has been added to the <appSettings> section of Web.config file.

Web.config File

  1. <appSettings>
  2.   <addkey="SiteSever"value="Site Server" />
  3.   <addkey="SiteCode"value="Site Code" />
  4.   <addkey="SCORCHWS"value="SCORCH Web Service URL" />
  5.   <addkey="RBUID"value="UID of the Application Request Action Runbook" />
  6.   </appSettings>

Conclusion -

So there we have it, my own custom application request notification and approval add on solution for Configuration Manager. The benefit to a solution such as this is that no longer will there be a need for manual investigation into the current list of applications requiring approval, nor will access to the console be required for the approval to take place. I hope that this post has provided you with an idea on how you would accomplish something similar were you to have the need.

As a reminder all Runbooks detailed in this post can be found on my connect site – Download Site.

Comments

  • Anonymous
    January 01, 2003
    This was a really great post I need a little help getting the web service started as I am new to creating these. Do you have any pointers you can provide. please. thank you.

  • Anonymous
    January 01, 2003
    Neil, Great Article!!! I'm wondering since this has been over a year now, do you have the ASP.NET code for the web application and any instructions how to configure it in IIS?

  • Anonymous
    January 01, 2003
    Hello,  I am having the same issue as Mats.  It looks like the Get email Address runbook relies on a integration pack that I do have have.  I downloaded the Data Manipulation IP as described above but that does not seem to be the missing integration pack.  It shows as all question marks and cannot display the properties.

  • Anonymous
    January 01, 2003
    That worked for me as well.  Thanks.

  • Anonymous
    January 01, 2003
    Sam, I do not have an installer at this time but will try and get one together shortly. I will post it to this blog if and when I get it completed. Thanks neilp

  • Anonymous
    January 01, 2003
    Hei Neil, Trying out RunBook, but hav esom e problems with approval site. Any chance to provide your code for "Approval.SCOService" ? Regards! CG

  • Anonymous
    January 01, 2003
    Thanks for the feedback, I have updated this blog to indicate that both the Data Manipulation and Active Director Integration packs must be deployed to the Runbook Designer before importing the sample Runbooks. Mats - if you are still having issues with this can you email me offline, I will assist. I have also received multiple requests for an installer that will install the Approval application. I have limited cycles at the moment but am working on one and hope to have it published within the next two weeks. neilp

  • Anonymous
    January 01, 2003
    How do you create the ASP.net program and where do I put it?

  • Anonymous
    January 01, 2003
    I apologize but I am not going to be able to provide a sample installer for this application. All of the code is included in this posing and can be used to piece together the application. Thanks. neilp

  • Anonymous
    February 15, 2013
    This is Awesome! exactly what I was looking for.Could you please include the installer for the ASP.NET application.Please!!1 my email address is skagyei@gmail.com or u can upload it

  • Anonymous
    February 18, 2013
    Thanks Neil.Just a quick question. I am using the Application Approval workflow accelerator so far so good,but when the Reviewer approves the activity on the self service portal the status still remains requested in ConfigMgr,is there a workflow that should set the status to approve? Thanks

  • Anonymous
    February 24, 2013
    Hi Neil, good article, helped me out heaps. I am new to Orchestrator. i am running 2012 SP1 and part of your runbook is not recognised, what can i do about this. and could you also please upload the ASP.net application. thanks

  • Anonymous
    February 25, 2013
    Hi Neil, same here. I imported the export in Orchestrator and the run book "get email address" does not work. Every icon shows a question mark. Hope you can help me with that. Regards Mats

  • Anonymous
    February 25, 2013
    Thanks Mats and Liam, I will look into this today and report back. neilp

  • Anonymous
    February 25, 2013
    Hi Neil, i think i worked it out, i may have been using a newer version of the "Data Manipulation" activity. i worked out what you had and replaced it so im all good now. i would really love that ASP.net application though Regards, Liam

  • Anonymous
    February 26, 2013
    Hi Liam, Wich version did you download and do you have a link? Regards, Mats

  • Anonymous
    February 26, 2013
    Hi Mats, orchestrator.codeplex.com/.../83934 Regards, Liam

  • Anonymous
    February 27, 2013
    Liam, I installed the data manipulation pack. It shows in SCO, but i still have the question marks. and an error that says: the property for this activity cannot be viewed. I have data manipulation IP and AD IP. Hope to hear from you Regards, Mats

  • Anonymous
    March 05, 2013
    Hi Neal, Thanks for your response. I fixed it by deleting the runbooks and importing them again. I didn't do that after installing the new IP's. The application i will try to install myself. If i haven't succeeded in 2 weeks i will come back ;-) Regards Mats

  • Anonymous
    May 15, 2013
    Hi Neil, First a big thank you for your post, it put me n the right way to code a real approval portal :) In the "Gather Data For Each Request" part you should add an IF $app is not null because if there is no approval demand with the status pending the script will fail with the error "You cannot call a method on a null-valued expression." and so the runbook Like this : if ($app -ne $null) {      foreach ($appr in $app) {$comment = $appr.Comments; $user = $appr.User; $appName = $appr.Application; $date = $appr.ConvertToDateTime($appr.LastModifiedDate)} [........]      $action = "SecondEmail"      } } else {      $action="None" } Regards,

  • Anonymous
    September 24, 2013
    -If there is interest in having an installer package please let me know. I'll let you know that there is massive interest of having an installer package. Im not experienced with asp.net at all and would very much appreciate if you could make this guide complete for dummies. Thanks!

  • Anonymous
    September 25, 2013
    has anyone been able to figure out the ASP portion?

  • Anonymous
    September 26, 2013
    Hey CG! were you able to figure out the approval.scoservice?

  • Anonymous
    October 17, 2013
    I would very much like to get the complete picture or installer for ASP side of things. This solution is very elegant and meets my needs perfectly.   Regards, Erik

  • Anonymous
    October 24, 2013
    I made some progress on the service. Please read the link below msdn.microsoft.com/.../60bb3efc-4174-4262-a98f-4f02104c28f8

  • Anonymous
    February 10, 2014
    Hi Neil and thanks for your great article. I'm not very familiar with ASP.NET, may i ask you an installer for it ? I've seen MS solution (SCCM Approval Worflow) but we have to install all System Center's products before tryint it :/.

  • Anonymous
    April 23, 2014
    This is Awesome! exactly what I was looking for.Could you please include the installer for the ASP.NET application.Please!!1 my email address is ximenjq@163.com or u can upload it thank you!

  • Anonymous
    June 18, 2014
    Pingback from Liste des outils pour Configuration Manager 2012 | D??ploiement Windows

  • Anonymous
    June 18, 2014
    Pingback from Liste des outils pour Configuration Manager 2012 | D??ploiement Windows

  • Anonymous
    June 18, 2014
    Pingback from Liste des outils pour Configuration Manager 2012 | D??ploiement Windows

  • Anonymous
    June 18, 2014
    Pingback from Liste des outils pour Configuration Manager 2012 | D??ploiement Windows

  • Anonymous
    June 18, 2014
    Pingback from Liste des outils pour Configuration Manager 2012 | D??ploiement Windows

  • Anonymous
    June 18, 2014
    Pingback from Liste des outils pour Configuration Manager 2012 | D??ploiement Windows

  • Anonymous
    June 18, 2014
    Pingback from Liste des outils pour Configuration Manager 2012 | D??ploiement Windows

  • Anonymous
    June 18, 2014
    Pingback from Liste des outils pour Configuration Manager 2012 | D??ploiement Windows

  • Anonymous
    November 10, 2014
    The comment has been removed

  • Anonymous
    November 10, 2014
    Please see the updated link at the very beginning of this blog post.

  • Anonymous
    November 11, 2014
    Nice, Thanks Neil

  • Anonymous
    December 12, 2014
    Download link says it has not been published yet.

  • Anonymous
    November 19, 2015
    Getting the following message when clicking on the link in the e-mail: No application request ID was specified or this application request has already been approved / denied....
    You may have reached this page in error.