BizTalk Server: Step-by-Step Guide For Restoring SSO Master Secret

Introduction

This is a step-by-step guide for restoring the SSO master secret.

This is a companion article (soon to be released for sysprep) that should be used as a guide for any automation that involves SSO Secret restoration using automation.

I wrote this specifically to overcome a specific gap in the SSOConfig management tool, as it requires human intervention to enter the password.

Prerequisites

  1. You must have a valid SSO Secret backup file.
  2. You must know the secret password that was used to generate the SSO Secret backup file.
  3. The user must be at least a LEVEL 4 user (see Minimum Security Rights for security levels).
  4. You must be able to compile the ssoSecretRestore project using Visual Studio 2013
  5. You must have the same version of Enterprise SSO in your development project as on the BizTalk Server.

Step by Step

  1. Compile the ssoSecretRestore project against your version of Enterprise Single Sign-on.
  2. Gather the secret backup file.
  3. Gather the secret backup password.
  4. Copy the ssoSecretRestore.exe and the Secret Backup file to the same folder.
  5. Stop all host instances.
  6. Confirm the Enterprise Single Sign-on Service is running.
  7. Confirm the SQL Server with the ESSO database is running.
  8. Start an Administrative command prompt.
  9. Change your working directory to the same directory as step #4
  10. run the ssoSecretRestore command.

ssoSecretRestore ssoBackup.bak password

Where ssoBackup.bak is the backup file and password is the secret password.

What could go wrong

  1. If you don't have the SSO Secret file, there is nothing you can do, you must rebuild your environment from scratch.
  2. If you don't have the SSO Secret password, there is nothing you can do, you must rebuild your environment from scratch.
  3. If you compile against the wrong version of the Microsoft.EnterpriseSingleSignOn.Interop.dll, then the program won't run.
  4. If you aren't a member of the SSO Administrators group, you will get an error "Error importing SSO Secret - User is not a member of the SSO Administrators group".
  5. If you don't have permissions to read the SSO Backup file you will get an error "Error importing SSO Secret - Input file error".
  6. If the SSO Backup file doesn't exist (e.g., you typed the name wrong) you will get an error "Error importing SSO Secret - Input file not found".
  7. If you have discovered a creative way to break the software, you will get an error "Error importing SSO Secret - Unexpected Error was encountered".

Source Code

using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using Microsoft.EnterpriseSingleSignOn.Interop;
using System.IO;
using System.Reflection.Assembly;
using System.Reflection;
using System.Globalization;
namespace ssoSecretRestore
{
    class Program
    {
         
 
        static string  Usage = @"ssoSecretRestore will restore the SSO Secret from a file
ssoSecretRestore filename password
example:
    ssoSecretRestore ssoBackup.bak pass@word1";
        static Dictionary<string, string> errorList = new  Dictionary<string, string>(3);
        static bool  exit = false;
        static byte[] commonSSOInteropToken = { 0x31, 0xbf, 0x38, 0x56, 0xad, 0x36, 0x4e, 0x35 };
        static string  filename, password = null;
        static void  Main(string[] args)
        {
            Console.Title = "SSO Secret Restore";
            Init(args);
 
            if (filename == null)
            {
                exit = true;
                Console.WriteLine("ERROR: Input filename is missing");
            }
            if (password == null)
            {
                exit = true;
                Console.WriteLine("ERROR: password is missing");
            }
            if (!exit)
            {
                ISSOConfigSS iSSO = new  Microsoft.EnterpriseSingleSignOn.Interop.ISSOConfigSS();
                try
                {
                    iSSO.RestoreSecret(filename, password);
                    Console.WriteLine("SSO Secret Restore succesful");
                }
                catch (Exception ex)
                {
                    if (ex.GetType() == typeof(COMException))
                    {
                        WriteException(ex, "COMException");
                    }
                    else if  (ex.GetType() == typeof(FileNotFoundException))
                    {
                        WriteException(ex, "FileNotFoundException");
                    }
                    else if  (ex.GetType() == typeof(UnauthorizedAccessException))
                    {
                        WriteException(ex, "UnauthorizedAccessException");
                    }
                    else
                    {
                        WriteException((Exception)ex, "Unknown");
                    }
                }
            }
            else
            {
                Console.WriteLine(Usage);
            }
        }
 
        private static  void Init(string[] args)
        {
            errorList.Add("COMException", "Error importing SSO Secret - Input file error");
            errorList.Add("FileNotFoundException", "Error importing SSO Secret - Input file not found");
            errorList.Add("UnauthorizedAccessException", "Error importing SSO Secret - User is not a member of the SSO Administrators group");
            filename = args.Length > 0 ? args[0] : null;
            password = args.Length > 1 ? args[1] : null;
        }
 
        private static  void WriteException(Exception exception,  string  ExceptionType)
        {
            Console.WriteLine("=================================================");
            if (errorList.ContainsKey(ExceptionType))
            { 
                Console.WriteLine(errorList[ExceptionType]); 
            }
            else
            {
                Console.WriteLine("Error importing SSO Secret - Unexpected Error was encountered");
            }
            Console.Write("Exception Message: " + exception.Message);
            Console.Write("Exception Stack: " + exception.StackTrace);
            if (exception.InnerException != null)
            {
                Console.WriteLine("Inner Exception Message: " + exception.InnerException.Message);
                Console.WriteLine("Inner Exception Stack: " + exception.InnerException.StackTrace);
            }
        }
    }
}

See Also

Another important place to find a huge amount of BizTalk-related articles is the TechNet Wiki. The best entry point is BizTalk Server Resources on the TechNet Wiki.