Thursday, April 30, 2015

Windows Server 2012 - Services

In some of my multi-part blog posts, I've examined some rather complex subjects such as Public Key Infrastructure (PKI) or various Exchange migration scenarios. In this post, I'd like to take a look at managing Windows services on Server 2012 R2. In particular, I noticed that there are (at least) three methods to manage services:


  1. Services.msc (GUI management console).
  2. sc.exe commands ("classic" command line).
  3. *-Service Powershell cmdlets: Get-Service, Set-Service, Stop-Service, Start-Service, etc..

The potential advantages of using Powershell rather than sc interests me in particular. For example, even though there are numerous Powershell cmdlets to manage network interfaces, it is my understanding that many administrators still prefer netsh.


Services.msc

I imagine that most Windows administrators are quite familiar with this interface with its four tabs.

Note: enter "services.msc" in the Start | Search box to open the console.


We can stop and start services (and more) by right-clicking on the service in question, in this case the Application Identity service:



I would wager over 90% of those reading this already know that but I'll compare this to the sc.exe and Powershell options later.

If we open the properties of a service, we have (as I wrote earlier) four tabs.

The general tab shows the names, description, start type and status of the service:



We can change the startup type and service status as needed.


Services "log on" and run under the credentials of an account, sometimes the Local System account or the Network Services account or a custom user account created in Active Directory with access to particular resources.




Under the Recovery tab, we configure behavior in case of failure of a service to start:


I do not believe I have ever needed to adjust the settings here but other admins may have had to.

Lastly, we can see service "dependencies" under the tab with the same name:


Basic service troubleshooting: if a service will not start, verify that the "pre-requisite" services are running first. In Microsoft Exchange, for example, if the Active Directory Topology Service is not running, many other Exchange services will simply refuse to start.



SC

SC is a command-line tool that manages services. If we enter...

sc

at the command prompt, a list of all the different commands will be displayed.

For example, sc query shows the status of a service. I'll use it to take a look at the Windows Remote Management service:

C:\>sc query winrm

SERVICE_NAME: winrm
        TYPE               : 20  WIN32_SHARE_PROCESS
        STATE              : 4  RUNNING
                                (STOPPABLE, NOT_PAUSABLE, ACCEPTS_SHUTDOWN)
        WIN32_EXIT_CODE    : 0  (0x0)
        SERVICE_EXIT_CODE  : 0  (0x0)
        CHECKPOINT         : 0x0
        WAIT_HINT          : 0x0sc

Among other information, we can see that the service is running.

A similar command, "sc qc servicename" displays the configuration of a service. Once again, we'll use the WinRM service as an example:

C:\>sc qc winrm
[SC] QueryServiceConfig SUCCESS

SERVICE_NAME: winrm
        TYPE               : 20  WIN32_SHARE_PROCESS
        START_TYPE         : 2   AUTO_START
        ERROR_CONTROL      : 1   NORMAL
        BINARY_PATH_NAME   : C:\Windows\System32\svchost.exe -k NetworkService
        LOAD_ORDER_GROUP   :
        TAG                : 0
        DISPLAY_NAME       : Windows Remote Management (WS-Management)
        DEPENDENCIES       : RPCSS
                           : HTTP
        SERVICE_START_NAME : NT AUTHORITY\NetworkService

Here (above) we can see that the service is set to start automatically (AUTO_START).

We can stop, start, pause and continue services with these SC commands (plus the name of the service of course):

sc stop
sc start
sc pause
sc continue

We can configure the startup type as shown below. Note the space between the = sign and the start(up) type. I have edited out some data for readability (snips).


C:\>sc config AppIDSvc start= auto
[SC] ChangeServiceConfig SUCCESS

C:\>sc qc AppIDSvc
[SC] QueryServiceConfig SUCCESS

SERVICE_NAME: AppIDSvc
        TYPE               : 20  WIN32_SHARE_PROCESS
        START_TYPE         : 2   AUTO_START
        ERROR_CONTROL      : 1   NORMAL
[snip]


C:\>sc config AppIDSvc start= demand
[SC] ChangeServiceConfig SUCCESS

C:\>
C:\>sc qc AppIDSvc
[SC] QueryServiceConfig SUCCESS

SERVICE_NAME: AppIDSvc
        TYPE               : 20  WIN32_SHARE_PROCESS
        START_TYPE         : 3   DEMAND_START
        ERROR_CONTROL      : 1   NORMAL
[snip]


Now let's look at the equivalent Powershell commands...



Powershell

We can see the various PowerShell cmdlets for managing services with this command:

PS C:\> Get-Command *service* | where { $_.CommandType -eq "Cmdlet" } | select name

Name
----
Get-Service
New-Service
Restart-Service
Resume-Service
Set-Service
Start-Service
Stop-Service
Suspend-Service

Note that "service" is always singular. The command also returns a "New-WebServiceProxy" that I have edited out for clarity.


As with the command "sc query", all services will be displayed if I enter...

Get-Service

It may be more useful to use Get-Service to find the name of the service (if you do not know it already) and then specify it like this (we'll use the WinRM service again).


PS C:\> Get-Service WinRM

Status   Name               DisplayName
------      ----                      -----------
Running  WinRM     Windows Remote Management (WS-Manag...


Get-Service provides fewer details than SC QUERY but we can obtain more with the format-list cmdlet (fl for short):

PS C:\> Get-Service WinRM | fl

Name                : WinRM
DisplayName         : Windows Remote Management (WS-Management)
Status              : Running
DependentServices   : {}
ServicesDependedOn  : {RPCSS, HTTP}
CanPauseAndContinue : False
CanShutdown         : True
CanStop             : True
ServiceType         : Win32ShareProcess

This is quite comparable to the SC QUERY output and perhaps more readable.



Stopping and starting a service (or suspending and resuming) with the PowerShell cmdlets is very straight-forward:

PS C:\> Stop-Service WinRM
PS C:\> Get-Service WinRM | fl name,status

Name   : WinRM
Status : Stopped


PS C:\> Start-Service WinRM
PS C:\> Get-Service WinRM | fl name,status

Name   : WinRM
Status : Running


But what about the startup type of a service? You may have noticed that Get-Service does not display this property. You may recall that SC QUERY did not show this either (see above). We had to use SC QC.

It may seem strange that we can configure the startup type of a service with the Set-Service cmdlet (we'll see that in a moment) but cannot see the current status with Get-Service.

Instead, we have to use the cmdlet Get-Wmiobject win32_service:

PS C:\> Get-Wmiobject win32_service -filter "name = 'WinRM'"

ExitCode   : 0
Name        : WinRM
ProcessId  : 888
StartMode : Auto
State          : Running
Status        : OK

You are welcome to experiment but I found that the syntax must be exactly as indicated. None of these options will work:

get-wmiobject win32_service WinRM
get-wmiobject win32_service -name WinRM
get-wmiobject win32_service -filter "name=WinRM"
get-wmiobject win32_service -filter "name = WinRM"

This was the most concise variant of the cmdlet that would function:

PS C:\> gwmi win32_service -f "name='WinRM'"

Note that...
  • gwmi is the alias of Get-WmiObject
  • We use win32_service even with a x64 operating system. win64_service is not a valid wmi class.
  • We may place a space before and after the = sign for the filter or simply omit these spaces.


Now we'll change the startup type (simply to illustrate the procedure) and then change it back to the original settings.

PS C:\> Set-Service WinRM -StartupType Manual
PS C:\>
PS C:\> gwmi win32_service -f "name='WinRM'"

ExitCode  : 0
Name      : WinRM
ProcessId : 888
StartMode : Manual
State     : Running
Status    : OK


PS C:\> Set-Service WinRM -StartupType Auto
PS C:\>
PS C:\> gwmi win32_service -f "name='WinRM'"


ExitCode  : 0
Name      : WinRM
ProcessId : 888
StartMode : Auto
State     : Running
Status    : OK


***

And that will be all for this post on managing services with either the Services management console, the SC commands or the PowerShell cmdlets.

One word of caution!

Many services are essential for the proper functioning of the operating system. Changing the startup type of certain services could prevent the OS from starting correctly (or at all).

Common sense would dictate that we do not experiment with these commands on production computers.

Sunday, April 19, 2015

Exchange 2010 - DAG (Database Availability Group) - change File Share Witness

When a DAG (Database Availability Group) is composed of an even number of mailbox servers, we need to implement what is known as a "File Share Witness" (FSW). This is a file share containing a very small but very important amount of data that allows the DAG to maintain "quorum" and remain functional if either of the two DAG members is momentarily unavailable (during maintenance for example).

Note: if we looked at the properties and content of the file share, this is what we would see:






This file share can reside on just about any server that is a domain member as long as it is not a member of the DAG itself. It can be another Exchange server, a non-Exchange server like a file or print server or even (in a test network) a domain controller.

Note: it is not advisable to use a domain controller in a production environment for security reasons. We would have to add the "Exchange Trusted Subsystem" group to the builtin Administrators group on the domain controller, which would give the members of this group (essentially the Exchange servers) excessive rights and thus violate the security principle of "least privilege".  

I explained how to configure a DAG in a previous blog post:

Exchange 2010 - DAG (Database Availability Group) - Part 1 - Configuration (initial)

 Please refer to that post if you want to create a new DAG.

In this post, I want do demonstrate how to change the location of the FSW from one server to another. We may need to do this for various reasons: the current server is being retired from service or perhaps has failed. In this latter case, the DAG will not cease functioning immediately (as long as the two DAG members are operational and can communicate with each other) but we will have to replace the FSW sooner or later. For example, with the FSW unavailable, we could not restart either of the two DAG members without causing a mailbox database dismount on the other member.

It is rather simple to change the location of the FSW provided that the new server meets the normal requirements for being a file share witness (domain member, Exchange Trusted Subsystem group added to the local administrators group if the server is not an Exchange server, not a member of the DAG itself).

In my case, this is the current FSW location:

[PS] C:\>Get-DatabaseAvailabilityGroup -status | fl name,wit*

Name                      : DAG1
WitnessServer        : fsw1.mynet.lan
WitnessDirectory   : C:\FSW_DAG1
WitnessShareInUse : Primary


We can change the location with the following command:

Set-DatabaseAvailabilityGroup DAG1 -WitnessServer fsw2.mynet.lan -WitnessDirectory C:\FSW_DAG1


Which leaves us with this:

[PS] C:\>Get-DatabaseAvailabilityGroup -status | fl name,wit*

Name                      : DAG1
WitnessServer        : fsw2.mynet.lan
WitnessDirectory   : C:\FSW_DAG1
WitnessShareInUse : Primary


And that's it.

Even after rebooting both of the DAG members (not at the same time), the mailboxes continue to be available just as they were before.

Note: I do place the DAG member in maintenance mode with the "StartDagServerMaintenance.ps1" script.




Sunday, April 12, 2015

PKI (Public Key Infrastructure) with ADCS, Part 9: web enrollment (web server certificate for the CA)

In my previous blog post, I explained that before clients can request a certificate from the issuing CA via the web interface, we must request and issue a separate certificate to the CA itself.

Separate? By separate, I mean a certificate besides the one granted to the issuing subordinate CA by the root CA for its role as a certificate authority. In addition to this certificate, the CA needs another designed specfically for server authentication. So we duplicated the "web server" template and now have a template suitable for "(web) server authentication".

***

First, we open IIS on the subordinate CA (PKI-Sub-CA-1 in my test network), select the CA and then (in the center pane) "Server Certificates":




In the right pane (not shown above - see below) we select "Create Certificate Request":


Note that the only existing certificate is the certificate issued for the (subordinate) certificate authority role by PKI-ROOT-CA. We cannot use this certificate for the web server role (or for server authentication in general).

We enter the required information in the resulting dialog box:



I keep the default CSP and select 2048 for the key length:



We save the certificate request as a text file (and click Finish):



Next, we open Internet Explorer on the subordinate issuing CA itself and enter the following URL:

http://pki-sub-ca-1/certsrv




Note: We enter http rather than https since the site does not yet have an appropriate certificate that would allow us to enable (or require) SSL. We can also enter "localhost" instead of the server name when we are at the CA itself.

We then click on the task "Request a certificate" (see above) which brings us to this page:


Select the second option.


At this point, I encountered the following error:



This can be caused by a number of factors:

  • You simply do not have permissions to the template. In my case, I was connected with the default domain administrator account (test network).
  • You used a Windows 2008 (v3) template when you duplicated the web server template. I made this mistake once but then duplicated the template a second time using the Windows 2003 option. For more information, this was discussed in my previous blog post.
  • Others encountering the problem have suggested that we need to move NTLM above Negotiate under the Providers for Windows authentication. See "NTLM" 1 and 2 screenshots below.
  • Yet others have suggested that the Application Pool Identity must be set to NetworkService. See the "Application Pool Identity" screenshot below.

***

NTLM 1




NTLM 2 - where do I find Providers?



Application Pool Identity



***

In one case, I was able to eliminate the error message after using a Windows 2003 version template. However, I had already moved NTLM above Negotiate and changed the App Pool ID to NetworkService. I was even able to change these last two settings back to their defaults and the templates remained accessible.

In another case, I selected the Windows 2003 version template but was only able to make the template appear after I set the App Pool ID to NetworkService.

Note: after making these changes, I did execute the command iisrest /noforce

All in all, it seems that we have to have the exact combination of some very particular settings for the templates to appear.

***

Once the templates are accessible, we continue the certificate request process as follows.

We open the certificate request file that we created earlier and then highlight and copy the entire content, including the request header and footer:


In the image above the text is not yet highlighted for copying and I "snipped" a portion of the content to show what I mean by the header and footer. In reality, you will not modify the content of the text file in any way. Simply copy it (all) as is...

And paste it here:


Lastly, click "Submit".

Since the certificate template was configured so it requires administrative approval, we now must wait until someone managing the CA approves and issues the certificate.

In this case, we are both the requestor and the CA administrator so we can now open the Certificate Authority console and browse to the Pending Requests folder:




We right-click on the certificate request, select "All Tasks" and then "Issue":




Once approved and issued, the certificate is moved to the "Issued Certificates" folder:




Now we can return to the web site where we submitted the request and view the status of our request. We click on the "View status (etc.)" link:


Note: here I use "localhost" in the Url which is an acceptable option as long as we are at the CA itself. Once we enable SSL on the site we will no longer be able to use "localhost" because this name will not be on the certificate.

We can see the certificate request:



We see that the certificate was issued and can be downloaded. In this case, we only need the certificate itself (not the chain) and will use the Base 64 encoded format:


There will probably be some sort of download prompt (depending on your browser settings):



We select a location to save the file:



Now we return to the IIS management console where we select the "Complete Certificate Request" option (click on the server icon in the left pane and then "Server Certificates" in the center pane):




We browse to the downloaded certificate and provide a name for it (click Next or Finish as needed):



Now we have the second certificate in place:



All we need to do is to bind it to the default website:



Select the certificate we just downloaded for https (port 443):



Once we have finished we can close Site Bindings...



And then enable SSL on the CertSrv website:



Now clients are able to access the website and request certificates.


***


At this point, we have a functional PKI and clients can either request certificates manually using the web interface or have certificates issued automatically via Group Policy, with membership in specific security groups determining exactly which certificates can be issued. Lastly, we could issue certificates to mobile users with (non-Windows) tablets or Smartphones using a third party product like AirWatch or MobileIron.

I may examine these options in future blog posts.

Even though my PKI is now functional, in a production environment we would have to consider aspects such as high availability, backups and key archiving. This series of blog posts does not address these aspects but they are, or course, crucial.

For the moment, and after nine blog posts about PKI, I will place this subject on "pause" so I can take a look at some other subjects that interest me.