PS Script Fails When Encrypted Password Used.

Hi all,

I have a Powershell script that downloads calendar content into a CSV file from an O365 account hosted on MS servers. It runs perfectly when I run the PS script manually and type in the passwords myself. When I encrypt those passwords to run the script via Task Manager, the script fails with the below errors.

This code comes with the original script (CalendarDumpToCSV.ps1 by Glen Scales) and works when I manually type in passwords.

$psCred = Get-Credential  
$creds = New-Object System.Net.NetworkCredential($psCred.UserName.ToString(),$psCred.GetNetworkCredential().password.ToString())  
$service.Credentials = $creds

Problem is, I need this to run this script automatically through a server for regular updates.
To set and store the encrypted pass, I use the following code.

$credential = Get-Credential
$credential.Password | ConvertFrom-SecureString | Set-Content c:\CSV\EncPass.txt

To use the encrypted pass (on the same machine), I use this in the script.

$emailusername = ""
$encrypted = Get-Content c:\CSV\EncPass.txt | ConvertTo-SecureString
$credential = New-Object System.Management.Automation.PsCredential($emailusername, $encrypted)

I have tried three different methods to store the password, including plain text, and consistently get the same error.

Errors below. Any suggestions appreciated.



====== ERRORS Encountered ======

PS F:\X\Powershell] ./CalendarDumpToCSV.ps1
Exception calling "Bind" with "2" argument(s): <strong>"The request failed. The remote server returned an error: (401) Unauthorized."</strong>
At F:\X\Powershell\CalendarDumpToCSV.ps1:93 char:63
+ $Calendar = [Microsoft.Exchange.WebServices.Data.Folder]::Bind [[[[ ($service,$folderid)
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : DotNetMethodException

Exception calling "FindAppointments" with "2" argument(s): "The element at position 0 is invalid
Parameter name: parentFolderIds"
At F:\X\Powershell\CalendarDumpToCSV.ps1:110 char:37
+ $fiItems = $service.FindAppointments [[[[ ($Calendar.Id,$CalendarView)
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : DotNetMethodException

So how do you run this script, which account is running the script and which account created the password-file?

When you are using ConvertTo/From-SecureString you’re using DPAPI by default.
With DPAPI you need to use the same account on the same machine.
So e.g. if you’re creating the password file using ConvertFrom-SecureString while logged in as Bob Smith on ComputerA.
Only Bob Smith on ComputerA can do a ConvertTo-SecureString.

If you need to make it more portable you can use the key parameter but then you need to store the key somewhere which you need to retreive and so forth.

Hi Fredrik,

As I specified, the password was encrypted on the same machine the script ran on. I’ve done this on a Win7 Workstation and a W2008 R2 server (encrypting the password on both machines) and both give the same (401) error when I run this. I have also used plain text passwords in the script as a test with the same results.

The PS script is run using the O365 admin account credentials.

FYI I have also tried:

New-Object -TypeName Microsoft.Exchange.WebServices.Data.WebCredentials(“SamAcctName”, “Password”, “NetBIOSDomain”)

With the same error message.

So just to be sure.

You don’t get the error if you are logged in as the o365 admin account while doing all steps manually.
But you are getting the problem while logged in as the o365 admin account if you turn it into a script.
Everything is done equally the only difference is that when it’s a script it fails?
No other user account is used in any of the steps no matter if it’s done manually or scripted?