UPDATE: A few highlighted changes below to cover the behavior in Windows Server 2012 R2 (and IE quirks).

Indications are a mechanism used in the Common Information Model (CIM) to provide events from a CIM server to a client application. The storage service can use these events to make sure its cached information is up-to-date with the provider and the arrays it manages.

When the storage service is the single management point, the chances are pretty good that the cache will be reasonably current. But if multiple management points exist, such as more than one SMI-S client, more than one SMI-S provider managing a single array, or out-of-band mechanisms like vendor tools, the state of a managed array can change and the storage service’s view of the discovered objects will become out-of-sync. Since discovery is a time consuming operation, it’s best to not require refreshing the cache (Update-StorageProviderCache cmdlet) more often than necessary.

Some examples of state that might change:

  • Volumes can be created or deleted or their size might change
  • Volumes can be unmasked to servers or masked from them
  • New storage pools can be created or deleted, they can be expanded or they can run out of free space
  • The FriendlyName of an object can be changed Various objects might change status, from healthy to unhealthy

Indications can help keep the cache updated, but some assembly is required. Out of the box, the storage service will subscribe to indications and it will listen for the indications, but more steps are necessary to set up the security so that the system can receive them. I will try to make this as painless as possible by providing a PowerShell script (see bottom of post) to do most of the heavy lifting.

Keep in mind that if you don’t follow these steps, the storage service will still attempt to subscribe to indications and the provider will not be able to deliver them. At best, this produces lots of messages in the provider’s log files; at worst, the provider may not accept indications from other clients and we have even seen providers fail completely.

Configuration for Indications

The storage service implements an HTTPS listener using TCP port 5990, in accordance with DMTF requirements. There is no support for HTTP delivery of indications. The instructions below apply to Windows Server 2012 systems and require PowerShell.

At this time, you must use a certificate with the Common Name set to “msstrgsvc”. You could use a signed certificate if you have the ability to create one. Otherwise, use a self-signed certificate as demonstrated below. Also note that I have ExportPolicy set to 1 in the script; this is for debugging purposes and is not required.

I avoided wrap around lines by using the PowerShell continuation character ‘`’, but if you encounter syntax errors, make sure double quotes are just normal double quote characters and not typographic ones. Same for dashes.

Step 1:  Copy the following script to a file called configsmis.ps1 or see the bottom of the post for a link:

# Install the Storage Service feature - safe if it is already installed
 
echo "Installing the feature - safe it is already installed"
Add-WindowsFeature WindowsStorageManagementService
 
# Create a firewall rule to allow incoming traffic on port 5990
echo "Adding a firewall rule for indications"
New-NetFirewallRule -DisplayName "CIMXML Indications" -Direction Inbound `
 –LocalPort 5990 -Protocol TCP –Enabled True –Action Allow `
 -Description "CIM-XML Indications come in on HTTPS" 
 
#Generate a self-signed certificate – the Common Name must be msstrgsvc
echo "creating a self-signed certificate"
$name = new-object -com "X509Enrollment.CX500DistinguishedName.1"
$name.Encode("CN=msstrgsvc", 0)
 
$key = new-object -com "X509Enrollment.CX509PrivateKey.1"
$key.ProviderName = "Microsoft RSA SChannel Cryptographic Provider"
$key.KeySpec = 1
$key.Length = 2048
$key.ExportPolicy = 1
$key.SecurityDescriptor = "D:PAI(A;;0xd01f01ff;;;SY)(A;;0xd01f01ff;;;BA)(A;;0x80120089;;;NS)"
$key.MachineContext = 1
$key.Create()
 
# create a certificate that is suitable for all purposes
$serverauthoid = new-object -com "X509Enrollment.CObjectId.1"
$serverauthoid.InitializeFromValue("1.3.6.1.4.1.311.10.12.1")
$ekuoids = new-object -com "X509Enrollment.CObjectIds.1"
$ekuoids.add($serverauthoid)
$ekuext = new-object -com "X509Enrollment.CX509ExtensionEnhancedKeyUsage.1"
$ekuext.InitializeEncode($ekuoids)
 
# this script will create certificate that is good for 1000 days – you can make it
# longer if you choose. After that time, the storage service will stop accepting
# indications and may stop handling mutual auth
$cert = new-object -com "X509Enrollment.CX509CertificateRequestCertificate.1"
$cert.InitializeFromPrivateKey(2, $key, "")
$cert.Subject = $name
$cert.Issuer = $cert.Subject
$cert.NotBefore = get-date
$cert.NotAfter = $cert.NotBefore.AddDays(1000)
$cert.X509Extensions.Add($ekuext)
$cert.Encode()
 
 
$enrollment = new-object -com "X509Enrollment.CX509Enrollment.1"
$enrollment.InitializeFromRequest($cert)
$certdata = $enrollment.CreateRequest(0)
$enrollment.InstallResponse(6, $certdata, 0, "")
 
# Now find the cert we just created (it will be in ‘MY’) and hold on to the thumbprint
cd cert:
$thumbprint=(dir -recurse | where {$_.Subject -match "CN=msstrgsvc*"} | `
  Select-Object -Last 1).thumbprint
$thumbprint
 
# clear out old certificates for this port and add our new one for all IPv4 and IPv6
# addresses. Deletes might fail if there were no old certificates.
# Note that I tried to use Server 2012 PowerShell cmdlets but I couldn’t exactly match
# all the requirements with the existing ones, so some of the commands rely on netsh
 
Set-Alias netsh c:\Windows\System32\netsh.exe
 
echo "You can ignore delete failures if this is a first time conifugration"
 
netsh http delete sslcert ipport=0.0.0.0:5990
netsh http delete sslcert ipport=[::]:5990
 
netsh http add sslcert ipport=0.0.0.0:5990 certhash=$($thumbprint) `
  appid="{468e21d1-a4cb-4134-8d9f-800c5ff2086f}"
netsh http add sslcert ipport=[::]:5990 certhash=$($thumbprint) `
  appid="{468e21d1-a4cb-4134-8d9f-800c5ff2086f}"
 
# Apply an ACL to the port so that NETWORK SERVICE can bind to it.
# Delete might fail if the ACL was never applied before.
netsh http delete urlacl url=https://*:5990/
netsh http add urlacl url=https://*:5990/ user="NT AUTHORITY\NETWORK SERVICE"
 
# restart the storage service so it can bind to the port properly
# you will need to perform Update-StorageProviderCache if level was > 0
echo "Restarting the service. Remember to run Update-StorageProviderCache since this resets the cache."
Restart-Service MSStrgSvc
 

Step 2: From a PowerShell Administrative Command prompt, execute these commands:

PS C:\Users\Administrator> $policy = Get-ExecutionPolicy

PS C:\Users\Administrator> Set-ExecutionPolicy Bypass

PS C:\Users\Administrator> .\configsmis.ps1 (assuming this is the correct directory)

PS C:\Users\Administrator> Set-ExecutionPolicy $policy

Test indications to port 5990

UPDATE: Before sending indication to port 5990, you may want to verify that HTTPS listener is working properly. Open https://localhost:5990 on the storage service machine. You should get a certificate error and IE will not proceed further and only allow you to close the page. That is sufficient for this purpose.

Note: Hit cancel if prompted for a certificate.

One-way authorization

The storage service only supports HTTPS connections for indications. When a CIM server attempts to connect to the storage service to deliver an indication, it will challenge the storage service and request a certificate. If the provider validates the server certificate, that certificate will need to be placed in the trusted store for the CIM server. This will vary depending on vendor implementation and is not described here.

 Very often the CIM server does little or no validation of the certificate and no other action is required.

Mutual Authentication

UPDATE:. Mutual Authentication is the process whereby the client and server will attempt to validate each other. If this is set correctly as instructed above, mutual authentication will proceed as expected. (It is very hard to configure and SSL implementations vary widely!)

Exporting the Storage Service certificate

The above script will place the msstgsvc certificate in the trusted store. Using the certificates snap-in, it is possible to export this cert for use by the provider if it does certificate validation. UPDATE: To export the certificate, do the following:

  1. Run MMC.EXE from an administrator command prompt.
  2. Add the Certificates Snap-in using the File\Add/Remove Snap-in menu.
  3. Make sure you select Computer Account when the wizard prompts you, select Next and leave Local Computer selected. Click Finish.
  4. Click OK.
  5. Expand Certificates (Local Computer), then Personal and select Certificates.
  6. In the middle pane, you should see the msstrgsvc certificate. Right click, select All Tasks, Export… That will bring up the Export Wizard.
  7. Click Next to not export the private key (this might be grayed out anyway), then select a suitable format. Typically DER or Base-64 encoded are used but some vendors may support .P7B files. For EMC, select Base-64.
  8. Specify a file to store the certificate. Note that Base-64 encoded certificates are text files and can be open with Notepad or any other editing program.

Registry values that affect Indications

 All registry values are located in

 HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\Current Version\Storage Management

 The defaults enable indications with certificate checking so no changes should be needed.

 

Value

Description

Default

DisableHttpsCommonNameCheck

Turns off Common Name (CN) checking

0 (CN does not need to match the provider machine name)

EnableHTTPListenerClientCertificateCheck

Turns on client certificate checking

1 (Enabled) The Indication provider must present a valid certificate

EnableIndications

Turns on indication subscriptions

1 (Enabled)

IndicationDeliveryFailurePolicy

See CIM_IndicationSubscription.On FatalErrorPolicy

4 (Remove) The subscription will attempt to set this to Remove. If that fails, it will retry without setting this property.