Powershell Script for looping through multiple O365 tenants - powershell

Community,
I have a script I pieced together online, that allows me to add a domain/sender to the block list via the Spam filter in Exchange Online. Currently, the script is written for one tenant. I would like it to loop through about 5 tenants, each with different credentials.
I was told I need to create PSCredential Objects, but I'm unsure of how to go about this. Or where to place the code.
Script:
# First we need credentials to use to connect to O365
Write-Host "Enter your O365 Global Administrator credentials"
$UserCredential = Get-Credential
Then we need to define the PS session to connect to O365
$Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://outlook.office365.com/powershell-liveid -Credential $UserCredential -Authentication Basic -AllowRedirection
Now we Open the Session
Import-PSSession $Session -AllowClobber
Prompt for vars
$domainlist = Read-Host -Prompt 'Domain(s) to add to Block list (press ENTER if none, use single space between entries): '
$addresslist = Read-Host -Prompt 'Email address to add to Block list (press ENTER if none, use single space between entries): '
$domains = $domainlist -split " "
$addresses = $addresslist -split " "
Add Domains to list, if any
if (!$domainlist) {
Write-Host "No domains to add...skipping"
} else {
Write-Host "Adding domain name(s) to Default spam Block list...."
Set-HostedContentFilterPolicy -Identity Default -BlockedSenderDomains #{Add=$domains}
}
Add email addresses to list, if any
if (!$addresslist) {
Write-Host "No addresses to add...skipping"
} else {
Write-Host "Adding email address(es) to Default spam Block list...."
Set-HostedContentFilterPolicy -Identity Default -BlockedSenders #{Add=$addresses}
}
Close the Session or bad things happen!!!
Remove-PSSession $Session

When you have to provide credentials in non-interactive mode, you can create a PSCredential object in the following way.
$secpasswd = ConvertTo-SecureString "PlainTextPassword" -AsPlainText –Force
$mycreds = New-Object System.Management.Automation.PSCredential ("username", $secpasswd)
Use it as part of a loop, and you should be able to create PSSesions automatically.
But the rest of your script is still interactive, and it still needs your input.
You could refer to the following link:
PowerShell – How to create a PSCredential object

Related

Powershell - O365 Migration script

I am using the following Syntax, to Migrate user`s and create O365 mailboxes in our organization:
# Mailbox Migration Script
Add-PSSnapin Microsoft.Exchange.Management.PowerShell.E2010;
$UserCredential = Get-Credential
$Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://outlook.office365.com/powershell-liveid/ -Credential $UserCredential -Authentication Basic -AllowRedirection
Import-PSSession $Session
Enable-RemoteMailbox -Identity user.name -PrimarySmtpAddress user.name#company.com -RemoteRoutingAddress user.name#company365.mail.onmicrosoft.com
sleep 30
# After the initial script has done running, run the following:
Get-RemoteMailbox user.name|Set-RemoteMailbox -EmailAddressPolicyEnabled:$true
Everything works ok , but what i would like to do is to convert this, so the data is being read from a CSV file instead so that the actual wont have to be touched.
Im guessing this should be with the import-csv, unfortunately i don`t know what the rest of the syntax should be.
The exact data i need to acquire via csv is the following:
-Identity user.name
-PrimarySmtpAddress user.name#company.com
-RemoteRoutingAddress user.name#company365.mail.onmicrosoft.com
Each part of the data should be acquired from a column in the CSV.
Please assist with creating this script.
Thanks a bunch , in advance to all.
You're right -- Import-CSV is the ticket here.
$ExchangeData = Import-CSV -path C:\MyExchangeData.csv
# Access the data to IMPORT each user.
# Assumes the CSV has "Email, UserName, RemoteEmail" as headers.
foreach ($user in $ExchangeData) {
Enable-RemoteMailbox -Identity $user.UserName -PrimarySmtpAddress $user.Email -RemoteRoutingAddress $user.RemoteEmail
}

PowerShell Computer StartUp-Script - Switch user-context?

Through Microsoft Group Policy I did define to run a Powershell-Script on Computer Start-Up. Also I have the requirement to run a Powershell-Script as Scheduled Task without saving credentials.
On both scenarios I have the same problem ...
I want to run a Citrix Powershell-Command (PSSnapIn) like:
Set-BrokerMachine -MachineName "domain.local\$env:COMPUTERNAME" -AdminAddress "RemoteServer.domain.local" -InMaintenanceMode $True
Manual: https://citrix.github.io/delivery-controller-sdk/Broker/Set-BrokerMachine/
Of course only users who have the permission could run those Citrix-commands. I would be able to give a domain-user the permission to run the command "Set-BrokerMachine", but in the mentioned scenarios the PowerShell-scripts run in context of the system-user.
I did simulate the system-user by PSExec:
Error running as System-User
My scripts do other things of course and I want to keep them running as System-User, but now I am looking for a clean solution to get those Citrix-commands running.
If possible, I don't want to save credentials in my scripts.
EDIT #1:
I would be able to workaround with the following code:
$Username = "MySpecialUser"
$Password = 'MyPassword'
$SecurePassword = ConvertTo-SecureString $Password -AsPlainText -Force
$Credential = New-Object System.Management.Automation.PSCredential $Username, $SecurePassword
$Result = Invoke-Command -Session ( New-PSSession -ComputerName "RemoteServer.domain.local" -Credential $Credential ) -ScriptBlock {
Add-PSSnapin Citrix*
Set-BrokerMachine -MachineName "domain.local\$args" -InMaintenanceMode $True
} -ArgumentList $env:COMPUTERNAME -HideComputerName
Remove-PSSession -InstanceId $Result.RunspaceId
I don't like this because:
The code has to contain credentials (ofc I could encrypt it ...)
I have to create a permission-system for this special user in Citrix
I have to put the special-user into a local-group on every server, to allow the remote-administration (security-risk)
I don't like to use PSSession
...
Is there a better/cleaner solution? Any ideas?

Start-Job with credential in custom task problems

I am trying to develop a custom task using Powershell which needs to use Start-Job -Cred to switch to another user in places. Agent is running as user A and I need to switch to user B. Logging in to the server running the agent as user A and then running the script works fine - the Start-Job switches credentials and runs a scriptblock as user B.
Running exactly the same thing from VSTS in the cloud using the same (on-prem) agent server running the agent as user A fails with the uninformative error:
"The background process reported an error with the following message: ."
I have done more debugging and there is no other error message anywhere. It seems to be related to the -Cred parameter of Start-Job as it makes no difference what is in the script block run and if I remove the -Cred parameter, it's also fine.
User A is in the Adminstrators group on the server running the agent
Agent runs as user A
Any ideas?
Try it with Invoke-Command, for example (output current user name):
$mypwd = ConvertTo-SecureString -String "[password, could use variable]" -Force -AsPlainText
$Cred = New-Object System.Management.Automation.PSCredential('[user name]',$mypwd)
$scriptToExecute =
{
$VerbosePreference='Continue'
Write-Output "$env:UserName"
# Write-Verbose "Verbose" 4>&1
}
$b = Invoke-Command -ComputerName localhost -ScriptBlock $scriptToExecute -Credential $Cred
Write-Output "Content of variable B"
Write-Host $b
Based on your experiences, your credentials are not being passed properly. Try this method and insert it into your script:
Outside of your script, get the securestring object-
Read-Host -AsSecureString | ConvertFrom-SecureString
Take the output of this command (where you enter the password), and put it before your start-job-
$Secure = ConvertTo-SecureString -String 'above output'
$Cred = New-Object System.Management.Automation.PSCredential('Username',$Secure)
Start-Job -Credential $Cred
The SecureString can be reversed by someone with know-how, but if the script and/or account is secure, then that doesn't matter.

Powershell script that calls a variable inside of a file path?

Whenever creating an FTP folder for an FTP client in my company, I have to create two folders on two servers; server A and server B. I've tried to give an example below.
E:\FTP\CompanyName
E:\FTP\CompanyName\Incoming
E:\FTP\CompanyName\Outgoing
It would need to look like this on both servers. It isn't that hard to do manually, but I am wanting to learn Powershell, so why not automate a simple task? Here is what I currently have:
$Company = Read-Host 'Enter Company Name:'
$Credentials = Get-Credential
Write-Host 'Thank you! Creating client FTP folder on ServerA.' -ForegroundColor Magenta -BackgroundColor White
Invoke-Command ServerA {mkdir ("e:\ftp" + $Company + "\INCOMING")} -Credential $Credentials
Invoke-Command ServerA {mkdir ("e:\ftp" + $Company + "\OUTGOING")} -Credential $Credentials
Write-Host 'Done. Now creating duplicate folder on ServerB.' -ForegroundColor Magenta -BackgroundColor White
Invoke-Command ServerB {mkdir e:\ftp\$Company\INCOMING} -Credential $Credentials
Invoke-Command ServerB {mkdir e:\ftp\$Company\OUTGOING} -Credential $Credentials
Write-Host 'Done.' -ForegroundColor Magenta -BackgroundColor White
We have a set of admin credentials that we use specifically for server access. The script asks for those credentials and then also asks the "CompanyName" is. In theory, I would like it to then apply that variable to the "CompanyName" section of the file path.
I tried it two different ways in the script, just to test. They both completely skip the variable and just create an incoming and outgoing folder in E:\ftp. What am I missing here?
Any other advice on how to clean up my script is welcome as well. I've learned a lot doing this, but there is quite a bit more to learn.
The variable $company does not exist in the session on the other server so it can´t be used to create the folder like you want.
You can pass your variable by using the -Argumentlist parameter of Invoke-Command like this:
Invoke-Command ServerA {mkdir ("e:\ftp" + $args[0] + "\INCOMING")} -ArgumentList $Company -Credential $Credentials
I had this problem once, my solution was something like:
Invoke-Command ServerA {param($Company) "mkdir e:\ftp\$Company\INCOMING"} -ArgumentList $Company -Credential $Credentials
Invoke-Command ServerA {param($Company) "mkdir e:\ftp\$Company\OUTGOING"} -ArgumentList $Company -Credential $Credentials
The param block is used to pass local values to the command that is being invoked in remote session.
Is explained in more detail in: How to pass arguments for remote commands
The other solution using $args[0] is also explained there.

Powershell Special characters / Automating build - PSRemoting

I am using Teamcity and Powershell to automate few builds. Teamcity runs under lets say account A. There are few executable that needs to be run under account B. Account B has access to DB (windows auth integrated security access) and needs to go and create few tables on install. Passwords for account B is saved in the text file. I am having few issues with this.
1) Account B can have any special characters. I am reading XML file (as this file can be saved in a location where only Account A has access) and new up PSCredential to do the PSRemoting. I am using something like
$secpasswd = ConvertTo-SecureString $passwordFromXMLFile -AsPlainText -Force
$mycreds = New-Object System.Management.Automation.PSCredential ("username", $secpasswd)
$PasswordFromXMLFile can have any special characters. How should I deal with this?
2) When I try to run the executable in context of account B (after I somehow escaped and connected using this account), I am seeing the executable runs under anonymous account instead of domainname\B account. Is there some setting that I need to make sure it runs under account B.
My code looks something like - this is not the exact code I am just extracting some relevant portion.
$secpasswd = ConvertTo-SecureString $passwordFromXMLFile -AsPlainText -Force
$mycreds = New-Object System.Management.Automation.PSCredential ("B", $secpasswd)
$session = New-PSSession -ComputerName $serverName -Credential $mycreds
I see the session connects fine. to the computer
$scriptblock = {
Start-Process $exeName $arguments - wait
}
invoke-command -session $session -scriptblock $scriptblock
Thoughts? Start-Process runs but it executes on anonymous authority instead of account B.