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);