Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SoupAPI Action password Encryption #4038

Merged
merged 6 commits into from
Dec 30, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@
<ColumnDefinition Width="200*"/>
</Grid.ColumnDefinitions>
<Label Style="{StaticResource @InputFieldLabelStyle}" Grid.Column="0" VerticalAlignment="Center" Margin="0,0,0,0">Password:</Label>
<Actions:UCValueExpression x:Name="PasswordTextBox" Grid.Column="1" VerticalAlignment="Center" ToolTip="The password to use in any authentications, overrides any password set for any TestRequests" />
<Actions:UCValueExpression x:Name="PasswordTextBox" Grid.Column="1" VerticalAlignment="Center" LostKeyboardFocus="PasswordTextBox_LostKeyboardFocus" ToolTip="The password to use in any authentications, overrides any password set for any TestRequests" />
</Grid>
</StackPanel>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ limitations under the License.
using Amdocs.Ginger.Common;
using Amdocs.Ginger.Repository;
using Ginger.UserControls;
using GingerCore;
using GingerCore.Actions;
using GingerCore.Actions.WebServices;
using System;
Expand Down Expand Up @@ -708,5 +709,36 @@ private void ClearPropertyFromList(ActSoapUiInputValue.ePropertyType propertyTyp
}

}

/// <summary>
/// Handles the LostKeyboardFocus event of the PasswordTextBox control.
/// Encrypts the password if needed.
/// </summary>
private void PasswordTextBox_LostKeyboardFocus(object sender, System.Windows.Input.KeyboardFocusChangedEventArgs e)
{
EncryptPasswordIfNeeded();
}
/// <summary>
/// Determines whether the password is a value expression.
/// </summary>
/// <returns>True if the password is a value expression; otherwise, false.</returns>
private bool IsPasswordValueExpression()
{
return ValueExpression.IsThisAValueExpression(mAct.GetInputParamValue(ActSoapUI.Fields.Password));
}

/// <summary>
/// Encrypts the password if it is not already encrypted and not a value expression.
/// </summary>
private void EncryptPasswordIfNeeded()
{
string password = mAct.GetInputParamValue(ActSoapUI.Fields.Password);
if (!string.IsNullOrEmpty(password) && !IsPasswordValueExpression() && !EncryptionHandler.IsStringEncrypted(password))
{
PasswordTextBox.ValueTextBox.Text = EncryptionHandler.EncryptwithKey(password);
}
}


}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@
<CheckBox x:Name="DoNotCertificateImportFile" Content="Import Certificate file to Solution folder" ToolTip="If checked the selected certificate file will be imported to ~Documents\Certificates\" HorizontalAlignment="Left" Margin="0,1,0,0" Style="{StaticResource @InputCheckBoxStyle}" Checked="DoNotCertificateImportFile_Checked"/>
</StackPanel>
<Label Style="{StaticResource @InputFieldLabelStyle}" Margin="0,5,0,0">Certificate Password:</Label>
<Actions:UCValueExpression x:Name="CertificatePasswordUCValueExpression" Margin="0,0,0,0"/>
<Actions:UCValueExpression x:Name="CertificatePasswordUCValueExpression" LostKeyboardFocus="CertificatePasswordUCValueExpression_LostKeyboardFocus" Margin="0,0,0,0"/>
</StackPanel>
<StackPanel Width="175" HorizontalAlignment="Left" Margin="0,5,0,0">
<Label Style="{StaticResource @InputFieldLabelStyle}">Security Type:</Label>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ limitations under the License.
using Amdocs.Ginger.Repository;
using Ginger.UserControls;
using Ginger.UserControlsLib.TextEditor;
using GingerCore;
using GingerCore.Actions;
using GingerCore.Actions.WebAPI;
using GingerCore.Actions.WebServices;
Expand Down Expand Up @@ -677,5 +678,35 @@ private void xViewRawRequestBtn_Click(object sender, RoutedEventArgs e)
}
Reporter.ToUser(eUserMsgKey.StaticErrorMessage, "Failed to load raw request preview, see log for details.");
}

/// <summary>
/// Handles the LostKeyboardFocus event for the CertificatePasswordUCValueExpression control.
/// Encrypts the password if needed.
/// </summary>
private void CertificatePasswordUCValueExpression_LostKeyboardFocus(object sender, System.Windows.Input.KeyboardFocusChangedEventArgs e)
{
EncryptPasswordIfNeeded();
}

/// <summary>
/// Determines if the password is a value expression.
/// </summary>
/// <returns>True if the password is a value expression; otherwise, false.</returns>
private bool IsPasswordValueExpression()
{
return ValueExpression.IsThisAValueExpression(mAct.GetInputParamValue(ActWebAPIBase.Fields.CertificatePassword));
}

/// <summary>
/// Encrypts the password if it is not already encrypted and not a value expression.
/// </summary>
private void EncryptPasswordIfNeeded()
{
string password = mAct.GetInputParamValue(ActWebAPIBase.Fields.CertificatePassword);
if (!string.IsNullOrEmpty(password) && !IsPasswordValueExpression() && !EncryptionHandler.IsStringEncrypted(password))
{
CertificatePasswordUCValueExpression.ValueTextBox.Text = EncryptionHandler.EncryptwithKey(password);
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
</StackPanel>
<StackPanel Orientation="Horizontal" Margin="0,10,0,0">
<Label Style="{StaticResource @InputFieldLabelStyle}" FontSize="13" VerticalAlignment="Center">Certificate Password:</Label>
<TextBox x:Name="CertificatePasswordUCValueExpression" HorizontalAlignment="Left" Width="235" VerticalContentAlignment="Center" Height="25" AcceptsReturn="True" Margin="2,0,0,0"/>
<Actions:UCValueExpression x:Name="CertificatePasswordUCValueExpression" HorizontalAlignment="Left" Width="260" VerticalContentAlignment="Center" Height="30" LostKeyboardFocus="CertificatePasswordUCValueExpression_LostKeyboardFocus" Margin="2,0,0,0"/>
</StackPanel>
</StackPanel>
<Label Style="{StaticResource @LabelStyle}" x:Name="xLabelUser" Visibility="Collapsed">SMTP User:</Label>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ limitations under the License.
using Amdocs.Ginger.Common;
using GingerCore;
using GingerCore.GeneralLib;
using System;
using System.Windows;
using System.Windows.Controls;
using CheckBox = System.Windows.Controls.CheckBox;
Expand Down Expand Up @@ -133,5 +134,52 @@ private void xSMTPPassTextBox_LostFocus(object sender, RoutedEventArgs e)
xSMTPPassTextBox.Text = EncryptionHandler.EncryptwithKey(xSMTPPassTextBox.Text);
}
}
/// <summary>
/// Handles the LostKeyboardFocus event for the CertificatePasswordUCValueExpression control.
/// Encrypts the password if needed.
/// </summary>
private void CertificatePasswordUCValueExpression_LostKeyboardFocus(object sender, System.Windows.Input.KeyboardFocusChangedEventArgs e)
{
try
{
EncryptPasswordIfNeeded();
}
catch (Exception ex)
{
Reporter.ToLog(eLogLevel.ERROR, "Failed to encrypt certificate password", ex);
}
}

/// <summary>
/// Checks if the CertificatePasswordUCValueExpression contains a value expression.
/// </summary>
/// <returns>True if it is a value expression, otherwise false.</returns>
private bool IsPasswordValueExpression()
{
return CertificatePasswordUCValueExpression?.ValueTextBox?.Text != null && ValueExpression.IsThisAValueExpression(CertificatePasswordUCValueExpression.ValueTextBox.Text);
}

/// <summary>
/// Encrypts the password in CertificatePasswordUCValueExpression if it is not already encrypted.
/// </summary>
private void EncryptPasswordIfNeeded()
{
try
{
if (string.IsNullOrEmpty(CertificatePasswordUCValueExpression.ValueTextBox.Text))
{
return;
}
string password = CertificatePasswordUCValueExpression.ValueTextBox.Text;
if (!string.IsNullOrEmpty(password) && !IsPasswordValueExpression() && !EncryptionHandler.IsStringEncrypted(password))
{
CertificatePasswordUCValueExpression.ValueTextBox.Text = EncryptionHandler.EncryptwithKey(password);
}
}
catch (Exception ex)
{
Reporter.ToLog(eLogLevel.ERROR, "Failed to encrypt certificate password", ex);
}
}
}
}
27 changes: 27 additions & 0 deletions Ginger/GingerCoreCommon/Actions/Act.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2119,5 +2119,32 @@ public bool AreEqual(object obj)
return AreEqual(obj as Act);
}

/// <summary>
/// Decrypts the given password. If the password is a value expression, it evaluates the expression before decryption.
/// </summary>
/// <param name="password">The password to decrypt.</param>
/// <param name="isPasswordValueExpression">Indicates if the password is a value expression.</param>
/// <param name="act">The Act instance containing the value expression.</param>
/// <returns>The decrypted password.</returns>
public static string DecryptPassword(string password, bool isPasswordValueExpression, Act act)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Move this method to GingerCoreNet proejct - > GeneralLib/General.cs class

{
if (password == null)
{
return null;
}

string decryptedPassword = string.Empty;
string evaluatedValue = password;

if (isPasswordValueExpression)
{
act.ValueExpression.Value = password;
evaluatedValue = act.ValueExpression.ValueCalculated;
}

decryptedPassword = EncryptionHandler.IsStringEncrypted(evaluatedValue) ? EncryptionHandler.DecryptwithKey(evaluatedValue) : evaluatedValue;

return decryptedPassword;
}
}
}
1 change: 1 addition & 0 deletions Ginger/GingerCoreCommon/Actions/Webservices/ActSoapUI.cs
Original file line number Diff line number Diff line change
Expand Up @@ -199,5 +199,6 @@ public bool isActionExecuted
return (System.IO.Directory.Exists(LastExecutionFolderPath));
}
}

}
}
2 changes: 1 addition & 1 deletion Ginger/GingerCoreCommon/GeneralLib/Email.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#region License
#region License
/*
Copyright © 2014-2024 European Support Limited

Expand Down
4 changes: 4 additions & 0 deletions Ginger/GingerCoreCommon/GingerCoreCommon.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,10 @@
<Folder Include="RunLib\Common\" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\GingerPluginCore\GingerPluginCore.csproj" />
</ItemGroup>

<ItemGroup>
<Reference Include="LiteDB">
<HintPath>..\..\..\..\..\.nuget\packages\litedb\4.1.4\lib\net40\LiteDB.dll</HintPath>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#region License
#region License
/*
Copyright © 2014-2024 European Support Limited

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,7 @@ private bool SetCertificates(HttpClientHandler handler)
{
string certificateKey = mAct.GetInputParamCalculatedValue(ActWebAPIBase.Fields.CertificatePassword);

certificateKey = Act.DecryptPassword(certificateKey, ValueExpression.IsThisAValueExpression(certificateKey), mAct);
if (!string.IsNullOrEmpty(path))
{
if (string.IsNullOrEmpty(certificateKey))
Expand Down Expand Up @@ -863,8 +864,8 @@ private void SetContentType()
{
eContentType = (ApplicationAPIUtils.eContentType)mAct.GetInputParamCalculatedValue<ApplicationAPIUtils.eContentType>(ActWebAPIRest.Fields.ContentType);

if (ContentType == null)
{
if (ContentType == null)
{
switch (eContentType)
{
case ApplicationAPIUtils.eContentType.JSon:
Expand Down
8 changes: 6 additions & 2 deletions Ginger/GingerCoreNET/Drivers/WebServicesDriver/SoapUIUtils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -150,8 +150,12 @@ public bool Command(ref string commandParam)
{ commandParam = commandParam + " -u" + Quotationmark + mAct.GetInputParamCalculatedValue(ActSoapUI.Fields.Username) + Quotationmark; }

//The password to use in any authentications, overrides any password set for any TestRequests
if (!string.IsNullOrEmpty(mAct.GetInputParamCalculatedValue(ActSoapUI.Fields.Password)))
{ commandParam = commandParam + " -p" + Quotationmark + mAct.GetInputParamCalculatedValue(ActSoapUI.Fields.Password) + Quotationmark; }
string password = mAct.GetInputParamCalculatedValue(ActSoapUI.Fields.Password);
if (!string.IsNullOrEmpty(password))
{
var decryptedPassword = Act.DecryptPassword(password, ValueExpression.IsThisAValueExpression(password), mAct);
commandParam = commandParam + " -p" + Quotationmark + decryptedPassword + Quotationmark;
}

//The domain to use in any authentications, overrides any domain set for any TestRequests
if (!string.IsNullOrEmpty(mAct.GetInputParamCalculatedValue(ActSoapUI.Fields.Domain)))
Expand Down
28 changes: 28 additions & 0 deletions Ginger/GingerCoreNET/GeneralLib/EmailOperations.cs
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,10 @@ public bool Send_SMTP()
{
string CertificateName = Path.GetFileName(Email.CertificatePath);
string CertificateKey = Email.CertificatePasswordUCValueExpression;
if (!string.IsNullOrEmpty(CertificateKey))
{
CertificateKey = DecryptPassword(CertificateKey, ValueExpression.IsThisAValueExpression(CertificateKey));
}
GokulBothe99 marked this conversation as resolved.
Show resolved Hide resolved
string targetPath = System.IO.Path.Combine(WorkSpace.Instance.Solution.Folder, @"Documents\EmailCertificates");//certificate is present in this folder //used this since relative path cannot be used during execution
string Certificatepath = Path.Combine(targetPath, CertificateName);
if (!string.IsNullOrEmpty(Certificatepath))
Expand Down Expand Up @@ -284,5 +288,29 @@ private bool CheckRequiredEmailFields(bool outlookEmail = false)
}
return true;
}
public string DecryptPassword(string password, bool isPasswordValueExpression)
{
if (password == null)
{
return null;
}
string decryptedPassword = string.Empty;

if (isPasswordValueExpression)
{


mVE.Value = password;
string evaluatedValue = mVE.ValueCalculated;

decryptedPassword = EncryptionHandler.IsStringEncrypted(evaluatedValue) ? EncryptionHandler.DecryptwithKey(evaluatedValue) : evaluatedValue;
}
else
{
decryptedPassword = EncryptionHandler.IsStringEncrypted(password) ? EncryptionHandler.DecryptwithKey(password) : password;
}

return decryptedPassword;
}
}
}
26 changes: 13 additions & 13 deletions Ginger/GingerCoreNET/ValueExpressionLib/ValueExpression.cs
Original file line number Diff line number Diff line change
Expand Up @@ -93,24 +93,24 @@ public class ValueExpression : IValueExpression
private static string rxVare = "";

// ^{} = exclude { inside or } inside - so we don't want to get var if there are 2 { - like VBS calc of 2 vars or if the } at the end
public static Regex rxVarPattern = new Regex(@"{(\bVar Name=)\w+\b[^{}]*}", RegexOptions.Compiled);
public static Regex rxVarPattern = new(@"{(\bVar Name=)\w+\b[^{}]*}", RegexOptions.Compiled);

public static readonly Regex rxVarFormulaParams = new Regex(@"[A-Za-z]*=[^,}]*", RegexOptions.Compiled);
public static readonly Regex rxVarFormulaParams = new(@"[A-Za-z]*=[^,}]*", RegexOptions.Compiled);

public static Regex rxGlobalParamPattern = new Regex(@"({GlobalAppsModelsParam Name=(\D*\d*\s*)}})|({GlobalAppsModelsParam Name=(\D*\d*\s*)})", RegexOptions.Compiled);
public static Regex rxGlobalParamPattern = new(@"({GlobalAppsModelsParam Name=(\D*\d*\s*)}})|({GlobalAppsModelsParam Name=(\D*\d*\s*)})", RegexOptions.Compiled);

private static Regex rxDSPattern = new Regex(@"{(\bDS Name=)\w+\b[^{}]*}", RegexOptions.Compiled);
public static Regex rxEnvParamPattern = new Regex(@"{(\bEnvParam App=)\w+\b[^{}]*}", RegexOptions.Compiled);
public static Regex rxEnvUrlPattern = new Regex(@"{(\bEnvURL App=)\w+\b[^{}]*}", RegexOptions.Compiled);
private static Regex rxFDPattern = new Regex(@"{(\bFD Object=)\w+\b[^{}]*}", RegexOptions.Compiled);
private static Regex rxExecutionJsonDataPattern = new Regex(@"{ExecutionJsonData}", RegexOptions.Compiled);
private static Regex rxDSPattern = new(@"{(\bDS Name=)\w+\b[^{}]*}", RegexOptions.Compiled);
public static Regex rxEnvParamPattern = new(@"{(\bEnvParam App=)\w+\b[^{}]*}", RegexOptions.Compiled);
public static Regex rxEnvUrlPattern = new(@"{(\bEnvURL App=)\w+\b[^{}]*}", RegexOptions.Compiled);
private static Regex rxFDPattern = new(@"{(\bFD Object=)\w+\b[^{}]*}", RegexOptions.Compiled);
private static Regex rxExecutionJsonDataPattern = new(@"{ExecutionJsonData}", RegexOptions.Compiled);

private static Regex VBSRegex = new Regex(@"{[V|E|VBS]" + rxVar + "[^{}]*}", RegexOptions.Compiled);
private static Regex rxe = new Regex(@"{RegEx" + rxVare + ".*}", RegexOptions.Compiled | RegexOptions.Singleline);
private static Regex VBSRegex = new(@"{[V|E|VBS]" + rxVar + "[^{}]*}", RegexOptions.Compiled);
private static Regex rxe = new(@"{RegEx" + rxVare + ".*}", RegexOptions.Compiled | RegexOptions.Singleline);

private static Regex rNestedfunc = new Regex("{Function(\\s)*Fun(\\s)*=(\\s)*([a-zA-Z]|\\d)*\\(([^()])*\\)}", RegexOptions.Compiled);
private static Regex MockDataExpPattern = new Regex("{MockDataExp({.*}|[^{}]*)*}", RegexOptions.Compiled, new TimeSpan(0, 0, 5));
private static Regex CsExppattern = new Regex("{CS Exp({.*}|[^{}]*)*}", RegexOptions.Compiled);
private static Regex rNestedfunc = new("{Function(\\s)*Fun(\\s)*=(\\s)*([a-zA-Z]|\\d)*\\(([^()])*\\)}", RegexOptions.Compiled);
private static Regex MockDataExpPattern = new("{MockDataExp({.*}|[^{}]*)*}", RegexOptions.Compiled, new TimeSpan(0, 0, 5));
private static Regex CsExppattern = new("{CS Exp({.*}|[^{}]*)*}", RegexOptions.Compiled);

// Enable setting value simply by assigned string,
// so no need to create new VE class everywhere in code
Expand Down
Loading