mirror of
https://github.com/GoodOlClint/PSProxmoxVE.git
synced 2026-07-26 07:58:14 +00:00
fix: use SecureString for guest password, validate Pool/CephPool conflict
Set-PveVmGuestPassword now accepts SecureString instead of plain string for the -Password parameter, matching the established pattern in Set-PvePassword. The password is converted via Marshal and zeroed from memory after use. New-PveStorage now validates that -Pool and -CephPool cannot both be specified, since both mapped to the same API key and CephPool silently overwrote Pool. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -15,7 +15,7 @@ namespace PSProxmoxVE.Cmdlets.Storage
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
[Cmdlet(VerbsCommon.New, "PveStorage", SupportsShouldProcess = true)]
|
[Cmdlet(VerbsCommon.New, "PveStorage", SupportsShouldProcess = true)]
|
||||||
[OutputType(typeof(PveStorage))]
|
[OutputType(typeof(PveStorage))]
|
||||||
public class NewPveStorageCmdlet : PveCmdletBase
|
public sealed class NewPveStorageCmdlet : PveCmdletBase
|
||||||
{
|
{
|
||||||
/// <summary>The unique storage identifier/name.</summary>
|
/// <summary>The unique storage identifier/name.</summary>
|
||||||
[Parameter(Mandatory = true, Position = 0, HelpMessage = "The storage pool name.")]
|
[Parameter(Mandatory = true, Position = 0, HelpMessage = "The storage pool name.")]
|
||||||
@@ -80,6 +80,14 @@ namespace PSProxmoxVE.Cmdlets.Storage
|
|||||||
if (!ShouldProcess(Storage, "Create PVE Storage"))
|
if (!ShouldProcess(Storage, "Create PVE Storage"))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(Pool) && !string.IsNullOrEmpty(CephPool))
|
||||||
|
{
|
||||||
|
ThrowTerminatingError(new ErrorRecord(
|
||||||
|
new PSArgumentException("Pool and CephPool cannot both be specified. Use Pool for ZFS pools or CephPool for Ceph/RBD pools."),
|
||||||
|
"PoolConflict", ErrorCategory.InvalidArgument, null));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var session = GetSession();
|
var session = GetSession();
|
||||||
using var client = new PveHttpClient(session);
|
using var client = new PveHttpClient(session);
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
using System.Management.Automation;
|
using System.Management.Automation;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Security;
|
||||||
using PSProxmoxVE.Core.Services;
|
using PSProxmoxVE.Core.Services;
|
||||||
|
|
||||||
namespace PSProxmoxVE.Cmdlets.Vms
|
namespace PSProxmoxVE.Cmdlets.Vms
|
||||||
@@ -12,6 +14,7 @@ namespace PSProxmoxVE.Cmdlets.Vms
|
|||||||
/// </para>
|
/// </para>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Cmdlet(VerbsCommon.Set, "PveVmGuestPassword", SupportsShouldProcess = true)]
|
[Cmdlet(VerbsCommon.Set, "PveVmGuestPassword", SupportsShouldProcess = true)]
|
||||||
|
[OutputType(typeof(void))]
|
||||||
public sealed class SetPveVmGuestPasswordCmdlet : PveCmdletBase
|
public sealed class SetPveVmGuestPasswordCmdlet : PveCmdletBase
|
||||||
{
|
{
|
||||||
/// <summary>The Proxmox VE node name.</summary>
|
/// <summary>The Proxmox VE node name.</summary>
|
||||||
@@ -33,7 +36,7 @@ namespace PSProxmoxVE.Cmdlets.Vms
|
|||||||
/// <para type="description">The new password for the user.</para>
|
/// <para type="description">The new password for the user.</para>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Parameter(Mandatory = true, HelpMessage = "The new password.")]
|
[Parameter(Mandatory = true, HelpMessage = "The new password.")]
|
||||||
public string Password { get; set; } = string.Empty;
|
public SecureString Password { get; set; } = new SecureString();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// <para type="description">When specified, indicates the password is already in crypted/hashed format.</para>
|
/// <para type="description">When specified, indicates the password is already in crypted/hashed format.</para>
|
||||||
@@ -48,9 +51,20 @@ namespace PSProxmoxVE.Cmdlets.Vms
|
|||||||
|
|
||||||
var session = GetSession();
|
var session = GetSession();
|
||||||
|
|
||||||
|
var ptr = Marshal.SecureStringToGlobalAllocUnicode(Password);
|
||||||
|
string plainPassword;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
plainPassword = Marshal.PtrToStringUni(ptr) ?? string.Empty;
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
Marshal.ZeroFreeGlobalAllocUnicode(ptr);
|
||||||
|
}
|
||||||
|
|
||||||
WriteVerbose($"Setting password for user '{Username}' on VM {VmId} via guest agent...");
|
WriteVerbose($"Setting password for user '{Username}' on VM {VmId} via guest agent...");
|
||||||
var service = new VmService();
|
var service = new VmService();
|
||||||
service.SetGuestPassword(session, Node, VmId, Username, Password, Crypted.IsPresent);
|
service.SetGuestPassword(session, Node, VmId, Username, plainPassword, Crypted.IsPresent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user