PowerShell + makecert.exe + !(Server2012)

I was recently asked to transition our server's self-signed certificates used by RDP from sha1 to sha2. Easy I thought, I'll use the cmdlet New-SelfSignedCertificate to create the certificate and WMI to apply it. Nope, the New-SelfSignedCertificate cmdlet is not available in Server 2008r2. That said, I had to come up with another way. Queue, makecert.exe. Makecert.exe is included in many of the Window SDKs. However, the version needed to create certificates with sha256 is 6.3.9600.17298. I was able to find this in the Windows Software Development Kit (SDK) for Windows 8.1. You can google and download the SDK or use the one I have linked below (assuming you trust me). 

Directly below is the launched script provided with three parameters to set the validity period of the cert as well as the domain name of the server and to show verbose output. Notice makecert.exe is in the same directory as the script, this is required

The script for the most part is fairly proofed:

  1. if makecert is missing it will tell you
  2. if multiple sha256 self-signed certs are present in the local store it will tell you
  3. if a sha256 self-signed cert does not exist in the personal store it will tell you
  4. if the newly created sha256 self-signed cert has been incorrectly applied to RDP it will tell you

As with all PowerShell scripts that run .exe's with parameters, it's not easy. So don't judge when you see how I did it :).

Below is an image of warning you get when connecting to a server using a self-signed certificate. Looking past that we can see that RDP is now using sha256. Super. 


Download script here.

Download makecert.exe here.


As always, Get-Help is your friend.

IIS Reverse Proxy and PlexRequests

The following details how to setup IIS (preferably in your DMZ) to reverse proxy requests to wherever you have PlexRequests running. You'll need to have chocolatey installed so you can install both URL Rewrite and Application Request Routing (ARR). In the example web.config file below '1.1.1.1' is my inside host running plexrequests. 

The following text will be your web.config. Place the below contents into a file named 'web.config' in whatever your plexrequests physical directory was. 

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <system.webServer>
        <rewrite>
            <rules>
                <rule name="ReverseProxyInboundRule1" stopProcessing="true">
                    <match url="(.*)" />
                    <action type="Rewrite" url="http://1.1.1.1:3000/{R:1}" />
                </rule>
            </rules>
            <outboundRules>
                <rule name="ReverseProxyOutboundRule1" preCondition="ResponseIsHtml1">
                    <match filterByTags="A, Form, Img" pattern="^http(s)?://1.1.1.1:3000/(.*)" />
                    <action type="Rewrite" value="http{R:1}://plexrequests.fqdn.com/{R:2}" />
                </rule>
                <preConditions>
                    <preCondition name="ResponseIsHtml1">
                        <add input="{RESPONSE_CONTENT_TYPE}" pattern="^text/html" />
                    </preCondition>
                </preConditions>
            </outboundRules>
        </rewrite>
    </system.webServer>
</configuration>

Metadata cleanup (easy to follow instructions)

Below are my notes for how to perform a metadata cleanup. Also below is the actual output from a metadata cleanup for when I removed dc01-denver.test.com. 

# enter ntdsutil
c:\tmp>ntdsutil

# activate ntds
ntdsutil: activate instance ntds

# enter metadata cleanup
ntdsutil: Metadata cleanup

# enter connections
metadata cleanup: connections

# connect to local server 
server connections: connect to server dc01-newyork

# quit server connection
server connections: quit

# now that we're returned to mc, enter select target
metadata cleanup: select operation target

# lets get a list of our sites (note the site containing our bad DC)
select operation target: list sites
0 .
1 ..
2 ...

# set a selected site from the list site output (in our case 0)
select  operation target: select site 0

# lets get a list of our domains (note the domain containing our bad DC)
select operation target: list domains in site
0 .
1 ..
2 ...

# set a selected domain from the list domain output (in our case 0)
select  operation target: select domain 0

# lets get a list of our servers (note our bad DC)
select operation target: list servers in site
0 .
1 ..
2 ...

# set a selected server from the list server output (in our case 0)
select operation target: select server 0

# unless we want to only delete a specific naming context on this server simply quit
select operation target: quit

# now we remove our bad dc
metadata cleanup: remove selected server

# manually removed server rep link container in dssite
# manually removed misc rep links for bad dc in dssite


C:\Windows\system32>ntdsutil
ntdsutil: activate instance ntds
Active instance set to "ntds".
ntdsutil: metadata cleanup
metadata cleanup: connections
server connections: connect to server dc01-newyork
Binding to dc01-newyork ...
Connected to dc01-newyork using credentials of locally logged on user.
server connections: quit
metadata cleanup: select operation target
select operation target: list sites
Found 3 site(s)
0 - CN=NEWYORK,CN=Sites,CN=Configuration,DC=test,DC=com
1 - CN=DENVER,CN=Sites,CN=Configuration,DC=test,DC=com
2 - CN=MIAMI,CN=Sites,CN=Configuration,DC=test,DC=com
select operation target: select site 1
Site - CN=DENVER,CN=Sites,CN=Configuration,DC=test,DC=com
No current domain
No current server
No current Naming Context
select operation target: list domains in site
Found 1 domain(s)
0 - DC=test,DC=com
select operation target: select domain 0
Site - CN=DENVER,CN=Sites,CN=Configuration,DC=test,DC=com
Domain - DC=test,DC=com
No current server
No current Naming Context
select operation target: list servers in site
Found 2 server(s)
0 - CN=DC01-DENVER,CN=Servers,CN=DENVER,CN=Sites,CN=Configuration,DC=test,DC=com

1 - CN=DC02-DENVER,CN=Servers,CN=DENVER,CN=Sites,CN=Configuration,DC=test,DC=com

select operation target: select server 0
Site - CN=DENVER,CN=Sites,CN=Configuration,DC=test,DC=com
Domain - DC=test,DC=com
Server - CN=DC01-DENVER,CN=Servers,CN=DENVER,CN=Sites,CN=Configuration,DC=test,D
C=com
        DSA object - CN=NTDS Settings,CN=DC01-DENVER,CN=Servers,CN=DENVER,CN=Sit
es,CN=Configuration,DC=test,DC=com
        DNS host name - DC01-DENVER.test.com
        Computer object - CN=DC01-DENVER,OU=Domain Controllers,DC=test,DC=com
No current Naming Context
select operation target: quit
metadata cleanup: remove selected server
Transferring / Seizing FSMO roles off the selected server.
Removing FRS metadata for the selected server.
Searching for FRS members under "CN=DC01-DENVER,OU=Domain Controllers,DC=test,DC
=com".
Deleting subtree under "CN=DC01-DENVER,OU=Domain Controllers,DC=test,DC=com".
The attempt to remove the FRS settings on CN=DC01-DENVER,CN=Servers,CN=DENVER,CN
=Sites,CN=Configuration,DC=test,DC=com failed because "Element not found.";
metadata cleanup is continuing.
"CN=DC01-DENVER,CN=Servers,CN=DENVER,CN=Sites,CN=Configuration,DC=test,DC=com" r
emoved from server "dc01-newyork"
metadata cleanup: quit
ntdsutil: quit

Scheduled Tasks, do your parameter values have spaces?

A few weeks ago I needed to queue up a script as a scheduled task. The script had a few string based parameters whose values contained spaces (e.g. MyScript.ps1 -ParamA 'My ParamA Value'). In order for my scheduled task action's add argument to work I had to use the following format. This also fixes the issue when you have spaces in your script name. 

-WindowStyle Hidden "& \"C:\PowerShell Modules and Scripts\wsus_approveUpdates.ps1\" -group \"Print Servers - Prod\" -days 30"

deleting stale print jobs via WMI

A few years ago I worked in an environment where for whatever reason some jobs\documents simply wouldn't print. These jobs\documents would sit in the queues for months and eventually cause the spooler to hang. I came up with the script below to collect all current jobs and if they were more than an hour old delete them. The script logs what it does to a local text file. 

syncronous robocopy with PowerShell

I recently needed to launch several large robocopy operations from within PowerShell. The script I was using to do this also did a lot of other stuff after robocopy was called. I wanted to monitor robocopy, have a log file, and also let the remainder of the script run and possibly complete while the robocopy operations still ran. I accomplished this with the function below. When supplied with a Source, Destination, and LogDirectory parameter it will launch a new PowerShell window running the robocopy operation. The new window containing the robocopy operation provides a start time and when complete displays the elapsed time as well as the Source, Destination, and LogDirectory parameters. Enjoy.