Securely manage Office 365 using shared passwords

Without any doubt, PowerShell is the the recommended way to manage Office 365 tenant or services.

To be able to connect to Office 365 to manage the services, one has to login using admin credentials (username and password). In a company, one person or a small group of people manages Office 365. All of them may have their own account with admin privileges or permissions. What if any one of them doesn’t have a strong password? What if the password leaks as they share the same account credentials, maybe for license reasons or to keep the count of accounts with administrator privileges to minimum?

How do you minimize the risk and at the same time keep a check on the number of admin accounts being used to manage the tenant or services?

Well, the answer is —

Windows PowerShell (version 5) provides the support for protecting messages using cryptography, i.e. certificates. One can make use of certificates to encrypt and decrypt a string. This feature is useful to securely store and retrieve admin credentials used to connect to Office 365.

How to do this?

Generate a certificate
A certificate will be used to encrypt and decrypt the password. An original certificate has both, private and public key. A public key is used to encrypt the password and private key is used to decrypt the password.

Tip: A certificate with only public key can also be exported, also known as public certificate. This is helpful when you wish to extend the use of encryption/decryption beyond just passwords. The public certificate can be used to encrypt the messages but only a certificate with private key (i.e. original certificate) will be able to decrypt it.

To generate a certificate, let us create an INF file which defines the certificate which we wish to generate. Save the following text to certificate.inf

[Version]
Signature = “$Windows NT$”
[Strings]
szOID_ENHANCED_KEY_USAGE = “2.5.29.37”
szOID_DOCUMENT_ENCRYPTION = “1.3.6.1.4.1.311.80.1”
[NewRequest]
Subject = “cn=PowerShell Security”
MachineKeySet = false
KeyLength = 2048
KeySpec = AT_KEYEXCHANGE
HashAlgorithm = Sha1
Exportable = true
RequestType = Cert
KeyUsage = “CERT_KEY_ENCIPHERMENT_KEY_USAGE | CERT_DATA_ENCIPHERMENT_KEY_USAGE”
ValidityPeriod = “Years”
ValidityPeriodUnits = “3”
[Extensions]
%szOID_ENHANCED_KEY_USAGE% = “{text}%szOID_DOCUMENT_ENCRYPTION%”
Note: You may want to change the “Subject” and “ValidityPeriodUnits” before using the above block.

Launch PowerShell and run the following command to request the certificate. This command will create a new public certificate and also install the certificate with both, public and private key, in the Certificate Store.

PS C:\> certreq -new certificate.inf certificate.cer

Encrypt the password using certificate
Launch PowerShell and load the certificate using Get-ChildItem command.

PS C:\Apps\Certs> $cert = Get-ChildItem Cert:\CurrentUser\My | Where-Object {$_.Subject -like "CN=PowerShell Security*"}

Then, encrypt the password using the certificate.

PS C:\Apps\certs> $password = ‘<replace-with-your-password>
PS C:\Apps\certs> Protect-CmsMessage -To $cert -Content $password

The output of this command will be the encrypted password. Copy the entire block of password inlcuding ‘ — — Begin CMS — -’ and ‘ — -End CMS — -’

You don’t have to do this always. Once encrypted, the encrypted password can now be included in your PowerShell script to connect to Office 365.

Decrypt the password and connect to Office 365

Now, lets see how to decrypt the password using the private key of the original certificate.

PS C:\Apps\certs> $EncryptedPassword = @'
-----BEGIN CMS-----
MIIBqAYJKoZIhvcNAQcDoIIBmTCCAZUCAQAxggFQMIIBTAIBADA0MCAxHjAcBgNVBAMMFVBvd2Vy.... trimmed for brevity...
-----END CMS-----
'@
PS C:\Apps\certs> $DecryptedPassword = $EncryptedPassword | Unprotect-CmsMessage -To $Cert | ConvertTo-SecureString -AsPlainText -Force

The decrypted password can now be used to connect to Office 365 and the services.

PS C:\Apps\certs> $Username = 'admin@contoso.onmicrosoft.com'
$Credentials = New-Object System.Management.Automation.PSCredential ($Username,$DecryptedPassword)
Connect-MSOLService -Credential $Credentials

Points to remember:

  1. Make sure whenever you move the original certificate across the machines, the option to allow export of private key is unchecked. This will help to make sure the private key is not exportable, thus reducing the risk of the leak of the private key.
  2. Install the certificate to Current User’s Personal store so that it cannot be accessed by other users on the installed machine.
  3. You can create a ‘connect-to-o365’ script which includes the commands from ‘Decrypt the password and connect to Office 365’ section. You can store this in a central location and import in your other scripts. This will help to maintain and update the encrypted password whenever the original password changes.
  4. The user who has the certificate with private key installed on the machine will be able to see the decrypted password by printing out the $DecryptedPassword. This method does not restrict the ability to view the password, so do not use this method if the end goal is to restrict access to the plain password to the authorized administrators.