Friday, 14 June 2019

Get info of all the configured Outlook profiles using Powershell

In Outlook client you can configure multiple email accounts as per your need. You can add your primary work email as default profile and configure personal email as secondary profile. Sometimes you may need to fetch details of all the configured profiles, you can use outlook client itself for this need, but an easiest way is Powershell to retrieve all the properties from multiple accounts.

Open the powershell console and run the below command to list DisplayName and SmtpAddress of all accounts.
$outlookApplication = New-Object -ComObject 'Outlook.Application'
$accounts = $outlookApplication.Session.Accounts
$accounts | Select DisplayName, SmtpAddress
Use below command to list all the available properties.
$accounts | FL
The below command returns the default profile name
$outlookApplication.Application.DefaultProfileName
Note: The above commands will work only in Outlook client installed machine as it uses the interface library "Microsoft.Office.Interop.Outlook.Application" which works under the logged-in user's outlook context.

Since the above commands are working under the logged-in user's outlook context, you have to open the powershell without Run as administrator privilege. If you have opened the powershell console with Run as administrator privilege, then you will get the below error :
PS C:\WINDOWS\system32> $outlookApplication = New-Object -ComObject 'Outlook.Application'
New-Object : Retrieving the COM class factory for component with CLSID {0006F03A-0000-0000-C000-000000000046} failed
due to the following error: 80080005 Server execution failed (Exception from HRESULT: 0x80080005
(CO_E_SERVER_EXEC_FAILURE)).
At line:1 char:23
+ $outlookApplication = New-Object -ComObject 'Outlook.Application'
+                       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : ResourceUnavailable: (:) [New-Object], COMException
    + FullyQualifiedErrorId : NoCOMClassIdentified,Microsoft.PowerShell.Commands.NewObjectCommand
Read More...

Wednesday, 5 June 2019

Get Azure AD Users with their Registered Devices using Powershell

In this post I am going to share Powershell script to find and list devices that are registered by Azure AD users. We can use the Get-AzureADUserRegisteredDevice cmdlet to get the registered devices.

Before proceed run the below command to connect Azure AD Powershell module.
Connect-AzureAD
The below command gets the devices that are registered to the specified user.
$user = Get-AzureADUser -SearchString "UserName"
Get-AzureADUserRegisteredDevice -ObjectId  $user.ObjectId -All $true

List registered devices of all Azure AD users :

To get a report of device list for all Azure AD users, first we need to get users by Get-AzureADUser cmdlet and pipe the users list to Get-AzureADUserRegisteredDevice cmdlet.
$Result=@()
$Users = Get-AzureADUser -All $true | Select UserPrincipalName,ObjectId
$Users | ForEach-Object {
$user = $_
Get-AzureADUserRegisteredDevice -ObjectId $user.ObjectId | ForEach-Object {
$Result += New-Object PSObject -property @{ 
DeviceOwner = $user.UserPrincipalName
DeviceName = $_.DisplayName
DeviceOSType = $_.DeviceOSType
ApproximateLastLogonTimeStamp = $_.ApproximateLastLogonTimeStamp
}
}
}
$Result | Select DeviceOwner,DeviceName,DeviceOSType,ApproximateLastLogonTimeStamp

Export Report to CSV file :

You can export the result to CSV file using the command Export-CSV.
$Result | Export-CSV "C:\\AzureADJoinedDevices.csv" -NoTypeInformation -Encoding UTF8
Read More...

Tuesday, 4 June 2019

How to Set Property Bag Value in SharePoint Online using Powershell

The SharePoint property bag is a hash table, which is used to store data in key-value pairs and it is good place to store and retrieve meta-data or custom properties. We can set and get property bag value using CSOM or SharePoint Online PnP cmdlets. In this post I am going to share steps to update property bag value using PnP Powershell Module.

Before proceed install SharePoint PnP PowerShell Online module by running below command.
Install-Module SharePointPnPPowerShellOnline -Force
Run the below command to connect site with PnPOnline powershell.
$SiteURL = "https://MyTenant.sharepoint.com/sites/testsite"
Connect-PnPOnline $SiteURL
Once you have connected the required site, run the below command to set required property value.
Set-PnPPropertyBagValue -Key "myCustomProperty" -Value "customValue"
The above command works without any issue if the site setting NoScript disabled, or else you will get the below error message.
Set-PnPPropertyBagValue : Site has NoScript enabled, and setting property bag values is not supported
At line:1 char:1
+ Set-PnPPropertyBagValue -Key "myCustomProperty" -Value "customValue"
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (SharePointPnP.P...ropertyBagValue:SetPropertyBagValue) [Set-PnPProper
   tyBagValue], Exception
    + FullyQualifiedErrorId : NoScriptEnabled,SharePointPnP.PowerShell.Commands.SetPropertyBagValue
To disable the NoScript setting, we need to set the property DenyAddAndCustomizePages as Disabled. Run the below command to disable NoScript setting for the given site.
$site = Get-PnPTenantSite -Detailed -Url $SiteURL 
$site.DenyAddAndCustomizePages = 'Disabled'
$site.Update()
$site.Context.ExecuteQuery()
-- OR -- You can also use the below command to set this value using Set-PnPTenantSite cmdlet in modern sharepoint sites.
Set-PnPTenantSite -Url $SiteURL  -NoScriptSite:$false
Now run the below command to re-connect the site and set required property bag value.
Connect-PnPOnline $SiteURL
Set-PnPPropertyBagValue -Key "myCustomProperty" -Value "customValue"

Get Property Bag value :

Use the below command to get the configured property value.
Get-PnPPropertyBag -Key "myCustomProperty"

Remove Property Bag value :

Run the below command to delete an existing property.
Remove-PnPPropertyBagValue -Key "myCustomProperty" -Force
Read More...

Thursday, 30 May 2019

Fix "Access to OData is disabled" error when read posts from mailbox using Graph API

I have been working with Microsoft Planner using Graph API and getting the error message ErrorAccessDenied : Access to OData is disabled while reading messages from Office 365 group mailbox.
Request URL: https://graph.microsoft.com/v1.0/groups/<groupId>/threads/<conversationThreadId>/posts
Request Method: GET
Status Code: 403 Forbidden

{
  "error": {
    "code": "ErrorAccessDenied",
    "message": "Access to OData is disabled.",
    "innerError": {
      "request-id": "b4bbe2f4-81d1-46cb-8fee-d79d02257e64",
      "date": "2019-05-30T05:39:21"
    }
  }
}

Solution :

After exploring some time, found that the exchange mailbox and calendar related graph api end-points are internally use EWS (Exchange Web Service) to fetch and update data in mailbox and calendar. You may received this error message either if the EWS access is disabled for all client applications or if EWS access is allowed only for particular applications.

You can check your current tenant EWS access policy by using the Exchange Online powershell cmdlet Get-OrganizationConfig. First, connect EXO powershell module and run the below command:
Get-OrganizationConfig | select EwsApplicationAccessPolicy, EwsAllowList, EwsBlockList
If you find any entries either for Allow access policy or Block access policy, then this might be the root cause for this error. If allow policy configured, then enusure that your client application is included for EWS access, or if block policy configured, then ensure that your client app is not included in block list.

Run the below command to remove the applied EWS access policy.
Set-OrganizationConfig -EwsApplicationAccessPolicy $null
You can refer below articles to know more about how to configure EWS access.
Read More...

Wednesday, 29 May 2019

Block Read Access for Non-Admin Users to Azure AD Powershell and Graph API

In Office 365 tenant, by default any user can easily connect Azure AD powershell and run the command Get-MsolUser or Get-AzureADUser to list all other user details including users’ personal data (ex: phone no, address, password last set time, etc..), and also fetch this info using users (https://graph.microsoft.com/v1.0/users) Graph Api end-point . This design may not be problem in some organisations, but it will create some serious security issue in secured organisations.

We can use the Set-MsolCompanySettings cmdlet from Azure AD Powershell v1 module (MSOnline) to block this read access for non-admin users. You should have Global Admin permission to run this command. Before proceed run the below command to connect Azure AD module.
Connect-MsolService
Run the below command to disable users' permission to read other users data.
Set-MsolCompanySettings -UsersPermissionToReadOtherUsersEnabled $false
After running the above command you can still use Global Admin account without any issue to read all users data, but if you connect Azure AD powershell with non-admin user account and run the Get-MsolUser cmdlet, then you will get the error "Get-MsolUser : Access Denied. You do not have permissions to call this cmdlet".
PS C:\> Get-MsolUser
Get-MsolUser : Access Denied. You do not have permissions to call this cmdlet.
At line:1 char:1
+ Get-MsolUser
+ ~~~~~~~~~~~~
    + CategoryInfo          : OperationStopped: (:) [Get-MsolUser], MicrosoftOnlineException
    + FullyQualifiedErrorId : Microsoft.Online.Administration.Automation.AccessDeniedException,Microsoft.Online.Admini
   stration.Automation.GetUser

Azure AD Powershell v2 module :

When you run the Get-AzureADUser cmdlet you will get the error message "Authorization_RequestDenied : Insufficient privileges to complete the operation"
PS C:\> Get-AzureADUser
Get-AzureADUser : Error occurred while executing GetUsers
Code: Authorization_RequestDenied
Message: Insufficient privileges to complete the operation.
RequestId: 784ed01e-094f-4ecd-8bcd-6557e5bc7b58
DateTimeStamp: Wed, 29 May 2019 18:09:40 GMT
HttpStatusCode: Forbidden
HttpStatusDescription: Forbidden
HttpResponseStatus: Completed
At line:1 char:1
+ Get-AzureADUser
+ ~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [Get-AzureADUser], ApiException
    + FullyQualifiedErrorId : Microsoft.Open.AzureAD16.Client.ApiException,Microsoft.Open.AzureAD16.PowerShell.GetUser

Graph Api - Users end-point :

You will also get Access Denied response when you connect users graph end-point using normal user account.
Request URL: https://graph.microsoft.com/v1.0/users
Request Method: GET
Status Code: 403 Forbidden

{
  "error": {
    "code": "Authorization_RequestDenied",
    "message": "Insufficient privileges to complete the operation.",
    "innerError": {
      "request-id": "b254adb3-8918-4921-b899-8c381b9ea611",
      "date": "2019-05-29T18:27:59"
    }
  }
}
Note: Blocking read access to other users' data may cause some problems in Microsoft Planner and Teams (ex: search users may not work when you add members to a plan).
Read More...

Change local system user account password using Powershell

We can use the Get-LocalUser cmdlet to get local user account details and use the Set-LocalUser cmdlet to update local account information. In this post will share powershell commands to reset local user password and steps to force user to change password at next logon.

Note: Open the Powershell console with Run as administrator privilege.

Run the below command to list specific user details.
Get-LocalUser -Name "testuser" | FL

Change Password :

We have to pass the new password text as Secure String password for the parameter Password in Set-LocalUser cmdlet. The below command reset password for the user "testuser", you can copy the command and replace your own username and new password text.
$SecurePassword = ConvertTo-SecureString "P@ssword!" -AsPlainText -Force
$UserAccount = Get-LocalUser -Name "testuser"
$UserAccount | Set-LocalUser -Password $SecurePassword

Force user to change password at next logon :

We can't use Set-LocalUser cmdlet to set the flag User must change password at next logon and we can use the native interface (ADSI WinNT Provider) to set this flag. Actually we need to expire an user's password to force the user to change password at next login. The below command sets value for passwordExpired property as 1 to make the user's password to expire state.
$user=[ADSI]'WinNT://localhost/testuser';
$user.passwordExpired = 1;
$user.setinfo();
Read More...

Tuesday, 28 May 2019

Hide mail enabled security group from GAL using Powershell

Mail-enabled security group is nothing but the security group which also act as a distribution list. The group's security related properties are controlled by Azure AD and Message distribution related stuffs are controlled by Exchange Online. So we can use the Exchange powershell cmdlet Set-DistributionGroup to hide its mail address from Global Address List.
Set-DistributionGroup "mail security group name" -HiddenFromAddressListsEnabled:$true
We are setting the attribute HiddenFromAddressListsEnabled as true to hide group mail id from global address book. You can use the following command to set this property for all mail-enabled security groups.
Get-DistributionGroup -RecipientTypeDetails MailUniversalSecurityGroup | Set-DistributionGroup -HiddenFromAddressListsEnabled:$true
The below command lists all groups with GAL visible status:
Get-DistributionGroup -RecipientTypeDetails MailUniversalSecurityGroup | Select DisplayName,HiddenFromAddressListsEnabled
Read More...

Find Owners and Members of Mail-Enabled Security Groups using Powershell

Mail-enabled security group is nothing but the security group which also act as a distribution list. In Office 365 environment this group can be used to distribute messages as well as to grant access permissions to SharePoint resources.

Since this group is being used for dual purpose, Security (controlled by Azure AD) and Message distribution (controlled by Exchange Online), the group object will be maintained in both places Azure AD and Exchange Online. You can use Azure AD Admin portal (and Azure AD Powershell module) to manage azure ad related properties and use Exchange Online Admin center (and Exchange Online powershell module) to update exchange related attributes.

Note: Before proceed connect both Azure AD and Exchange Online powershell modules.

List mail-enabled security groups:

We can use the Get-AzureADGroup cmdlet to list only mail enabled security groups.
Get-AzureADGroup -Filter "SecurityEnabled eq true and MailEnabled eq true"
We can also use the Exchange Online powershell command Get-DistributionGroup to list mail enabled security groups.
Get-DistributionGroup -RecipientTypeDetails MailUniversalSecurityGroup

Find Owners of mail-enabled security groups

We can use the Azure AD powershell command Get-AzureADGroupOwner to list owners of security groups, but it will not list mail-enabled security group owners. So we can extract owners info from ManagedBy attribute in Get-DistributionGroup cmdlet.
Get-DistributionGroup -RecipientTypeDetails MailUniversalSecurityGroup |
Select DisplayName,ManagedBy

Find Members of mail-enabled security groups

We can use the Get-AzureADGroupMember cmdlet to retrieve members of Azure AD groups.
$group = Get-AzureADGroup -SearchString "TestSecurityGroup"
Get-AzureADGroupMember -ObjectId $group.ObjectId |select DisplayName, UserPrincipalName
You can use the below command to list members of all mail-enabled security groups.
$mailGroups = Get-AzureADGroup -Filter "SecurityEnabled eq true and MailEnabled eq true"
$Result = @()
$mailGroups | ForEach-Object {
$group = $_
Get-AzureADGroupMember -ObjectId $group.ObjectId | ForEach-Object {
$member = $_
$Result += New-Object PSObject -property @{ 
GroupName = $group.DisplayName
Member = $member.DisplayName
UserPrincipalName = $member.UserPrincipalName
}
}
}
$Result | Select GroupName,Member,UserPrincipalName
We can also use the Exchange powershell cmdlet Get-DistributionGroupMember to list members.
$mailGroups = Get-DistributionGroup -RecipientTypeDetails MailUniversalSecurityGroup
$Result = @()
$mailGroups | ForEach-Object {
$group = $_
Get-DistributionGroupMember -Identity $group.Identity | ForEach-Object {
$member = $_
$Result += New-Object PSObject -property @{ 
GroupName = $group.DisplayName
Member = $member.DisplayName
PrimarySmtpAddress = $member.PrimarySmtpAddress
}
}
}
$Result | Select GroupName,Member,PrimarySmtpAddress
You can export the result to CSV file using the command Export-CSV.
$Result | Export-CSV "C:\\Mail-Security-Group-Members.csv" -NoTypeInformation -Encoding UTF8
Read More...