Check who is Cached mode client - Exchange 2019 on premiss, Office365 Clients - powershell

In the last few days i was looking for a way to make report or gather information about all outlook users, which of them are using Chache mode, and who are connected online.
As mentioned in Title, we are working with Exchange 2019 on premiss, and all of our clients using Office365.
Here and there, i found few ways to find out about it, but all of thos ways are related to older server/client versions. like:
Some scripts looking for some registry values. in specific - "00036601" key, but not only. because some offers other keys which supposed to be there for Office365 clients, but are not there in my case.
Use Exchange Shell involving Get-LogonStatistics, but this cmdlet is not working in Exchange 2019.
Proccess RPC Client Access Logs, but RPC connections are blocked in our network, and Outlook clients access the servers via HTTPS. tried to look into HTTP MAPI logs, but coudn't find there somthing that tells me weather the client is Cached mode or not.
The only way i've found that works, is to use client-side script, base on user identity, to load MAPI to Powershell and find out it's status:
$outlook = New-Object -com Outlook.Application
$namespace = $outlook.GetNamespace("MAPI")
$mailbox = $namespace.Stores | ? {$_.displayname.split("#")[0] -like $env:USERNAME}
$result = $env:USERNAME + ": " + $env:COMPUTERNAME + ": " + $mailbox.IsCachedExchange
$result | Add-Content -Path "\\server\Network-Shared-Folder\chache.txt"
if (!(Test-Path C:\users\$env:username\documents\cache)) {
New-Item -ItemType Directory -Name cache -Path C:\users\$env:username\documents\
}
"Done" | Add-Content -Path C:\users\$env:username\documents\cache\testresult.txt
I can distribute this script with SCCM and some of the line i wrote for detection method. so i can run it also with Invoke-Command or other ways.
But in the bottom line, i'm not eager to use this way, since it's involve the client side and identity, and can interfere with his own work on outlook.
I'm looking for different way, server-side preferably, to gather this information.
Ofcource, something that is works with Exchange 2019 On-Premiss, and Office365 Clients which connecting via HTTPS.
Thanks for help.
Yosi.

I don't think you can do that from the server - caching is client-only feature, plus a single Outlook profile can access the primary mailbox in the cached mode, but a delegate mailbox in on online mode.
More than that, for some feature cached Outlook might open server objects in the online mode, e.g. when searching, and the user wants older items not cached locally.

Related

Running powershell without useriteraction

start "odopen://sync/?siteId=$siteid17&webId=$webid17&listId=$listid17&userEmail=$upn&webUrl=$URL17&webtitle=$webtitle17&listtitle=$listtitle17"
How is it possible to run the following command inside Powershell without an appearing popup window or any userinteraction? I've tried adding /ArgumentList "/S", "/Background". Also tried with -WindowStyle Hidden at the end. Appreciate some help :)
Your command as-is basically says "Start the program that opens odopen:// (OneDrive) links" and can't really be given any silent style instructions. The proper way to configure this kind of thing is through OneDrive Group Policies, but we can cheat and set registry keys.
The link above goes into detail about how to configure group policy, but also tells us that the specific group policy setting to "Configure team site libraries to sync automatically" sets this registry key:
[HKCU\Software\Policies\Microsoft\OneDrive\TenantAutoMount]"LibraryName"="LibraryID"
And that your LibraryID is in this format, which looks familiar:
tenantId=xxx&siteId=xxx&webId=xxx&listId=xxx&webUrl=httpsxxx&version=1
So to put it in a script, I would use something like this, adapted from Nicola Suter's blog post here:
$tenantAutoMountRegKey = "HKLM:\SOFTWARE\Policies\Microsoft\OneDrive\TenantAutoMount"
$autoMountTeamSitesList= #{
#Enter your SharePoint libraries to configure here as key/value pairs
MySharePoint="odopen://sync/?siteId=$siteid17&webId=$webid17&listId=$listid17&userEmail=$upn&webUrl=$URL17&webtitle=$webtitle17&listtitle=$listtitle17"
}
# Check if the key exists and create if missing:
if (-not (Test-Path $tenantAutoMountRegKey)){ New-Item -Path $tenantAutoMountRegKey -Force }
# Add the sites for automatic mounting
$autoMountTeamSitesList | Set-ItemProperty -Path $tenantAutoMountRegKey -Name $_.Key -Value $_.Value
This generally takes effect the next time a user signs into OneDrive, though Microsoft warns it may take up to 8 hours to start syncing (Keeps hundreds of users from syncing the same library at the same time)
TL;DR: You cannot.
Using odopen will always show sign-in window (as stated here: https://learn.microsoft.com/en-us/onedrive/deploy-on-windows#help-users-sign-in), what you can do is only populate it with data, which is what you are already doing.
If you want to do it silently, there is documentation about it: https://learn.microsoft.com/en-us/onedrive/use-silent-account-configuration

Using Application ID to automate Seamless SSO kerberos decryption key rollover

I would like to automate the rollover of kerberos description keys used for seamless SSO. In doing this, I cannot use global administrator USER accounts, as they may receive spray attacks (I cannot use domain IDs as there are so many domains, and thus I will have to make so many Global Admins). I am thinking that by using application ID and certificates, I can securely automate this job.
The problem is, every sample code I could find has uses the "AuthenticationContext". Something like this:
New-AzureADSSOAuthenticationContext -CloudCredentials $CloudCredentials
Update-AzureADSSOForest -OnPremCredentials $OnpremCredentials
Is it possible to use application IDs to automate this process? And if it is, how do i code it?
Thank you for your kind help.
I'm afraid you could not use the service principal(i.e. the application ID) to do that.
Currently, we could just use domain admin and tenant global admin credentials in a scheduled task.
You could refer to this sample:
# Requirements:
# Microsoft Online Services Sign-In Assistant.
# 64-bit Azure Active Directory module for Windows PowerShell.
$CloudUser = 'service_account#domain.com'
$CloudEncrypted = Get-Content "C:\Scripts\Cloud_Encrypted_Password.txt" | ConvertTo-SecureString
$CloudCred = New-Object System.Management.Automation.PsCredential($CloudUser,$CloudEncrypted)
$OnpremUser = 'DOMAIN\service_account'
$OnpremEncrypted = Get-Content "C:\Scripts\Onprem_Encrypted_Password.txt" | ConvertTo-SecureString
$OnpremCred = New-Object System.Management.Automation.PsCredential($OnpremUser,$OnpremEncrypted)
Import-Module 'C:\Program Files\Microsoft Azure Active Directory Connect\AzureADSSO.psd1'
New-AzureADSSOAuthenticationContext -CloudCredentials $CloudCred
Update-AzureADSSOForest -OnPremCredentials $OnpremCred
Besides, Azure Team is also working on getting this automated, see the feedback:
https://feedback.azure.com/forums/169401-azure-active-directory/suggestions/33773926-automate-seamless-sso-kerberos-decryption-key-roll

How to get SMTP server name through PowerShell when $PSEmailServer is empty?

Windows 7, PowerShell 4.0. Computer is in the Windows domain.
I need to get SMTP server name (for using of the send-mailmessage cmdlet). The $PSEmailServer is empty.
I read this TechNet page about the Get-AcceptedDomain cmdlet. But I see this (on the TechNet page):
This cmdlet is available in on-premises Exchange Server 2016 and in
the cloud-based service.
How can I get SMTP server name or its IP-address?
If properly defined, the SMTP server address, either host name or IP, can be set through the SCP record in AD or Autodiscover DNS record of Exchange Server. There is a Powershell solution for querying SCP but Autodiscover solution is shorter, so I'll go on with it.
This works on Exchange Server 2010 and later. It should work with Exchange Server 2007 also but personally I have never used it.
You can get the host name;
$MailServer = [Net.DNS]::GetHostByAddress([Net.DNS]::GetHostEntry("Autodiscover").AddressList[0]).Hostname
or IP address (as string);
$MailServer = [Net.DNS]::GetHostByAddress([Net.DNS]::GetHostEntry("Autodiscover").AddressList[0]).AddressList[0].IPAddressToString
Since the GetHostByAddress(string) returns an instance of class System.Net.IPHostEntry, you can have some properties to make use of. For details, please read Microsoft Docs.
PS: I know, that's not the best practice to use the index of integers for values, but AddressList is an array of strings. So it does not define a method such as FirstOrDefault() or a property like DefaultAddress. So far, that is the most optimal and practical solution AFAIK.
Assuming the computer is member of a domain with Exchange deployed, and you want to use Exchange as STMP relay for send-mailmessage, you could ask the exchange configuration in the AD Configuration Context:
import-module activedirectory
$ag = "Exchange Administrative Group (ABCDEFGHIJKLM)" #enter your EAD
$c = "Acme" # Enter your company name (get this form ADSIEdit if unknown)
$sb = ("CN=Servers,CN=" + $ag + ",CN=Administrative Groups,CN=" + $c + ",CN=Microsoft Exchange,CN=Services,CN=Configuration,DC=staff,DC=hsrw")
$server = Get-ADObject -Properties cn, msExchSMTPReceiveConnectorFQDN, msExchSmtpReceiveBindings, msExchSMTPReceiveInboundSecurityFlag -SearchBase $sb -filter { objectClass -eq "msExchSmtpReceiveConnector"}
$server | ft cn, msExchSMTPReceiveConnectorFQDN, msExchSmtpReceiveBindings, msExchSMTPReceiveInboundSecurityFlag
This will spit out the hostnames and port bindings of every receive connector in your organisation. You then have to choose which one to use.
As I don't know how much Exchange knowledge you have, I will stop here. If something's unclear, just ask.

Configure SharePoint 2010 UPS with PowerShell

SOLUTION FOUND: For anyone else that happens to come across this problem, have a look-see at this: http://www.harbar.net/archive/2010/10/30/avoiding-the-default-schema-issue-when-creating-the-user-profile.aspx
TL;DR When you create UPS through CA, it creates a dbo user and schema on the SQL server using the farm account, however when doing it through powershell it creates it with a schema and user named after the farm account, but still tries to manage SQL using the dbo schema, which of course fails terribly.
NOTE: I've only included the parts of my script I believe to be relevant. I can provide other parts as needed.
I'm at my wit's end on this one. Everything seems to work fine, except the UPS Synchronization service is stuck on "Starting", and I've left it over 12 hours.
It works fine when it's set up through the GUI, but I'm trying to automate every step possible. While automating I'm trying to include every option available from the GUI so that it's present if it ever needs to be changed.
Here's what I have so far:
$domain = "DOMAIN"
$fqdn = "fully.qualified.domain.name"
$admin_pass = "password"
New-SPManagedPath "personal" -WebApplication "http://portal.$($fqdn):9000/"
$upsPool = New-SPServiceApplicationPool -Name "SharePoint - UPS" -Account "$domain\spsvc"
$upsApp = New-SPProfileServiceApplication -Name "UPS" -ApplicationPool $upsPool -MySiteLocation "http://portal.$($fqdn):9000/" -MySiteManagedPath "personal" -ProfileDBName "UPS_ProfileDB" -ProfileSyncDBName "UPS_SyncDB" -SocialDBName "UPS_SocialDB" -SiteNamingConflictResolution "None"
New-SPProfileServiceApplicationProxy -ServiceApplication $upsApp -Name "UPS Proxy" -DefaultProxyGroup
$upsServ = Get-SPServiceInstance | Where-Object {$_.TypeName -eq "User Profile Service"}
Start-SPServiceInstance $upsServ.Id
$upsSync = Get-SPServiceInstance | Where-Object {$_.TypeName -eq "User Profile Synchronization Service"}
$upsApp.SetSynchronizationMachine("Portal", $upsSync.Id, "$domain\spfarm", $admin_pass)
$upsApp.Update()
Start-SPServiceInstance $upsSync.Id
I've tried running each line one at a time by just copying it directly into the shell window after defining the variables, and none of them give an error, but there has to be something the CA GUI does that I'm missing.
For anyone else that happens to come across this problem, have a look-see at this: http://www.harbar.net/archive/2010/10/30/avoiding-the-default-schema-issue-when-creating-the-user-profile.aspx
TL;DR When you create UPS through CA, it creates a dbo user and schema on the SQL server using the farm account, however when doing it through powershell it creates it with a schema and user named after the farm account, but still tries to manage SQL using the dbo schema, which of course fails terribly.
The workaround is to put my code into its own script file, and then use Start-Process to run the script as the farm account (it's a lot cleaner than the Job method described in the linked article):
$credential = Get-Credential ("$domain\spfarm", $SecureString)
Start-Process -FilePath powershell.exe -ArgumentList "-File C:\upsSync.ps1" -Credential $credential

Trouble setting up MSMQ ACL using PowerShell cmdlet

My MSMQ queue gets created by PowerShell DSC engine. I can see queues created. Since DSC engine runs from SYSTEM account, then queue owner also gets set to SYSTEM.
When I try to set MSMQ ACL from PowerShell console I constantly get following error:
PS C:\Users\Administrator.DOMAIN> whoami; Get-MsmqQueue queue1 | Set-MsmqQueueACL -UserName "Everyone" -Allow FullControl
DOMAIN\administrator
Set-MsmqQueueACL : Failed to set security descriptor. Error code: 3222143013
At line:1 char:50
+ whoami; Get-MsmqQueue incredipay_atm_processor | Set-MsmqQueueACL -UserName "Eve ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidResult: (FullControl:MessageQueueAccessRights) [Set-MsmqQueueACL], Win32Exception
+ FullyQualifiedErrorId : Failed to set security descriptor. Error code: 3222143013,Microsoft.Msmq.PowerShell.Commands.SetMSMQQueueACLCommand
I also can't set MSMQ ACL using custom DSC resource, which is basically doing the same thing only from SYSTEM account.
So the question is are there any way to set MSMQ permissions from within PowerShell DSC engine using Set-MSMQQueueACL cmdlet. Or at least if I'll be able to solve previously mentioned mentioned error, then maybe I'll be able to solve also DSC problem.
I'm running Windows 2012 and WMF 4.0.
Thanks in advance.
I did something similar recently and hit the same problem. You have to take ownership of the queue first (admin rights required), and then you can change the permissions.
Try these manual steps in the Computer Management snap-in first to check it solves your error, and then work out how to reproduce it via PowerShell.
Start -> Run -> compmgmt.msc
Expand "Computer management (Local) -> Services and Applications -> Message Queuing -> Private Queues"
Right click -> Properties -> Security -> Advanced -> Owner -> Other users or groups...
Enter your user name (DOMAIN\administrator)
Click OK, then OK again
You should now be able to edit security via script
I ended up writing some PInvoke code to take ownership of the queue using C#, which I compiled on the fly with Add-Type in PowerShell. I can't share it unfortunately as it's proprietary, but this question might give you some pointers:
How do I set the owner of a message queue?
P.S. error code 3222143013 is 0xC00E0025, which translates to MQ_ERROR_ACCESS_DENIED (see http://msdn.microsoft.com/en-us/library/ms700106%28v=vs.85%29.aspx)
I've managed to overcome this issue by using following code in my custom DSC resource:
$ScriptBlock={
param(
[String] $QueueName,
[String] $Username,
[String[]] $MessageQueueAccessRight,
[ValidateSet("Allow","Deny")]
[String] $MessageQueueAccessType
)
$params = #{}
$queue = Get-MSMQQueue -Name $QueueName
$params.Add("InputObject",$queue)
$params.Add("Username",$Username)
switch ($MessageQueueAccessType)
{
"Allow" {$params.Add("Allow","$MessageQueueAccessRight"); Break;}
"Deny" {$params.Add("Deny","$MessageQueueAccessRight"); Break;}
}
Set-MsmqQueueACL #params
}
Foreach($MessageQueueAccessRight in $MessageQueueAccessRights)
{
Invoke-Command -ScriptBlock $ScriptBlock -ComputerName . -Credential $DomainAdministratorCredential -ArgumentList $QueueName,$Username,$MessageQueueAccessRight,$MessageQueueAccessType
}
Of course it's necessary to use the same approach when MSMQ queue gets created by DSC. So MSMQ queue creation should be made by the same account, whose initially going to adjust ACLs.
To do this in DSC, you can run your command using different credentials by having your custom DSC resource take a [PSCredential] parameter.
To do this securely requires some significant changes to your DSC infrastructure. See my answer to this question: https://serverfault.com/questions/632390/protecting-credentials-in-desired-state-configuration-using-certificates/#632836
If you just want to test before making those changes, you can tell DSC to allow storing your credentials in plaintext using PSDscAllowPlainTextPassword = $true in your configuration data (see here for details).
I also created a custom DSC resource to setup/modify my MSMQ queues within my web farm. Since DSC runs as SYSTEM you must ensure that the SYSTEM account has access to create/modify MSMQ's on the node.
There is a way to have DSC run as an account. If that is the case then you have to ensure that you are passing in that account when attempting to create/modify your MsmqQueue.
I understand I am responding to an old thread. But someone else in the near future may be facing the same issue and come across this thread.
Enjoy & Good Luck!