PowerShell scripts that acts on both local AD and Azure objects - powershell

I have a PowerShell scripts that opens sessions to both our on-prem Exchange server and online Exchange server to manage distribution lists specific to each environment. Problem is, when running
Add-DistributionGroupMember -Identity "TestAzureGroup#domain.com" -Member "TestUser"
Which is a distribution list defined in online Exchange, it throws an error saying it can't find the list on our local AD.
Is it possible to specify which session to work on within the command? Or another way?
Thanks

To answer my own question, if you add '-Prefix' to the Import-PSSession command, you remove name collision when you have multiple commands imported with the same name. For example,
Import-PSSession $LocalSession -AllowClobber -Prefix "Local"
Import-PSSession $AzureSession -AllowClobber -Prefix "Remote"
Creates two different Add-DistributionGroupMember commands, one called Add-LocalDistributionGroupMember and the other called Add-RemoteDistributionGroupMember so you can then work on both sessions at the same time using the two different command names.

Related

Double-Hop Errors when running Skype for Business Cmdlets

I am attempting to automate the Skype for Business Server installation process in Powershell, I have a script that remotes into specified machines and begins preparing them as Front-End servers. The problem lies when certain SfB cmdlets (SfB commands are all of the form "verb-Cs...", ex. Get-CsUser or Get-CsPool) are run in remote sessions, they throw the double-hop error:
Exception: Active Directory error "-2147016672" occurred while searching for domain controllers in domain...
This is after running Enable-CsComputer, which enables the computer's role-based off its definition in the topology (topology was published successfully). The user object is in all required groups (RTCUniversalServerAdmins, Schema Admins, CsAdministrators & Local Admin rights on all SfB Servers). Oddly enough, the command 'Import-CsConfiguration -localstore" does not throw errors, and it's in the same remote session. There may be other local or domain groups that I need to be in, but I cannot pinpoint exactly which and have not seen them documented in the Skype build guides. Skype commands that have parameters to specify targets or just pull data, such as Get-CsPool or Get-CsAdForest, do not have errors because they are run in the local scope. The Enable-CsComputer has no parameter for the computer name, it has to be executed from that machine itself.
Enabling CredSSP delegation on each server is not an option, and I'm not understanding why there is a "second hop" in this command! If the second hop was a resource on a file server or database, that would make sense, and be easy to solve, but in this case, I can't track it. Can anyone tell me what I may be missing?
Here's a code sample to try and illustrate. From the jumbox I get the pool data to create an array, and a session is opened to each machine:
$ServerArray =get-cspool -identity $poolName
$i=0
$SessionArray = #{}
foreach($server in $ServerArray.Computers){$SessionArray[$i] = new-PsSession -ComputerName $server}
foreach($session in $SessionArray.values){
invoke-Command -session $session -scriptBlock {
#remote commands:
import-csConfiguration -<config file path> -localstore; #no errors
enable-CsReplica; #no errors
enable-cscomputer; #double hop error here
}}
If I log into that machine and run the same command, it executes fine but the intention of the project is to automate it on an arbitrary number of machines.
It looks like it's just trying to authenticate to a domain controller, which is reasonable. You'll have to approach this like any other double-hop issue.
Microsoft has an article dedicated to the double hop issue, and has a few solutions other than CredSSP that you can look at: Making the second hop in PowerShell Remoting

i'am trying to remove a user from a local group throught AD (powershell)

i'm trying to develop a script that remove a domain user from local administrators group (i can use computer management from ad but its a graphical interface i need to do it with commands) for now i'm using invoke command to remotely connect to machines and remove their users from local admins group .
im using this command : Invoke-Command -ComputerName $line2.split(";")[0] -ScriptBlock { net localgroup "administrators" $using:notadmin /DELETE } -Credential $Cred
the problem here if a the machine is not online i need to wait until it will be online , i'm searching how to remove users from local group (administrators for example ) through ad
is there a command to do that ?
I see two approaches:
If you would like to use Group Policy, you may check for: Restricted groups.
https://www.petri.com/manage-local-active-directory-groups-using-group-policy-restricted-groups
Another option would be to incoroporate Test-Connection in your script, validating if computer is online. If it is - execute the script, if it is not, store it in another list with offline machines.
Then later run the script against the offline machine list ... and so on until all the computers are being covered.
P.S. And yes, as suggested in the commments, consider using remove-localgroupmember, if your powershell version support it.
Again, depends of the case.
Hope it helps!
$RemoteComputer = "yourComputer"
$Computer = [ADSI]("WinNT://$RemoteComputer,computer")
$Group = $Computer.PSBase.Children.Find("Administrators")
ForEach ($User in (Get-Content
"c:\users\administrator.domain\desktop\localadmin.txt"))
{ $Group.Remove("WinNT://$User")
}
i tired this code and it really helped me thnx for help

remote powershell script issue for adding IP address as relay - exchange 2010

firstly just to say my powershell skills are limited so please be gentle ;-)...
So I've built 4 or 5 runbooks using microsoft Orchestrator to essentially run some remote powershell scripts which do various simple exchange tasks, such as setting OutOfOffice reply, enabling mailboxes, creating shared mailboxes with various permissions etc. I had been using the same basic connection structure/method for these which works fine, ie
$ExchangeCAS = "<CASServerName>"
$Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri http://<CASServerNameFQDN>/PowerShell/
import-PSSession $Session
<script body with exchange cmdlets>
remove-PSSession $Session
However, I'm trying to create an additional runbook to automatically add IP addresses as relay to our 4 hub servers - its a pretty basic script (that I dug out/tweaked from internet) but its not working when run from Orchestrator. It does work fine when I run it from the Powershell ISE on the server that has the Exchange Tools installed, and the fact that the other exchange (similar) scripts that do work would at least rule out any permissions issues for the Orchestrator service account executing the script. For reference below is the full script I'm trying to run from Orchestrator as a .Net Activity and am testing using the powershell ISE on orchestrator server:-
$ExchangeCAS = "<ExCAS>"
$Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri http://<ExCASFQDN>/PowerShell/
import-PSSession $Session
# Get Receive Connectors to update
$listofIPs = Import-Csv \\<TargetSERVER>\d$\psscripts\MailboxRightsScript\scorch\AddIPlist.TXT
$recCons= Get-ReceiveConnector | Where {$_.Name -match"Anonymous Relay"}
ForEach ($recCon in $recCons)
{
Write-Host "Updating", $recCon.Identity
forEach($line in $listofIPs)
{
$recCon.RemoteIPRanges +=$line.IP
}
Set-ReceiveConnector $recCon -RemoteIPRanges $recCon.RemoteIPRanges
}
remove-PSSession $Session
The error I can see from the Orchestrator server ISE is as below:
Cannot process argument transformation on parameter 'Identity'. Cannot convert the "\Anonymous Relay" value of type "Deserialized.Microsoft.Exchange.Data.Directory.SystemConfiguration.ReceiveConnector" to
type "Microsoft.Exchange.Configuration.Tasks.ReceiveConnectorIdParameter".
From trawling through some articles it seems this is an issue with how data is passed between local and remote powershell and 'hydration' of objects. TBH a lot of the detail of those discussions is a bit over my head when it comes to powershell, so not wishing to be lazy would anyone be able to provide a powershell script solution based on what I was trying above which I can run as a .net activity from Orchestrator to add an IP address/addresses (prefer from input file) as relay. It would be good to know if the solution is easily modified to remove an address as relay aswell.
Any help much appreciated...
Use server distinguish name. It will work
Set-ReceiveConnector $recCon.DistinguishName -RemoteIPRanges $recCon.RemoteIPRanges

How to create a Powershell scipt to automatically connect to o365 and run as a schedlued task

I would like A PowerShell script to automatically connect to office 365 and to run as a scheduled task twice a day, THEN assign Reviewer permissions to new users if not possible then reviewer for all users. the reason being is because when a new user is created in outlook 365 their calendar permissions are set to free/busy.
i suggest you take a look at: OfficeDev/PnP - TimerJob
Shows how to create "remote timer job", which could be installed to be running as a WebJob to Windows Azure or scheduled to windows scheduler for on-premises deployment.
This is entirely possible, with the obvious downside that you'll need to store credentials for an account with permissions to edit all user calendars by default to run the script with.
There are two parts to the script that you'll require:
Connecting to Exchange Online
As shown here, connecting to Exchange Online is a very simple process.
Leaving the question of how to store credentials in a secure method out of scope of this question, this will result in a PowerShell session to the Exchange servers:
$UserCredential = Get-Credential
$Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://outlook.office365.com/powershell-liveid/ -Credential $UserCredential -Authentication Basic -AllowRedirection
Import-PSSession $Session
Selecting New Users
You'll then need to either select the new users (by passing them to this script, or scanning AD - this will depend on how you're creating your users - synced from AD or just created in-cloud), and apply the permission change to them. However...
Changing Default Permissions on Calendars
In this case, as I don't know how you're creating the new users, or how best to test that, I'm simply applying it to everyone. This will take far longer in a large environment, and is just a pretty bad idea.
Get-Mailbox -Filter {RecipientType -eq 'UserMailbox' -and IsShared -eq $false}| %{
Set-MailboxFolderPermissions -Identity "$($_.Alias):\Calendar" -User Default -AccessRights Reviewer
}
Finally, according to the original article, you should close the remote session.
Remove-PSSession $Session
Scheduled Tasks
After fixing the issue with credentials, you'll then want to save the script (ensuring that it complies with the Execution Policy on the system you'll be running it on), and create a new scheduled task to run it.
Configure a Scheduled Task as appropriate (in terms of triggers and conditions), and set the Action as Start a program, with that program being powershell.exe. Arguments should include -File C:\Path\to\Saved\Script.ps1 and any arguments (such as a file of new users).
Having said all of that, what you should actually do is change the sharing policy in 365, which will allow you to set the default permission for calendars.

New-MailboxExportRequest don't work in remote PSsession

i often use the New-MailboxExportRequest 's command on an exchange server in powershell console, like this one :
Add-PSSnapin Microsoft.Exchange.Management.PowerShell.E2010;
New-MailboxExportRequest -Mailbox jadrego –filepath \\computer1\c$\test.pst -verbose
it works correctly. But if I run those commands in PS remote session like this one :
I use the same User (Domain Admin, Exchange Admin)
Invoke-Command -ComputerName vdiv03 -ScriptBlock {
Add-PSSnapin Microsoft.Exchange.Management.PowerShell.E2010;
New-MailboxExportRequest -Mailbox jadrego –filepath \\computer1\c$\test.pst
}
I obtain this error :
failed to comunicate with mailbox database
with -verbose
Loading the snapin like that isn't supported in Exchange 2010.
IMHO, you'd be much better off just leveraging the native remoting built into Exchange for management tasks.
$ExchangeServer = <exchange serer name>
$SessionParams =
#{
ConfigurationName = 'Microsoft.Exchange'
ConnectionURI = "http://$ExchangeServer/powershell/"
Authentication = 'Kerberos'
# Credential = $Creds
}
$Session = New-PSSession #SessionParams
Invoke-command -ScriptBlock {New-MailboxExportRequest -Mailbox jadrego –filepath \\computer1\c$\test.pst} -Session $Session
Remove-PSSession $Session
Set $ExchangeServer to the name of one of your Exchange 2010 servers. The account will need to be a member of the necessary RBAC role for the function you're performing, and you can uncomment the Credential parameter and provide alternate credentials for the session if you need to.
This will also elimnatat the need to have the management tools installed on the computer that's running the script, and the associated headaches of keeping it patched to the same level as what's on the servers.
If you're working interactively, or running a script that uses many Exchange cmdlets you can add the session creation to your profile, and do an Import-PSSession and you'll have proxy functions for the Exchange cmdlets available locally that you can use the same as if you'd loaded the snapin.
Import-PSSsession $Session
Some caveates to be aware of:
When you use implicit remoting like this, the account of the credentiaals used to establish the session will determine what capablilities you will have. What appear to be Exchange cmdlets added to the local session are actually proxy functions ( you can verify this using Get-Command). This set of proxy functions is created dynamically by Exchange when you initially establish the session and will be customized according to the RBAC roles the account making the connection belongs to. If it doesn't have permissions to perform given functions you will not get the proxy functions for those cmdlets, or functions may not have parameters for those functions.
The results you get back will not be the same as the same as the native objects returned if you used an EMS shell, or loaded the snapin. They will be deserialized objects, which means they may be missing methods and will lose some fidelity compared to the native objects. There will be very few instances where this will be an issue, or cannot by worked around.
Also be aware that when you use implicit remoting, updates are made under the authority of an Exchange system account, not your credentials. When you use the snapin, your account must have permission to update the Exchange properties stored in AD directly, and those changes will be logged in Windows audit logs (if enabled) as having been made by that account. When you use implicit remoting they will be recorded as being done by the Exchange service account. Exchange will record the details of the actual user account that made the request in it's admin audit log, and you can use Search-AdminAuditLog to find out when changes were made, and by who even if Windows audit logging is not enabled. If you use the snapin directly and do not have AD audit logging enabled you will lose that audit trail.