Usar credenciales de PowerShell sin que se le solicite una contraseña

148

Me gustaría reiniciar una computadora remota que pertenece a un dominio. Tengo una cuenta de administrador pero no sé cómo usarla desde powershell.

Sé que hay un Restart-Computercmdlet y que puedo pasar la credencial, pero si mi dominio es, por ejemplo mydomain, mi nombre de usuario myusery mi contraseña es mypasswordla sintaxis correcta para usarlo.

Necesito programar el reinicio para no tener que escribir la contraseña.

todos los ojos en mí
fuente
Deberías leer este enlace
atasca el
¿Qué significa get-credential domain01 \ admin01? El siguiente comando es restart-computer -computername $ s -force -throttlelimit 10 -credential $ c. ¿Significa que get-credential recupera la contraseña sin pedirla?
Todos los ojos sobre mí

Respuestas:

203

El problema Get-Credentiales que siempre solicitará una contraseña. Sin embargo, hay una forma de evitar esto, pero implica almacenar la contraseña como una cadena segura en el sistema de archivos.

El siguiente artículo explica cómo funciona esto:

Usando PSCredentials sin un aviso

En resumen, crea un archivo para almacenar su contraseña (como una cadena encriptada). La siguiente línea solicitará una contraseña y luego la almacenará c:\mysecurestring.txtcomo una cadena encriptada. Sólo necesitas hacer esto una vez:

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

Siempre que vea un -Credentialargumento en un comando de PowerShell, significa que puede pasar un PSCredential. Entonces en tu caso:

$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>

Es posible que necesite un -Authenticationvalor de cambio diferente porque no conozco su entorno.

Kev
fuente
24
También puedes hacer ConvertTo-SecureString "password" -AsPlainText -Force.
x0n
15
Solo para dejarlo claro,$password = ConvertTo-SecureString "password" -AsPlainText -Force
Akira Yamamoto
-Credential [nombre de usuario] fue requerido en los parámetros de Read-Host para mí, de lo contrario, PowerShell simplemente se bloquea. Después de pasar -Credential a read-host, se le solicitará directamente en la consola de PowerShell y la contraseña se almacenará correctamente. ¡Gracias!
sephirot
Estoy tratando de descubrir cómo hacer que esto funcione cuando uso la función Send-MailMessage en powershell. Quiero almacenar las credenciales de mi usuario de correo electrónico y aprobarlas para no tener que seguir ingresándolo. ¿Alguna idea de cómo hacerlo?
KangarooRIOT
@ user3681591 - Recomiendo hacer una nueva pregunta en lugar de hacerlo en los comentarios. Gracias.
Kev
71

Hay otra forma, pero ...

NO HAGA ESTO SI NO DESEA SU CONTRASEÑA EN EL ARCHIVO DE ESCRITURAS (No es una buena idea almacenar contraseñas en scripts, pero a algunos de nosotros nos gusta saber cómo hacerlo).

Ok, esa fue la advertencia, aquí está el código:

$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 tendrá las credenciales de John Doe con la contraseña "ABCDEF".

Medios alternativos para obtener la contraseña lista para usar:

$password = convertto-securestring -String "notverysecretpassword" -AsPlainText -Force
Jeroen Landheer
fuente
Gracias. Esto es muy útil. En mi caso, estaba creando un cmdlet de PowerShell personalizado que toma un nombre de usuario y contraseña (como secureString). Internamente, el cmdlet llama a varios otros cmdlets, algunos solo necesitan un usuario y una contraseña, pero uno de ellos necesita una credencial, por lo que no necesito codificar la contraseña en mi script.
BenR
20
Algo más simple: $ contraseña = convertto-securestring -String "notverysecretpassword" -AsPlainText -Force
Sam
Estoy tratando de descubrir cómo hacer que esto funcione cuando uso la función Send-MailMessage en powershell. Quiero almacenar las credenciales de mi usuario de correo electrónico y aprobarlas para no tener que seguir ingresándolo. ¿Alguna idea de cómo hacerlo?
KangarooRIOT
@ user3681591 Eso sería Send-MailMessage -Credential $ cred (con $ cred creado como se muestra en esta publicación)
Jeroen Landheer
@JeroenLandheer He intentado tu respuesta (¡gracias por ayudar!) Sin embargo, no funcionó. Mi error es: -Credential: el término '-Credential' no se reconoce como el nombre de un cmdlet, función, archivo de script o programa operable.
KangarooRIOT
29

Con respecto al almacenamiento de credenciales, utilizo dos funciones (que normalmente están en un módulo que se carga desde mi perfil):

#=====================================================================
# 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
}

Y éste:

#=====================================================================
# 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
}

Lo usas así:

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

Si el archivo de credenciales no existe, se le solicitará la primera vez, en ese momento almacenará las credenciales en una cadena encriptada dentro de un archivo XML. La segunda vez que ejecuta esa línea, el archivo xmlfile está allí y se abrirá automáticamente.

Winfred
fuente
10

Tengo que ejecutar las funciones de SCOM 2012 desde un servidor remoto que requiere una credencial diferente. Evito las contraseñas de texto claro al pasar la salida de una función de descifrado de contraseña como entrada a ConvertTo-SecureString. Para mayor claridad, esto no se muestra aquí.

Me gusta escribir fuertemente mis declaraciones. La declaración de tipo para $ strPass funciona correctamente.

[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
fuente
4

Aquí hay dos formas de hacerlo, si está programando el reinicio.

Primero, puede crear una tarea en una máquina utilizando credenciales que tengan los derechos necesarios para conectarse y reiniciar otra máquina. Esto hace que el planificador sea responsable de almacenar de forma segura las credenciales. El comando de reinicio (soy un chico de Powershell, pero esto es más limpio) es:

SHUTDOWN /r /f /m \\ComputerName

La línea de comando para crear una tarea programada en la máquina local, para reiniciar remotamente otra, sería:

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"

Prefiero la segunda forma, donde usa sus credenciales actuales para crear una tarea programada que se ejecuta con la cuenta del sistema en una máquina remota.

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

Esto también funciona a través de la GUI, solo ingrese SYSTEM como nombre de usuario, dejando en blanco los campos de contraseña.

Nathan Hartley
fuente
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

Tenga mucho cuidado al almacenar contraseñas de esta manera ... no es tan seguro como ...

MockMyBeret
fuente
1

Vi un ejemplo que usa Import / Export-CLIXML.

Estos son mis comandos favoritos para el problema que intenta resolver. Y la forma más sencilla de usarlos es.

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

Entonces, si el archivo no existe localmente, solicitará las credenciales y las almacenará. Esto tomará un [pscredential]objeto sin problemas y ocultará las credenciales como una cadena segura.

Finalmente, solo use la credencial como lo hace normalmente.

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

Nota sobre seguridad :

Almacenar credenciales de forma segura en el disco

Al leer la Solución, al principio es posible que tenga cuidado al almacenar una contraseña en el disco. Si bien es natural (y prudente) tener cuidado de ensuciar su disco duro con información confidencial, el cmdlet Export-CliXml cifra los objetos de credenciales utilizando la API de protección de datos estándar de Windows. Esto garantiza que solo su cuenta de usuario pueda descifrar adecuadamente su contenido. Del mismo modo, el cmdlet ConvertFrom-SecureString también cifra la contraseña que proporciona.

Editar: solo vuelva a leer la pregunta original. Lo anterior funcionará siempre que haya inicializado [pscredential]en el disco duro. Es decir, si coloca eso en su secuencia de comandos y ejecuta la secuencia de comandos una vez que creará ese archivo y luego ejecutar la secuencia de comandos desatendida será simple.

ScriptingDad
fuente
1

Solución

$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

Para máquinas de compilación
En el código anterior, reemplace los valores de nombre de usuario y contraseña por variables de entorno secretas ("ocultas de los registros") de su máquina de compilación

Resultados de la prueba por

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

y verás

# Results
test-domain
test-login
test-password
it3xl
fuente
-3

¿Por qué no pruebas algo muy simple?

use psexec con el comando 'shutdown / r / f / t 0' y una lista de PC de CMD.

Root Loop
fuente
Ese es un caso específico. El punto no es generar una ventana de inicio de sesión en ningún escenario aleatorio.
Overmind