Skip to content

Commit

Permalink
Merge pull request #9 from NileshGhodekar/master
Browse files Browse the repository at this point in the history
Update to NormalizeString and RunPowerShellScript
  • Loading branch information
NileshGhodekar committed Mar 5, 2016
2 parents 51263ca + c1a7a0d commit e4afc31
Show file tree
Hide file tree
Showing 4 changed files with 79 additions and 63 deletions.
24 changes: 18 additions & 6 deletions src/Scripts/EncryptData.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,22 @@
at http://msdn.microsoft.com/en-us/library/ms998283.aspx (How To: Encrypt Configuration Sections in ASP.NET 2.0 Using RSA), but for the FIM Service account.
#>

$Error.Clear()

Add-Type -AssemblyName "System.Security"
Add-Type -AssemblyName "MicrosoftServices.IdentityManagement.WorkflowActivityLibrary, Version=2.14.611.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
# use the full name for WAL assembly to eliminate need to assembly redirects for dependent assemblies.
Add-Type -AssemblyName "MicrosoftServices.IdentityManagement.WorkflowActivityLibrary, Version=2.16.305.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"

if ($Error)
{
Write-Host "Aborting script execution."
return
}

function TestCertificateBasedEncryptionDecryption
{
$thumbprint = "9C697919FB2FB2D6324ADE42D5F8CB49E8778C08" # cert to be used for encryption.
$outFile = Join-Path -Path $PWD -ChildPath "cert-p.txt"

$base64EncodedPublicKeyXml = [MicrosoftServices.IdentityManagement.WorkflowActivityLibrary.Common.ProtectedData]::GetCertificatePublicKeyXml($thumbprint, "My", "LocalMachine")

Expand All @@ -22,17 +31,18 @@ function TestCertificateBasedEncryptionDecryption

$encryptedData = [MicrosoftServices.IdentityManagement.WorkflowActivityLibrary.Common.ProtectedData]::EncryptData($secret, $base64EncodedPublicKeyXml)

$encryptedData | Out-File cert-p.txt

$encryptedDataConfig = "cert:\localmachine\my\$thumbprint,$encryptedData"

$encryptedDataConfig | Out-File $outFile

$decryptedData = [MicrosoftServices.IdentityManagement.WorkflowActivityLibrary.Common.ProtectedData]::DecryptData($encryptedDataConfig)

$plainText = [MicrosoftServices.IdentityManagement.WorkflowActivityLibrary.Common.ProtectedData]::ConvertToUnsecureString($decryptedData)

if ($plainText -eq $secretToEncrypt)
{
Write-Host "`nEncryption and Decryption test using certificate '$thumbprint' succeeded!`n"
Write-Host "`nThe password config is saved in '$outFile'`n"
}
else
{
Expand All @@ -43,12 +53,13 @@ function TestCertificateBasedEncryptionDecryption
function TestDPAPIBasedEncryptionDecryption
{
$secretToEncrypt = "Pass@word1"
$outFile = Join-Path -Path $PWD -ChildPath "dpapi-p.txt"

$secret = ConvertTo-SecureString -AsPlainText $secretToEncrypt -Force

$encryptedData = [MicrosoftServices.IdentityManagement.WorkflowActivityLibrary.Common.ProtectedData]::EncryptData($secret, [System.Security.Cryptography.DataProtectionScope]::LocalMachine)

$encryptedData | Out-File dpapi-p.txt
$encryptedData | Out-File $outFile

$decryptedData = [MicrosoftServices.IdentityManagement.WorkflowActivityLibrary.Common.ProtectedData]::DecryptData($encryptedData, [System.Security.Cryptography.DataProtectionScope]::LocalMachine)

Expand All @@ -57,13 +68,14 @@ function TestDPAPIBasedEncryptionDecryption
if ($plainText -eq $secretToEncrypt)
{
Write-Host "`nEncryption and Decryption test using DPAPI succeeded!`n"
Write-Host "`nThe encrypted password is saved in '$outFile'`n"
}
else
{
Write-Error "`nEncryption and Decryption test using DPAPI failed!`n"
}
}

TestDPAPIBasedEncryptionDecryption
TestCertificateBasedEncryptionDecryption
#TestDPAPIBasedEncryptionDecryption

#TestCertificateBasedEncryptionDecryption
4 changes: 2 additions & 2 deletions src/VersionInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ internal static class VersionInfo
/// Build Number (MMDD)
/// Revision (if any on the same day)
/// </summary>
internal const string Version = "2.16.0130.0";
internal const string Version = "2.16.0305.0";

/// <summary>
/// File Version information for the assembly consists of the following four values:
Expand All @@ -31,6 +31,6 @@ internal static class VersionInfo
/// Build Number (MMDD)
/// Revision (if any on the same day)
/// </summary>
internal const string FileVersion = "2.16.0130.0";
internal const string FileVersion = "2.16.0305.0";
}
}
111 changes: 57 additions & 54 deletions src/WorkflowActivityLibrary/Activities/RunPowerShellScript.cs
Original file line number Diff line number Diff line change
Expand Up @@ -882,75 +882,78 @@ private object RunScript(string script, IEnumerable scriptArguments, Dictionary<
throw Logger.Instance.ReportError(EventIdentifier.RunPowerShellScriptRunScriptInvocationError, new WorkflowActivityLibraryException(Messages.RunPowerShellScript_ScriptInvocationError, ex, ex.Message));
}

// Let's go soft on the the non-terminating errors and trapped exceptions.
// We'll just log the error streams.
// If script wants to kill the activity, it should throw an exception.
if (shell.Streams.Error.Count == 0)
{
if (this.ReturnType == PowerShellReturnType.None)
StringBuilder message = new StringBuilder();
message.AppendFormat(Messages.RunPowerShellScript_ScriptExecutionFailedError, shell.Streams.Error.Count);
foreach (ErrorRecord error in shell.Streams.Error)
{
return null;
message.AppendFormat("{0}\n", error);
}

if (results != null && results.Count == 1)
{
return results[0].BaseObject;
}
Logger.Instance.WriteError(EventIdentifier.RunPowerShellScriptRunScriptExecutionFailedError, message.ToString());
}

if (results == null || results.Count < 1)
{
return null;
}
if (this.ReturnType == PowerShellReturnType.None)
{
return null;
}

// If multiple values were found for the lookup, verify that they are of a consistent type
Type type = null;
bool consistentType = true;
foreach (PSObject pso in results)
{
if (type == null)
{
type = pso.BaseObject.GetType();

Logger.Instance.WriteVerbose(EventIdentifier.RunPowerShellScriptRunScript, "The PowerShell script returned type: '{0}'.", type);
}
else if (pso.BaseObject.GetType() != type)
{
consistentType = false;
Logger.Instance.WriteError(EventIdentifier.RunPowerShellScriptRunScriptInconsistentScriptReturnTypeError, Messages.RunPowerShellScript_InconsistentScriptReturnTypeError, pso.BaseObject.GetType(), type);
}
}
if (results != null && results.Count == 1)
{
return results[0].BaseObject;
}

// If we have multiple values of an inconsistent type, there is a problem
// which needs to be addressed by the administrator
if (!consistentType)
{
throw Logger.Instance.ReportError(EventIdentifier.RunPowerShellScriptRunScriptInconsistentScriptReturnTypeError, new WorkflowActivityLibraryException(Messages.RunPowerShellScript_InvalidReturnTypeError));
}
if (results == null || results.Count < 1)
{
return null;
}

// Because we have multiple values returned for the PowerShell script,
// we want to return them in the form of a strongly-typed list
// For example: List<string> instead of List<object>
// Use reflection to create a new strongly-typed list
Type listType = typeof(List<>).MakeGenericType(new Type[] { type });
var typedList = Activator.CreateInstance(listType);

// Using reflection, fetch the add method for the new list
// and invoke it to add each value from the original PSobject collection to the new collection
// Return the strongly-typed list
MethodInfo add = listType.GetMethod("Add");
foreach (PSObject pso in results)
{
add.Invoke(typedList, new object[] { pso.BaseObject });
}
// If multiple values were found for the lookup, verify that they are of a consistent type
Type type = null;
bool consistentType = true;
foreach (PSObject pso in results)
{
if (type == null)
{
type = pso.BaseObject.GetType();

return typedList;
Logger.Instance.WriteVerbose(EventIdentifier.RunPowerShellScriptRunScript, "The PowerShell script returned type: '{0}'.", type);
}
else if (pso.BaseObject.GetType() != type)
{
consistentType = false;
Logger.Instance.WriteError(EventIdentifier.RunPowerShellScriptRunScriptInconsistentScriptReturnTypeError, Messages.RunPowerShellScript_InconsistentScriptReturnTypeError, pso.BaseObject.GetType(), type);
}
}

// If we have multiple values of an inconsistent type, there is a problem
// which needs to be addressed by the administrator
if (!consistentType)
{
throw Logger.Instance.ReportError(EventIdentifier.RunPowerShellScriptRunScriptInconsistentScriptReturnTypeError, new WorkflowActivityLibraryException(Messages.RunPowerShellScript_InvalidReturnTypeError));
}

StringBuilder message = new StringBuilder();
message.AppendFormat(Messages.RunPowerShellScript_ScriptExecutionFailedError, shell.Streams.Error.Count);
foreach (ErrorRecord error in shell.Streams.Error)
// Because we have multiple values returned for the PowerShell script,
// we want to return them in the form of a strongly-typed list
// For example: List<string> instead of List<object>
// Use reflection to create a new strongly-typed list
Type listType = typeof(List<>).MakeGenericType(new Type[] { type });
var typedList = Activator.CreateInstance(listType);

// Using reflection, fetch the add method for the new list
// and invoke it to add each value from the original PSobject collection to the new collection
// Return the strongly-typed list
MethodInfo add = listType.GetMethod("Add");
foreach (PSObject pso in results)
{
message.AppendFormat("{0}\n", error);
add.Invoke(typedList, new object[] { pso.BaseObject });
}

throw Logger.Instance.ReportError(EventIdentifier.RunPowerShellScriptRunScriptExecutionFailedError, new WorkflowActivityLibraryException(message.ToString()));
return typedList;
}
}
}
Expand Down
3 changes: 2 additions & 1 deletion src/WorkflowActivityLibrary/Common/ExpressionFunction.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2900,7 +2900,8 @@ private string NormalizeString()
{
string[] substituionPairs = substitutions.Split(new string[] { "|" }, StringSplitOptions.RemoveEmptyEntries);

foreach (string[] substitution in substituionPairs.Select(substituionPair => substituionPair.Split(new string[] { ":" }, StringSplitOptions.RemoveEmptyEntries)).Where(substitution => substitution.Length == 2))
// Changed StringSplitOptions for substituionPairs from RemoveEmptyEntries to None so that soft and hard signs such as"Ь" can be simply dropped
foreach (string[] substitution in substituionPairs.Select(substituionPair => substituionPair.Split(new string[] { ":" }, StringSplitOptions.None)).Where(substitution => substitution.Length == 2))
{
input = input.Replace(substitution[0].Trim(), substitution[1].Trim());
input = input.Replace(substitution[0], substitution[1].Trim());
Expand Down

0 comments on commit e4afc31

Please sign in to comment.