155

I'd like to restart a remote computer that belongs to a domain. I have an administrator account but I don't know how to use it from powershell.

I know that there is a Restart-Computer cmdlet and that I can pass credential but if my domain is for instance mydomain, my username is myuser and my password is mypassword what's the right syntax to use it?

I need to schedule the reboot so I don't have to type the password.

Kev
  • 112,868
  • 50
  • 288
  • 373
all eyez on me
  • 1,553
  • 2
  • 10
  • 5
  • You should read this [link](http://technet.microsoft.com/en-us/library/dd315301.aspx) – jams Jun 04 '11 at 22:05
  • What does get-credential domain01\admin01 means? Next command is restart-computer -computername $s -force -throttlelimit 10 -credential $c. Does it mean that get-credential retrieve the password without asking it? – all eyez on me Jun 04 '11 at 22:23
  • http://technet.microsoft.com/en-us/library/dd315327.aspx – jams Jun 04 '11 at 22:34

9 Answers9

207

The problem with Get-Credential is that it will always prompt for a password. There is a way around this however but it involves storing the password as a secure string on the filesystem.

The following article explains how this works:

Using PSCredentials without a prompt

In summary, you create a file to store your password (as an encrypted string). The following line will prompt for a password then store it in c:\mysecurestring.txt as an encrypted string. You only need to do this once:

read-host -assecurestring | convertfrom-securestring | out-file C:\mysecurestring.txt

Wherever you see a -Credential argument on a PowerShell command then it means you can pass a PSCredential. So in your case:

$username = "domain01\admin01"
$password = Get-Content 'C:\mysecurestring.txt' | ConvertTo-SecureString
$cred = new-object -typename System.Management.Automation.PSCredential `
         -argumentlist $username, $password

$serverNameOrIp = "192.168.1.1"
Restart-Computer -ComputerName $serverNameOrIp `
                 -Authentication default `
                 -Credential $cred
                 <any other parameters relevant to you>

You may need a different -Authentication switch value because I don't know your environment.

JohnLBevan
  • 18,988
  • 5
  • 75
  • 151
Kev
  • 112,868
  • 50
  • 288
  • 373
  • 25
    You can also do `ConvertTo-SecureString "password" -AsPlainText -Force`. – x0n Nov 26 '13 at 03:33
  • 15
    Just to make it clear, `$password = ConvertTo-SecureString "password" -AsPlainText -Force` – Akira Yamamoto Nov 29 '13 at 13:36
  • **-Credential [username]** was required in Read-Host parameters for me, otherwise powershell just hangs. After passing -Credential to read-host you will be prompted directly in powershell console and password is stored correctly. Thank You! – sephirot Mar 01 '17 at 08:23
  • I am trying to figure out how to get this to work when I use the Send-MailMessage function in powershell. I am wanting to store the credentials of my email user and pass so I do not have to keep entering it in. Any idea how to do this? – KangarooRIOT May 24 '17 at 18:27
  • @user3681591 - I'd recommend asking a new question rather than doing this in the comments. Thanks. – Kev May 24 '17 at 19:24
  • A gotcha with -Authentication Basic: I found that -Authentication Default works fine with username = "computer-or-domain\username" but if you use -Authentication Basic and are using username "computername\username" you will get an Access Denied error. This can be resolved by only specifying the username in the PSCredential that is given to the cmdlet, in my case Invoke-Command/New-PSSession. – Johan Andersson Sep 22 '17 at 08:38
72

There is another way, but...

DO NOT DO THIS IF YOU DO NOT WANT YOUR PASSWORD IN THE SCRIPT FILE (It isn't a good idea to store passwords in scripts, but some of us just like to know how.)

Ok, that was the warning, here's the code:

$username = "John Doe"
$password = "ABCDEF"
$secstr = New-Object -TypeName System.Security.SecureString
$password.ToCharArray() | ForEach-Object {$secstr.AppendChar($_)}
$cred = new-object -typename System.Management.Automation.PSCredential -argumentlist $username, $secstr

$cred will have the credentials from John Doe with the password "ABCDEF".

Alternative means to get the password ready for use:

$password = convertto-securestring -String "notverysecretpassword" -AsPlainText -Force
Frank V
  • 23,732
  • 32
  • 98
  • 142
Jeroen Landheer
  • 7,600
  • 1
  • 32
  • 41
  • Thanks. This is very helpful. In my case I was creating a custom powershell cmdlet that takes a user name and password (as secureString). Internally the cmdlet calls several other cmdlets, some need just a user and password but one of them needs a credential so I don't actually need to hard-code the password in my script. – BenR Aug 31 '12 at 17:20
  • 20
    Somewhat simpler: $password = convertto-securestring -String "notverysecretpassword" -AsPlainText -Force – Sam Nov 05 '12 at 09:25
  • I am trying to figure out how to get this to work when I use the Send-MailMessage function in powershell. I am wanting to store the credentials of my email user and pass so I do not have to keep entering it in. Any idea how to do this? – KangarooRIOT May 24 '17 at 18:26
  • @user3681591 That would be Send-MailMessage -Credential $cred (with $cred created as shown in this post) – Jeroen Landheer May 25 '17 at 06:16
  • @JeroenLandheer I have tried your answer (thanks for helping!) however it did not work. My error is: -Credential : The term '-Credential' is not recognized as the name of a cmdlet, function, script file, or operable program. – KangarooRIOT May 25 '17 at 20:00
  • @BenR's example is very well spoken, I believe it's important to note that this example is only insecure/aka a bad idea if you STORE the unencrypted password in the file. If you are say... passing in the password as a parameter (in-memory) or accessing an encrypted password in a different way this is a perfectly good solution (and not-insecure at all). – David Rogers Feb 13 '20 at 15:53
30

Regarding storing credentials, I use two functions(that are normally in a module that is loaded from my profile):

#=====================================================================
# Get-MyCredential
#=====================================================================
function Get-MyCredential
{
param(
$CredPath,
[switch]$Help
)
$HelpText = @"

    Get-MyCredential
    Usage:
    Get-MyCredential -CredPath `$CredPath

    If a credential is stored in $CredPath, it will be used.
    If no credential is found, Export-Credential will start and offer to
    Store a credential at the location specified.

"@
    if($Help -or (!($CredPath))){write-host $Helptext; Break}
    if (!(Test-Path -Path $CredPath -PathType Leaf)) {
        Export-Credential (Get-Credential) $CredPath
    }
    $cred = Import-Clixml $CredPath
    $cred.Password = $cred.Password | ConvertTo-SecureString
    $Credential = New-Object System.Management.Automation.PsCredential($cred.UserName, $cred.Password)
    Return $Credential
}

And this one:

#=====================================================================
# Export-Credential
# Usage: Export-Credential $CredentialObject $FileToSaveTo
#=====================================================================
function Export-Credential($cred, $path) {
      $cred = $cred | Select-Object *
      $cred.password = $cred.Password | ConvertFrom-SecureString
      $cred | Export-Clixml $path
}

You use it like this:

$Credentials = Get-MyCredential (join-path ($PsScriptRoot) Syncred.xml)

If the credential file doesnt exist, you will be prompted the first time, at that point it will store the credentials in an encrypted string inside an XML file. The second time you run that line, the xmlfile is there and will be opened automatically.

Winfred
  • 948
  • 7
  • 19
10

I have to run SCOM 2012 functions from a remote server that requires a different credential. I avoid clear-text passwords by passing the output of a password decryption function as input to ConvertTo-SecureString. For clarity, this is not shown here.

I like to strongly type my declarations. The type declaration for $strPass works correctly.

[object] $objCred = $null
[string] $strUser = 'domain\userID'
[System.Security.SecureString] $strPass = '' 

$strPass = ConvertTo-SecureString -String "password" -AsPlainText -Force
$objCred = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList ($strUser, $strPass)
Bruce Gavin
  • 339
  • 3
  • 7
4

Here are two ways you could do this, if you are scheduling the reboot.

First you could create a task on one machine using credentials that have rights needed to connect and reboot another machine. This makes the scheduler responsible for securely storing the credentials. The reboot command (I'm a Powershell guy, but this is cleaner.) is:

SHUTDOWN /r /f /m \\ComputerName

The command line to create a scheduled task on the local machine, to remotely reboot another, would be:

SCHTASKS /Create /TN "Reboot Server" /TR "shutdown.exe /r /f /m \\ComputerName" /SC ONCE /ST 00:00 /SD "12/24/2012" /RU "domain\username" /RP "password"

I prefer the second way, where you use your current credentials to create a scheduled task that runs with the system account on a remote machine.

SCHTASKS /Create /TN "Reboot Server" /TR "shutdown.exe /r /f" /SC ONCE /ST 00:00 /SD "12/24/2012" /RU SYSTEM /S ComputerName

This also works through the GUI, just enter SYSTEM as the user name, leaving the password fields blank.

Nathan Hartley
  • 3,483
  • 1
  • 38
  • 45
2

I saw one example that uses Import/Export-CLIXML.

These are my favorite commands for the issue you're trying to resolve. And the simplest way to use them is.

$passwordPath = './password.txt'
if (-not (test-path $passwordPath)) {
    $cred = Get-Credential -Username domain\username -message 'Please login.'
    Export-CliXML -InputObject $cred -Path $passwordPath
}
$cred = Import-CliXML -path $passwordPath

So if the file doesn't locally exist it will prompt for the credentials and store them. This will take a [pscredential] object without issue and will hide the credentials as a secure string.

Finally just use the credential like you normally do.

Restart-Computer -ComputerName ... -Credentail $cred

Note on Securty:

Securely store credentials on disk

When reading the Solution, you might at first be wary of storing a password on disk. While it is natural (and prudent) to be cautious of littering your hard drive with sensitive information, the Export-CliXml cmdlet encrypts credential objects using the Windows standard Data Protection API. This ensures that only your user account can properly decrypt its contents. Similarly, the ConvertFrom-SecureString cmdlet also encrypts the password you provide.

Edit: Just reread the original question. The above will work so long as you've initialized the [pscredential] to the hard disk. That is if you drop that in your script and run the script once it will create that file and then running the script unattended will be simple.

1
read-host -assecurestring | convertfrom-securestring | out-file C:\securestring.txt
$pass = cat C:\securestring.txt | convertto-securestring
$mycred = new-object -typename System.Management.Automation.PSCredential -argumentlist "test",$pass
$mycred.GetNetworkCredential().Password

Be very careful with storing passwords this way... it's not as secure as ...

1

Solution

$userName = 'test-domain\test-login'
$password = 'test-password'

$pwdSecureString = ConvertTo-SecureString -Force -AsPlainText $password
$credential = New-Object -TypeName System.Management.Automation.PSCredential `
    -ArgumentList $userName, $pwdSecureString

For Build Machines
In the previous code replace user name and password values by secret ("hidden from logs") environment variables of your build-machine

Test results by

'# Results'
$credential.GetNetworkCredential().Domain
$credential.GetNetworkCredential().UserName
$credential.GetNetworkCredential().Password

and you'll see

# Results
test-domain
test-login
test-password
it3xl
  • 1,279
  • 14
  • 28
-3

why dont you try something very simple?

use psexec with command 'shutdown /r /f /t 0' and a PC list from CMD.

Root Loop
  • 2,477
  • 8
  • 36
  • 61