Skip to content

Commit

Permalink
Merge pull request #85 from NileshGhodekar/master
Browse files Browse the repository at this point in the history
MIMWAL Enhancements 2.20.0523.0
  • Loading branch information
NileshGhodekar authored May 23, 2020
2 parents 4998e11 + addd2ef commit 23487d9
Show file tree
Hide file tree
Showing 11 changed files with 291 additions and 40 deletions.
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,5 @@ GeneratedArtifacts/
_Pvt_Extensions/
ModelManifest.xml
/src/ReferencedAssemblies
/src/Scripts
/src/SolutionOutput
/src/WAL.snk
18 changes: 17 additions & 1 deletion ChangeLog.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,19 @@ All notable changes to MIMWAL project will be documented in this file. The "Unre
* Support for `[//Value]` lookups in Query definitions across rest of the activities.
------------

### Version 2.19.0111.0
### Version 2.20.0523.0

#### Added

* New [IndexByValueFunction][IndexByValue] function
* New [CRFunction][CR] function
* New [DateTimeUtcToLocalTimeFunction][DateTimeUtcToLocalTime] function
* New optional culture name parameter to [DateTimeFormatFunction][DateTimeFormat] function
* Added support for WAL Lookup resolution for PowerShellUserName and PowerShellUserPassword properties of [Run PowerShell Script][RunPowerShellScript] activity.

------------

### Version 2.19.0112.0

#### Changed

Expand Down Expand Up @@ -225,13 +237,15 @@ To get the backward compatible behaviour, define the app setting GenerateUniqueV
[CreateSqlParameterFunction]: https://github.com/Microsoft/MIMWAL/wiki/CreateSqlParameter-Function
[CreateSqlParameter2Function]: https://github.com/Microsoft/MIMWAL/wiki/CreateSqlParameter2-Function
[CRLFFunction]: https://github.com/Microsoft/MIMWAL/wiki/CRLF-Function
[CRFunction]: https://github.com/Microsoft/MIMWAL/wiki/CR-Function
[DateTimeAddFunction]: https://github.com/Microsoft/MIMWAL/wiki/DateTimeAdd-Function
[DateTimeFormatFunction]: https://github.com/Microsoft/MIMWAL/wiki/DateTimeFormat-Function
[DateTimeFromFileTimeUTCFunction]: https://github.com/Microsoft/MIMWAL/wiki/DateTimeFromFileTimeUTC-Function
[DateTimeFromStringFunction]: https://github.com/Microsoft/MIMWAL/wiki/DateTimeFromString-Function
[DateTimeNowFunction]: https://github.com/Microsoft/MIMWAL/wiki/DateTimeNow-Function
[DateTimeSubtractFunction]: https://github.com/Microsoft/MIMWAL/wiki/DateTimeSubtract-Function
[DateTimeToFileTimeUTCFunction]: https://github.com/Microsoft/MIMWAL/wiki/DateTimeToFileTimeUTC-Function
[DateTimeUtcToLocalTimeFunction]: https://github.com/Microsoft/MIMWAL/wiki/DateTimeUtcToLocalTime-Function
[DivideFunction]: https://github.com/Microsoft/MIMWAL/wiki/Divide-Function
[EqFunction]: https://github.com/Microsoft/MIMWAL/wiki/Eq-Function
[EscapeDNComponentFunction]: https://github.com/Microsoft/MIMWAL/wiki/EscapeDNComponent-Function
Expand All @@ -244,6 +258,7 @@ To get the backward compatible behaviour, define the app setting GenerateUniqueV
[GreaterThanFunction]: https://github.com/Microsoft/MIMWAL/wiki/GreaterThan-Function
[IIFFunction]: https://github.com/Microsoft/MIMWAL/wiki/IIF-Function
[InsertValuesFunction]: https://github.com/Microsoft/MIMWAL/wiki/InsertValues-Function
[IndexByValueFunction]: https://github.com/Microsoft/MIMWAL/wiki/IndexByValue-Function
[IsPresentFunction]: https://github.com/Microsoft/MIMWAL/wiki/IsPresent-Function
[LastFunction]: https://github.com/Microsoft/MIMWAL/wiki/Last-Function
[LeftFunction]: https://github.com/Microsoft/MIMWAL/wiki/Left-Function
Expand Down Expand Up @@ -288,3 +303,4 @@ To get the backward compatible behaviour, define the app setting GenerateUniqueV
[WrapXPathFilterFunction]: https://github.com/Microsoft/MIMWAL/wiki/WrapXPathFilter-Function
[MIMWalFunctionsTable]: https://github.com/Microsoft/MIMWAL/wiki/Functions-Table
[GenerateUniqueValueActivity]: https://github.com/Microsoft/MIMWAL/wiki/Generate-Unique-Value-Activity
[RunPowerShellScriptActivity]: https://github.com/Microsoft/MIMWAL/wiki/Run-PowerShell-Script-Activity
72 changes: 72 additions & 0 deletions src/Scripts/EncryptConnectionString.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
<#
This script demonstrates how to encrypt connection strings used by WAL ExecutSql* functions.
If a connection string contains SQL user's password information, it's highly recommended that you do not leave them unencrypted in the app config file.
For more information, see: https://docs.microsoft.com/en-us/dotnet/framework/data/adonet/connection-strings-and-configuration-files#encrypting-configuration-file-sections-using-protected-configuration
NOTE: This script will need to to be run on each FIMService server.
#>

param (
[string] $sectionName = "connectionStrings",
[string] $dataProtectionProvider = "DataProtectionConfigurationProvider"
)

$Error.Clear()

#The System.Configuration assembly must be loaded
$configurationAssembly = "System.Configuration, Version=2.0.0.0, Culture=Neutral, PublicKeyToken=b03f5f7f11d50a3a"
[void] [Reflection.Assembly]::Load($configurationAssembly)

function TestIsAdministrator
{
$currentUser = [Security.Principal.WindowsIdentity]::GetCurrent()
(New-Object Security.Principal.WindowsPrincipal $currentUser).IsInRole([Security.Principal.WindowsBuiltinRole]::Administrator)
}

if(!(TestIsAdministrator))
{
throw $("Admin rights are required to run this script.")
}

Write-Host "Encrypting configuration section: '$sectionName'.."

$appService = "FIMService"
$appPath = [string](Get-WmiObject -Query "Select * from Win32_Service Where Name='$appService'").PathName

if ($appPath -eq $null)
{
Write-Error "Unable to find get application path for windows service '$appService'."
return
}
else
{
$appPath = $appPath.Trim('"')
}

Write-Host "The app config file path is: '$appPath'."

$appConfig = [System.Configuration.ConfigurationManager]::OpenExeConfiguration($appPath)
$section = $appConfig.GetSection($sectionName)

if (!$section.SectionInformation.IsProtected)
{
$section.SectionInformation.ProtectSection($dataProtectionProvider);
$section.SectionInformation.ForceSave = [System.Boolean]::True;
$appConfig.Save([System.Configuration.ConfigurationSaveMode]::Modified);

if ($Error.Count -eq 0)
{
Write-Host "Success!! Encrypted the config section '$sectionName' in the app config file '$appPath'."
}
}
else
{
Write-Host "The config section '$sectionName' in the app config file '!$appPath' is already encrypted."
}

if ($Error)
{
Write-Host "There were errors executing the script."
}
4 changes: 2 additions & 2 deletions src/Scripts/EncryptData.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,14 @@
Finding Assembly verion and PublicKeyToken
gacutil.exe -l | findstr WorkflowActivityLibrary
Creatinig a self signed certificate for MIMWAL (You can use a legacy CSP such as Microsoft Strong Cryptographic Provider as shown in the example below)
$cert = New-SelfSignedCertificate -DnsName "MIMWAL" -CertStoreLocation "cert:\LocalMachine\My" -Provider "Microsoft Strong Cryptographic Provider"
$cert = New-SelfSignedCertificate -DnsName "MIMWAL Encryption (Do Not Delete)" -CertStoreLocation "cert:\LocalMachine\My" -Provider "Microsoft Strong Cryptographic Provider" -NotAfter (Get-Date).AddYears(20)
$cert.Thumbprint
As of version v2.18.1110.0, only FIMService account needs read access to the private key of the MIMWAL certificate created above.
#>

$Error.Clear()

$walAssemblyVersion = "2.16.0710.0"
$walAssemblyVersion = "2.20.0523.0"
$walAssemblyPublicKeyToken = "31bf3856ad364e35"
$encryptionCertThumbprint = "9C697919FB2FB2D6324ADE42D5F8CB49E8778C08" # cert to be used for encryption (from the cert:\localmachine\my\ store).

Expand Down
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.19.0112.0";
internal const string Version = "2.20.0523.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.19.0112.0";
internal const string FileVersion = "2.20.0523.0";
}
}
8 changes: 4 additions & 4 deletions src/WorkflowActivityLibrary.UI/ActivitySettings.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions src/WorkflowActivityLibrary.UI/ActivitySettings.resx
Original file line number Diff line number Diff line change
Expand Up @@ -658,19 +658,19 @@
<value>PowerShell Script User</value>
</data>
<data name="PowerShellUserHelpText" xml:space="preserve">
<value>Specify the user to be used to construct PowerShell Credential object. When impersonating, the user name must be in the domain\userName or UPN format.</value>
<value>Specify the user to be used to construct PowerShell Credential object. When impersonating, the user name must be in the domain\userName or UPN format or must be a valid WAL Lookup expression.</value>
</data>
<data name="PowerShellUserPassword" xml:space="preserve">
<value>PowerShell Script User Password</value>
</data>
<data name="PowerShellUserPasswordHelpText" xml:space="preserve">
<value>Specify the password to be used to construct PowerShell Credential object. The expected format is: [base64EncodedEncryptedData] | [app:\appSettings\[key],[LocalMachine|CurrentUser]] | [cert:\[LocalMachine|CurrentUser]\my\[thumbprint],base64EncodedEncryptedData]]</value>
<value>Specify the password to be used to construct PowerShell Credential object. The expected format is: [base64EncodedEncryptedData] | [app:\appSettings\[key],[LocalMachine|CurrentUser]] | [cert:\[LocalMachine|CurrentUser]\my\[thumbprint],base64EncodedEncryptedData]]. It can also be a valid WAL Lookup expression returing data in any one of these formats.</value>
</data>
<data name="PowerShellImpersonationSettingsValidationError" xml:space="preserve">
<value>Specify UserName and Password of the impersonated user.</value>
</data>
<data name="PowerShellUserFormatValidationError" xml:space="preserve">
<value>The PowerShell user must be specified in the domain\userName or UPN format when Impersonate PowerShell User option is selected.</value>
<value>The PowerShell user must be specified in the domain\userName or UPN format or must be a valid WAL Lookup expression when Impersonate PowerShell User option is selected.</value>
</data>
<data name="RequestActorValidationError" xml:space="preserve">
<value>Authorization Policy cannot be applied when Request Actor is Service Account</value>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -554,7 +554,9 @@ public override bool ValidateInputs()

if (!string.IsNullOrEmpty(this.powerShellUser.Value))
{
if (this.impersonatePowerShellUser.Value)
var powerShellUserIsExpression = evaluator.ParseIfExpression(this.powerShellUser.Value);

if (this.impersonatePowerShellUser.Value && !powerShellUserIsExpression)
{
if (!this.powerShellUser.Value.Contains(@"\") && !this.powerShellUser.Value.Contains("@"))
{
Expand Down
56 changes: 51 additions & 5 deletions src/WorkflowActivityLibrary/Activities/RunPowerShellScript.cs
Original file line number Diff line number Diff line change
Expand Up @@ -653,6 +653,16 @@ private void Prepare_ExecuteCode(object sender, EventArgs e)
// If the activity is configured for conditional execution, parse the associated expression
this.ActivityExpressionEvaluator.ParseIfExpression(this.ActivityExecutionCondition);

if (!string.IsNullOrEmpty(this.PowerShellUser))
{
this.ActivityExpressionEvaluator.ParseIfExpression(this.PowerShellUser);
}

if (!string.IsNullOrEmpty(this.PowerShellUserPassword))
{
this.ActivityExpressionEvaluator.ParseIfExpression(this.PowerShellUserPassword);
}

if (this.InputType == PowerShellInputType.Arguments &&
this.Arguments != null &&
this.Arguments.Count > 0)
Expand Down Expand Up @@ -1018,18 +1028,54 @@ private PSCredential GetPowerShellCredential()
return null;
}

var userName = this.PowerShellUser;
var userPassword = this.PowerShellUserPassword;

if (ExpressionEvaluator.IsExpression(userName))
{
try
{
object resolved = this.ActivityExpressionEvaluator.ResolveExpression(userName);
if (resolved != null)
{
userName = resolved.ToString();
}
}
catch (WorkflowActivityLibraryException)
{
// This may happen if the design time username starts with a $
// Do nothing. Any valid error should already be reported.
}
}

if (ExpressionEvaluator.IsExpression(userPassword))
{
try
{
object resolved = this.ActivityExpressionEvaluator.ResolveExpression(userPassword);
if (resolved != null)
{
userPassword = resolved.ToString();
}
}
catch (WorkflowActivityLibraryException)
{
// Do nothing. Any valid error should already be reported.
}
}

if (this.ImpersonatePowerShellUser)
{
string[] userParts = this.PowerShellUser.Split(new string[] { @"\" }, StringSplitOptions.RemoveEmptyEntries);
if (userParts.Length != 2 && !this.PowerShellUser.Contains("@"))
string[] userParts = userName.Split(new string[] { @"\" }, StringSplitOptions.RemoveEmptyEntries);
if (userParts.Length != 2 && !userName.Contains("@"))
{
throw Logger.Instance.ReportError(EventIdentifier.RunPowerShellScriptRunScriptExecutionFailedError, new WorkflowActivityLibraryException(Messages.RunPowerShellActivity_InvalidUserFormat, this.PowerShellUser));
throw Logger.Instance.ReportError(EventIdentifier.RunPowerShellScriptRunScriptExecutionFailedError, new WorkflowActivityLibraryException(Messages.RunPowerShellActivity_InvalidUserFormat, userName));
}
}

SecureString password = ProtectedData.DecryptData(this.PowerShellUserPassword);
SecureString password = ProtectedData.DecryptData(userPassword);

return new PSCredential(this.PowerShellUser, password);
return new PSCredential(userName, password);
}

/// <summary>
Expand Down
33 changes: 24 additions & 9 deletions src/WorkflowActivityLibrary/Common/EventIdentifier.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1296,7 +1296,12 @@ public static class EventIdentifier
/// <summary>
/// The event identifier for ExpressionFunction CR events
/// </summary>
public const int ExpressionFunctionCr = 11688;
public const int ExpressionFunctionCR = 11688;

/// <summary>
/// The event identifier for ExpressionFunction DateTimeUtcToLocalTime events
/// </summary>
public const int ExpressionFunctionDateTimeUtcToLocalTime = 11689;

/// <summary>
/// The event identifier for LookupEvaluator Constructor events
Expand Down Expand Up @@ -2358,6 +2363,11 @@ public static class EventIdentifier
/// </summary>
public const int ExpressionFunctionDateTimeFormatInvalidFirstFunctionParameterTypeError = 41621;

/// <summary>
/// The event identifier for ExpressionFunction DateTimeFormat events
/// </summary>
public const int ExpressionFunctionDateTimeFormatInvalidThirdFunctionParameterTypeError = 41621;

/// <summary>
/// The event identifier for ExpressionFunction DateTimeNow events
/// </summary>
Expand Down Expand Up @@ -2758,11 +2768,6 @@ public static class EventIdentifier
/// </summary>
public const int ExpressionFunctionCrlfInvalidFunctionParameterCountError = 41658;

/// <summary>
/// The event identifier for ExpressionFunction CR events
/// </summary>
public const int ExpressionFunctionCrInvalidFunctionParameterCountError = 41658;

/// <summary>
/// The event identifier for ExpressionFunction EscapeDNComponent events
/// </summary>
Expand Down Expand Up @@ -3194,14 +3199,24 @@ public static class EventIdentifier
public const int ExpressionFunctionModInvalidSecondFunctionParameterTypeError = 41686;

/// <summary>
/// The event identifier for ExpressionFunction ValueByIndex events
/// The event identifier for ExpressionFunction IndexByValue events
/// </summary>
public const int ExpressionFunctionIndexByValueInvalidFunctionParameterCountError = 41687;

/// <summary>
/// The event identifier for ExpressionFunction IndexByValue events
/// The event identifier for ExpressionFunction CR events
/// </summary>
public const int ExpressionFunctionCRInvalidFunctionParameterCountError = 41688;

/// <summary>
/// The event identifier for ExpressionFunction DateTimeUtcToLocalTime events
/// </summary>
public const int ExpressionFunctionDateTimeUtcToLocalTimeInvalidFunctionParameterCountError = 41689;

/// <summary>
/// The event identifier for ExpressionFunction DateTimeUtcToLocalTime events
/// </summary>
public const int ExpressionFunctionIndexByValueNullFunctionParameterError = 41645;
public const int ExpressionFunctionDateTimeUtcToLocalTimeInvalidSecondFunctionParameterTypeError = 41689;

/// <summary>
/// The event identifier for LookupEvaluator Constructor events
Expand Down
Loading

0 comments on commit 23487d9

Please sign in to comment.