Skip to content

Commit e1c3bcb

Browse files
committed
Merge pull request #30 from AzCiS/set-assvd-new-params
Add new params to SetASSVirtualDevice for snapshot mgr passwd and admin ...
2 parents d860931 + 7ff6564 commit e1c3bcb

File tree

7 files changed

+165
-33
lines changed

7 files changed

+165
-33
lines changed

src/ServiceManagement/StorSimple/Commands.StorSimple/Cmdlets/DeviceDetails/NewAzureStorSimpleNetworkConfig.cs

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -31,76 +31,77 @@ public class NewAzureStorSimpleNetworkConfig : StorSimpleCmdletBase
3131
{
3232
#region Parameters
3333

34+
/// <summary>
35+
/// Interface alias of interface for which settings are being supplied. A value
36+
/// from Data0 to Data5
37+
/// </summary>
38+
[Parameter(Mandatory = true, Position = 0, HelpMessage = StorSimpleCmdletHelpMessage.InterfaceAlias)]
39+
[ValidateSetAttribute(new string[] { "Data0", "Data1", "Data2", "Data3", "Data4", "Data5" })]
40+
public string InterfaceAlias { get; set; }
41+
3442
/// <summary>
3543
/// Whether the net interface is iscsi enabled/disabled
3644
/// </summary>
37-
[Parameter(Mandatory=false, Position = 0, HelpMessage = StorSimpleCmdletHelpMessage.IsIscsiEnabled)]
45+
[Parameter(Mandatory=false, Position = 1, HelpMessage = StorSimpleCmdletHelpMessage.IsIscsiEnabled)]
3846
[ValidateNotNullOrEmpty]
3947
public bool? EnableIscsi { get; set; }
4048

4149
/// <summary>
4250
/// Whether the net interface is cloud enabled/disabled
4351
/// </summary>
44-
[Parameter(Mandatory = false, Position = 1, HelpMessage = StorSimpleCmdletHelpMessage.IsCloudEnabled)]
52+
[Parameter(Mandatory = false, Position = 2, HelpMessage = StorSimpleCmdletHelpMessage.IsCloudEnabled)]
4553
[ValidateNotNullOrEmpty]
4654
public bool? EnableCloud { get; set; }
4755

4856
/// <summary>
4957
/// IPv4Address for controller 0, should be used only with Data0 interface
5058
/// </summary>
51-
[Parameter(Mandatory = false, Position = 2, HelpMessage = StorSimpleCmdletHelpMessage.Controller0IPv4Address)]
59+
[Parameter(Mandatory = false, Position = 3, HelpMessage = StorSimpleCmdletHelpMessage.Controller0IPv4Address)]
5260
[ValidateNotNullOrEmpty]
5361
public string Controller0IPv4Address { get; set; }
5462

5563
/// <summary>
5664
/// IPv4Address for controller 1, should be used only with Data0 interface
5765
/// </summary>
58-
[Parameter(Mandatory = false, Position = 3, HelpMessage = StorSimpleCmdletHelpMessage.Controller1IPv4Address)]
66+
[Parameter(Mandatory = false, Position = 4, HelpMessage = StorSimpleCmdletHelpMessage.Controller1IPv4Address)]
5967
[ValidateNotNullOrEmpty]
6068
public string Controller1IPv4Address { get; set; }
6169

6270
/// <summary>
6371
/// IPv4 net mask for interface
6472
/// </summary>
65-
[Parameter(Mandatory = false, Position = 4, HelpMessage = StorSimpleCmdletHelpMessage.IPv6Gateway)]
73+
[Parameter(Mandatory = false, Position = 5, HelpMessage = StorSimpleCmdletHelpMessage.IPv6Gateway)]
6674
[ValidateNotNullOrEmpty]
6775
public string IPv6Gateway { get; set; }
6876

6977
/// <summary>
7078
/// IPv4 Address of gateway
7179
/// </summary>
72-
[Parameter(Mandatory = false, Position = 5, HelpMessage = StorSimpleCmdletHelpMessage.IPv4Gateway)]
80+
[Parameter(Mandatory = false, Position = 6, HelpMessage = StorSimpleCmdletHelpMessage.IPv4Gateway)]
7381
[ValidateNotNullOrEmpty]
7482
public string IPv4Gateway { get; set; }
7583

7684
/// <summary>
7785
/// IPv4 Address for the net interface
7886
/// </summary>
79-
[Parameter(Mandatory = false, Position = 6, HelpMessage = StorSimpleCmdletHelpMessage.IPv4Address)]
87+
[Parameter(Mandatory = false, Position = 7, HelpMessage = StorSimpleCmdletHelpMessage.IPv4Address)]
8088
[ValidateNotNullOrEmpty]
8189
public string IPv4Address { get; set; }
8290

8391
/// <summary>
8492
/// IPv6 Prefix for the net interface
8593
/// </summary>
86-
[Parameter(Mandatory = false, Position = 7, HelpMessage = StorSimpleCmdletHelpMessage.IPv6Prefix)]
94+
[Parameter(Mandatory = false, Position = 8, HelpMessage = StorSimpleCmdletHelpMessage.IPv6Prefix)]
8795
[ValidateNotNullOrEmpty]
8896
public string IPv6Prefix { get; set; }
8997

9098
/// <summary>
9199
/// IPv4 netmask for this interface
92100
/// </summary>
93-
[Parameter(Mandatory = false, Position = 8, HelpMessage = StorSimpleCmdletHelpMessage.IPv4Netmask)]
101+
[Parameter(Mandatory = false, Position = 9, HelpMessage = StorSimpleCmdletHelpMessage.IPv4Netmask)]
94102
[ValidateNotNullOrEmpty]
95103
public string IPv4Netmask { get; set; }
96104

97-
/// <summary>
98-
/// Interface alias of interface for which settings are being supplied. A value
99-
/// from Data0 to Data5
100-
/// </summary>
101-
[Parameter(Mandatory = true, Position = 9, HelpMessage = StorSimpleCmdletHelpMessage.InterfaceAlias)]
102-
[ValidateSetAttribute(new string[] { "Data0", "Data1", "Data2", "Data3", "Data4", "Data5" })]
103-
public string InterfaceAlias { get; set; }
104105
#endregion
105106

106107
private IPAddress controller0Address;

src/ServiceManagement/StorSimple/Commands.StorSimple/Cmdlets/DeviceDetails/SetAzureStorSimpleVirtualDevice.cs

Lines changed: 37 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -38,25 +38,41 @@ public class SetAzureStorSimpleVirtualDevice : StorSimpleCmdletBase
3838
[Parameter(Mandatory = true, Position = 0, HelpMessage = StorSimpleCmdletHelpMessage.DeviceName)]
3939
[ValidateNotNullOrEmpty]
4040
public string DeviceName { get; set; }
41-
42-
/// <summary>
43-
/// TimeZone for the device.
44-
/// </summary>
45-
[Parameter(Mandatory = false, Position = 1, HelpMessage = StorSimpleCmdletHelpMessage.TimeZone, ValueFromPipeline=true)]
46-
[ValidateNotNullOrEmpty]
47-
public TimeZoneInfo TimeZone { get; set; }
4841

4942
/// <summary>
5043
/// Service Encryption Key for the resource.
5144
/// </summary>
52-
[Parameter(Mandatory=true, Position = 2, HelpMessage = StorSimpleCmdletHelpMessage.SEK)]
45+
[Parameter(Mandatory=true, Position = 1, HelpMessage = StorSimpleCmdletHelpMessage.SEK)]
5346
[ValidateNotNullOrEmpty]
5447
public string SecretKey { get; set; }
5548

49+
/// <summary>
50+
/// Device administrator password
51+
/// </summary>
52+
[Parameter(Mandatory=true, Position=2, HelpMessage = StorSimpleCmdletHelpMessage.AdministratorPasswd)]
53+
[ValidateNotNullOrEmpty]
54+
public string AdministratorPassword { get; set; }
55+
56+
/// <summary>
57+
/// Snapshot manager password
58+
/// </summary>
59+
[Parameter(Mandatory=true, Position=3, HelpMessage=StorSimpleCmdletHelpMessage.SnapshotManagerPasswd)]
60+
[ValidateNotNullOrEmpty]
61+
public string SnapshotManagerPassword { get; set; }
62+
63+
/// <summary>
64+
/// TimeZone for the device.
65+
/// </summary>
66+
[Parameter(Mandatory = false, Position = 4, HelpMessage = StorSimpleCmdletHelpMessage.TimeZone, ValueFromPipeline = true)]
67+
[ValidateNotNullOrEmpty]
68+
public TimeZoneInfo TimeZone { get; set; }
69+
5670
public override void ExecuteCmdlet()
5771
{
5872
try
5973
{
74+
ValidateParams();
75+
6076
// Make sure we have a device for supplied name and get its device id.
6177
var deviceId = StorSimpleClient.GetDeviceId(DeviceName);
6278
if (deviceId == null)
@@ -73,7 +89,8 @@ public override void ExecuteCmdlet()
7389
string cik = EncryptionCmdLetHelper.RetrieveCIK(this, StorSimpleContext.ResourceId);
7490

7591
// Update device details.
76-
StorSimpleClient.UpdateVirtualDeviceDetails(deviceDetails, TimeZone, SecretKey, cik);
92+
var cryptoManager = new StorSimpleCryptoManager(StorSimpleClient);
93+
StorSimpleClient.UpdateVirtualDeviceDetails(deviceDetails, TimeZone, SecretKey, AdministratorPassword, SnapshotManagerPassword, cik, cryptoManager);
7794

7895
// Make request with updated data
7996
WriteVerbose(string.Format(Resources.BeginningDeviceConfiguration, deviceDetails.DeviceProperties.FriendlyName));
@@ -92,7 +109,17 @@ public override void ExecuteCmdlet()
92109
this.HandleException(exception);
93110
}
94111
}
95-
112+
113+
/// <summary>
114+
///
115+
/// </summary>
116+
/// <returns></returns>
117+
private void ValidateParams() {
118+
ValidateLength(AdministratorPassword, 8, 15, Resources.AdminPasswordLengthError);
119+
ValidateLength(SnapshotManagerPassword, 14, 15, Resources.SnapshotPasswordLengthError);
120+
ValidatePasswordComplexity(AdministratorPassword, "AdministratorPassword");
121+
ValidatePasswordComplexity(SnapshotManagerPassword, "SnapshotManagerPassword");
122+
}
96123
}
97124
}
98125

src/ServiceManagement/StorSimple/Commands.StorSimple/Properties/Resources.Designer.cs

Lines changed: 31 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/ServiceManagement/StorSimple/Commands.StorSimple/Properties/Resources.resx

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -513,7 +513,21 @@
513513
<data name="CIKInvalidWithException" xml:space="preserve">
514514
<value>Invalid value for Registration Key. CIK provided couldnt be used to decrypt the secrets! The exact exception while decrypting is "{0}"!</value>
515515
</data>
516+
<data name="PasswordCharacterCriteriaError" xml:space="preserve">
517+
<value>{0} is not complex enough. It must contain 3 of the following:
518+
a lowercase character
519+
an uppercase character
520+
a number
521+
a special character</value>
522+
</data>
523+
<data name="AdminPasswordLengthError" xml:space="preserve">
524+
<value>The AdministratorPassword must be between 8 to 15 characters.</value>
525+
</data>
526+
<data name="SnapshotPasswordLengthError" xml:space="preserve">
527+
<value>The SnapshotManagerPassword must be either 14 or 15 characters long</value>
528+
</data>
516529
<data name="SetAzureStorSimpleDeviceNoSettingsProvided" xml:space="preserve">
517530
<value>No settings were provided for updating device details.</value>
531+
518532
</data>
519533
</root>

src/ServiceManagement/StorSimple/Commands.StorSimple/ServiceClients/StorSimpleDevicesClient.cs

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,7 @@ private void UpdateDeviceDetailsObject(DeviceDetails deviceDetails, string newNa
202202
deviceDetails.WebProxy = null;
203203
}
204204

205-
public void UpdateVirtualDeviceDetails(DeviceDetails details, TimeZoneInfo timeZone, string sek, string cik)
205+
public void UpdateVirtualDeviceDetails(DeviceDetails details, TimeZoneInfo timeZone, string sek, string adminPasswd, string snapshotPasswd, string cik, StorSimpleCryptoManager cryptoManager)
206206
{
207207
if (timeZone != null)
208208
{
@@ -215,10 +215,20 @@ public void UpdateVirtualDeviceDetails(DeviceDetails details, TimeZoneInfo timeZ
215215

216216
// Also set the CIK before making the request - service needs it.
217217
var encryptedCik = this.EncryptWithDevicePublicKey(details.DeviceProperties.DeviceId, cik);
218-
219218
details.VirtualApplianceProperties.EncodedChannelIntegrityKey = encryptedCik;
220219

221-
details.VirtualApplianceProperties.IsServiceEncryptionKeySet = true;
220+
// Set the admin password
221+
string encryptedAdminPasswd = null;
222+
cryptoManager.EncryptSecretWithRakPub(adminPasswd, out encryptedAdminPasswd);
223+
details.RemoteMinishellSecretInfo.MinishellSecret = encryptedAdminPasswd;
224+
225+
// Set the snapshot manager password
226+
string encryptedSnapshotManagerPasswd = null;
227+
cryptoManager.EncryptSecretWithRakPub(snapshotPasswd, out encryptedSnapshotManagerPasswd);
228+
details.Snapshot.SnapshotSecret = encryptedSnapshotManagerPasswd;
229+
230+
// Set the cert thumbprint for the key used.
231+
details.SecretEncryptionCertThumbprint = cryptoManager.GetSecretsEncryptionThumbprint();
222232

223233
// mark everything that we dont intend to modify as null - indicating
224234
// to the service that there has been no change
@@ -227,9 +237,6 @@ public void UpdateVirtualDeviceDetails(DeviceDetails details, TimeZoneInfo timeZ
227237
details.DnsServer = null;
228238
details.NetInterfaceList = null;
229239
details.RemoteMgmtSettingsInfo = null;
230-
details.RemoteMinishellSecretInfo = null;
231-
details.SecretEncryptionCertThumbprint = null;
232-
details.Snapshot = null;
233240
details.WebProxy = null;
234241
}
235242
}

src/ServiceManagement/StorSimple/Commands.StorSimple/StorSimpleCmdletBase.cs

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -518,5 +518,56 @@ internal bool IsValidAsciiString(string s)
518518
{
519519
return Regex.IsMatch(s, "[ -~]+");
520520
}
521+
522+
/// <summary>
523+
/// Validate that the string provided has length within the specified constraints.
524+
///
525+
/// Throws an ArgumentException with the specified error message if the validation fails.
526+
/// </summary>
527+
/// <param name="data">string to be validated</param>
528+
/// <param name="minLength">minimum allowable length for the string</param>
529+
/// <param name="maxLength">maximum allowable length for the string</param>
530+
/// <param name="errorMessage">error message for the exception raised in case of invalid data</param>
531+
internal void ValidateLength(string data, uint minLength, uint maxLength, string errorMessage)
532+
{
533+
if (data.Length < minLength || data.Length > maxLength)
534+
{
535+
throw new ArgumentException(errorMessage);
536+
}
537+
}
538+
539+
/// <summary>
540+
/// Most of the passwords in the device must contain 3 of the following:
541+
/// - a lowercase character
542+
/// - an uppercase character
543+
/// - a number
544+
/// - a special character
545+
///
546+
/// Raises an ArgumentException with appropriate error message notifying the above
547+
/// conditions when the validation fails.
548+
/// </summary>
549+
/// <param name="data"></param>
550+
internal void ValidatePasswordComplexity(string data, string passwordName)
551+
{
552+
string errorMessage = string.Format(Resources.PasswordCharacterCriteriaError, passwordName);
553+
var criteriaFulfilled = 0;
554+
// Regular expressions for lowercase letter, uppercase letter, digit and special char
555+
// respectively
556+
string[] criteriaRegexs = { ".*[a-z]", ".*[A-Z]", ".*\\d", ".*\\W" };
557+
558+
foreach(var regexStr in criteriaRegexs){
559+
// The static IsMatch method is supposed to use an Application-wide cache of compiled regexes
560+
// and hence should save computation time (though not very significant because we are not doing tens of
561+
// thousands of such tests)
562+
if(Regex.IsMatch(data, regexStr)){
563+
criteriaFulfilled += 1;
564+
}
565+
}
566+
567+
// If atleast 3 criteria have been fulfilled, then the password is complex enough
568+
if(criteriaFulfilled < 3){
569+
throw new ArgumentException(errorMessage);
570+
}
571+
}
521572
}
522573
}

src/ServiceManagement/StorSimple/Commands.StorSimple/StorSimpleCmdletHelpMessage.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ internal static class StorSimpleCmdletHelpMessage
119119
public const string ToTime = "End of time interval for which to filter results.";
120120
public const string DeviceJobStatus = "Status of job.";
121121
public const string DeviceJobType = "Type of job.";
122-
122+
public const string AdministratorPasswd = "Administrator password for the device.";
123+
public const string SnapshotManagerPasswd = "Password for snapshot manager";
123124
}
124125
}

0 commit comments

Comments
 (0)