using System; using System.Collections.Generic; using System.IO; using System.Net; using System.Security; using System.Text; using System.Management.Automation; using Newtonsoft.Json; using PSProxmox.Models; namespace PSProxmox.Session { /// /// Handles authentication and session management for Proxmox VE. /// public class ProxmoxSession { /// /// Authenticates with the Proxmox VE API. /// /// The server hostname or IP address. /// The port number. /// Whether to use HTTPS. /// Whether to skip SSL certificate validation. /// The username for authentication. /// The password for authentication. /// The realm for authentication. /// The PowerShell cmdlet making the request. /// A connection object with authentication information. public static ProxmoxConnection Login( string server, int port, bool useSSL, bool skipCertificateValidation, string username, SecureString password, string realm, PSCmdlet cmdlet) { var connection = new ProxmoxConnection(server, port, useSSL, skipCertificateValidation, username, realm); // Create the login URL string loginUrl = $"{connection.ApiUrl}/access/ticket"; // Log the URL if verbose is enabled if (cmdlet != null) { cmdlet.WriteVerbose($"Authenticating to {loginUrl}"); } // Create the request var request = (HttpWebRequest)WebRequest.Create(loginUrl); request.Method = "POST"; request.ContentType = "application/x-www-form-urlencoded"; // Skip certificate validation if requested if (skipCertificateValidation && request.RequestUri.Scheme == "https") { request.ServerCertificateValidationCallback = (sender, certificate, chain, sslPolicyErrors) => true; } // Convert SecureString to plain text (only for sending to API) string plainPassword = new System.Net.NetworkCredential(string.Empty, password).Password; // Create the request body string postData = $"username={Uri.EscapeDataString(username)}&password={Uri.EscapeDataString(plainPassword)}&realm={Uri.EscapeDataString(realm)}"; byte[] byteArray = Encoding.UTF8.GetBytes(postData); request.ContentLength = byteArray.Length; // Send the request using (Stream dataStream = request.GetRequestStream()) { dataStream.Write(byteArray, 0, byteArray.Length); } // Get the response try { using (var response = (HttpWebResponse)request.GetResponse()) using (var reader = new StreamReader(response.GetResponseStream())) { string responseText = reader.ReadToEnd(); var loginResponse = JsonConvert.DeserializeObject>(responseText); if (loginResponse?.Data == null) { throw new Exception("Invalid response from server"); } return connection.WithAuthentication( loginResponse.Data.Ticket, loginResponse.Data.CSRFPreventionToken); } } catch (WebException ex) { if (ex.Response != null) { using (var errorResponse = (HttpWebResponse)ex.Response) using (var reader = new StreamReader(errorResponse.GetResponseStream())) { string errorText = reader.ReadToEnd(); throw new Exception($"Authentication failed: {errorText}"); } } throw; } } /// /// Logs out from the Proxmox VE API. /// /// The connection to log out from. /// The PowerShell cmdlet making the request. public static void Logout(ProxmoxConnection connection, PSCmdlet cmdlet) { if (connection == null || !connection.IsAuthenticated) { return; } // Create the logout URL string logoutUrl = $"{connection.ApiUrl}/access/ticket"; // Log the URL if verbose is enabled if (cmdlet != null) { cmdlet.WriteVerbose($"Logging out from {logoutUrl}"); } // Create the request var request = (HttpWebRequest)WebRequest.Create(logoutUrl); request.Method = "DELETE"; request.Headers.Add("Cookie", $"PVEAuthCookie={connection.Ticket}"); request.Headers.Add("CSRFPreventionToken", connection.CSRFPreventionToken); // Skip certificate validation if requested if (connection.SkipCertificateValidation && request.RequestUri.Scheme == "https") { request.ServerCertificateValidationCallback = (sender, certificate, chain, sslPolicyErrors) => true; } // Send the request and ignore the response try { using (var response = (HttpWebResponse)request.GetResponse()) { // Just to ensure the request is completed } } catch (WebException) { // Ignore errors during logout } } } }