I'm looking to build a proof of concept / demo webpage that will:
- Run as a service (no authentication required initially)
- Prompt for credentials (i.e. to allow providing alternate credentials, ideally capture this as System.Management.Automation.PSCredential). No authentication is required here, I just need to capture the credentials.
- Pass credentials in to PowerShell (e.g. shell.Commands.AddArgument(pscred) )
- Use these credentials in PowerShell (pass in as, or convert to System.Management.Automation.PSCredential)
- To clarify: I do not want to authenticate credentials. I just want to collect them in a secure way. For all I care at the moment, it is gibberish, but gibberish that I presumably want to protect
I have an ASP.NET Web Application project with Visual C# (similar to the one here). I have the page up and running (i.e. it runs with the appropriate account, it runs PowerShell, etc.) - I want to prompt for and store credentials in a reasonably secure manner. I assume there is some standard way to do this. Or am I reading too much into this as this is a server side application?
Here are excerpts from my code thus far:
Default.aspx (these will be changed depending on the scenario):
<asp:TextBox ID="Input" runat="server" TextMode="MultiLine" Width="400px" Height="73px" ></asp:TextBox> <asp:TextBox ID="InputParam" runat="server" TextMode="MultiLine" Width="200px" Height="20px" ></asp:TextBox> <asp:Button ID="ExecuteCode" runat="server" Text="Execute" Width="200" onclick="ExecuteCode_Click" /> <asp:TextBox ID="ResultBox" TextMode="MultiLine" Width="700" Height="200" runat="server"></asp:TextBox> <asp:TextBox ID="ErrorBox" TextMode="MultiLine" Width="700" Height="200" runat="server"></asp:TextBox>
Default.aspx.cs:
protected void ExecuteCode_Click(object sender, EventArgs e) { // Clean the Result TextBox ResultBox.Text = string.Empty; // Initialize PowerShell engine var shell = PowerShell.Create(); // Add the script and an argument to the PowerShell object shell.Commands.AddScript(Input.Text); shell.Commands.AddArgument(InputParam.Text); // Execute the script var results = shell.Invoke(); // display results, with BaseObject converted to string // Note : use | out-string for console-like output if (results.Count > 0) { // We use a string builder ton create our result text var builder = new StringBuilder(); foreach (var psObject in results) { // Convert the Base Object to a string and append it to the string builder. // Add \r\n for line breaks builder.Append(psObject.BaseObject.ToString() + "\r\n"); } // Encode the string in HTML (prevent security issue with 'dangerous' caracters like < > ResultBox.Text = Server.HtmlEncode(builder.ToString()); } //Collect errors var PSErrors = shell.Streams.Error.ReadAll(); if (PSErrors != null) { // We use a string builder ton create our error text var builder = new StringBuilder(); foreach (var psError in PSErrors) { // Convert the exception Object to a string and append it to the string builder. // Add \r\n for line breaks builder.Append(psError.Exception.ToString() + "\r\n"); } // Encode the string in HTML (prevent security issue with 'dangerous' caracters like < > ErrorBox.Text = Server.HtmlEncode(builder.ToString()); } }
This code won't work from what I understand, but the concept is exactly what I am looking to do.
PSCredential pscred = this.Host.UI.PromptForCredential("Enter username/password","", "", ""); shell.Commands.AddArgument(pscred);
I think the easiest way is to use impersonation. i.e. you get the credentials of the user, and launch the powershell process as that user which allows you to execute anything you want as that user.
See:
Execute PowerShell cmdlets from ASP.NET With User Impersonation - Has steps to impersonate the current user to run PowerShell
or
How to run PowerShell scripts from ASP.NET with Impersonation - StackOverflow question on how to run PowerShell with impersonation.