This web portal is part of Executing a Linux programs from PHP web server. In earlier part I used only PHP to remotely execute commands on Linux server. In this it is a combination of PHP and PowerShell. Once you launch portal you will need to provide Domain username and password to authenticate and Linux server IP/Hostname to reboot Server.
To run command on Linux from windows it uses plink.exe tool utility to connect through SSH. I have provided the plink.exe in the zip file that you will need to copy it on PHP Web server under C:\Windows. To host PHP Web server I am using XAMPP application for windows. I have downloaded it and installed. run XAMPP controller and start Apache services as shown in Executing a Linux programs from PHP web server. Copy complete project under C:\xampp\htdocs. And load the URL in browser.
Whether user able to restart Linux server remotely, success or failure, it will register a log in the file under /log/reboot.log.
Download this complete project PHP_reboot_linux_PowerShell.zip here or it is also available on github.com.
How to Setup this project?
On the Windows server where you installed XAMPP / PHP webserver. Configure and add Domain Users to Remote Management Users in Local groups from Computer Management. (Members of this Remote Management Users group can access WMI resources over management protocols (such as WS-Management via the Windows Remote Management service). This applies only to WMI namespaces that grant access to the user.). For lab purpose I have added large group such as Domain Users. You can tweak it with your custom group. With custom group you can achieve time based access to users on the group to perform reboot action.
Below is the file code used in this project.
Index.html - This is landing page where you put credentials and Linux server information.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 |
<!doctype html> <html lang=en> <head> <meta charset=utf-8> <title>Linux Reboot Tool</title> <link rel="icon" type="image/x-icon" href="favicon.ico"> <style> body { font-family: Calibri, 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; text-align: center; font-weight: lighter; } div { margin: auto; width: 50%; border: 3px solid coral; padding: 10px; border-radius: 0.3cm; } table { margin: 0 auto; /* or margin: 0 auto 0 auto */ /* color: #606060; */ } .toolheader { font-size: x-large; font-weight: 600; } input[type=text] { width: 100%; padding: 12px 20px; margin: 8px 0; box-sizing: border-box; border: 1px solid gray; outline: none; color: #606060; } input[type=text]:focus { background-color: coral; color: white; border: 1px solid gray; } input[type=password] { width: 100%; padding: 12px 20px; margin: 8px 0; box-sizing: border-box; border: 1px solid gray; outline: none; color: #606060; } input[type=password]:focus { background-color: coral; color: white; border: 1px solid gray; } .button { background-color: coral; /* Green */ border: none; color: white; padding: 15px 32px; text-align: center; text-decoration: none; display: inline-block; font-size: 16px; margin: 4px 2px; cursor: pointer; -webkit-transition-duration: 0.4s; /* Safari */ transition-duration: 0.4s; } .button:hover { box-shadow: 0 12px 16px 0 rgba(0,0,0,0.24),0 17px 50px 0 rgba(0,0,0,0.19); } .loading { margin-left: auto; margin-right: auto; width: 128px; height: 128px; display: none; } /* .toolbox { display: none; } */ </style> <script> function ClearFields() { // document.getElementById("searchBox").value = ''; document.getElementById("user").value = ""; document.getElementById("pass").value = ""; document.getElementById("ip").value = ""; } </script> <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script> </head> <body> <div> <table class="toolheader toolbox" id="toolbox"> <tr> <td colspan="2"> <img src="loremipsumlogo.png" alt="loremipsumlogo" width="256px"> </td> </tr> <tr> <td style="text-align: center; vertical-align: middle;">Linux Server Reboot</td> <td><img src="reboot.png" alt="reboot.icon" width="48" height="48"></td> <td style="text-align: center; vertical-align: middle;">tool</td> </tr> </table> <table class="toolbox"> <tr> <th>UserName    </th> <td><input id="user" type="text" name="username" value="UserName" autocomplete="UserName"></td> </tr> <tr> <th>Password    </th> <td><input id="pass" type="password" name="password" value="Password"></td> </tr> <tr> <th>Server    </th> <td><input id="ip" type="text" name="servername" value="Type server hostname or IP"></td> </tr> <!-- <tr> <th></th> <td><button class="button searchButton" id="login">Log In</button></td> </tr> --> </table> <button class="button searchButton toolbox" id="rebootserverbutton">Reboot Server</button> <!-- //instead of Class if id is used use #searchButton --> <input class="button clearButton toolbox" type="reset" name="Clear" value="Clear" onclick="ClearFields();"><br> <br> <br> <img class="loading" id="loading" src="loading.gif" alt="Loading, Waiting, Spinner"> </div> <p class="showData"></p> <!--Show data from php here --> <script> $(document).ready(function(){ $("#rebootserverbutton").click(function(){ //instead of Class if id is used use #searchButton //document.getElementById("loading").style.display = 'block'; $("#loading").css("display", "block") $("p.showData").html('') //document.getElementClassNyName("showData").innerHTML = ""; $.ajax({ method: "POST", url: "wrap.php", data: { //text: $("p.unbroken").text(), //keep adding parameters here with comma // servername: $("input:text").val(), //keep adding parameters here with comma servername: $("input[name=servername]").val(), //keep adding parameters here with comma username: $("input[name=username]").val(), password: $("input[name=password]").val(), } }) .done(function( response ) { $("p.showData").html(response); //class showData reference //document.getElementById("loading").style.display = "none"; $("#loading").css("display", "none") }); }); }); </script> </body> </html> |
wrap.php - Information fed into landing page will be passed to this PHP code and it will execute PowerShell script to reboot Linux server.
1 2 3 4 5 6 7 8 9 10 11 12 |
<?php $username = isset($_POST['username']) ? $_POST['username'] : ''; $password = isset($_POST['password']) ? $_POST['password'] : ''; $servername = isset($_POST['servername']) ? $_POST['servername'] : ''; echo "<div id='phpBox' class='phpData' style='background-color: coral; color: white'>"; #$userName = shell_exec('powershell -ExecutionPolicy Unrestricted -Command $env:USERNAME'); echo "<h3 class='maintext' style='display: block;'>'<strong>$username</strong>' trying to submit reboot request for server '<strong>$servername</strong>'</h3>"; $psfileoutput = shell_exec("PowerShell -ExecutionPolicy Unrestricted -NonInteractive -File Reboot-LinuxServer.ps1 -Server $servername -UserName $username -Password $password" ); echo '<div>' . $psfileoutput . '</div>'; echo "</div>"; |
Reboot-LinuxServer.ps1 - In the background below PowerShell script will be executed. Change Linux user credentials on line 27 and 28. You can make addition to this ps1 such a way that only allowed users on allowed servers from database can run this Web tool.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
param( [string]$Server, [string]$UserName, [string]$Password ) $cimsession = $null try { $secureString = $Password | ConvertTo-SecureString -AsPlainText -Force | ConvertFrom-SecureString $credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $UserName, ($secureString | ConvertTo-SecureString) $cimsession = New-CimSession -ComputerName $env:COMPUTERNAME -Credential $credential -ErrorAction Stop } catch { $error.exception.message > c:\temp\command_output.txt "<h3> Reboot job submission failed $Server `n The user name or password is incorrect. `n </h3>" #$htmlReport | Out-File c:\temp\logs.txt -Append "$server,$UserName,WrongPassword,$(Get-Date -UFormat "%m/%d/%Y_%R")" | Out-File -FilePath C:\xampp\htdocs\reboot\log\reboot.log -Append } if ($null -ne $cimsession) { echo y | plink -ssh -no-antispoof -pw ubuntu ubuntu@$server 'sudo whoami' > 'C:\xampp\htdocs\reboot\log\first_command_output.txt' 2>&1 echo y | plink -ssh -no-antispoof -pw ubuntu ubuntu@$server 'sudo shutdown -r' > 'C:\xampp\htdocs\reboot\log\second_command_output.txt' 2>&1 $log = Get-Content C:\xampp\htdocs\reboot\log\second_command_output.txt $mainMessage = $log[0].trim('plink : ') -creplace ('Shutdown','Reboot') $htmlReport = "<h4>Server reboot job submitted for '$Server'</h4>" $htmlReport += "<h3>$mainMessage</h3>" if ($mainMessage -match 'scheduled') { "$server,$UserName,Scheduled,$(Get-Date -UFormat "%m/%d/%Y_%R")" | Out-File -FilePath C:\xampp\htdocs\reboot\log\reboot.log -Append } elseif ($mainMessage -match 'fatal') { "$server,$UserName,Error,$(Get-Date -UFormat "%m/%d/%Y_%R")" | Out-File -FilePath C:\xampp\htdocs\reboot\log\reboot.log -Append } else { "$server,$UserName,unknown,$(Get-Date -UFormat "%m/%d/%Y_%R")" | Out-File -FilePath C:\xampp\htdocs\reboot\log\reboot.log -Append } $htmlReport } |
Useful Articles
Executing PowerShell script from PHP HTML web server
Send system disk space utilization HTML report Email using PowerShell
Send Email using PowerShell with .net object System.Net.Mail.MailMessage
PowerShell XML OperationStopped: No coercion operator is defined between types 'System.Object&' and 'System.Object'
Powershell Create new file if not exist, if exist Rename file
PowerShell Create XML document with XmlWriter .net object
PowerShell save export data to XML file
Bulk change multiple file names with OneLiner PowerShell command
Resolved PowerShell Visual studio code stuck with 'Starting up PowerShell' in status bar
Building basic simple Web Server using PowerShell
Running Your First PowerShell Scripts With Jenkins and Git
Git clone or push Missing or invalid credentials fatal authentication failed
PowerShell How to find file and folders in Azure Storage Account Blobs and Containers