├── .vscode ├── launch.json └── pinned-files.json ├── Posh365 ├── .vscode │ └── launch.json ├── Posh365.psd1 ├── Posh365.psm1 ├── Private │ ├── Azure │ │ ├── Get-AzureLoadBalancerHelper.ps1 │ │ ├── Get-AzureVMHelper.ps1 │ │ └── Get-AzureVNetHelper.ps1 │ ├── Compliance │ │ ├── Add-ToCaseReport.ps1 │ │ ├── Connect-OnPremExchange.ps1 │ │ ├── Invoke-FindSpill.ps1 │ │ ├── MessageSearch.ps1 │ │ ├── New-CompliancePurge.ps1 │ │ └── SpillFinder.ps1 │ ├── Connect │ │ ├── Connect-CloudDeleteCredential.ps1 │ │ ├── Connect-CloudMFAClip.ps1 │ │ ├── Connect-CloudModuleImport.ps1 │ │ ├── Connect-EXOPSSession.ps1 │ │ ├── Connect-Exchange2.ps1 │ │ ├── Connect-IPPSSession.ps1 │ │ ├── Connect-PoshGraphOld.ps1 │ │ ├── Connect-PoshGraphRefresh.ps1 │ │ ├── RemoveBrokenOrClosedPSSession.ps1 │ │ ├── Test-365ServiceConnection.ps1 │ │ ├── Test-Uri.ps1 │ │ └── UpdateImplicitRemotingHandler.ps1 │ ├── DLL │ │ ├── Microsoft.SharePoint.Client.Runtime.dll │ │ └── Microsoft.SharePoint.Client.dll │ ├── Decision │ │ └── Get-DecisionbyOGV.ps1 │ ├── Discovery │ │ ├── Convert-TransportXMLtoCSV.ps1 │ │ ├── Export-EmailsOnePerLineOneOff.ps1 │ │ ├── Get-MsolUserMFAHash.ps1 │ │ └── Get-TransportRuleHash.ps1 │ ├── Forest │ │ ├── Convert-CanonicalToDistinguished.ps1 │ │ ├── Convert-DistinguishedToCanonical.ps1 │ │ ├── ConvertTo-NetBios.ps1 │ │ └── Get-DomainNameHash.ps1 │ ├── GitHub │ │ └── Get-GitHubGistID.ps1 │ ├── Graph │ │ └── Get-GraphGroupData.ps1 │ ├── Hash │ │ ├── Get-DistributionGroupMembers.ps1 │ │ ├── Get-DistributionGroupMembersHash.ps1 │ │ ├── Get-LegacyDNHash.ps1 │ │ └── Get-RecipientCNHash.ps1 │ ├── Intune │ │ ├── Apps │ │ │ ├── Get-MemMobileAppConfigData.ps1 │ │ │ ├── Get-MemMobileAppConfigTargetedData.ps1 │ │ │ ├── Get-MemMobileAppData.ps1 │ │ │ ├── Get-MemMobileAppProtectionAndroidData.ps1 │ │ │ └── Get-MemMobileAppProtectioniOSData.ps1 │ │ ├── Devices │ │ │ ├── Get-AADMemDeviceData.ps1 │ │ │ ├── Get-MemDeviceData.ps1 │ │ │ ├── Get-MemDeviceWindowsUpdateData.ps1 │ │ │ ├── Get-MemMobileDeviceComplianceAndroidWorkData.ps1 │ │ │ ├── Get-MemMobileDeviceComplianceiOSData.ps1 │ │ │ ├── Get-MemMobileDeviceConfigiOSDeviceRestrictionsData.ps1 │ │ │ ├── Get-MemMobileDeviceConfigiOSEmailData.ps1 │ │ │ ├── Get-MemMobileDeviceConfigiOSWiFiData.ps1 │ │ │ └── Get-MemMobileDeviceListData.ps1 │ │ └── Get-IntunePolicyHash.ps1 │ ├── License │ │ ├── Get-CloudSku.ps1 │ │ ├── Get-CloudSkuTable.ps1 │ │ ├── Get-Sku2Service.ps1 │ │ ├── Get-UglyToFriendlyOptionHash.ps1 │ │ ├── Get-UglyToFriendlySkuHash.ps1 │ │ ├── Get-UniqueString.ps1 │ │ ├── Get-UserLicense.ps1 │ │ ├── Invoke-SetCloudLicense.ps1 │ │ ├── New-Password.ps1 │ │ └── Set-SkuChange.ps1 │ ├── Migration │ │ ├── BitTitan │ │ │ ├── Get-BTDeviceHash.ps1 │ │ │ ├── Get-BTTicket.ps1 │ │ │ ├── Get-BTUserHash.ps1 │ │ │ ├── Get-MWMailboxConnector.ps1 │ │ │ ├── Get-MWTicket.ps1 │ │ │ ├── Import-BTSharePointExcelDecision.ps1 │ │ │ ├── Invoke-EnterBTCustomer.ps1 │ │ │ ├── Invoke-GetBTUser.ps1 │ │ │ ├── Invoke-GetBTUserTrimmed.ps1 │ │ │ ├── Invoke-GetDeploymentProStatistics.ps1 │ │ │ ├── Invoke-GetMWMailboxMove.ps1 │ │ │ ├── Invoke-GetMWMailboxMovePasses.ps1 │ │ │ ├── Invoke-GetMWMailboxMoveStatistics.ps1 │ │ │ ├── Invoke-NewBTUser.ps1 │ │ │ ├── Invoke-NewMWMailboxMove.ps1 │ │ │ ├── Invoke-NewMWMailboxStatsandNoStats.ps1 │ │ │ ├── Invoke-RemoveBTUser.ps1 │ │ │ ├── Invoke-SetBTUser.ps1 │ │ │ ├── Invoke-SetDeploymentProSchedule.ps1 │ │ │ ├── Invoke-SetMWMailboxMove.ps1 │ │ │ └── Invoke-SetMWMailboxMoveForwards.ps1 │ │ ├── CloudData │ │ │ ├── Add-ProxyToRecipient.ps1 │ │ │ ├── Clear-ADEmailAddressPolicyAttributes.ps1 │ │ │ ├── Compare-AddX500FromContact.ps1 │ │ │ ├── Get-ADEmailAddressPolicyHash.ps1 │ │ │ ├── Get-CloudMailboxHash.ps1 │ │ │ ├── Get-DupesLocal.ps1 │ │ │ ├── Get-RemoteMailboxHash.ps1 │ │ │ ├── Invoke-AddX500FromContact.ps1 │ │ │ ├── Invoke-CompareGuid.ps1 │ │ │ ├── Invoke-CompleteCloudDataSync.ps1 │ │ │ ├── Invoke-DisableMailboxEmailAddressPolicy.ps1 │ │ │ ├── Invoke-GetCloudData.ps1 │ │ │ ├── Invoke-GetDupePrefix.ps1 │ │ │ ├── Invoke-NewCloudData.ps1 │ │ │ ├── Invoke-SetMailboxFlag.ps1 │ │ │ ├── Invoke-SetmsExchVersion.ps1 │ │ │ ├── Invoke-SyncRemoteRoutingAddress.ps1 │ │ │ ├── Select-CloudDataConnection.ps1 │ │ │ ├── Select-CompleteCloudDataSync.ps1 │ │ │ ├── Select-DisableMailboxEmailAddressPolicy.ps1 │ │ │ └── Select-SetmsExchVersion.ps1 │ │ ├── Decision │ │ │ ├── Get-BTUserDecision.ps1 │ │ │ ├── Get-ContinueDecision.ps1 │ │ │ ├── Get-LicenseDecision.ps1 │ │ │ ├── Get-MailboxMovePermissionBatchDecision.ps1 │ │ │ ├── Get-MailboxMovePermissionLinkDecision.ps1 │ │ │ ├── Get-MwItemType.ps1 │ │ │ ├── Get-NumberOfDaysDecision.ps1 │ │ │ ├── Get-PermissionDecision.ps1 │ │ │ ├── Get-PermissionDecisionBatch.ps1 │ │ │ ├── Get-PermissionDirectionDecision.ps1 │ │ │ ├── Get-ScheduleDecision.ps1 │ │ │ ├── Get-UserDecision.ps1 │ │ │ ├── Import-MailboxCsvDecision.ps1 │ │ │ ├── Import-MailboxCsvDecisionDomainChoice.ps1 │ │ │ ├── Import-MailboxMoveDecision.ps1 │ │ │ ├── Import-SharePointExcelDecision.ps1 │ │ │ ├── Invoke-GetMailboxMovePermissionBatchDecision.ps1 │ │ │ └── Update-MailboxMovePermissionBatchHelper.ps1 │ │ ├── Get-MailboxMoveReportData.ps1 │ │ ├── Get-MailboxMoveReportDataHelper.ps1 │ │ ├── Invoke-AddMailboxMovePermission.ps1 │ │ ├── Invoke-CompleteMailboxMove.ps1 │ │ ├── Invoke-GetMailboxMove.ps1 │ │ ├── Invoke-GetMailboxMoveLicenseUserSku.ps1 │ │ ├── Invoke-GetMailboxMoveLicenseUserSkuWithType.ps1 │ │ ├── Invoke-GetMailboxMovePassThru.ps1 │ │ ├── Invoke-GetMailboxMovePermissionLink.ps1 │ │ ├── Invoke-GetMailboxMoveStatistics.ps1 │ │ ├── Invoke-GetMailboxMoveStatisticsHelper.ps1 │ │ ├── Invoke-NewMailboxMove.ps1 │ │ ├── Invoke-RemoveMailboxMove.ps1 │ │ ├── Invoke-RemoveMailboxMovePermission.ps1 │ │ ├── Invoke-ResumeMailboxMove.ps1 │ │ ├── Invoke-SetMailboxMove.ps1 │ │ ├── Invoke-SetMailboxMoveAddressBookPolicy.ps1 │ │ ├── Invoke-SetMailboxMoveConvertToShared.ps1 │ │ ├── Invoke-SetMailboxMoveForwards.ps1 │ │ ├── Invoke-SetMailboxMoveLicense.ps1 │ │ ├── Invoke-SetMailboxMoveRetentionPolicy.ps1 │ │ ├── Invoke-SuspendMailboxMove.ps1 │ │ ├── Invoke-T2TCompleteMailboxMove.ps1 │ │ ├── Invoke-T2TNewMailboxMove.ps1 │ │ ├── Invoke-TestMailboxMove.ps1 │ │ ├── Invoke-UpdateMailboxMovePermissionBatch.ps1 │ │ ├── OnPremises │ │ │ ├── Get-MailboxMoveOnPremisesReportHelper.ps1 │ │ │ ├── Get-MailboxMoveRecipientHash.ps1 │ │ │ └── Get-OnPremExchangeMailboxStatistics.ps1 │ │ ├── Task │ │ │ ├── Add-UserToADGroup.ps1 │ │ │ └── Get-ADUserGuid.ps1 │ │ └── Test │ │ │ └── Test-UpnMatch.ps1 │ ├── Office365 │ │ └── Invoke-GetOfficeEndpoints.ps1 │ ├── Okta │ │ ├── Get-OktaAppHash.ps1 │ │ ├── Get-OktaAppUserHash.ps1 │ │ ├── Get-OktaAppUserReport.ps1 │ │ ├── Get-OktaGroupHash.ps1 │ │ ├── Get-OktaGroupMemberHash.ps1 │ │ ├── Get-OktaMemberGroupHash.ps1 │ │ ├── Get-OktaMemberGroupIDHash.ps1 │ │ └── Get-OktaUserHash.ps1 │ ├── Options │ │ ├── Select-SamAccountNameCharacters.ps1 │ │ ├── Select-SamAccountNameNumberOfFirstNameCharacters.ps1 │ │ ├── Select-SamAccountNameNumberOfLastNameCharacters.ps1 │ │ └── Select-SamAccountNameOrder.ps1 │ ├── Outlook │ │ └── Invoke-GetOutlookData.ps1 │ ├── Permissions │ │ ├── DistributionGroup │ │ │ └── Get-DGSendAsPerms.ps1 │ │ ├── EXO │ │ │ ├── Get-LegacyDNToPrimarySmtpHash.ps1 │ │ │ ├── Get-MailboxLegacyExchangeDNHash.ps1 │ │ │ ├── Get-RecipientDNHash.ps1 │ │ │ ├── Get-RecipientHash.ps1 │ │ │ ├── Get-RecipientLiveIDHash.ps1 │ │ │ ├── Get-RecipientMailHash.ps1 │ │ │ ├── Get-RecipientNameHash.ps1 │ │ │ └── Get-RecipientPrimaryToTypeHash.ps1 │ │ ├── Hashtable │ │ │ ├── Get-ADHash.ps1 │ │ │ ├── Get-ADHashCN.ps1 │ │ │ ├── Get-ADHashDG.ps1 │ │ │ ├── Get-ADHashDGDN.ps1 │ │ │ ├── Get-ADHashDN.ps1 │ │ │ ├── Get-ADHashDisplay.ps1 │ │ │ ├── Get-ADHashDisplayName.ps1 │ │ │ ├── Get-ADHashDisplayNameToGuid.ps1 │ │ │ ├── Get-ADHashMailToGuid.ps1 │ │ │ └── Get-ADHashType.ps1 │ │ ├── Helper │ │ │ ├── Get-FullAccessPerms.ps1 │ │ │ ├── Get-MailboxFolderPerms.ps1 │ │ │ ├── Get-MigrationChain.ps1 │ │ │ ├── Get-SendAsPerms.ps1 │ │ │ └── Get-SendOnBehalfPerms.ps1 │ │ ├── MailboxMove │ │ │ ├── Get-MailboxMoveApplyPermissionResult.ps1 │ │ │ ├── Get-MailboxMoveDelegateResult.ps1 │ │ │ ├── Get-MailboxMoveFolderPermission.ps1 │ │ │ ├── Get-MailboxMoveFolderResult.ps1 │ │ │ ├── Get-MailboxMoveMailboxPermission.ps1 │ │ │ ├── Get-MailboxMovePermissionLinkResult.ps1 │ │ │ └── Get-MailboxMovePermissionResult.ps1 │ │ └── OnPrem │ │ │ ├── ActiveDirectory │ │ │ ├── Get-ADGroupMemberHash.ps1 │ │ │ ├── Get-ADGroupsWithProxyAddress.ps1 │ │ │ ├── Get-ADObjectsWithProxyAddress.ps1 │ │ │ ├── Get-ADUsersAndGroups.ps1 │ │ │ ├── Get-ADUsersAndGroupsWithProxyAddress.ps1 │ │ │ └── Get-ADUsersWithProxyAddress.ps1 │ │ │ ├── PublicFolder │ │ │ ├── Get-PFSendAsPerms.ps1 │ │ │ └── Get-PFSendOnBehalfPerms.ps1 │ │ │ └── Recursive │ │ │ ├── Get-FullAccessPermsRecursive.ps1 │ │ │ ├── Get-SendAsPermsRecursive.ps1 │ │ │ └── Get-SendOnBehalfPermsRecursive.ps1 │ ├── Security │ │ ├── ConditionalAccess │ │ │ └── Get-ConditionalAccessPolicyData.ps1 │ │ ├── Get-DNSSECDetails.ps1 │ │ ├── Get-DmarcPolicy.ps1 │ │ ├── Get-DmarcRecordText.ps1 │ │ ├── Get-DmarcSubdomainPolicy.ps1 │ │ ├── Get-DomainFederationDataFromO365.ps1 │ │ ├── Get-LowestPreferenceMX.ps1 │ │ ├── Get-MTASTSDetails.ps1 │ │ ├── Get-O365FederationHostname.ps1 │ │ ├── Get-SpfRecordMode.ps1 │ │ ├── Get-SpfRecordText.ps1 │ │ ├── Invoke-SearchAuditLog.ps1 │ │ ├── Invoke-TestSPFRecord.ps1 │ │ ├── Test-AADIsUnmanaged.ps1 │ │ ├── Test-AdfsFederationMetadataUrl.ps1 │ │ ├── Test-DNSHostingProvider.ps1 │ │ ├── Test-DNSNameAdministrator.ps1 │ │ ├── Test-DmarcRecordExists.ps1 │ │ ├── Test-ExchangeOnlineDomain.ps1 │ │ ├── Test-MXHandler.ps1 │ │ ├── Test-MtaStsRecordExists.ps1 │ │ ├── Test-O365DirectoryID.ps1 │ │ ├── Test-O365Dkim.ps1 │ │ ├── Test-O365DomainTenantName.ps1 │ │ ├── Test-O365FederationProvider.ps1 │ │ ├── Test-O365IsFederated.ps1 │ │ └── Test-SpfRecordExists.ps1 │ ├── SharePointandOneDrive │ │ └── Invoke-LoadMethod.ps1 │ └── WatcherFunctions │ │ ├── Watch-ToLicense.ps1 │ │ └── Watch-ToSetRetention.ps1 └── Public │ ├── ADConnect │ └── Get-ADConnectError.ps1 │ ├── ActiveDirectory │ ├── Contact │ │ └── Get-ActiveDirectoryContact.ps1 │ ├── Group │ │ └── Get-ActiveDirectoryGroup.ps1 │ ├── SPN │ │ └── Get-SPN.ps1 │ └── User │ │ ├── Convert-Id.ps1 │ │ ├── Get-ActiveDirectoryObject.ps1 │ │ ├── Get-ActiveDirectoryUser.ps1 │ │ └── Get-ActiveDirectoryUserByOU.ps1 │ ├── AddressList │ ├── Get-ExchangeAddressBookPolicy.ps1 │ ├── Get-ExchangeAddressList.ps1 │ ├── Get-ExchangeGlobalAddressList.ps1 │ └── Get-ExchangeOfflineAddressBook.ps1 │ ├── Azure │ ├── Get-AzureInventory.ps1 │ ├── Get-AzureLoadBalancerReport.ps1 │ ├── Get-AzureNSGReport.ps1 │ ├── Get-AzureStorageReport.ps1 │ ├── Get-AzureTrafficManagerEndpointReport.ps1 │ ├── Get-AzureTrafficManagerReport.ps1 │ ├── Get-AzureVMReport.ps1 │ ├── Get-AzureVNetReport.ps1 │ ├── Get-AzureVPNReport.ps1 │ └── Get-DiscoveryAzure.ps1 │ ├── AzureAD │ ├── Export-AzureADAppAndPermissions.ps1 │ ├── Get-AzureActiveDirectoryDevice.ps1 │ ├── Get-AzureActiveDirectoryUser.ps1 │ ├── Get-AzureUserOnPremisesOUs.ps1 │ └── Import-AzureADAppAndPermissions.ps1 │ ├── Compliance │ ├── Find-Spill.ps1 │ ├── Get-EdiscoveryCase.ps1 │ ├── Get-MfaStats.ps1 │ ├── Get-ModifiedMailboxItem.ps1 │ ├── Get-RetentionLinks.ps1 │ ├── New-MessageSearch.ps1 │ └── Search-AuditLog.ps1 │ ├── Connect │ ├── Connect-Cloud.ps1 │ ├── Connect-CloudMFA.ps1 │ ├── Connect-Exchange.ps1 │ ├── Connect-OktaSecure.ps1 │ ├── Connect-PoshGraph.ps1 │ ├── Connect-SharePointPNP.ps1 │ ├── CreateSecureConnetions │ │ ├── New-ExoCBAConnection.ps1 │ │ └── New-PoshSelfSignedCert.ps1 │ ├── Get-Cred.ps1 │ └── Switch-AzureADModule.ps1 │ ├── Contact │ └── Get-EXOMailContact.ps1 │ ├── Discovery │ ├── Compare-Csv.ps1 │ ├── Compare-GroupMembership.ps1 │ ├── Compare-List.ps1 │ ├── Compare-TenantAliases.ps1 │ ├── Compare-TenantEmails.ps1 │ ├── Expand-IdFixReport.ps1 │ ├── Export-CsvData.ps1 │ ├── Export-CsvDataForGroups.ps1 │ ├── Export-CsvJoinedData.ps1 │ ├── Export-EmailsOnePerLine.ps1 │ ├── Export-MembersOnePerLine.ps1 │ ├── Export-QCsvData.ps1 │ ├── Get-ADReplication.ps1 │ ├── Get-ActiveCasConnection.ps1 │ ├── Get-ActiveDirectoryUserFiltered.ps1 │ ├── Get-DiscoveryIntune.ps1 │ ├── Get-DiscoveryOffice365.ps1 │ ├── Get-DiscoveryOnPrem.ps1 │ ├── Get-DomainMatchingServicePrincipal.ps1 │ ├── Get-ExchangeListandPolicy.ps1 │ ├── Get-UsersInOuNotInCloud.ps1 │ ├── Get-VirtualDirectoryInfo.ps1 │ └── Google │ │ ├── Export-GoogleAddress.ps1 │ │ ├── Export-GoogleAlias.ps1 │ │ ├── Export-GoogleInitialandPhone.ps1 │ │ ├── Export-GoogleOrganization.ps1 │ │ └── Export-GooglePhysicalAddress.ps1 │ ├── Domain │ ├── Remove-365Domain.ps1 │ ├── Remove-GroupAddress.ps1 │ ├── Remove-MailboxAddress.ps1 │ └── Remove-UnifiedGroupAddress.ps1 │ ├── EOP │ ├── Add-ConnectionFilterPolicyDetail.ps1 │ ├── Add-ContentFilterPolicyDetail.ps1 │ ├── Get-ATPAntiPhishPolicy.ps1 │ ├── Get-ATPAntiPhishRule.ps1 │ ├── Get-ATPSafeAttachmentPolicy.ps1 │ ├── Get-ATPSafeAttachmentRule.ps1 │ ├── Get-ATPSafeLinksPolicy.ps1 │ ├── Get-ATPSafeLinksRule.ps1 │ ├── Get-EOPConnectionPolicy.ps1 │ ├── Get-EOPContentPolicy.ps1 │ ├── Get-EOPContentRule.ps1 │ ├── Get-EOPOutboundSpamPolicy.ps1 │ └── Get-EOPOutboundSpamRule.ps1 │ ├── EmailAddressPolicy │ └── Get-ExEmailAddressPolicy.ps1 │ ├── Forest │ ├── Convert-CanonicalToDistinguished.ps1 │ └── Convert-DistinguishedToCanonical.ps1 │ ├── Format │ └── Format-Vertical.ps1 │ ├── GitHub │ └── Get-GitHubGist.ps1 │ ├── Graph │ ├── Export-GraphConfig.ps1 │ ├── GalSync │ │ ├── Get-GSGraphDeltaUser.ps1 │ │ ├── Get-GSGraphExchangeUser.ps1 │ │ └── Get-GSGraphUserAll.ps1 │ ├── Get-GraphDeltaMailEnabledUser.ps1 │ ├── Get-GraphMailEnabledUser.ps1 │ ├── Get-GraphMailFolder.ps1 │ ├── Get-GraphMailFolderAll.ps1 │ ├── Get-GraphMailFolderChild.ps1 │ ├── Get-GraphMailFolderMessage.ps1 │ ├── Get-GraphMailFolderMessageByID.ps1 │ ├── Get-GraphMailFolderPathId.ps1 │ ├── Get-GraphMailFolderRecoverableItems.ps1 │ ├── Get-GraphMailMessage.ps1 │ ├── Get-GraphOrgContact.ps1 │ ├── Get-GraphSecureScore.ps1 │ ├── Get-GraphUser.ps1 │ ├── Get-GraphUserAll.ps1 │ ├── Get-GraphUserContacts.ps1 │ ├── Get-GraphUserList.ps1 │ ├── Get-TreePrintOut.ps1 │ ├── GraphIdentities │ │ ├── Get-AzureADSP.ps1 │ │ ├── Get-GraphGroup.ps1 │ │ ├── Get-GraphLocation.ps1 │ │ └── Get-GraphUnifiedRole.ps1 │ ├── New-GraphUser.ps1 │ ├── Register-GraphApplication.ps1 │ ├── Remove-GraphMailMessage.ps1 │ └── Save-GraphConfig.ps1 │ ├── Group │ ├── Get-365MsolGroupMember.ps1 │ ├── Get-DistributionGroupMembership.ps1 │ ├── Get-DistributionGroupMembershipHash.ps1 │ ├── Get-EXOGroup.ps1 │ ├── Get-ExDistributionGroupMember.ps1 │ ├── Get-ExDistributionGroupOwner.ps1 │ ├── Get-ExchangeDistributionGroup.ps1 │ ├── Unified │ │ ├── Export-AndImportUnifiedGroups.ps1 │ │ ├── Get-UnifiedGroupOwnersMembersSubscribers.ps1 │ │ └── Set-GroupCreationRestriction.ps1 │ └── Update-ExchangeGroupMembership.ps1 │ ├── Hybrid │ ├── Get-ExchangeLog.ps1 │ └── Get-IISLog.ps1 │ ├── Import │ ├── Add-ForwarderToExoMailbox.ps1 │ ├── Clear-SFBAttribute.ps1 │ ├── Google │ │ ├── Export-GoogleForward.ps1 │ │ ├── Import-GoogleAliasToEXOGroup.ps1 │ │ ├── Import-GoogleAliasToEXOMailbox.ps1 │ │ ├── Import-GoogleCalendarPermissionToEXO.ps1 │ │ ├── Import-GoogleTo365Group.ps1 │ │ ├── Import-GoogleToChangeUpn.ps1 │ │ ├── Import-GoogleToEXOGroup.ps1 │ │ ├── Import-GoogleToEXOGroupMember.ps1 │ │ ├── Import-GoogleToMsolDetail.ps1 │ │ ├── Import-GoogleToResourceMailbox.ps1 │ │ ├── Import-GoogleToSharedMailbox.ps1 │ │ └── Import-PoshAlias.ps1 │ ├── Import-365MsolUser.ps1 │ ├── Import-365UnifiedGroup.ps1 │ ├── Import-ADData.ps1 │ ├── Import-ADGroupProxyAddress.ps1 │ ├── Import-ADUserProxyAddress.ps1 │ ├── Import-ActiveDirectoryGroupMember.ps1 │ ├── Import-AzureADProperty.ps1 │ ├── Import-AzureADUser.ps1 │ ├── Import-EXOGroup.ps1 │ ├── Import-EXOGroupPermissions.ps1 │ ├── Import-EXOMailboxPermissions.ps1 │ ├── Import-EXOResourceMailboxSettings.ps1 │ ├── Import-ExchangeFolderPermission.ps1 │ ├── Import-ExchangeFullAccess.ps1 │ ├── Import-ExchangeSendAs.ps1 │ ├── Import-ExchangeSendOnBehalf.ps1 │ ├── Import-MsolProperty.ps1 │ ├── Import-PrimarySmtpasUpn.ps1 │ ├── Import-QADAlias.ps1 │ ├── Import-QADData.ps1 │ ├── New-ActiveDirectoryGroup.ps1 │ ├── New-ActiveDirectoryUser.ps1 │ ├── Remove-PublicFolderSMTP.ps1 │ ├── Switch-AddressDomain.ps1 │ ├── Switch-PrimarySmtp.ps1 │ └── Update-GoogleCalendarACL.ps1 │ ├── ImportExcel │ ├── Export-PoshExcel.ps1 │ ├── Import-PoshCsv.ps1 │ └── Import-SharePointExcel.ps1 │ ├── Intune │ ├── Add-MemMobileAppAssignmentiOS.ps1 │ ├── Compare-IntunePolicy.ps1 │ ├── Find-MemDevice.ps1 │ ├── Get-AADMemDevice.ps1 │ ├── Get-ConditionalAccessPolicy.ps1 │ ├── Get-MemAssignments.ps1 │ ├── Get-MemAuthenticationMethods.ps1 │ ├── Get-MemDevice.ps1 │ ├── Get-MemGroupAppAssignment.ps1 │ ├── Get-MemMobileApp.ps1 │ ├── Get-MemMobileAppConfig.ps1 │ ├── Get-MemMobileAppConfigTargeted.ps1 │ ├── Get-MemMobileAppProtectionAndroid.ps1 │ ├── Get-MemMobileAppProtectioniOS.ps1 │ ├── Get-MemMobileDeviceComplianceAndroidWork.ps1 │ ├── Get-MemMobileDeviceComplianceiOS.ps1 │ ├── Get-MemMobileDeviceConfigiOSDeviceRestrictions.ps1 │ ├── Get-MemMobileDeviceConfigiOSEmail.ps1 │ ├── Get-MemMobileDeviceConfigiOSWifi.ps1 │ ├── Remove-AADMemMobileDevice.ps1 │ ├── Remove-MemMobileDevice.ps1 │ └── Set-MemMobileDevice.ps1 │ ├── Lab │ ├── New-TestUser.ps1 │ └── Send-PoshMessage.ps1 │ ├── License │ ├── Get-CloudLicense.ps1 │ └── Set-CloudLicense.ps1 │ ├── Logging │ ├── Write-HostLog.ps1 │ └── Write-HostProgress.ps1 │ ├── MSOL │ ├── Get-365MsolGroup.ps1 │ └── Get-365MsolUser.ps1 │ ├── MailFlow │ ├── Add-TransportRuleDetail.ps1 │ ├── Get-ExchangeReceiveConnector.ps1 │ ├── Get-ExchangeSendConnector.ps1 │ ├── Get-InboundConnectorReport.ps1 │ ├── Get-OutboundConnectorSummary.ps1 │ ├── Get-TransportRuleReport.ps1 │ ├── New-EXOMailTransportRuleReport.ps1 │ ├── Trace-ExchangeMessage.ps1 │ └── Trace-Message.ps1 │ ├── Mailbox │ ├── Get-EXCalendarProcessing.ps1 │ ├── Get-EXOResourceMailbox.ps1 │ ├── Get-EXOnlineMailbox.ps1 │ ├── Get-ExMailbox.ps1 │ ├── Get-ExMailboxStatistics.ps1 │ ├── Get-ExchangeMailbox.ps1 │ └── Get-ExchangeMailboxStatistics.ps1 │ ├── Migration │ ├── Archive │ │ ├── Get-EXOMigrationStatistics.ps1 │ │ └── Test-Preflight.ps1 │ ├── CloudData │ │ ├── Complete-CloudDataSync.ps1 │ │ ├── Convert-CloudData.ps1 │ │ ├── Get-CloudDataRegionalSettings.ps1 │ │ ├── Get-DestinationRecipientHash.ps1 │ │ ├── Get-DupePrefix.ps1 │ │ ├── Main │ │ │ ├── Add-X500FromContactToContact.ps1 │ │ │ ├── Add-X500FromContactToRemoteMailbox.ps1 │ │ │ ├── Disable-MailboxEmailAddressPolicy.ps1 │ │ │ ├── Get-SourceContactHash.ps1 │ │ │ ├── Get-SourceQuotaHash.ps1 │ │ │ ├── Set-MailboxFlag.ps1 │ │ │ ├── Set-msExchVersion.ps1 │ │ │ └── Sync-Guid.ps1 │ │ ├── New-CloudData.ps1 │ │ ├── Set-CloudDataRegionalSettings.ps1 │ │ ├── Set-ExchangeGuid.ps1 │ │ ├── Sync-CloudData.ps1 │ │ └── Sync-RemoteRoutingAddress.ps1 │ ├── Convert │ │ └── ConvertTo-x500.ps1 │ └── MailboxMove │ │ ├── Base │ │ ├── Complete-MailboxMove.ps1 │ │ ├── Get-MailboxMove.ps1 │ │ ├── Get-MailboxMoveStatistics.ps1 │ │ ├── New-MailboxMove.ps1 │ │ ├── Remove-MailboxMove.ps1 │ │ ├── Resume-MailboxMove.ps1 │ │ ├── Set-MailboxMove.ps1 │ │ └── Suspend-MailboxMove.ps1 │ │ ├── Batches │ │ ├── Convert-MWMailboxMovePermissionAddresses.ps1 │ │ ├── Update-MWMailboxMoveBatchesReport.ps1 │ │ ├── Update-MWMailboxMoveBatchesReportWithTargetTenantAddress.ps1 │ │ └── Update-MailboxMoveBatchesReport.ps1 │ │ ├── BitTitan │ │ ├── Connect-BitTitan.ps1 │ │ ├── Connect-MigrationWiz.ps1 │ │ ├── Enter-BTCustomer.ps1 │ │ ├── Enter-MWProject.ps1 │ │ ├── Get-BTUser.ps1 │ │ ├── Get-DeploymentProStatistics.ps1 │ │ ├── Get-MWMailboxMove.ps1 │ │ ├── Get-MWMailboxMovePasses.ps1 │ │ ├── Get-MWMailboxMoveStatistics.ps1 │ │ ├── Invoke-NewMWMailboxMovePass.ps1 │ │ ├── New-BTUser.ps1 │ │ ├── New-MWMailboxMove.ps1 │ │ ├── New-MWMailboxMovePass.ps1 │ │ ├── Remove-BTUser.ps1 │ │ ├── Set-BTUser.ps1 │ │ ├── Set-DeploymentProSchedule.ps1 │ │ ├── Set-MWMailboxMove.ps1 │ │ └── Set-MWMailboxMoveForward.ps1 │ │ ├── Connect │ │ └── Connect-MailboxMove.ps1 │ │ ├── Credential │ │ └── Remove-MailboxMoveCredential.ps1 │ │ ├── EXO │ │ └── Permission │ │ │ └── Get-EXOMailboxFolderPerms.ps1 │ │ ├── License │ │ ├── Get-MailboxMoveLicense.ps1 │ │ ├── Get-MailboxMoveLicenseCount.ps1 │ │ ├── Get-MailboxMoveLicenseReport.ps1 │ │ ├── Get-MailboxMoveLicenseUser.ps1 │ │ └── Set-MailboxMoveLicense.ps1 │ │ ├── OnPremises │ │ ├── Get-MailboxMoveOnPremisesMailboxReport.ps1 │ │ └── Get-MailboxMoveOnPremisesPermissionReport.ps1 │ │ ├── Permission │ │ ├── Add-MailboxMovePermission.ps1 │ │ ├── Get-MailboxMovePermission.ps1 │ │ ├── Get-MailboxMovePermissionLink.ps1 │ │ ├── Remove-MailboxMovePermission.ps1 │ │ └── Update-MailboxMovePermissionBatch.ps1 │ │ ├── PostMigrationTask │ │ ├── Set-MailboxMoveAddressBookPolicy.ps1 │ │ ├── Set-MailboxMoveConvertToShared.ps1 │ │ ├── Set-MailboxMoveForward.ps1 │ │ └── Set-MailboxMoveRetentionPolicy.ps1 │ │ ├── Report │ │ └── Get-MailboxMoveReport.ps1 │ │ └── Test │ │ ├── Set-TimedMailboxMove.ps1 │ │ └── Test-MailboxMove.ps1 │ ├── Mobile │ └── Get-365MobileDevice.ps1 │ ├── OPP │ └── Remove-OfficeLicense.ps1 │ ├── Office365 │ └── Get-OfficeEndpoints.ps1 │ ├── Okta │ ├── Add-UserToOktaApp.ps1 │ ├── Add-UserToOktaGroup.ps1 │ ├── Get-DiscoveryOkta.ps1 │ ├── Get-OktaGroupMembership.ps1 │ ├── Get-SingleOktaUserReport.ps1 │ ├── Remove-OktaGroup.ps1 │ ├── Remove-OktaUser.ps1 │ ├── Remove-OktaUserfromApp.ps1 │ ├── Remove-UserfromOktaApp.ps1 │ └── Report │ │ ├── Convert-OktaRateLimitToSleep.ps1 │ │ ├── Get-OktaAppGroupReport.ps1 │ │ ├── Get-OktaAppReport.ps1 │ │ ├── Get-OktaGroupMemberReport.ps1 │ │ ├── Get-OktaGroupReport.ps1 │ │ ├── Get-OktaGroupUserMembershipReport.ps1 │ │ ├── Get-OktaPolicyReport.ps1 │ │ ├── Get-OktaUserAppReport.ps1 │ │ ├── Get-OktaUserGroupMembershipReport.ps1 │ │ └── Get-OktaUserReport.ps1 │ ├── Options │ ├── Install-ModuleOnServer.ps1 │ ├── Select-ADConnectServer.ps1 │ ├── Select-DisplayNameFormat.ps1 │ ├── Select-DomainController.ps1 │ ├── Select-ExchangeServer.ps1 │ ├── Select-Options.ps1 │ ├── Select-SamAccountNameOptions.ps1 │ └── Select-TargetAddressSuffix.ps1 │ ├── Outlook │ └── Get-OutlookVersions.ps1 │ ├── PSGSuite │ ├── Get-PSGCalendar.ps1 │ ├── Get-PSGCalendarACL.ps1 │ ├── Get-PSGGroup.ps1 │ ├── Get-PSGGroupDetails.ps1 │ ├── Get-PSGUser.ps1 │ └── Remove-PSGGroupCalendarOwnersAndHide.ps1 │ ├── Permissions │ ├── Add-ExMailboxFolderPermission.ps1 │ ├── Add-ExMailboxPermission.ps1 │ ├── EXO │ │ ├── Get-EXODGPerms.ps1 │ │ ├── Get-EXODGSendOnBehalfPerms.ps1 │ │ ├── Get-EXOFullAccessPerms.ps1 │ │ ├── Get-EXOMailboxPerms.ps1 │ │ ├── Get-EXOSendAsPerms.ps1 │ │ ├── Get-EXOSendOnBehalfPerms.ps1 │ │ ├── RecursiveGroupMembers │ │ │ ├── Get-EXOFullAccessRecursePerms.ps1 │ │ │ ├── Get-EXOMailboxRecursePerms.ps1 │ │ │ ├── Get-EXOSendAsRecursePerms.ps1 │ │ │ └── Get-EXOSendOnBehalfRecursePerms.ps1 │ │ └── Set-EXODGPerms.ps1 │ ├── Get-DGPerms.ps1 │ ├── Get-PFMailboxPerms.ps1 │ └── Get-PermissionChain.ps1 │ ├── PublicFolder │ ├── Get-EXOPublicFolder.ps1 │ ├── Get-EXPublicFolder.ps1 │ ├── Get-EXPublicFolderRights.ps1 │ ├── Get-InvalidMailPublicFolderAliasReport.ps1 │ ├── Get-InvalidModernPublicFolderCharacterReport.ps1 │ └── Get-InvalidPublicFolderCharacterReport.ps1 │ ├── Recipient │ ├── Add-365RecipientEmailAddresses.ps1 │ ├── Get-365Recipient.ps1 │ ├── Get-365RecipientEmailAddresses.ps1 │ └── Remove-BadProxyAddress.ps1 │ ├── Roles │ ├── Get-AzureADRoleReport.ps1 │ ├── Get-ComplianceRoleReport.ps1 │ ├── Get-ExchangeRoleReport.ps1 │ ├── Get-MsolRoleReport.ps1 │ ├── New-GroupManagementRoleWithECPAccess.ps1 │ ├── Update-GroupManagementRole.ps1 │ └── Update-RoleEntry.ps1 │ ├── Security │ ├── Get-EmailSecurityRecords.ps1 │ └── Test-SPFRecord.ps1 │ ├── SharePointPNP │ ├── Add-PoshPnPFile.ps1 │ └── Copy-SharePointFile.ps1 │ ├── SharePointandOneDrive │ ├── Get-OneDriveReport.ps1 │ ├── Get-SPOWeb.ps1 │ └── Grant-OneDriveAdminAccess.ps1 │ ├── Sync │ ├── Sync-AD.ps1 │ └── Sync-ADConnect.ps1 │ ├── Tasks │ ├── Add-Task.ps1 │ ├── Add-TaskByMinute.ps1 │ ├── Add-TaskDaily.ps1 │ └── Add-TaskWeekly.ps1 │ └── User │ ├── ConvertTo-Shared.ps1 │ ├── Disable-Employee.ps1 │ ├── Grant-FullAccessToMailbox.ps1 │ ├── New-HybridMailbox.ps1 │ ├── Rename-SamAccount.ps1 │ └── Rename-User.ps1 └── README.md /.vscode/pinned-files.json: -------------------------------------------------------------------------------- 1 | {"version":"2","pinnedList":["c:/Scripts/git/kevinblumenfeld/Posh365/Posh365/Private/Connect/Connect-PoshGraphRefresh.ps1","c:/Scripts/git/kevinblumenfeld/Posh365/Posh365/Public/Intune/GraphIdentities/Get-AzureADServicePrincipal.ps1","c:/Scripts/git/kevinblumenfeld/Posh365/Posh365/Public/Discovery/Get-DiscoveryIntune.ps1","c:/Scripts/git/kevinblumenfeld/Posh365/Posh365/Public/Connect/Connect-GraphInteractive.ps1"],"aliasMap":{}} -------------------------------------------------------------------------------- /Posh365/.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "name": "PowerShell: Interactive Session", 9 | "type": "PowerShell", 10 | "request": "launch", 11 | "cwd": "" 12 | } 13 | ] 14 | } -------------------------------------------------------------------------------- /Posh365/Posh365.psd1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kevinblumenfeld/Posh365/17628091caa09c90caf51d1171396d1a74beab96/Posh365/Posh365.psd1 -------------------------------------------------------------------------------- /Posh365/Posh365.psm1: -------------------------------------------------------------------------------- 1 | Get-ChildItem -Path "$PSScriptRoot/Public", "$PSScriptRoot/Private" -File -Recurse *.ps1 | ForEach-Object { 2 | . $_.FullName 3 | } 4 | -------------------------------------------------------------------------------- /Posh365/Private/Azure/Get-AzureVNetHelper.ps1: -------------------------------------------------------------------------------- 1 | function Get-AzureVNetHelper { 2 | param ( 3 | [Parameter(Mandatory, ValueFromPipeline, ValueFromPipelineByPropertyName)] 4 | $VNet, 5 | 6 | [Parameter(Mandatory)] 7 | [int] $MaxSubnets 8 | ) 9 | 10 | begin { 11 | 12 | } 13 | process { 14 | foreach ($CurVNet in $VNet) { 15 | 16 | $VNetObj = [ordered]@{ 17 | ResourceGroupName = $CurVNet.ResourceGroupName 18 | Location = $CurVNet.Location 19 | VNetName = $CurVNet.Name 20 | AddressSpace = ($CurVNet.AddressSpace.AddressPrefixes | Where-Object {$_ -ne $null}) -join ',' 21 | } 22 | 23 | $SubnetVNet = $CurVNet.Subnets 24 | 25 | foreach ( $Index in 0..($MaxSubnets - 1) ) { 26 | $CurSubnetVNet = $SubnetVNet[$Index] 27 | $SubnetName = "Subnet" + $Index 28 | $SubnetAddressSpace = "SubnetAddressSpace" + $Index 29 | 30 | $VNetObj.Add($SubnetName, $CurSubnetVNet.Name) 31 | $VNetObj.Add($SubnetAddressSpace, $CurSubnetVNet.AddressPrefix) 32 | } 33 | [PSCustomObject]$VNetObj 34 | } 35 | } 36 | end { 37 | 38 | } 39 | } 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /Posh365/Private/Compliance/New-CompliancePurge.ps1: -------------------------------------------------------------------------------- 1 | function New-CompliancePurge { 2 | [CmdletBinding()] 3 | param( 4 | [Parameter(Mandatory)] 5 | $NewCS 6 | ) 7 | do { 8 | if ($NewCS.name) { $Name = $NewCS.Name } 9 | else { $Name = $NewCS } 10 | $CurrentStatus = Get-ComplianceSearch $Name 11 | $Choice = $null 12 | $Choice = @("Delete $($CurrentStatus.Items) emails from: $Name", 'QUIT') | ForEach-Object { 13 | [PSCustomObject]@{ ACTION = $_ } 14 | } | Out-GridView -PassThru -Title "Compliance Search: $Name Status is $($CurrentStatus.Status). Choose to delete $($CurrentStatus.Items) emails from mailboxes or quit?" 15 | } until ($CurrentStatus.Status -eq 'Completed' -or $Choice.Action -eq 'QUIT') 16 | if ($Choice.Action -like 'Delete*') { 17 | Get-DecisionbyOGV 18 | New-ComplianceSearchAction -SearchName $Name -Purge -Confirm:$false -PurgeType $Script:HardOrSoft 19 | $Script:HardOrSoft = $null 20 | } 21 | else { 22 | Write-Host "Halting script as Quit was selected" -ForegroundColor DarkRed 23 | continue 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Posh365/Private/Connect/Connect-CloudDeleteCredential.ps1: -------------------------------------------------------------------------------- 1 | function Connect-CloudDeleteCredential { 2 | [CmdletBinding()] 3 | param 4 | ( 5 | [parameter(Mandatory)] 6 | [string] 7 | $CredFile 8 | ) 9 | end { 10 | try { 11 | Remove-Item $CredFile -force -ErrorAction Stop 12 | } 13 | catch { 14 | $_.Exception.Message 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Posh365/Private/Connect/RemoveBrokenOrClosedPSSession.ps1: -------------------------------------------------------------------------------- 1 | function global:RemoveBrokenOrClosedPSSession() { 2 | <# 3 | .SYNOPSIS Remove broken and closed sessions 4 | #> 5 | $psBroken = Get-PSSession | where-object {$_.State -like "*Broken*"} 6 | $psClosed = Get-PSSession | where-object {$_.State -like "*Closed*"} 7 | 8 | if ($psBroken.count -gt 0) { 9 | for ($index = 0; $index -lt $psBroken.count; $index++) { 10 | Remove-PSSession -session $psBroken[$index] 11 | } 12 | } 13 | 14 | if ($psClosed.count -gt 0) { 15 | for ($index = 0; $index -lt $psClosed.count; $index++) { 16 | Remove-PSSession -session $psClosed[$index] 17 | } 18 | } 19 | } -------------------------------------------------------------------------------- /Posh365/Private/Connect/Test-365ServiceConnection.ps1: -------------------------------------------------------------------------------- 1 | function Test-365ServiceConnection { 2 | [CmdletBinding()] 3 | Param 4 | ( 5 | [Parameter()] 6 | [switch] 7 | $ExchangeOnline, 8 | 9 | [Parameter()] 10 | [switch] 11 | $MSOnline, 12 | 13 | [Parameter()] 14 | [switch] 15 | $AzureAD, 16 | 17 | [Parameter()] 18 | [switch] 19 | $Compliance 20 | ) 21 | end { 22 | $EA = $ErrorActionPreference 23 | $ErrorActionPreference = 'SilentlyContinue' 24 | if ($ExchangeOnline) { 25 | $tenantEX = (Get-AcceptedDomain).where( { $_.Default }).domainname.split('.')[0] 26 | $TenantName = $tenantEX 27 | } 28 | if ($AzureAD) { 29 | $tenantAZ = ((Get-AzureADTenantDetail).verifiedDomains | Where-Object { $_.initial -eq "$true" }).name.split(".")[0] 30 | $TenantName = $tenantAZ 31 | } 32 | if ($MSOnline) { 33 | $tenantMS = (Get-MsolDomain).where( { $_.IsInitial }).name.split('.')[0] 34 | $TenantName = $tenantMS 35 | } 36 | if ($Compliance) { 37 | $tenantCO = (Get-Group | Select-Object -First 1).organizationalunit.replace('.onmicrosoft.com/Configuration', '').split('/')[2] 38 | $TenantName = $tenantCO 39 | } 40 | $TenantName 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /Posh365/Private/Connect/Test-Uri.ps1: -------------------------------------------------------------------------------- 1 | function Test-Uri { 2 | <# 3 | .SYNOPSIS 4 | Validates a given Uri 5 | #> 6 | [CmdletBinding()] 7 | [OutputType([bool])] 8 | Param 9 | ( 10 | # Uri to be validated 11 | [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true, Position = 0)] 12 | [string] 13 | $UriString 14 | ) 15 | 16 | [Uri]$uri = $UriString -as [Uri] 17 | $uri.AbsoluteUri -ne $null -and $uri.Scheme -eq 'https' 18 | } -------------------------------------------------------------------------------- /Posh365/Private/DLL/Microsoft.SharePoint.Client.Runtime.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kevinblumenfeld/Posh365/17628091caa09c90caf51d1171396d1a74beab96/Posh365/Private/DLL/Microsoft.SharePoint.Client.Runtime.dll -------------------------------------------------------------------------------- /Posh365/Private/DLL/Microsoft.SharePoint.Client.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kevinblumenfeld/Posh365/17628091caa09c90caf51d1171396d1a74beab96/Posh365/Private/DLL/Microsoft.SharePoint.Client.dll -------------------------------------------------------------------------------- /Posh365/Private/Decision/Get-DecisionbyOGV.ps1: -------------------------------------------------------------------------------- 1 | function Get-DecisionbyOGV { 2 | [CmdletBinding()] 3 | param ( ) 4 | $OGVDecision = @{ 5 | Title = 'Do You Want To Continue Or Quit?' 6 | OutputMode = 'Single' 7 | } 8 | $Decision = 'Yes, I want to continue', 'Quit' | Out-GridView @OGVDecision 9 | if ($Decision -ne 'Yes, I want to continue') { 10 | Write-Host "Halting script as Quit was selected" -ForegroundColor DarkRed 11 | continue 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /Posh365/Private/Discovery/Convert-TransportXMLtoCSV.ps1: -------------------------------------------------------------------------------- 1 | function Convert-TransportXMLtoCSV { 2 | param ( 3 | [Parameter(Mandatory)] 4 | $TRuleColList, 5 | 6 | [Parameter()] 7 | [hashtable] 8 | $TransportHash 9 | ) 10 | foreach ($TRule in $TRuleColList) { 11 | foreach ($Rule in $TRule.rules.rule) { 12 | [PSCustomObject]@{ 13 | Name = $Rule.name 14 | Priority = $TransportHash[$Rule.Name].Priority 15 | State = $TransportHash[$Rule.Name].State 16 | Description = $TransportHash[$Rule.Name].Description 17 | Command = $Rule.version.commandblock."#cdata-section" 18 | } 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Posh365/Private/Discovery/Get-MsolUserMFAHash.ps1: -------------------------------------------------------------------------------- 1 | function Get-MsolUserMFAHash { 2 | param ( 3 | [Parameter(Mandatory)] 4 | $MsolUserList 5 | ) 6 | 7 | $MFAHash = @{ } 8 | foreach ($MsolUser in $MsolUserList) { 9 | $MFAHash[$MsolUser.ObjectID] = @{ 10 | 'MFA_State' = $MsolUser.MFA_State 11 | 'UserPrincipalName' = $MsolUser.UserPrincipalName 12 | 'IsLicensed' = $MsolUser.IsLicensed 13 | 'LastDirSyncTime' = $MsolUser.LastDirSyncTime 14 | 'BlockCredential' = $MsolUser.BlockCredential 15 | 'PasswordNeverExpires' = $MsolUser.PasswordNeverExpires 16 | } 17 | } 18 | $MFAHash 19 | } 20 | -------------------------------------------------------------------------------- /Posh365/Private/Discovery/Get-TransportRuleHash.ps1: -------------------------------------------------------------------------------- 1 | function Get-TransportRuleHash { 2 | param ( 3 | [Parameter(Mandatory)] 4 | $TransportData 5 | ) 6 | 7 | $TransportHash = @{ } 8 | foreach ($Transport in $TransportData) { 9 | $TransportHash.Add($Transport.Name.ToString() , @{ 10 | 'Description' = $Transport.Description 11 | 'Priority' = $Transport.Priority 12 | 'State' = $Transport.State 13 | }) 14 | } 15 | $TransportHash 16 | } 17 | -------------------------------------------------------------------------------- /Posh365/Private/Forest/Convert-CanonicalToDistinguished.ps1: -------------------------------------------------------------------------------- 1 | function Convert-CanonicalToDistinguished { 2 | [cmdletbinding()] 3 | param( 4 | [Parameter(Mandatory = $true)] 5 | [ValidateNotNullOrEmpty()] 6 | [string] 7 | $CanonicalName 8 | ) 9 | end { 10 | $nameTranslate = New-Object -ComObject NameTranslate 11 | # $nameTranslate.Init(3, '') 12 | # To PS2: 13 | [__ComObject].InvokeMember('Init', 'InvokeMethod', $null, $nameTranslate, @(3, ''), $null, (Get-Culture), $null) 14 | # Get an identity using the canonicalName 15 | # $nameTranslate.Set(2, $canonicalName) 16 | # To PS2: 17 | [__ComObject].InvokeMember('Set', 'InvokeMethod', $null, $nameTranslate, @(2, $canonicalName), $null, (Get-Culture), $null) 18 | # Convert the identity to a DistinguishedName 19 | # $nameTranslate.Get(1) 20 | # To PS2: 21 | [__ComObject].InvokeMember('Get', 'InvokeMethod', $null, $nameTranslate, @(1), $null, (Get-Culture), $null) 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Posh365/Private/Forest/Convert-DistinguishedToCanonical.ps1: -------------------------------------------------------------------------------- 1 | function Convert-DistinguishedToCanonical { 2 | Param ( 3 | [Parameter(Mandatory, ValueFromPipeline)] 4 | [string[]] 5 | $DistinguishedName 6 | ) 7 | process { 8 | foreach ($dn in $DistinguishedName) { 9 | $d = $dn.Split(',') 10 | $arr = (@(($d | Where-Object { $_ -notmatch 'DC=' }) | ForEach-Object { $_.Substring(3) })) 11 | [array]::Reverse($arr) 12 | "{0}/{1}" -f (($d | Where-Object { $_ -match 'dc=' } | ForEach-Object { $_.Replace('DC=', '') }) -join '.'), ($arr -join '/') 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Posh365/Private/Forest/ConvertTo-NetBios.ps1: -------------------------------------------------------------------------------- 1 | Function ConvertTo-NetBios { 2 | 3 | Param( 4 | $domainName 5 | ) 6 | 7 | $root = [adsi] "LDAP://$domainname/RootDSE" 8 | $configContext = $root.Properties["configurationNamingContext"][0] 9 | $searchr = [adsi] "LDAP://cn=Partitions,$configContext" 10 | 11 | $search = new-object System.DirectoryServices.DirectorySearcher 12 | $search.SearchRoot = $searchr 13 | $search.SearchScope = [System.DirectoryServices.SearchScope] "OneLevel" 14 | $search.filter = "(&(objectcategory=Crossref)(dnsRoot=$domainName)(netBIOSName=*))" 15 | 16 | $result = $search.Findone() 17 | 18 | if ($result) { 19 | 20 | $result.Properties["netbiosname"] 21 | } 22 | 23 | } -------------------------------------------------------------------------------- /Posh365/Private/Forest/Get-DomainNameHash.ps1: -------------------------------------------------------------------------------- 1 | Function Get-DomainNameHash { 2 | 3 | param ( 4 | 5 | ) 6 | end { 7 | $DomainNameHash = @{ } 8 | 9 | $DomainList = ([System.DirectoryServices.ActiveDirectory.Forest]::GetCurrentForest().domains) | Select -ExpandProperty Name 10 | foreach ($Domain in $DomainList) { 11 | $DomainNameHash[$Domain] = (ConvertTo-NetBios -domain $Domain) 12 | } 13 | $DomainNameHash 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Posh365/Private/GitHub/Get-GitHubGistID.ps1: -------------------------------------------------------------------------------- 1 | function Get-GitHubGistID { 2 | [CmdletBinding()] 3 | param ( 4 | [Parameter(Mandatory)] 5 | [string] 6 | $Username, 7 | 8 | [Parameter(Mandatory)] 9 | [string] 10 | $FileName 11 | ) 12 | 13 | $Params = @{ 14 | Uri = 'https://api.github.com/users/{0}/gists' -f $Username 15 | method = 'Get' 16 | } 17 | $GistList = Invoke-RestMethod @Params 18 | foreach ($Gist in $GistList) { 19 | if ($Gist.files.${FileName}) { 20 | $Gist.ID 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Posh365/Private/Graph/Get-GraphGroupData.ps1: -------------------------------------------------------------------------------- 1 | function Get-GraphGroupData { 2 | [CmdletBinding(DefaultParameterSetName = 'PlaceHolder')] 3 | param ( 4 | [Parameter(ParameterSetName = 'GroupID')] 5 | $GroupId, 6 | 7 | [Parameter(ParameterSetName = 'Name')] 8 | $Name 9 | ) 10 | 11 | if ([datetime]::UtcNow -ge $TimeToRefresh) { Connect-PoshGraphRefresh } 12 | switch ($PSCmdlet.ParameterSetName) { 13 | 'Name' { 14 | $RestSplat = @{ 15 | Uri = "https://graph.microsoft.com/beta/groups/?`$filter=displayName eq '$Name'" 16 | Headers = @{ "Authorization" = "Bearer $Token" } 17 | Method = 'Get' 18 | } 19 | } 20 | 'GroupID' { 21 | $RestSplat = @{ 22 | Uri = 'https://graph.microsoft.com/beta/groups/{0}' -f $GroupId 23 | Headers = @{ "Authorization" = "Bearer $Token" } 24 | Method = 'Get' 25 | } 26 | } 27 | default { 28 | $RestSplat = @{ 29 | Uri = 'https://graph.microsoft.com/beta/groups/' 30 | Headers = @{ "Authorization" = "Bearer $Token" } 31 | Method = 'Get' 32 | } 33 | } 34 | } 35 | Invoke-RestMethod @RestSplat -Verbose:$false 36 | } 37 | -------------------------------------------------------------------------------- /Posh365/Private/Hash/Get-DistributionGroupMembersHash.ps1: -------------------------------------------------------------------------------- 1 | function Get-DistributionGroupMembersHash { 2 | <# 3 | .SYNOPSIS 4 | Creates a hash table from data returned from Get-DistributionGroupMembership 5 | 6 | .DESCRIPTION 7 | Creates a hash table from data returned from Get-DistributionGroupMembership 8 | 9 | .PARAMETER Recurse 10 | Reveals nested group membership 11 | 12 | .EXAMPLE 13 | "group01@contoso.com" | Get-DistributionGroupMembersHash -Recurse -Verbose 14 | 15 | .EXAMPLE 16 | Get-DistributionGroup -resultsize unlimited | Get-DistributionGroupMembersHash -Recurse -Verbose 17 | 18 | #> 19 | [CmdletBinding()] 20 | param( 21 | [Parameter(Mandatory = $true, ValueFromPipeline = $True, ValueFromPipelineByPropertyName = $True)] 22 | [string[]]$Identity, 23 | 24 | [Parameter()] 25 | [switch]$Recurse 26 | ) 27 | begin { 28 | $GroupHash = @{} 29 | } 30 | process { 31 | foreach ($CurIdentity in $Identity) { 32 | Write-Verbose "Looking up memberships for '$CurIdentity'." 33 | if ($Recurse) { 34 | $GroupHash[$CurIdentity] = $CurIdentity | Get-DistributionGroupMembers -Recurse 35 | } 36 | else { 37 | $GroupHash[$CurIdentity] = $CurIdentity | Get-DistributionGroupMembers 38 | } 39 | } 40 | } 41 | end { 42 | $GroupHash 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /Posh365/Private/Hash/Get-LegacyDNHash.ps1: -------------------------------------------------------------------------------- 1 | Function Get-LegacyDNHash { 2 | param ( 3 | [Parameter(Mandatory)] 4 | $ADUserList 5 | ) 6 | end { 7 | $LegacyDNHash = @{ } 8 | $ADUserList = $ADUserList.where( { $_.LegacyExchangeDN }) 9 | foreach ($ADUser in $ADUserList) { 10 | $LegacyDNHash[$ADUser.LegacyExchangeDN] = @{ 11 | DisplayName = $ADUser.DisplayName 12 | UserPrincipalName = $ADUser.UserPrincipalName 13 | } 14 | } 15 | $LegacyDNHash 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Posh365/Private/Hash/Get-RecipientCNHash.ps1: -------------------------------------------------------------------------------- 1 | function Get-RecipientCNHash { 2 | [CmdletBinding()] 3 | 4 | param ( ) 5 | 6 | $RecipientHash = @{ } 7 | 8 | $RecipientList = Get-Recipient -ResultSize Unlimited 9 | 10 | foreach ($Recipient in $RecipientList) { 11 | 12 | $RecipientHash[$Recipient.Identity] = $Recipient.samAccountName 13 | } 14 | 15 | $RecipientHash 16 | 17 | } 18 | -------------------------------------------------------------------------------- /Posh365/Private/Intune/Apps/Get-MemMobileAppConfigData.ps1: -------------------------------------------------------------------------------- 1 | function Get-MemMobileAppConfigData { 2 | [CmdletBinding()] 3 | param ( 4 | 5 | ) 6 | if ([datetime]::UtcNow -ge $TimeToRefresh) { Connect-PoshGraphRefresh } 7 | $RestSplat = @{ 8 | Uri = 'https://graph.microsoft.com/beta/deviceAppManagement/mobileAppConfigurations?$expand=assignments' 9 | Headers = @{ "Authorization" = "Bearer $Token" } 10 | Method = 'Get' 11 | } 12 | Invoke-RestMethod @RestSplat -Verbose:$false | Select-Object -ExpandProperty Value 13 | 14 | } 15 | -------------------------------------------------------------------------------- /Posh365/Private/Intune/Apps/Get-MemMobileAppConfigTargetedData.ps1: -------------------------------------------------------------------------------- 1 | function Get-MemMobileAppConfigTargetedData { 2 | [CmdletBinding()] 3 | param ( 4 | 5 | ) 6 | if ([datetime]::UtcNow -ge $TimeToRefresh) { Connect-PoshGraphRefresh } 7 | $RestSplat = @{ 8 | Uri = 'https://graph.microsoft.com/beta/deviceAppManagement/targetedManagedAppConfigurations?$expand=assignments,apps' 9 | Headers = @{ "Authorization" = "Bearer $Token" } 10 | Method = 'Get' 11 | } 12 | Invoke-RestMethod @RestSplat -Verbose:$false | Select-Object -ExpandProperty Value 13 | 14 | } 15 | -------------------------------------------------------------------------------- /Posh365/Private/Intune/Apps/Get-MemMobileAppData.ps1: -------------------------------------------------------------------------------- 1 | function Get-MemMobileAppData { 2 | [CmdletBinding()] 3 | param ( 4 | [Parameter] 5 | $AppId, 6 | 7 | [Parameter(ParameterSetName = 'Name')] 8 | $Name 9 | ) 10 | if ([datetime]::UtcNow -ge $TimeToRefresh) { Connect-PoshGraphRefresh } 11 | switch ($PSCmdlet.ParameterSetName) { 12 | 'Name' { 13 | # $Uri = "https://graph.microsoft.com/beta/deviceAppManagement/mobileApps/?`$filter=(isof('microsoft.graph.managedIOSStoreApp') and microsoft.graph.managedApp/appAvailability eq microsoft.graph.managedAppAvailability'lineOfBusiness') or isof('microsoft.graph.iosLobApp') or isof('microsoft.graph.iosStoreApp') or isof('microsoft.graph.iosVppApp') or isof('microsoft.graph.managedIOSLobApp') or (isof('microsoft.graph.managedIOSStoreApp'))&`$search=$Name" 14 | $Uri = "https://graph.microsoft.com/beta/deviceAppManagement/mobileApps/?`$filter=displayName eq '$Name'" 15 | } 16 | default { 17 | $Uri = 'https://graph.microsoft.com/beta/deviceAppManagement/mobileApps/{0}?$expand=assignments' -f $AppId 18 | } 19 | } 20 | 21 | $RestSplat = @{ 22 | Uri = $Uri 23 | Headers = @{ "Authorization" = "Bearer $Token" } 24 | Method = 'Get' 25 | } 26 | Invoke-RestMethod @RestSplat -Verbose:$false #| Select-Object -ExpandProperty Value 27 | } 28 | -------------------------------------------------------------------------------- /Posh365/Private/Intune/Apps/Get-MemMobileAppProtectionAndroidData.ps1: -------------------------------------------------------------------------------- 1 | function Get-MemMobileAppProtectionAndroidData { 2 | [CmdletBinding()] 3 | param ( 4 | 5 | ) 6 | if ([datetime]::UtcNow -ge $TimeToRefresh) { Connect-PoshGraphRefresh } 7 | $RestSplat = @{ 8 | Uri = "https://graph.microsoft.com/beta/deviceAppManagement/androidManagedAppProtections?`$expand=deploymentSummary,apps,assignments" 9 | Headers = @{ "Authorization" = "Bearer $Token" } 10 | Method = 'Get' 11 | } 12 | Invoke-RestMethod @RestSplat -Verbose:$false | Select-Object -ExpandProperty Value 13 | 14 | } 15 | -------------------------------------------------------------------------------- /Posh365/Private/Intune/Apps/Get-MemMobileAppProtectioniOSData.ps1: -------------------------------------------------------------------------------- 1 | function Get-MemMobileAppProtectioniOSData { 2 | [CmdletBinding()] 3 | param ( 4 | 5 | ) 6 | if ([datetime]::UtcNow -ge $TimeToRefresh) { Connect-PoshGraphRefresh } 7 | $RestSplat = @{ 8 | Uri = "https://graph.microsoft.com/beta/deviceAppManagement/iosManagedAppProtections?`$expand=deploymentSummary,apps,assignments" 9 | Headers = @{ "Authorization" = "Bearer $Token" } 10 | Method = 'Get' 11 | } 12 | Invoke-RestMethod @RestSplat -Verbose:$false | Select-Object -ExpandProperty Value 13 | 14 | } 15 | -------------------------------------------------------------------------------- /Posh365/Private/Intune/Devices/Get-MemDeviceData.ps1: -------------------------------------------------------------------------------- 1 | function Get-MemDeviceData { 2 | [CmdletBinding(DefaultParameterSetName = 'PlaceHolder')] 3 | param ( 4 | [Parameter(Mandatory, ParameterSetName = 'SerialNumber')] 5 | $SerialNumber, 6 | 7 | [Parameter(Mandatory, ParameterSetName = 'imei')] 8 | $imei, 9 | 10 | [Parameter(Mandatory, ParameterSetName = 'ManagementState')] 11 | [ValidateSet('retirePending', 'managed')] 12 | $managementState 13 | ) 14 | if ([datetime]::UtcNow -ge $TimeToRefresh) { Connect-PoshGraphRefresh } 15 | 16 | if ($imei) { 17 | $filter = "?`$filter=imei eq '$imei'" 18 | } 19 | elseif ($SerialNumber) { 20 | $filter = "?`$filter=serialNumber eq '$SerialNumber'" 21 | } 22 | elseif ($managementState) { 23 | $filter = "?`$filter=managementState eq '$ManagementState'" 24 | } 25 | $RestSplat = @{ 26 | Uri = "https://graph.microsoft.com/beta/deviceManagement/managedDevices/{0}" -f $filter 27 | Headers = @{ "Authorization" = "Bearer $Token" } 28 | Method = 'Get' 29 | } 30 | Invoke-RestMethod @RestSplat -Verbose:$false | Select-Object -ExpandProperty Value 31 | 32 | } 33 | -------------------------------------------------------------------------------- /Posh365/Private/Intune/Devices/Get-MemDeviceWindowsUpdateData.ps1: -------------------------------------------------------------------------------- 1 | function Get-MemMobileDeviceConfigData { 2 | [CmdletBinding()] 3 | param ( 4 | 5 | ) 6 | if ([datetime]::UtcNow -ge $TimeToRefresh) { Connect-PoshGraphRefresh } 7 | $RestSplat = @{ 8 | Uri = "https://graph.microsoft.com/beta/deviceManagement/deviceConfigurations?`$filter=isof('microsoft.graph.windowsUpdateForBusinessConfiguration')&`$expand=assignments" 9 | Headers = @{ "Authorization" = "Bearer $Token" } 10 | Method = 'Get' 11 | } 12 | Invoke-RestMethod @RestSplat -Verbose:$false | Select-Object -ExpandProperty value 13 | 14 | } 15 | -------------------------------------------------------------------------------- /Posh365/Private/Intune/Devices/Get-MemMobileDeviceComplianceAndroidWorkData.ps1: -------------------------------------------------------------------------------- 1 | function Get-MemMobileDeviceComplianceAndroidWorkData { 2 | [CmdletBinding()] 3 | param ( 4 | 5 | ) 6 | if ([datetime]::UtcNow -ge $TimeToRefresh) { Connect-PoshGraphRefresh } 7 | $RestSplat = @{ 8 | Uri = "https://graph.microsoft.com/beta/deviceManagement/deviceCompliancePolicies?`$filter=isof('microsoft.graph.androidWorkProfileCompliancePolicy')&`$expand=assignments,scheduledActionsForRule(`$expand=scheduledActionConfigurations)" 9 | Headers = @{ "Authorization" = "Bearer $Token" } 10 | Method = 'Get' 11 | } 12 | Invoke-RestMethod @RestSplat -Verbose:$false | Select-Object -ExpandProperty value 13 | 14 | } 15 | -------------------------------------------------------------------------------- /Posh365/Private/Intune/Devices/Get-MemMobileDeviceComplianceiOSData.ps1: -------------------------------------------------------------------------------- 1 | function Get-MemMobileDeviceComplianceiOSData { 2 | [CmdletBinding()] 3 | param ( 4 | 5 | ) 6 | if ([datetime]::UtcNow -ge $TimeToRefresh) { Connect-PoshGraphRefresh } 7 | $RestSplat = @{ 8 | Uri = "https://graph.microsoft.com/beta/deviceManagement/deviceCompliancePolicies?`$filter=isof('microsoft.graph.iosCompliancePolicy')&`$expand=assignments,scheduledActionsForRule(`$expand=scheduledActionConfigurations)" 9 | Headers = @{ "Authorization" = "Bearer $Token" } 10 | Method = 'Get' 11 | } 12 | Invoke-RestMethod @RestSplat -Verbose:$false | Select-Object -ExpandProperty value 13 | 14 | } 15 | -------------------------------------------------------------------------------- /Posh365/Private/Intune/Devices/Get-MemMobileDeviceConfigiOSDeviceRestrictionsData.ps1: -------------------------------------------------------------------------------- 1 | function Get-MemMobileDeviceConfigiOSDeviceRestrictionsData { 2 | [CmdletBinding()] 3 | param ( 4 | 5 | ) 6 | if ([datetime]::UtcNow -ge $TimeToRefresh) { Connect-PoshGraphRefresh } 7 | $RestSplat = @{ 8 | Uri = "https://graph.microsoft.com/beta/deviceManagement/deviceConfigurations?`$filter=isof('microsoft.graph.iosGeneralDeviceConfiguration')&`$expand=assignments" 9 | Headers = @{ "Authorization" = "Bearer $Token" } 10 | Method = 'Get' 11 | } 12 | Invoke-RestMethod @RestSplat -Verbose:$false | Select-Object -ExpandProperty value 13 | 14 | } 15 | -------------------------------------------------------------------------------- /Posh365/Private/Intune/Devices/Get-MemMobileDeviceConfigiOSEmailData.ps1: -------------------------------------------------------------------------------- 1 | function Get-MemMobileDeviceConfigiOSEmailData { 2 | [CmdletBinding()] 3 | param ( 4 | 5 | ) 6 | if ([datetime]::UtcNow -ge $TimeToRefresh) { Connect-PoshGraphRefresh } 7 | $RestSplat = @{ 8 | Uri = "https://graph.microsoft.com/beta/deviceManagement/deviceConfigurations?`$filter=isof('microsoft.graph.iosEasEmailProfileConfiguration')&`$expand=assignments" 9 | Headers = @{ "Authorization" = "Bearer $Token" } 10 | Method = 'Get' 11 | } 12 | Invoke-RestMethod @RestSplat -Verbose:$false | Select-Object -ExpandProperty value 13 | 14 | } 15 | -------------------------------------------------------------------------------- /Posh365/Private/Intune/Devices/Get-MemMobileDeviceConfigiOSWiFiData.ps1: -------------------------------------------------------------------------------- 1 | function Get-MemMobileDeviceConfigiOSWiFiData { 2 | [CmdletBinding()] 3 | param ( 4 | 5 | ) 6 | if ([datetime]::UtcNow -ge $TimeToRefresh) { Connect-PoshGraphRefresh } 7 | $RestSplat = @{ 8 | Uri = "https://graph.microsoft.com/beta/deviceManagement/deviceConfigurations?`$filter=isof('microsoft.graph.iosWiFiConfiguration')&`$expand=assignments" 9 | Headers = @{ "Authorization" = "Bearer $Token" } 10 | Method = 'Get' 11 | } 12 | Invoke-RestMethod @RestSplat -Verbose:$false | Select-Object -ExpandProperty value 13 | 14 | } 15 | -------------------------------------------------------------------------------- /Posh365/Private/Intune/Devices/Get-MemMobileDeviceListData.ps1: -------------------------------------------------------------------------------- 1 | function Get-MemMobileDeviceListData { 2 | [CmdletBinding()] 3 | param ( 4 | 5 | ) 6 | if ([datetime]::UtcNow -ge $TimeToRefresh) { Connect-PoshGraphRefresh } 7 | $RestSplat = @{ 8 | Uri = "https://graph.microsoft.com/beta/deviceManagement/managedDevices" 9 | Headers = @{ "Authorization" = "Bearer $Token" } 10 | Method = 'Get' 11 | } 12 | do { 13 | if ([datetime]::UtcNow -ge $TimeToRefresh) { Connect-PoshGraphRefresh } 14 | $Response = Invoke-RestMethod @RestSplat -Verbose:$false 15 | $Response.value 16 | if ($Response.'@odata.nextLink' -match 'skip') { $Next = $Response.'@odata.nextLink' } 17 | else { $Next = $null } 18 | $RestSplat = @{ 19 | Uri = $Next 20 | Headers = @{ "Authorization" = "Bearer $Token" } 21 | Method = 'Get' 22 | } 23 | } until (-not $next) 24 | } 25 | -------------------------------------------------------------------------------- /Posh365/Private/Intune/Get-IntunePolicyHash.ps1: -------------------------------------------------------------------------------- 1 | function Get-IntunePolicyHash { 2 | [CmdletBinding()] 3 | param ( 4 | [Parameter(Mandatory)] 5 | $Policy 6 | ) 7 | 8 | $PropertyHash = @{ } 9 | 10 | foreach ($Item in $Policy.psobject.properties) { 11 | $PropertyHash[$Item.Name] = $Item.value 12 | 13 | } 14 | 15 | $PropertyHash 16 | } -------------------------------------------------------------------------------- /Posh365/Private/License/Get-UniqueString.ps1: -------------------------------------------------------------------------------- 1 | Function Get-UniqueString { 2 | param( 3 | [Parameter(Mandatory = $true)] 4 | $searchStrings 5 | ) 6 | 7 | $suffixes = " .* 8 | _E3 9 | _E5 10 | _P1 11 | _P2 12 | _P3 13 | _1 14 | _2 15 | 2 16 | _GOV 17 | _MIDMARKET 18 | _STUDENT 19 | _FACULTY 20 | _A 21 | _O365" -split "`r`n" 22 | $sthash = @{} 23 | $uniques = @() 24 | foreach ($searchString in $searchStrings) { 25 | $ss = $searchString 26 | foreach ($suffix in $suffixes) { 27 | $searchString = $searchString -replace "$suffix$", "REPLACED" 28 | } 29 | $uniques += $searchString -replace "REPLACED" 30 | if (!($sthash.ContainsKey($uniques[(($uniques.count) - 1)]))) { 31 | $sthash.($uniques[(($uniques.count) - 1)]) = $ss 32 | } 33 | } 34 | # $uniques | Select -Unique 35 | $sthash 36 | } 37 | -------------------------------------------------------------------------------- /Posh365/Private/Migration/BitTitan/Get-BTDeviceHash.ps1: -------------------------------------------------------------------------------- 1 | function Get-BTDeviceHash { 2 | [CmdletBinding()] 3 | Param 4 | ( 5 | 6 | ) 7 | end { 8 | $Script:DeviceHash = @{ } 9 | $DeviceSplat = @{ 10 | Ticket = $BitTic 11 | Environment = 'BT' 12 | RetrieveAll = $true 13 | IsDeleted = $false 14 | } 15 | foreach ($Device in Get-BT_CustomerDevice @DeviceSplat ) { 16 | if (-not $DeviceHash.ContainsKey($Device.Id.ToString())) { 17 | $DeviceHash.Add($Device.Id.ToString(), @{ 18 | DeviceName = $Device.DeviceName 19 | OSName = $Device.OSName 20 | Manufacturer = $Device.Manufacturer 21 | Model = $Device.Model 22 | DiskSpaceTotal = [math]::Round([Double]$Device.DiskSpaceTotal / 1GB, 0) 23 | DiskSpaceFree = [math]::Round([Double]$Device.DiskSpaceFree / 1GB, 0) 24 | DomainJoinStatus = $Device.DomainJoinStatus 25 | } 26 | ) 27 | } 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Posh365/Private/Migration/BitTitan/Get-BTTicket.ps1: -------------------------------------------------------------------------------- 1 | function Get-BTTicket { 2 | [CmdletBinding()] 3 | Param 4 | ( 5 | [Parameter()] 6 | $CredFile, 7 | 8 | [Parameter()] 9 | $OrganizationId 10 | ) 11 | end { 12 | switch ($true) { 13 | { $OrganizationId } { 14 | $Script:BitTic = Get-BT_Ticket -Ticket $BitTic -OrganizationId $OrganizationId -SetDefault 15 | } 16 | Default { 17 | [System.Management.Automation.PSCredential]$Credential = Import-Clixml -Path $CredFile 18 | $Script:BitTic = Get-BT_Ticket -Credentials $Credential -ServiceType BitTitan -SetDefault 19 | } 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Posh365/Private/Migration/BitTitan/Get-BTUserHash.ps1: -------------------------------------------------------------------------------- 1 | function Get-BTUserHash { 2 | [CmdletBinding()] 3 | Param 4 | ( 5 | 6 | ) 7 | end { 8 | $Script:UserHash = @{ } 9 | foreach ($User in Get-BT_CustomerEndUser -Ticket $BitTic -IsDeleted:$false -RetrieveAll:$true) { 10 | if (-not $UserHash.ContainsKey($User.Id.ToString())) { 11 | $UserHash.Add($User.Id.ToString(), @{ 12 | DisplayName = $User.DisplayName 13 | FirstName = $User.FirstName 14 | LastName = $User.LastName 15 | PrimaryEmailAddress = $User.PrimaryEmailAddress 16 | AgentSendStatus = $User.AgentSendStatus 17 | } 18 | ) 19 | } 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Posh365/Private/Migration/BitTitan/Get-MWMailboxConnector.ps1: -------------------------------------------------------------------------------- 1 | function Get-MWMailboxConnector { 2 | [CmdletBinding()] 3 | Param 4 | ( 5 | 6 | ) 7 | end { 8 | Get-MW_MailboxConnector -Ticket $MigWizTicket -RetrieveAll:$true 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /Posh365/Private/Migration/BitTitan/Get-MWTicket.ps1: -------------------------------------------------------------------------------- 1 | function Get-MWTicket { 2 | [CmdletBinding()] 3 | Param 4 | ( 5 | [Parameter()] 6 | $CredFile 7 | ) 8 | end { 9 | [System.Management.Automation.PSCredential]$Credential = Import-Clixml -Path $CredFile 10 | $Script:MigWizTicket = Get-MW_Ticket -Credentials $Credential -SetDefault 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Posh365/Private/Migration/BitTitan/Invoke-EnterBTCustomer.ps1: -------------------------------------------------------------------------------- 1 | function Invoke-EnterBTCustomer { 2 | [CmdletBinding()] 3 | Param 4 | ( 5 | 6 | ) 7 | end { 8 | Get-BT_Customer -RetrieveAll:$true -IsArchived:$False -SortBy_Updated_Descending 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /Posh365/Private/Migration/BitTitan/Invoke-GetBTUser.ps1: -------------------------------------------------------------------------------- 1 | function Invoke-GetBTUser { 2 | [CmdletBinding()] 3 | Param 4 | ( 5 | 6 | ) 7 | end { 8 | Get-BT_CustomerEndUser -Ticket $BitTic -IsDeleted:$false -RetrieveAll:$true 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /Posh365/Private/Migration/BitTitan/Invoke-GetBTUserTrimmed.ps1: -------------------------------------------------------------------------------- 1 | function Invoke-GetBTUserTrimmed { 2 | [CmdletBinding()] 3 | Param 4 | ( 5 | 6 | ) 7 | end { 8 | $Now = [DateTime]::Now 9 | Invoke-GetBTUser | Select-Object @( 10 | 'AgentSendStatus' 11 | 'DisplayName' 12 | 'PrimaryEmailAddress' 13 | 'UserPrincipalName' 14 | @{ 15 | Name = 'SinceCreated' 16 | Expression = { '{0:dd}d {0:hh}h {0:mm}m' -f $Now.subtract(($_.Created).ToLocalTime()) } 17 | } 18 | @{ 19 | Name = 'SinceUpdated' 20 | Expression = { '{0:dd}d {0:hh}h {0:mm}m' -f $Now.subtract(($_.Updated).ToLocalTime()) } 21 | } 22 | 'FirstName' 23 | 'LastName' 24 | 'Id' 25 | ) 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Posh365/Private/Migration/BitTitan/Invoke-GetMWMailboxMove.ps1: -------------------------------------------------------------------------------- 1 | function Invoke-GetMWMailboxMove { 2 | [CmdletBinding()] 3 | Param 4 | ( 5 | 6 | ) 7 | end { 8 | Get-MW_Mailbox -Ticket $MigWizTicket -ConnectorId $MWProject.Id -RetrieveAll:$true 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /Posh365/Private/Migration/BitTitan/Invoke-GetMWMailboxMovePasses.ps1: -------------------------------------------------------------------------------- 1 | function Invoke-GetMWMailboxMovePasses { 2 | [CmdletBinding()] 3 | Param 4 | ( 5 | [Parameter(ValueFromPipeline)] 6 | $MailboxList 7 | ) 8 | process { 9 | foreach ($Mailbox in $MailboxList) { 10 | Get-MW_MailboxMigration -MailboxId $Mailbox.Id -RetrieveAll | Select-Object @( 11 | @{ 12 | Name = 'Source' 13 | Expression = { $Mailbox.Source } 14 | } 15 | @{ 16 | Name = 'Target' 17 | Expression = { $Mailbox.Target } 18 | } 19 | 'Type' 20 | 'Status' 21 | @{ 22 | Name = 'FolderFilter' 23 | Expression = { $Mailbox.FolderFilter } 24 | } 25 | @{ 26 | Name = 'NumberOfDays' 27 | Expression = { if ($_.Type -ne 'Verification') { (New-TimeSpan -Start $_.ItemEndDate -End (Get-Date)).Days } } 28 | } 29 | 'ItemTypes' 30 | 'StartDate' 31 | 'CompleteDate' 32 | 'FailureMessage' 33 | ) 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /Posh365/Private/Migration/CloudData/Get-ADEmailAddressPolicyHash.ps1: -------------------------------------------------------------------------------- 1 | function Get-ADEmailAddressPolicyHash { 2 | [CmdletBinding()] 3 | param ( 4 | [Parameter(Mandatory)] 5 | [string] 6 | $DomainController 7 | ) 8 | if (-not (Get-Module -Name 'ActiveDirectory' -ListAvailable)) { 9 | Write-Host "ActiveDirectory Module not present. Halting." -ForegroundColor Red 10 | continue 11 | } 12 | $BadEAPHash = @{ } 13 | $ADUserList = Get-ADUser -server $DomainController -Filter * -Properties msExchPoliciesIncluded, msExchPoliciesExcluded, DisplayName 14 | foreach ($ADUser in $ADUserList) { 15 | if ($ADUser.msExchPoliciesIncluded -or 16 | $ADUser.msExchPoliciesExcluded.Count -ne 1 -or 17 | $ADUser.msExchPoliciesExcluded -ne '{26491CFC-9E50-4857-861B-0CB8DF22B5D7}') { 18 | $BadEAPHash[$ADUser.ObjectGUID.ToString()] = @{ 19 | msExchPoliciesIncluded = $ADUser.msExchPoliciesIncluded 20 | msExchPoliciesExcluded = $ADUser.msExchPoliciesExcluded 21 | DisplayName = $ADUser.DisplayName 22 | UserPrincipalName = $ADUser.UserPrincipalName 23 | } 24 | } 25 | } 26 | $BadEAPHash 27 | } 28 | -------------------------------------------------------------------------------- /Posh365/Private/Migration/CloudData/Get-CloudMailboxHash.ps1: -------------------------------------------------------------------------------- 1 | function Get-CloudMailboxHash { 2 | [CmdletBinding()] 3 | param ( 4 | ) 5 | 6 | 7 | $CloudSelect = @( 8 | 'UserPrincipalName', 'Identity', 'DisplayName' 9 | 'Name', 'SamAccountName', 'WindowsEmailAddress' 10 | 'PrimarySmtpAddress', 'ExchangeGuid', 'ArchiveGuid' 11 | ) 12 | 13 | $CloudList = Get-Mailbox -ResultSize Unlimited | Select-Object $CloudSelect 14 | 15 | $CloudHash = @{ } 16 | foreach ($Cloud in $CloudList) { 17 | $CloudHash[$Cloud.UserPrincipalName] = @{ 18 | 'Identity' = $Cloud.Identity 19 | 'DisplayName' = $Cloud.DisplayName 20 | 'Name' = $Cloud.Name 21 | 'SamAccountName' = $Cloud.SamAccountName 22 | 'WindowsEmailAddress' = $Cloud.WindowsEmailAddress 23 | 'PrimarySmtpAddress' = $Cloud.PrimarySmtpAddress 24 | 'ExchangeGuid' = ($Cloud.ExchangeGuid).ToString() 25 | 'ArchiveGuid' = ($Cloud.ArchiveGuid).ToString() 26 | } 27 | } 28 | $CloudHash 29 | } -------------------------------------------------------------------------------- /Posh365/Private/Migration/CloudData/Get-DupesLocal.ps1: -------------------------------------------------------------------------------- 1 | function Get-DupesLocal { 2 | param ( 3 | 4 | [Parameter()] 5 | $Prefix, 6 | 7 | [Parameter()] 8 | $Address, 9 | 10 | [Parameter()] 11 | $Hash, 12 | 13 | [Parameter()] 14 | $Recipient 15 | ) 16 | Write-Host "Prefix Overlap: $($Recipient.PrimarySmtpAddress)" -ForegroundColor Red 17 | [PSCustomObject]@{ 18 | Prefix = $Prefix 19 | Address = $Address 20 | Type = $Hash[$Prefix]['RecipientTypeDetails'] 21 | DisplayName = $Hash[$Prefix]['DisplayName'] 22 | PrimarySmtpAddress = $Hash[$Prefix]['PrimarySmtpAddress'] 23 | EmailAddresses = @($Hash[$Prefix]['EmailAddresses']) -match [regex]::Escape(":$Prefix@") -join '|' 24 | DupePrefix = $Prefix 25 | DupeType = $Recipient.RecipientTypeDetails 26 | DupeDisplayName = $Recipient.DisplayName 27 | DupePrimarySmtpAddress = $Recipient.PrimarySmtpAddress 28 | DupeEmailAddresses = @($Recipient.EmailAddresses) -match [regex]::Escape(":$Prefix@") -join '|' 29 | } 30 | } -------------------------------------------------------------------------------- /Posh365/Private/Migration/CloudData/Invoke-AddX500FromContact.ps1: -------------------------------------------------------------------------------- 1 | function Invoke-AddX500FromContact { 2 | [CmdletBinding()] 3 | param ( 4 | 5 | [Parameter(Mandatory)] 6 | $MatchingPrimary 7 | ) 8 | $AllFound = $MatchingPrimary.where{ $_.Found -eq 'TRUE' } | Sort-Object TargetDisplayName 9 | $Count = @($AllFound).Count 10 | $i = 0 11 | foreach ($Item in $AllFound) { 12 | $i++ 13 | [PSCustomObject]@{ 14 | Num = '[{0} of {1}]' -f $i, $Count 15 | TargetDisplayName = $Item.TargetDisplayName 16 | SourceDisplayName = $Item.SourceDisplayName 17 | TargetType = $Item.TargetType 18 | PrimarySmtpAddress = $Item.PrimarySmtpAddress 19 | LegacyExchangeDN = $Item.LegacyExchangeDN 20 | X500 = $Item.X500 21 | TargetGUID = $Item.TargetGUID 22 | TargetIdentity = $Item.TargetIdentity 23 | SourceName = $Item.SourceName 24 | SourceEmailAddresses = $Item.SourceEmailAddresses 25 | TargetEmailAddresses = $Item.TargetEmailAddresses 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /Posh365/Private/Migration/CloudData/Select-SetmsExchVersion.ps1: -------------------------------------------------------------------------------- 1 | function Select-SetmsExchVersion { 2 | [CmdletBinding()] 3 | param ( 4 | [Parameter()] 5 | $RemoteMailboxList, 6 | 7 | [Parameter()] 8 | $UserHash 9 | ) 10 | $Count = @($RemoteMailboxList).Count 11 | $i = 0 12 | foreach ($RemoteMailbox in $RemoteMailboxList) { 13 | $i++ 14 | [PSCustomObject]@{ 15 | Num = '[{0} of {1}]' -f $i, $Count 16 | msExchVersion = if ($Ver = $UserHash[$RemoteMailbox.Guid.ToString()].msExchVersion) { $Ver.ToString() } else { $null } 17 | DisplayName = $RemoteMailbox.DisplayName 18 | EmailAddressPolicyEnabled = $RemoteMailbox.EmailAddressPolicyEnabled 19 | OrganizationalUnit = $RemoteMailbox.OnPremisesOrganizationalUnit 20 | Alias = $RemoteMailbox.Alias 21 | PrimarySmtpAddress = $RemoteMailbox.PrimarySmtpAddress 22 | EmailCount = $RemoteMailbox.EmailAddresses.Count 23 | EmailAddresses = @($RemoteMailbox.EmailAddresses) -match 'smtp:' -join '|' 24 | EmailAddressesNotSmtp = @($RemoteMailbox.EmailAddresses) -notmatch 'smtp:' -join '|' 25 | Guid = $RemoteMailbox.Guid.ToString() 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Posh365/Private/Migration/Decision/Get-ContinueDecision.ps1: -------------------------------------------------------------------------------- 1 | function Get-ContinueDecision { 2 | [CmdletBinding()] 3 | param ( 4 | 5 | ) 6 | end { 7 | $OGVDecision = @{ 8 | Title = 'Do You Want To Continue Or Quit?' 9 | OutputMode = 'Single' 10 | } 11 | $Decision = 'Yes, I want to continue', 'Quit' | Out-GridView @OGVDecision 12 | if ($Decision -eq 'Yes, I want to continue') { 13 | $UserChoice = $true 14 | } 15 | else { 16 | $UserChoice = $false 17 | } 18 | $UserChoice 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Posh365/Private/Migration/Decision/Get-LicenseDecision.ps1: -------------------------------------------------------------------------------- 1 | function Get-LicenseDecision { 2 | [CmdletBinding()] 3 | param ( 4 | 5 | ) 6 | end { 7 | 8 | $LicenseSkuSplat = @{ 9 | Title = 'Choose one or more options and click OK' 10 | OutputMode = 'Multiple' 11 | } 12 | $LicenseSkuDecision = @( 13 | [PSCustomObject]@{ 14 | 'Options' = 'AddSkus' 15 | }, 16 | [PSCustomObject]@{ 17 | 'Options' = 'AddOptions' 18 | }, 19 | [PSCustomObject]@{ 20 | 'Options' = 'RemoveSkus' 21 | }, 22 | [PSCustomObject]@{ 23 | 'Options' = 'RemoveOptions' 24 | } 25 | ) 26 | $LicenseSkuDecision | Out-GridView @LicenseSkuSplat 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Posh365/Private/Migration/Decision/Get-MwItemType.ps1: -------------------------------------------------------------------------------- 1 | function Get-MwItemType { 2 | [CmdletBinding()] 3 | param ( 4 | 5 | ) 6 | end { 7 | $OGVType = @{ 8 | Title = 'Choose ItemTypes' 9 | OutputMode = 'Multiple' 10 | } 11 | 'Mail' | Out-GridView @OGVType 12 | # 'Mail', 'Calendar', 'Contact', 'Journal', 'Note', 'Task', 'Rule' | Out-GridView @OGVType 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Posh365/Private/Migration/Decision/Get-NumberOfDaysDecision.ps1: -------------------------------------------------------------------------------- 1 | function Get-NumberOfDaysDecision { 2 | [CmdletBinding()] 3 | param ( 4 | 5 | ) 6 | end { 7 | $OGVDays = @{ 8 | Title = 'Migrate items with a date that is earlier than the specified number of days' 9 | OutputMode = 'Single ' 10 | } 11 | ForEach-Object { 12 | for ($i = 30; $i -lt 181; $i = $i + 30) { $i } 13 | } | Sort-Object -Descending | Out-GridView @OGVDays 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Posh365/Private/Migration/Decision/Get-PermissionDecision.ps1: -------------------------------------------------------------------------------- 1 | function Get-PermissionDecision { 2 | [CmdletBinding()] 3 | param ( 4 | 5 | ) 6 | end { 7 | 8 | $PermissionSplat = @{ 9 | Title = 'Choose one or more options and click OK' 10 | OutputMode = 'Multiple' 11 | } 12 | $PermissionDecision = @( 13 | [PSCustomObject]@{ 14 | 'Options' = 'FullAccess' 15 | }, 16 | [PSCustomObject]@{ 17 | 'Options' = 'SendAs' 18 | }, 19 | [PSCustomObject]@{ 20 | 'Options' = 'SendOnBehalf' 21 | }, 22 | [PSCustomObject]@{ 23 | 'Options' = 'Folder' 24 | } 25 | ) 26 | $PermissionDecision | Out-GridView @PermissionSplat 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Posh365/Private/Migration/Decision/Get-PermissionDecisionBatch.ps1: -------------------------------------------------------------------------------- 1 | function Get-PermissionDecisionBatch { 2 | [CmdletBinding()] 3 | param ( 4 | 5 | ) 6 | $PermissionSplat = @{ 7 | Title = 'Choose one or more options and click OK' 8 | OutputMode = 'Multiple' 9 | } 10 | $PermissionDecision = @( 11 | [PSCustomObject]@{ 12 | 'Options' = 'FullAccess' 13 | }, 14 | [PSCustomObject]@{ 15 | 'Options' = 'SendAs' 16 | }, 17 | [PSCustomObject]@{ 18 | 'Options' = 'SendOnBehalf' 19 | }, 20 | [PSCustomObject]@{ 21 | 'Options' = 'Folder' 22 | }, 23 | [PSCustomObject]@{ 24 | 'Options' = 'AddToBatch' 25 | } 26 | ) 27 | $PermissionDecision | Out-GridView @PermissionSplat 28 | } 29 | -------------------------------------------------------------------------------- /Posh365/Private/Migration/Decision/Get-PermissionDirectionDecision.ps1: -------------------------------------------------------------------------------- 1 | function Get-PermissionDirectionDecision { 2 | [CmdletBinding()] 3 | param ( 4 | 5 | ) 6 | end { 7 | 8 | $PermissionSplat = @{ 9 | Title = 'Choose one or more options and click OK' 10 | OutputMode = 'Multiple' 11 | } 12 | $PermissionDirectionDecision = @( 13 | [PSCustomObject]@{ 14 | 'Options' = 'Show me delegates (those granted access to mailbox(es) you just selected)' 15 | }, 16 | [PSCustomObject]@{ 17 | 'Options' = 'Show me delegated (the mailboxes that can be accessed by mailbox(es) you just selected)' 18 | } 19 | ) 20 | $PermissionDirectionDecision | Out-GridView @PermissionSplat 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Posh365/Private/Migration/Decision/Get-ScheduleDecision.ps1: -------------------------------------------------------------------------------- 1 | function Get-ScheduleDecision { 2 | [CmdletBinding()] 3 | param ( 4 | 5 | ) 6 | end { 7 | 8 | $OGVDate = @{ 9 | Title = 'Choose the date (your local time zone)' 10 | OutputMode = 'Single ' 11 | } 12 | $OGVTime = @{ 13 | Title = 'Choose the time of day (your local time zone)' 14 | OutputMode = 'Single ' 15 | } 16 | 17 | $DateChoice = 0..365 | ForEach-Object { [DateTime]::Now.Date.AddDays($_).ToString("M/d/yyyy") } | Out-GridView @OGVDate 18 | $TimeChoice = 1..12 | ForEach-Object { 19 | for ($i = 0; $i -lt 60; $i = $i + 5) { 20 | '{0}:{1:d2}AM' -f $_, $i 21 | '{0}:{1:d2}PM' -f $_, $i 22 | } 23 | } | Sort-Object { [DateTime]$_ } | Out-GridView @OGVTime 24 | 25 | $TimeandDate = (([DateTime]$DateChoice) + ([DateTime]$TimeChoice).TimeOfDay).ToUniversalTime() 26 | $TimeandDate 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Posh365/Private/Migration/Decision/Import-MailboxCsvDecision.ps1: -------------------------------------------------------------------------------- 1 | function Import-MailboxCsvDecision { 2 | 3 | [CmdletBinding(DefaultParameterSetName = 'PlaceHolder')] 4 | param ( 5 | 6 | [Parameter(Mandatory, ParameterSetName = 'MailboxCsv')] 7 | [ValidateNotNullOrEmpty()] 8 | [string] 9 | $MailboxCsv, 10 | 11 | [Parameter(Mandatory, ParameterSetName = 'Object')] 12 | [ValidateNotNullOrEmpty()] 13 | $Object, 14 | 15 | [Parameter()] 16 | [switch] 17 | $NoBatch 18 | ) 19 | 20 | if ($MailboxCSV){ 21 | $DecisionObject = Import-Csv -Path $MailboxCSV 22 | } 23 | else { 24 | $DecisionObject = $Object 25 | } 26 | $UserChoiceSplat = @{ 27 | DecisionObject = $DecisionObject 28 | NoBatch = $NoBatch 29 | } 30 | 31 | $UserChoice = Get-UserDecision @UserChoiceSplat 32 | $UserChoice 33 | } 34 | -------------------------------------------------------------------------------- /Posh365/Private/Migration/Decision/Import-MailboxCsvDecisionDomainChoice.ps1: -------------------------------------------------------------------------------- 1 | function Import-MailboxCsvDecisionDomainChoice { 2 | 3 | [CmdletBinding()] 4 | param ( 5 | [Parameter(Mandatory)] 6 | [ValidateNotNullOrEmpty()] 7 | [string] 8 | $MailboxCsv, 9 | 10 | [Parameter()] 11 | [switch] 12 | $ChooseDomain 13 | ) 14 | end { 15 | $UserChoiceSplat = @{ 16 | DecisionObject = Import-Csv -Path $MailboxCSV 17 | ChooseDomain = $ChooseDomain 18 | } 19 | $UserChoice = Get-UserDecision @UserChoiceSplat 20 | $UserChoice 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Posh365/Private/Migration/Decision/Import-MailboxMoveDecision.ps1: -------------------------------------------------------------------------------- 1 | function Import-MailboxMoveDecision { 2 | 3 | [CmdletBinding()] 4 | param ( 5 | [Parameter()] 6 | [switch] 7 | $NotCompleted 8 | ) 9 | end { 10 | if ($NotCompleted) { 11 | $DecisionObject = Invoke-GetMailboxMove -NotCompleted | Sort-Object @( 12 | @{ 13 | Expression = "BatchName" 14 | Descending = $true 15 | } 16 | @{ 17 | Expression = "DisplayName" 18 | Descending = $false 19 | } 20 | ) 21 | $UserChoice = Get-UserDecision -DecisionObject $DecisionObject 22 | $UserChoice 23 | } 24 | else { 25 | $DecisionObject = Invoke-GetMailboxMove | Sort-Object @( 26 | @{ 27 | Expression = "BatchName" 28 | Descending = $true 29 | } 30 | @{ 31 | Expression = "DisplayName" 32 | Descending = $false 33 | } 34 | ) 35 | $UserChoice = Get-UserDecision -DecisionObject $DecisionObject 36 | $UserChoice 37 | } 38 | } 39 | } 40 | 41 | -------------------------------------------------------------------------------- /Posh365/Private/Migration/Decision/Update-MailboxMovePermissionBatchHelper.ps1: -------------------------------------------------------------------------------- 1 | function Update-MailboxMovePermissionBatchHelper { 2 | [CmdletBinding(DefaultParameterSetName = 'SharePoint')] 3 | param ( 4 | [Parameter(ParameterSetName = 'SharePoint')] 5 | [ValidateNotNullOrEmpty()] 6 | [string] 7 | $SharePointURL, 8 | 9 | [Parameter(ParameterSetName = 'SharePoint')] 10 | [ValidateNotNullOrEmpty()] 11 | [string] 12 | $ExcelFile, 13 | 14 | [Parameter()] 15 | $BatchLink, 16 | 17 | [Parameter()] 18 | [psobject] 19 | $UserChoice, 20 | 21 | [Parameter()] 22 | [ValidateNotNullOrEmpty()] 23 | [string] 24 | $UserInputBatch 25 | ) 26 | end { 27 | $BatchLink | Select-Object -ExcludeProperty BatchName -Property @( 28 | @{ 29 | Name = "BatchName" 30 | Expression = { if ($_.PrimarySmtpAddress -in $UserChoice.PrimarySmtpAddress) { 31 | $UserInputBatch 32 | } 33 | else { $_.BatchName } 34 | } 35 | } 36 | '*' 37 | ) 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /Posh365/Private/Migration/Get-MailboxMoveReportData.ps1: -------------------------------------------------------------------------------- 1 | Function Get-MailboxMoveReportData { 2 | 3 | [CmdletBinding()] 4 | param ( 5 | [Parameter(Mandatory)] 6 | $WantsDetailOnTheseMoveRequests 7 | ) 8 | Write-Host "Please stand by... exporting data to Posh365 directory on your Desktop..." -ForegroundColor Cyan 9 | foreach ($Wants in $WantsDetailOnTheseMoveRequests) { 10 | Get-MailboxMoveReportDataHelper -Wants $Wants | Sort-Object -Property CreationTime -Descending 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Posh365/Private/Migration/Get-MailboxMoveReportDataHelper.ps1: -------------------------------------------------------------------------------- 1 | Function Get-MailboxMoveReportDataHelper { 2 | 3 | [CmdletBinding()] 4 | param ( 5 | [Parameter(Mandatory)] 6 | $Wants 7 | ) 8 | 9 | $Stats = Get-MoveRequestStatistics -Identity $Wants.Guid -IncludeReport 10 | $Size = [regex]::Matches("$($Stats.TotalMailboxSize)", "^[^(]*").value 11 | foreach ($Log in $Stats.Report.Entries) { 12 | [PSCustomObject]@{ 13 | DisplayName = $Wants.DisplayName 14 | CreationTime = $Log.CreationTime.toLocalTime() 15 | Log = $Log.Message 16 | PercentComplete = $Stats.PercentComplete 17 | MailboxSize = $Size 18 | Detail = $Stats.StatusDetail.value 19 | ItemsTransferred = $Stats.ItemsTransferred 20 | ItemCount = $Stats.TotalMailboxItemCount 21 | Message = $Stats.Message 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Posh365/Private/Migration/Invoke-GetMailboxMovePassThru.ps1: -------------------------------------------------------------------------------- 1 | Function Invoke-GetMailboxMovePassThru { 2 | [CmdletBinding()] 3 | param 4 | ( 5 | [Parameter()] 6 | [switch] 7 | $IncludeCompleted, 8 | 9 | [Parameter()] 10 | [switch] 11 | $RemoveAndRestart 12 | ) 13 | 14 | if ($IncludeCompleted) { 15 | Invoke-GetMailboxMove | Out-GridView -Title "All mailbox moves" -OutputMode Multiple 16 | } 17 | else { 18 | Invoke-GetMailboxMove -NotCompleted | Out-GridView -Title "All mailbox moves that are not yet complete" -OutputMode Multiple 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Posh365/Private/Migration/Invoke-RemoveMailboxMove.ps1: -------------------------------------------------------------------------------- 1 | Function Invoke-RemoveMailboxMove { 2 | [CmdletBinding()] 3 | param ( 4 | [Parameter()] 5 | $RandRObject 6 | ) 7 | end { 8 | if ($RandRObject) { 9 | $UserChoice = $RandRObject | Select-Object @( 10 | 'DisplayName' 11 | @{ 12 | Name = 'Guid' 13 | Expression = { $_.ExchangeGuid.toString() } 14 | } 15 | ) 16 | } 17 | else { 18 | $UserChoice = Import-MailboxMoveDecision 19 | } 20 | 21 | if ($UserChoice -ne 'Quit' ) { 22 | foreach ($User in $UserChoice) { 23 | try { 24 | Remove-MoveRequest -Identity $User.Guid -Confirm:$false -ErrorAction Stop 25 | [PSCustomObject]@{ 26 | DisplayName = $User.DisplayName 27 | Result = 'SUCCESS' 28 | Log = 'SUCCESS' 29 | Action = 'REMOVE' 30 | } 31 | } 32 | catch { 33 | [PSCustomObject]@{ 34 | DisplayName = $User.DisplayName 35 | Result = 'FAILED' 36 | Log = $_.Exception.Message 37 | Action = 'REMOVE' 38 | } 39 | } 40 | } 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /Posh365/Private/Migration/Invoke-SuspendMailboxMove.ps1: -------------------------------------------------------------------------------- 1 | Function Invoke-SuspendMailboxMove { 2 | [CmdletBinding()] 3 | param 4 | ( 5 | 6 | [Parameter()] 7 | $UserChoice 8 | ) 9 | if ( -not $UserChoice ) { 10 | $UserChoice = Import-MailboxMoveDecision -NotCompleted 11 | } 12 | if ($UserChoice -ne 'Quit' ) { 13 | $SuspendSplat = @{ 14 | Confirm = $false 15 | ErrorAction = 'Stop' 16 | } 17 | foreach ($User in $UserChoice) { 18 | try { 19 | Suspend-MoveRequest -Identity $User.ExchangeGuid @SuspendSplat 20 | [PSCustomObject]@{ 21 | DisplayName = $User.DisplayName 22 | ExchangeGuid = $User.ExchangeGuid 23 | Action = 'SUSPEND' 24 | Result = 'Success' 25 | Message = '' 26 | } 27 | } 28 | catch { 29 | [PSCustomObject]@{ 30 | DisplayName = $User.DisplayName 31 | ExchangeGuid = $User.ExchangeGuid 32 | Action = 'SUSPEND' 33 | Result = 'Failed' 34 | Message = $_.Exception.Message 35 | } 36 | } 37 | } 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /Posh365/Private/Migration/Invoke-T2TCompleteMailboxMove.ps1: -------------------------------------------------------------------------------- 1 | function Invoke-T2TCompleteMailboxMove { 2 | [cmdletbinding()] 3 | param ( 4 | [Parameter(ValueFromPipeline, Mandatory)] 5 | [ValidateNotNullOrEmpty()] 6 | $UserList 7 | ) 8 | process { 9 | foreach ($User in $UserList) { 10 | try { 11 | $Param = @{ 12 | Identity = $User.Guid 13 | BatchName = $User.BatchName 14 | Confirm = $False 15 | CompleteAfter = $null 16 | ErrorAction = 'Stop' 17 | } 18 | Set-MoveRequest @Param 19 | [PSCustomObject]@{ 20 | DisplayName = $User.DisplayName 21 | CompleteAfter = 'NULL' 22 | Action = 'SET' 23 | Result = 'Success' 24 | Message = '' 25 | } 26 | } 27 | catch { 28 | [PSCustomObject]@{ 29 | DisplayName = $User.DisplayName 30 | CompleteAfter = $LocalTime 31 | CompleteAfterUTC = $UTCTime 32 | Action = 'SET' 33 | Result = 'Failed' 34 | Message = $_.Exception.Message 35 | } 36 | } 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /Posh365/Private/Migration/OnPremises/Get-MailboxMoveRecipientHash.ps1: -------------------------------------------------------------------------------- 1 | Function Get-MailboxMoveRecipientHash { 2 | [CmdletBinding()] 3 | param 4 | ( 5 | ) 6 | end { 7 | $RecipientHash = @{ } 8 | $RecipientList = Get-Recipient -ResultSize Unlimited 9 | foreach ($Recipient in $RecipientList) { 10 | $RecipientHash[$Recipient.DistinguishedName] = @{ 11 | PrimarySMTPAddress = $Recipient.PrimarySMTPAddress 12 | RecipientTypeDetails = $Recipient.RecipientTypeDetails 13 | } 14 | } 15 | $RecipientHash 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Posh365/Private/Migration/Task/Add-UserToADGroup.ps1: -------------------------------------------------------------------------------- 1 | function Add-UsertoADGroup { 2 | [CmdletBinding()] 3 | param ( 4 | [Parameter(Mandatory, ValueFromPipeline)] 5 | [ValidateNotNullOrEmpty()] 6 | $GuidList, 7 | 8 | [Parameter(Mandatory)] 9 | [ValidateNotNullOrEmpty()] 10 | $Group 11 | ) 12 | process { 13 | foreach ($Guid in $GuidList) { 14 | Add-ADGroupMember -Identity $Group -Members $Guid 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Posh365/Private/Migration/Task/Get-ADUserGuid.ps1: -------------------------------------------------------------------------------- 1 | function Get-ADUserGuid { 2 | [CmdletBinding()] 3 | param ( 4 | [Parameter(ValueFromPipeline)] 5 | [ValidateNotNullOrEmpty()] 6 | $UserList 7 | ) 8 | process { 9 | foreach ($User in $UserList) { 10 | $FilterString = "UserPrincipalName -eq '{0}'" -f $User.UserPrincipalName 11 | (Get-ADUser -filter $filterString).ObjectGUID 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Posh365/Private/Okta/Get-OktaAppHash.ps1: -------------------------------------------------------------------------------- 1 | function Get-OktaAppHash { 2 | 3 | $AppHash = @{} 4 | 5 | $App = Get-OktaApp 6 | 7 | foreach ($CurApp in $App) { 8 | 9 | $Id = $CurApp.Id 10 | $Accessibility = ($CurApp).Accessibility 11 | $Visibility = ($CurApp).Visibility 12 | $Credentials = ($CurApp).Credentials 13 | $Features = ($CurApp).Features 14 | 15 | $AppHash[$Id] = @{ 16 | Name = $CurApp.Name 17 | Label = $CurApp.Label 18 | Status = $CurApp.Status 19 | Created = $CurApp.Created 20 | LastUpdated = $CurApp.LastUpdated 21 | Activated = $CurApp.Activated 22 | UserNameTemplate = $Credentials.UserNameTemplate.Template 23 | UserNameTemplateType = $Credentials.UserNameTemplate.Type 24 | CredentialScheme = $Credentials.Scheme 25 | Features = ($Features -join (';')) 26 | } 27 | 28 | } 29 | 30 | $AppHash 31 | } -------------------------------------------------------------------------------- /Posh365/Private/Okta/Get-OktaAppUserHash.ps1: -------------------------------------------------------------------------------- 1 | function Get-OktaAppUserHash { 2 | param ( 3 | 4 | ) 5 | $App = Get-OktaApp 6 | Foreach ($CurApp in $App.id) { 7 | $Users = @{} 8 | Get-OktaAppUser -AppId $CurApp | ForEach-Object { 9 | if (-not $Users.Contains($CurApp)) { 10 | $Users[$CurApp] = [system.collections.arraylist]::new() 11 | } 12 | $null = $Users[$CurApp].Add($_.id) 13 | } 14 | $Users 15 | } 16 | } -------------------------------------------------------------------------------- /Posh365/Private/Okta/Get-OktaGroupHash.ps1: -------------------------------------------------------------------------------- 1 | function Get-OktaGroupHash { 2 | Param ( 3 | 4 | ) 5 | 6 | $Group = Get-OktaGroupReport 7 | $GroupHash = @{ } 8 | 9 | foreach ($CurGroup in $Group) { 10 | $GId = $CurGroup.Id 11 | $GName = $CurGroup.Name 12 | $GDescription = $CurGroup.Description 13 | $GType = $CurGroup.Type 14 | $Wqdn = $CurGroup.windowsDomainQualifiedName 15 | $GroupType = $CurGroup.GroupType 16 | $GroupScope = $CurGroup.GroupScope 17 | $samAccountName = $CurGroup.samAccountName 18 | $DistinguishedName = $CurGroup.DistinguishedName 19 | $Created = $CurGroup.Created 20 | $LastUpdated = $CurGroup.LastUpdated 21 | $LastMembershipUpdated = $CurGroup.LastMembershipUpdated 22 | 23 | $GroupHash[$GId] = @{ 24 | Name = $GName 25 | Description = $GDescription 26 | Type = $GType 27 | windowsDomainQualifiedName = $Wqdn 28 | GroupType = $GroupType 29 | GroupScope = $GroupScope 30 | samAccountName = $samAccountName 31 | DistinguishedName = $DistinguishedName 32 | Created = $Created 33 | LastUpdated = $LastUpdated 34 | LastMembershipUpdated = $LastMembershipUpdated 35 | } 36 | } 37 | $GroupHash 38 | } 39 | -------------------------------------------------------------------------------- /Posh365/Private/Okta/Get-OktaGroupMemberHash.ps1: -------------------------------------------------------------------------------- 1 | function Get-OktaGroupMemberHash { 2 | Param ( 3 | 4 | [Parameter(Mandatory)] 5 | [hashtable] $Member2Group 6 | 7 | ) 8 | $Group2Member = @{ } 9 | foreach ($Entry in $Member2Group.GetEnumerator()) { 10 | $User = $Entry.Key 11 | foreach ($Group in $Entry.Value) { 12 | if (-not $Group2Member.ContainsKey($Group)) { 13 | $Group2Member[$Group] = [System.Collections.Generic.List[string]]::new() 14 | } 15 | $Group2Member[$Group].Add($User) 16 | } 17 | } 18 | $Group2Member 19 | } -------------------------------------------------------------------------------- /Posh365/Private/Okta/Get-OktaMemberGroupHash.ps1: -------------------------------------------------------------------------------- 1 | function Get-OktaMemberGroupHash { 2 | Param ( 3 | 4 | ) 5 | $groupId2NameHash = @{ } 6 | $groupList = Get-OktaGroupReport 7 | $member2GroupHash = @{ } 8 | foreach ($Group in $groupList) { 9 | if (-not $groupId2NameHash.Contains($Group.Id)) { 10 | $groupId2NameHash[$Group.Id] = $Group.Name 11 | } 12 | Start-Sleep -Milliseconds 100 13 | $memberList = Get-OktaGroupMembership -GroupId $Group.id 14 | 15 | foreach ($Member in $memberList) { 16 | 17 | if (-not $member2GroupHash.Contains($Member.login)) { 18 | $member2GroupHash[$Member.login] = [system.collections.arraylist]::new() 19 | } 20 | $null = $member2GroupHash[$Member.login].Add($Group.Id) 21 | } 22 | } 23 | $Script:groupId2NameHash = $groupId2NameHash 24 | $member2GroupHash 25 | } -------------------------------------------------------------------------------- /Posh365/Private/Okta/Get-OktaMemberGroupIDHash.ps1: -------------------------------------------------------------------------------- 1 | function Get-OktaMemberGroupIDHash { 2 | Param ( 3 | 4 | ) 5 | $Group = Get-OktaGroupReport 6 | $Member2Group = @{ } 7 | foreach ($CurGroup in $Group) { 8 | $GId = $CurGroup.id 9 | Start-Sleep -Milliseconds 100 10 | $GrpMember = Get-OktaGroupMembership -GroupId $CurGroup.id 11 | 12 | foreach ($CurGrpMember in $GrpMember) { 13 | $Login = $CurGrpMember.login 14 | if (-not $Member2Group.Contains($Login)) { 15 | $Member2Group[$Login] = [system.collections.arraylist]::new() 16 | } 17 | $null = $Member2Group[$Login].Add($GId) 18 | } 19 | } 20 | $Member2Group 21 | } -------------------------------------------------------------------------------- /Posh365/Private/Okta/Get-OktaUserHash.ps1: -------------------------------------------------------------------------------- 1 | function Get-OktaUserHash { 2 | 3 | $UserHash = @{} 4 | 5 | $User = Get-OktaUser 6 | 7 | foreach ($CurUser in $User) { 8 | 9 | $Id = $CurUser.Id 10 | $ProfileDetails = ($CurUser).Profile 11 | $CredDetails = ($CurUser).Credentials 12 | 13 | $UserHash[$Id] = @{ 14 | FirstName = $ProfileDetails.FirstName 15 | LastName = $ProfileDetails.LastName 16 | Login = $ProfileDetails.Login 17 | Email = $ProfileDetails.Email 18 | Status = $CurUser.Status 19 | Created = $CurUser.Created 20 | Activated = $CurUser.Activated 21 | StatusChanged = $CurUser.StatusChanged 22 | LastLogin = $CurUser.LastLogin 23 | LastUpdated = $CurUser.LastUpdated 24 | PasswordChanged = $CurUser.PasswordChanged 25 | ProviderType = $CredDetails.Provider.Type 26 | ProviderName = $CredDetails.Provider.Name 27 | RecoveryQuestion = $CredDetails.RecoveryQuestion.Question 28 | } 29 | 30 | } 31 | 32 | $UserHash 33 | } -------------------------------------------------------------------------------- /Posh365/Private/Options/Select-SamAccountNameCharacters.ps1: -------------------------------------------------------------------------------- 1 | function Select-SamAccountNameCharacters { 2 | param () 3 | $RootPath = $env:USERPROFILE + "\ps\" 4 | $User = $env:USERNAME 5 | 6 | if (!(Test-Path $RootPath)) { 7 | try { 8 | New-Item -ItemType Directory -Path $RootPath -ErrorAction STOP | Out-Null 9 | } 10 | catch { 11 | throw $_.Exception.Message 12 | } 13 | } 14 | [array]$SamAccountNameCharacters = "1", "2", "3", "4", "5", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20" | 15 | Out-GridView -OutputMode Single -Title "Select the Maximum number of characters in your SamAccountName (Choose 1 and click OK)" 16 | $SamAccountNameCharacters | Out-File ($RootPath + "$($user).SamAccountNameCharacters") -Force 17 | } 18 | -------------------------------------------------------------------------------- /Posh365/Private/Options/Select-SamAccountNameOrder.ps1: -------------------------------------------------------------------------------- 1 | function Select-SamAccountNameOrder { 2 | param () 3 | $RootPath = $env:USERPROFILE + "\ps\" 4 | $User = $env:USERNAME 5 | 6 | if (!(Test-Path $RootPath)) { 7 | try { 8 | New-Item -ItemType Directory -Path $RootPath -ErrorAction STOP | Out-Null 9 | } 10 | catch { 11 | throw $_.Exception.Message 12 | } 13 | } 14 | 15 | [array]$SamAccountNameOrder = "First Name then Last Name (example: JSmith)", "Last Name then First Name (example: SmithJ)" | 16 | Out-GridView -OutputMode Single -Title "The SamAccountName is represented by First Name and Last Name - In which order (Choose 1 and click OK)" 17 | 18 | if ($SamAccountNameOrder -eq "First Name then Last Name (example: JSmith)") { 19 | "SamFirstFirst" | Out-File ($RootPath + "$($user).SamAccountNameOrder") -Force 20 | } 21 | else { 22 | "SamLastFirst" | Out-File ($RootPath + "$($user).SamAccountNameOrder") -Force 23 | } 24 | 25 | } -------------------------------------------------------------------------------- /Posh365/Private/Outlook/Invoke-GetOutlookData.ps1: -------------------------------------------------------------------------------- 1 | function Invoke-GetOutlookData { 2 | [CmdletBinding()] 3 | param ( 4 | [Parameter()] 5 | $LogPath 6 | ) 7 | If (Test-Path $LogPath) { 8 | Get-Content -path $LogPath | ConvertFrom-Csv -Header @( 9 | 'date-time', 'session-id', 'seq-number', 'client-name', 'organization-info' 10 | 'client-software', 'client-software-version', 'client-mode', 'client-ip' 11 | 'server-ip', 'protocol', 'application-idoperation', 'rpc-status' 12 | 'processing-time', 'operation-specific', 'failures' 13 | ) | Where-Object { ($_."client-software" -eq 'OUTLOOK.EXE') -and ($_."client-name" -ne $null) } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Posh365/Private/Permissions/EXO/Get-LegacyDNToPrimarySmtpHash.ps1: -------------------------------------------------------------------------------- 1 | Function Get-LegacyDNToPrimarySmtpHash { 2 | [CmdletBinding()] 3 | param ( 4 | [Parameter()] 5 | $Mailbox, 6 | 7 | [Parameter()] 8 | $MailUser, 9 | 10 | [Parameter()] 11 | $MailContact, 12 | 13 | [Parameter()] 14 | $DistributionGroup 15 | ) 16 | $LegDNHash = @{ } 17 | foreach ($Recipient in @($Mailbox ; $MailUser ; $MailContact ; $DistributionGroup)) { 18 | $LegDNHash[$Recipient.LegacyExchangeDN] = $Recipient.PrimarySMTPAddress 19 | } 20 | $LegDNHash 21 | } 22 | -------------------------------------------------------------------------------- /Posh365/Private/Permissions/EXO/Get-MailboxLegacyExchangeDNHash.ps1: -------------------------------------------------------------------------------- 1 | Function Get-MailboxLegacyExchangeDNHash { 2 | <# 3 | .SYNOPSIS 4 | 5 | .EXAMPLE 6 | 7 | #> 8 | param ( 9 | 10 | ) 11 | Begin { 12 | $MailboxLegacyExchangeDNHash = @{ } 13 | } 14 | 15 | Process { 16 | $MailboxLegacyExchangeDNHash[$_.LegacyExchangeDN] = $_.PrimarySMTPAddress 17 | } 18 | End { 19 | $MailboxLegacyExchangeDNHash 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Posh365/Private/Permissions/EXO/Get-RecipientDNHash.ps1: -------------------------------------------------------------------------------- 1 | Function Get-RecipientDNHash { 2 | <# 3 | .SYNOPSIS 4 | 5 | .EXAMPLE 6 | 7 | #> 8 | param ( 9 | 10 | ) 11 | Begin { 12 | $RecipientDNHash = @{ } 13 | } 14 | 15 | Process { 16 | $RecipientDNHash[$_.DistinguishedName] = @{ 17 | Name = $_.Name 18 | PrimarySMTPAddress = $_.PrimarySMTPAddress 19 | } 20 | } 21 | End { 22 | $RecipientDNHash 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Posh365/Private/Permissions/EXO/Get-RecipientHash.ps1: -------------------------------------------------------------------------------- 1 | Function Get-RecipientHash { 2 | <# 3 | .SYNOPSIS 4 | 5 | .EXAMPLE 6 | 7 | #> 8 | param ( 9 | 10 | ) 11 | Begin { 12 | $RecipientHash = @{ } 13 | } 14 | 15 | Process { 16 | $RecipientHash[$_.Name] = @{ 17 | PrimarySMTPAddress = $_.PrimarySMTPAddress 18 | RecipientTypeDetails = $_.RecipientTypeDetails 19 | } 20 | } 21 | End { 22 | $RecipientHash 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Posh365/Private/Permissions/EXO/Get-RecipientLiveIDHash.ps1: -------------------------------------------------------------------------------- 1 | Function Get-RecipientLiveIDHash { 2 | <# 3 | .SYNOPSIS 4 | 5 | .EXAMPLE 6 | 7 | #> 8 | param ( 9 | 10 | ) 11 | Begin { 12 | $RecipientLiveIDHash = @{ } 13 | } 14 | 15 | Process { 16 | $RecipientLiveIDHash[$_.WindowsLiveID] = @{ 17 | PrimarySMTPAddress = $_.PrimarySMTPAddress 18 | Name = $_.Name 19 | RecipientTypeDetails = $_.RecipientTypeDetails 20 | } 21 | } 22 | End { 23 | $RecipientLiveIDHash 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Posh365/Private/Permissions/EXO/Get-RecipientMailHash.ps1: -------------------------------------------------------------------------------- 1 | Function Get-RecipientMailHash { 2 | <# 3 | .SYNOPSIS 4 | 5 | .EXAMPLE 6 | 7 | #> 8 | param ( 9 | 10 | ) 11 | Begin { 12 | $RecipientMailHash = @{ } 13 | } 14 | 15 | Process { 16 | $RecipientMailHash[$_.PrimarySMTPAddress] = @{ 17 | Name = $_.Name 18 | RecipientTypeDetails = $_.RecipientTypeDetails 19 | } 20 | } 21 | End { 22 | $RecipientMailHash 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Posh365/Private/Permissions/EXO/Get-RecipientNameHash.ps1: -------------------------------------------------------------------------------- 1 | Function Get-RecipientNameHash { 2 | <# 3 | .SYNOPSIS 4 | 5 | .EXAMPLE 6 | 7 | #> 8 | param ( 9 | 10 | ) 11 | Begin { 12 | $RecipientNameHash = @{ } 13 | } 14 | 15 | Process { 16 | $RecipientNameHash[$_.Name] = $_.PrimarySMTPAddress 17 | } 18 | End { 19 | $RecipientNameHash 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Posh365/Private/Permissions/EXO/Get-RecipientPrimaryToTypeHash.ps1: -------------------------------------------------------------------------------- 1 | function Get-RecipientPrimaryToTypeHash { 2 | param ( 3 | [Parameter(Mandatory)] 4 | $RecipientList 5 | ) 6 | 7 | end { 8 | $RecipientMailToTypeHash = @{ } 9 | foreach ($Recipient in $RecipientList) { 10 | if ($Recipient.PrimarySMTPAddress) { 11 | $RecipientMailToTypeHash.Add($Recipient.PrimarySMTPAddress, $Recipient.RecipientTypeDetails) 12 | } 13 | } 14 | $RecipientMailToTypeHash 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Posh365/Private/Permissions/Hashtable/Get-ADHash.ps1: -------------------------------------------------------------------------------- 1 | Function Get-ADHash { 2 | param ( 3 | [parameter(ValueFromPipeline = $true)] 4 | $ADUserList 5 | ) 6 | begin { 7 | $ADHash = @{ } 8 | } 9 | process { 10 | foreach ($ADUser in $ADUserList) { 11 | $ADHash[$ADUser.logon] = @{ 12 | DisplayName = $ADUser.DisplayName 13 | UserPrincipalName = $ADUser.UserPrincipalName 14 | PrimarySMTPAddress = $ADUser.PrimarySMTPAddress 15 | msExchRecipientTypeDetails = $ADUser.msExchRecipientTypeDetails 16 | msExchRecipientDisplayType = $ADUser.msExchRecipientDisplayType 17 | Objectguid = $ADUser.Objectguid 18 | objectClass = $ADUser.objectClass 19 | } 20 | } 21 | } 22 | end { 23 | $ADHash 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Posh365/Private/Permissions/Hashtable/Get-ADHashCN.ps1: -------------------------------------------------------------------------------- 1 | function Get-ADHashCN { 2 | param ( 3 | [parameter(ValueFromPipeline = $true)] 4 | $ADUserList 5 | ) 6 | begin { 7 | $ADHashCN = @{ } 8 | } 9 | process { 10 | foreach ($ADUser in $ADUserList) { 11 | $ADHashCN[$ADUser.CanonicalName] = @{ 12 | DisplayName = $ADUser.DisplayName 13 | UserPrincipalName = $ADUser.UserPrincipalName 14 | Logon = $ADUser.logon 15 | PrimarySMTPAddress = $ADUser.PrimarySMTPAddress 16 | msExchRecipientTypeDetails = $ADUser.msExchRecipientTypeDetails 17 | msExchRecipientDisplayType = $ADUser.msExchRecipientDisplayType 18 | } 19 | } 20 | } 21 | end { 22 | $ADHashCN 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Posh365/Private/Permissions/Hashtable/Get-ADHashDG.ps1: -------------------------------------------------------------------------------- 1 | Function Get-ADHashDG { 2 | <# 3 | .SYNOPSIS 4 | .EXAMPLE 5 | 6 | #> 7 | param ( 8 | [parameter(ValueFromPipeline = $true)] 9 | $DistinguishedName 10 | ) 11 | begin { 12 | $ADHashDG = @{ } 13 | } 14 | process { 15 | foreach ($CurDN in $DistinguishedName) { 16 | $ADHashDG[$CurDN.logon] = @{ 17 | DisplayName = $CurDN.DisplayName 18 | UserPrincipalName = $CurDN.UserPrincipalName 19 | PrimarySMTPAddress = $CurDN.PrimarySMTPAddress 20 | } 21 | } 22 | } 23 | end { 24 | $ADHashDG 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Posh365/Private/Permissions/Hashtable/Get-ADHashDGDN.ps1: -------------------------------------------------------------------------------- 1 | Function Get-ADHashDGDN { 2 | <# 3 | .SYNOPSIS 4 | 5 | .EXAMPLE 6 | 7 | #> 8 | param ( 9 | [parameter(ValueFromPipeline = $true)] 10 | $DistinguishedName 11 | ) 12 | Begin { 13 | $ADHashDGDN = @{ } 14 | } 15 | Process { 16 | foreach ($CurDN in $DistinguishedName) { 17 | $ADHashDGDN[$CurDN.DistinguishedName] = @{ 18 | DisplayName = $CurDN.DisplayName 19 | UserPrincipalName = $CurDN.UserPrincipalName 20 | PrimarySmtpAddress = $CurDN.PrimarySmtpAddress 21 | Logon = $CurDN.logon 22 | } 23 | } 24 | } 25 | End { 26 | $ADHashDGDN 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Posh365/Private/Permissions/Hashtable/Get-ADHashDN.ps1: -------------------------------------------------------------------------------- 1 | Function Get-ADHashDN { 2 | param ( 3 | [parameter(ValueFromPipeline = $true)] 4 | $MailboxList 5 | ) 6 | begin { 7 | $ADHashDN = @{ } 8 | } 9 | process { 10 | foreach ($Mailbox in $MailboxList) { 11 | $ADHashDN[$Mailbox.DistinguishedName] = @{ 12 | DisplayName = $Mailbox.DisplayName 13 | UserPrincipalName = $Mailbox.UserPrincipalName 14 | Logon = $Mailbox.logon 15 | PrimarySMTPAddress = $Mailbox.PrimarySMTPAddress 16 | } 17 | } 18 | } 19 | end { 20 | $ADHashDN 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Posh365/Private/Permissions/Hashtable/Get-ADHashDisplayName.ps1: -------------------------------------------------------------------------------- 1 | Function Get-ADHashDisplayName { 2 | 3 | param ( 4 | [parameter(ValueFromPipeline = $true)] 5 | $ADUserList 6 | ) 7 | begin { 8 | $ADHashDisplayName = @{ } 9 | } 10 | process { 11 | foreach ($ADUser in $ADUserList) { 12 | $ADHashDisplayName[$ADUser.DisplayName] = @{ 13 | UserPrincipalName = $ADUser.UserPrincipalName 14 | PrimarySMTPAddress = $ADUser.PrimarySMTPAddress 15 | msExchRecipientTypeDetails = $ADUser.msExchRecipientTypeDetails 16 | msExchRecipientDisplayType = $ADUser.msExchRecipientDisplayType 17 | Logon = $ADUser.Logon 18 | objectClass = $ADUser.objectClass 19 | } 20 | } 21 | } 22 | end { 23 | $ADHashDisplayName 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Posh365/Private/Permissions/Hashtable/Get-ADHashDisplayNameToGuid.ps1: -------------------------------------------------------------------------------- 1 | Function Get-ADHashDisplayNameToGuid { 2 | <# 3 | .SYNOPSIS 4 | 5 | .EXAMPLE 6 | 7 | #> 8 | param ( 9 | [parameter(ValueFromPipeline = $true)] 10 | $row 11 | ) 12 | Begin { 13 | $ADHashDisplayToGuid = @{} 14 | } 15 | Process { 16 | foreach ($curRow in $row) { 17 | $ADHashDisplayToGuid[$curRow.DisplayName] = $curRow.ObjectGuid 18 | } 19 | } 20 | End { 21 | $ADHashDisplayToGuid 22 | } 23 | } -------------------------------------------------------------------------------- /Posh365/Private/Permissions/Hashtable/Get-ADHashMailToGuid.ps1: -------------------------------------------------------------------------------- 1 | Function Get-ADHashMailToGuid { 2 | param ( 3 | [parameter(ValueFromPipeline = $true)] 4 | $row 5 | ) 6 | begin { 7 | $ADHashMailToGuid = @{ } 8 | } 9 | process { 10 | foreach ($curRow in $row) { 11 | $ADHashMailToGuid[$curRow.mail] = $curRow.ObjectGuid 12 | } 13 | } 14 | end { 15 | $ADHashMailToGuid 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Posh365/Private/Permissions/MailboxMove/Get-MailboxMoveDelegateResult.ps1: -------------------------------------------------------------------------------- 1 | 2 | function Get-MailboxMoveDelegateResult { 3 | [CmdletBinding()] 4 | param ( 5 | [Parameter(Mandatory)] 6 | [ValidateNotNullOrEmpty()] 7 | $PermissionChoice, 8 | 9 | [Parameter(Mandatory)] 10 | [ValidateNotNullOrEmpty()] 11 | $DirectionChoice, 12 | 13 | [Parameter(Mandatory)] 14 | [ValidateNotNullOrEmpty()] 15 | $MailboxPermission, 16 | 17 | [Parameter(Mandatory)] 18 | [ValidateNotNullOrEmpty()] 19 | $UserChoiceRegex 20 | ) 21 | end { 22 | $MailboxPermissionRegex = (($PermissionChoice | Where-Object { $_.Options -match "FullAccess|SendAs|SendOnBehalf" }) | 23 | ForEach-Object { [Regex]::Escape($_.Options) }) -join '|' 24 | 25 | $OrElements = foreach ($Direction in $DirectionChoice.Options) { 26 | if ($Direction -match 'delegates') { 27 | '$_.PrimarySMTPAddress -match $UserChoiceRegex' 28 | } 29 | 30 | if ($Direction -match 'delegated') { 31 | '$_.GrantedSMTP -match $UserChoiceRegex' 32 | } 33 | } 34 | $AndElements = '$_.Permission -match $MailboxPermissionRegex' 35 | $Filter = [ScriptBlock]::Create((($OrElements -join ' -or '), $AndElements -join " -and ")) 36 | foreach ($Permission in $MailboxPermission) { 37 | $Permission | Where-Object $Filter 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /Posh365/Private/Permissions/MailboxMove/Get-MailboxMoveFolderPermission.ps1: -------------------------------------------------------------------------------- 1 | Function Get-MailboxMoveFolderPermission { 2 | [CmdletBinding()] 3 | param ( 4 | [Parameter(Mandatory = $true)] 5 | $MailboxList, 6 | 7 | [Parameter(Mandatory = $true)] 8 | $ADUserList, 9 | 10 | [parameter()] 11 | [hashtable] 12 | $ADHashType, 13 | 14 | [parameter()] 15 | [hashtable] 16 | $ADHashDisplay 17 | ) 18 | end { 19 | $FolderSelect = @( 20 | 'Object', 'UserPrincipalName', 'PrimarySMTPAddress', 'Folder', 'AccessRights' 21 | 'Granted', 'GrantedUPN', 'GrantedSMTP', 'TypeDetails', 'DisplayType' 22 | ) 23 | Write-Verbose "Caching hashtable. DisplayName as Key and Values of UPN, PrimarySMTP, msExchRecipientTypeDetails & msExchRecipientDisplayType" 24 | $ADHashDisplayName = $ADUserList | Get-ADHashDisplayName -erroraction silentlycontinue 25 | 26 | $FolderPermSplat = @{ 27 | ADHashDisplayName = $ADHashDisplayName 28 | ADHashType = $ADHashType 29 | ADHashDisplay = $ADHashDisplay 30 | UserGroupHash = $UserGroupHash 31 | GroupMemberHash = $GroupMemberHash 32 | 33 | } 34 | Write-Verbose "Getting Folder Permissions for each mailbox and writing to file" 35 | $MailboxList | Get-MailboxFolderPerms @FolderPermSplat | Select-Object $FolderSelect 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /Posh365/Private/Permissions/MailboxMove/Get-MailboxMoveFolderResult.ps1: -------------------------------------------------------------------------------- 1 | 2 | function Get-MailboxMoveFolderResult { 3 | [CmdletBinding()] 4 | param ( 5 | [Parameter(Mandatory)] 6 | [ValidateNotNullOrEmpty()] 7 | $DirectionChoice, 8 | 9 | [Parameter(Mandatory)] 10 | [ValidateNotNullOrEmpty()] 11 | $FolderPermission, 12 | 13 | [Parameter(Mandatory)] 14 | [ValidateNotNullOrEmpty()] 15 | $UserChoiceRegex 16 | ) 17 | end { 18 | $OrElements = foreach ($Direction in $DirectionChoice.Options) { 19 | if ($Direction -match 'delegates') { 20 | '$_.PrimarySMTPAddress -match $UserChoiceRegex' 21 | } 22 | 23 | if ($Direction -match 'delegated') { 24 | '$_.GrantedSMTP -match $UserChoiceRegex' 25 | } 26 | } 27 | $AndElements = '$_.AccessRights -ne "AvailabilityOnly"' 28 | $Filter = [ScriptBlock]::Create((($OrElements -join ' -or '), $AndElements -join ' -and ')) 29 | foreach ($Permission in $FolderPermission) { 30 | $Permission | Where-Object $Filter 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /Posh365/Private/Permissions/OnPrem/ActiveDirectory/Get-ADGroupsWithProxyAddress.ps1: -------------------------------------------------------------------------------- 1 | Function Get-ADGroupsWithProxyAddress { 2 | <# 3 | .SYNOPSIS 4 | 5 | 6 | .EXAMPLE 7 | 8 | 9 | #> 10 | param ( 11 | [Parameter()] 12 | [hashtable] $DomainNameHash 13 | ) 14 | Try { 15 | import-module activedirectory -ErrorAction Stop -Verbose:$false 16 | } 17 | Catch { 18 | Write-Host "This module depends on the ActiveDirectory module." 19 | Write-Host "Please download and install from https://www.microsoft.com/en-us/download/details.aspx?id=45520" 20 | throw 21 | } 22 | 23 | # Find writable Global Catalog 24 | $context = New-Object System.DirectoryServices.ActiveDirectory.DirectoryContext('Forest') 25 | $dc = ([System.DirectoryServices.ActiveDirectory.GlobalCatalog]::FindOne($context, [System.DirectoryServices.ActiveDirectory.LocatorOptions]'ForceRediscovery, WriteableRequired')).name 26 | 27 | Get-ADGroup -filter 'proxyaddresses -ne "$null"' -server ($dc + ":3268") -SearchBase (Get-ADRootDSE).rootdomainnamingcontext -SearchScope Subtree -Properties mail 28 | } -------------------------------------------------------------------------------- /Posh365/Private/Permissions/OnPrem/ActiveDirectory/Get-ADObjectsWithProxyAddress.ps1: -------------------------------------------------------------------------------- 1 | Function Get-ADObjectsWithProxyAddress { 2 | 3 | param ( 4 | [Parameter()] 5 | [hashtable] $DomainNameHash 6 | ) 7 | 8 | # Find writable Global Catalog 9 | $context = New-Object System.DirectoryServices.ActiveDirectory.DirectoryContext('Forest') 10 | $dc = ([System.DirectoryServices.ActiveDirectory.GlobalCatalog]::FindOne($context, [System.DirectoryServices.ActiveDirectory.LocatorOptions]'ForceRediscovery, WriteableRequired')).name 11 | 12 | $Properties = @( 13 | 'UserPrincipalName', 'samaccountname', 'displayname', 'canonicalname', 'proxyaddresses' 14 | 'mail', 'msExchRecipientDisplayType', 'msExchRecipientTypeDetails') 15 | 16 | $Selectproperties = @( 17 | 'UserPrincipalName', 'distinguishedname', 'canonicalname', 'displayname', 'mail' 18 | 'Objectguid', 'msExchRecipientDisplayType', 'msExchRecipientTypeDetails' 19 | ) 20 | $CalculatedProps = @( 21 | @{n = "logon"; e = { ($DomainNameHash.($_.distinguishedname -replace '^.+?DC=' -replace ',DC=', '.')) + "\" + $_.samaccountname } }, 22 | @{n = "PrimarySMTPAddress" ; e = { ( $_.proxyAddresses | Where-Object { $_ -cmatch "SMTP:" }).Substring(5) } } 23 | ) 24 | Get-ADObject -filter 'proxyaddresses -ne "$null"' -server ($dc + ":3268") -SearchBase (Get-ADRootDSE).rootdomainnamingcontext -SearchScope Subtree -Properties $Properties | 25 | Select-Object ($Selectproperties + $CalculatedProps) 26 | } 27 | -------------------------------------------------------------------------------- /Posh365/Private/Permissions/OnPrem/ActiveDirectory/Get-ADUsersWithProxyAddress.ps1: -------------------------------------------------------------------------------- 1 | Function Get-ADUsersWithProxyAddress { 2 | <# 3 | .SYNOPSIS 4 | 5 | 6 | .EXAMPLE 7 | 8 | 9 | #> 10 | param ( 11 | [Parameter()] 12 | [hashtable] $DomainNameHash 13 | ) 14 | Try { 15 | import-module activedirectory -ErrorAction Stop -Verbose:$false 16 | } 17 | Catch { 18 | Write-Host "This module depends on the ActiveDirectory module." 19 | Write-Host "Please download and install from https://www.microsoft.com/en-us/download/details.aspx?id=45520" 20 | throw 21 | } 22 | 23 | # Find writable Global Catalog 24 | $context = New-Object System.DirectoryServices.ActiveDirectory.DirectoryContext('Forest') 25 | $dc = ([System.DirectoryServices.ActiveDirectory.GlobalCatalog]::FindOne($context, [System.DirectoryServices.ActiveDirectory.LocatorOptions]'ForceRediscovery, WriteableRequired')).name 26 | 27 | Get-ADUser -filter 'proxyaddresses -ne "$null"' -server ($dc + ":3268") -SearchBase (Get-ADRootDSE).rootdomainnamingcontext -SearchScope Subtree -Properties displayname, canonicalname, mail, proxyaddresses | Select distinguishedname, mail, ObjectGUID, canonicalname, displayname, userprincipalname, @{n = "logon"; e = {($DomainNameHash.($_.distinguishedname -replace '^.+?DC=' -replace ',DC=', '.')) + "\" + $_.samaccountname}}, @{n = "PrimarySmtpAddress" ; e = {( $_.proxyAddresses | Where-Object {$_ -cmatch "SMTP:"})}} 28 | } -------------------------------------------------------------------------------- /Posh365/Private/Security/ConditionalAccess/Get-ConditionalAccessPolicyData.ps1: -------------------------------------------------------------------------------- 1 | function Get-ConditionalAccessPolicyData { 2 | [CmdletBinding()] 3 | param ( 4 | 5 | ) 6 | if ([datetime]::UtcNow -ge $TimeToRefresh) { Connect-PoshGraphRefresh } 7 | $RestSplat = @{ 8 | Uri = "https://graph.microsoft.com/beta/identity/conditionalAccess/policies" 9 | Headers = @{ "Authorization" = "Bearer $Token" } 10 | Method = 'Get' 11 | } 12 | Invoke-RestMethod @RestSplat -Verbose:$false | Select-Object -ExpandProperty value 13 | 14 | } 15 | -------------------------------------------------------------------------------- /Posh365/Private/Security/Get-DNSSECDetails.ps1: -------------------------------------------------------------------------------- 1 | function Get-DNSSECDetails { 2 | [CmdletBinding()] 3 | param ( 4 | [Parameter()] 5 | $DomainName 6 | ) 7 | $ResolveSplat = @{ 8 | Name = $DomainName 9 | Type = 'DNSKEY' 10 | ErrorAction = 'SilentlyContinue' 11 | WarningAction = 'SilentlyContinue' 12 | Server = '8.8.8.8' 13 | } 14 | $dnskey_dnsrecord = Resolve-DnsName @ResolveSplat | Where-Object { $_.Type -eq 'DNSKEY' } 15 | $dnskey_exists = (($dnskey_dnsrecord | Measure-Object | Select-Object -ExpandProperty Count) -gt 0) 16 | 17 | # If we don't detect an MTA-STS DNS record, return 18 | if ($dnskey_dnsrecord -eq $null) { 19 | Write-Verbose "Couldn't locate a DNSKEY record for domain: $DomainName" 20 | $dnskey_dnsrecord = "N/A" 21 | } 22 | 23 | [PSCustomObject]@{ 24 | 'DNSKeyExists' = $dnskey_exists 25 | 'DNSKEYRecord' = $dnskey_dnsrecord 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Posh365/Private/Security/Get-DmarcPolicy.ps1: -------------------------------------------------------------------------------- 1 | function Get-DmarcPolicy { 2 | [CmdletBinding()] 3 | param ( 4 | [Parameter()] 5 | $DomainData 6 | ) 7 | $record = $DomainData.DMARC | Where-Object { $_.Strings -like '*v=DMARC1*' } -ErrorAction SilentlyContinue | Select-Object -ExpandProperty Strings -ErrorAction SilentlyContinue 8 | 9 | if ($record -eq $null) { return "N/A" } 10 | 11 | $domainPolicy = $record.Split(';') | Where-Object { $_ -like "* p=*" } 12 | 13 | if ($domainPolicy) { 14 | $domainPolicy = $domainPolicy.Replace(' ', '') 15 | $domainPolicy = $domainPolicy.Replace('p=', '') 16 | $domainPolicy.ToUpper() 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Posh365/Private/Security/Get-DmarcRecordText.ps1: -------------------------------------------------------------------------------- 1 | function Get-DmarcRecordText { 2 | [CmdletBinding()] 3 | param ( 4 | [Parameter()] 5 | $DomainData 6 | ) 7 | $record = $DomainData.DMARC | Where-Object { $_.Strings -like '*v=DMARC1*' } -ErrorAction SilentlyContinue | 8 | Select-Object -ExpandProperty Strings -ErrorAction SilentlyContinue 9 | 10 | if ($record) { 11 | return $record 12 | } 13 | else { 14 | return "N/A" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Posh365/Private/Security/Get-DmarcSubdomainPolicy.ps1: -------------------------------------------------------------------------------- 1 | function Get-DmarcSubdomainPolicy { 2 | [CmdletBinding()] 3 | param ( 4 | [Parameter()] 5 | $DomainData 6 | ) 7 | $record = $DomainData.DMARC | Where-Object { $_.Strings -like '*v=DMARC1*' } -ErrorAction SilentlyContinue | Select-Object -ExpandProperty Strings -ErrorAction SilentlyContinue 8 | 9 | if ($record -eq $null) { return "N/A" } 10 | 11 | $subDomainPolicy = $record.Split(';') | Where-Object { $_ -like "*sp=*" } 12 | 13 | if ($subDomainPolicy) { 14 | $subDomainPolicy = $subDomainPolicy.Replace(' ', '') 15 | $subDomainPolicy = $subDomainPolicy.Replace('sp=', '') 16 | $subDomainPolicy.ToUpper() 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Posh365/Private/Security/Get-DomainFederationDataFromO365.ps1: -------------------------------------------------------------------------------- 1 | function Get-DomainFederationDataFromO365 { 2 | [CmdletBinding()] 3 | param ( 4 | [Parameter()] 5 | $DomainName 6 | ) 7 | try { 8 | $uri = "https://login.microsoftonline.com/common/userrealm/?user=testuser@$DomainName&api-version=2.1&checkForMicrosoftAccount=true" 9 | 10 | Invoke-RestMethod -Uri $uri -ErrorAction Stop -UseBasicParsing 11 | 12 | } 13 | catch { 14 | Write-Verbose "Couldn't retrieve federation data for domain: $DomainName" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Posh365/Private/Security/Get-LowestPreferenceMX.ps1: -------------------------------------------------------------------------------- 1 | function Get-LowestPreferenceMX { 2 | [CmdletBinding()] 3 | param ( 4 | [Parameter()] 5 | $DomainData 6 | ) 7 | if ($DomainData.MX -eq $null) { return } 8 | 9 | $DomainData.MX | Sort-Object -Property Preference | Select-Object -First 1 -ExpandProperty NameExchange -ErrorAction SilentlyContinue -WarningAction SilentlyContinue 10 | } 11 | -------------------------------------------------------------------------------- /Posh365/Private/Security/Get-O365FederationHostname.ps1: -------------------------------------------------------------------------------- 1 | function Get-O365FederationHostname { 2 | [CmdletBinding()] 3 | param ( 4 | [Parameter()] 5 | $DomainData 6 | ) 7 | if ((Test-O365IsFederated $DomainData) -eq $false) { 8 | return 'N/A' 9 | } 10 | else { 11 | # Determine the auth URL hostname component. Not as elegant as a regex, but it works 12 | $authUrlHost = $DomainData.FEDERATION.AuthURL 13 | if ($authUrlHost) { 14 | $authUrlHost = $authUrlHost.Replace('https://', '') # Remove HTTPS:// from the URL 15 | $authUrlHost = $authUrlHost.Replace('http://', '') # Remove HTTP:// from the URL, almost 0% chance of this ever existing 16 | $authUrlHost = $authUrlHost.Split('/')[0] # Split the auth URL, and grab the first component, the hostname 17 | 18 | return $authUrlHost 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Posh365/Private/Security/Get-SpfRecordMode.ps1: -------------------------------------------------------------------------------- 1 | function Get-SpfRecordMode { 2 | [CmdletBinding()] 3 | param ( 4 | [Parameter()] 5 | $DomainData 6 | ) 7 | $record = Get-SpfRecordText $DomainData 8 | 9 | if ($record) { 10 | switch -Wildcard ($record) { 11 | '*-all' { $determination = "HARDFAIL" } 12 | '*+all' { $determination = "PASS" } 13 | '*~all' { $determination = "SOFTFAIL" } 14 | '*`?all' { $determination = "NEUTRAL" } 15 | 16 | Default { $determination = "Other/Undetermined" } 17 | } 18 | 19 | return $determination 20 | } 21 | else { 22 | return "N/A" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Posh365/Private/Security/Get-SpfRecordText.ps1: -------------------------------------------------------------------------------- 1 | function Get-SpfRecordText { 2 | [CmdletBinding()] 3 | param ( 4 | [Parameter()] 5 | $domainData 6 | ) 7 | $record = $domainData.TXT | Where-Object { $_.Strings -like '*v=spf1*' } -ErrorAction SilentlyContinue 8 | 9 | if ($record -eq $null) { return } 10 | 11 | if (($record[0].Strings | Measure-Object).Count -gt 1) { 12 | $record[0].Strings -join '' 13 | } 14 | else { 15 | $record[0].Strings[0] 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Posh365/Private/Security/Invoke-TestSPFRecord.ps1: -------------------------------------------------------------------------------- 1 | function Invoke-TestSPFRecord { 2 | [CmdletBinding()] 3 | param ( 4 | [Parameter()] 5 | $DomainName 6 | ) 7 | # $web = Invoke-WebRequest -Uri 'http://www.kitterman.com/spf/validate.html' -UseBasicParsing 8 | # $web.forms[0].fields.domain = $DomainName 9 | $result = Invoke-RestMethod "http://www.kitterman.com/spf/getspf3.py?serial=fred12&domain=${DomainName}" -UseBasicParsing 10 | $result.replace("`r`n", "--") 11 | } 12 | -------------------------------------------------------------------------------- /Posh365/Private/Security/Test-AADIsUnmanaged.ps1: -------------------------------------------------------------------------------- 1 | function Test-AADIsUnmanaged { 2 | [CmdletBinding()] 3 | param ( 4 | [Parameter()] 5 | $DomainData 6 | ) 7 | if ($DomainData.FEDERATION -eq $null) { return "N/A" } 8 | 9 | if ($DomainData.FEDERATION.IsViral -eq $null) { return $false } 10 | 11 | $DomainData.FEDERATION.IsViral 12 | } 13 | -------------------------------------------------------------------------------- /Posh365/Private/Security/Test-DNSHostingProvider.ps1: -------------------------------------------------------------------------------- 1 | function Test-DnsHostingProvider { 2 | [CmdletBinding()] 3 | param ( 4 | [Parameter()] 5 | $DomainData 6 | ) 7 | if ($DomainData.NS) { 8 | $nameServerRecords = ($DomainData.NS | Where-Object { $_.NameHost -ne $null } -ErrorAction SilentlyContinue | Select-Object -ExpandProperty NameHost -ErrorAction SilentlyContinue) 9 | 10 | if ($nameServerRecords) { $nameServerRecords -join ',' } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Posh365/Private/Security/Test-DNSNameAdministrator.ps1: -------------------------------------------------------------------------------- 1 | function Test-DnsNameAdministrator { 2 | [CmdletBinding()] 3 | param ( 4 | [Parameter()] 5 | $DomainData 6 | ) 7 | $DomainData.SOA | Select-Object -First 1 -ExpandProperty NameAdministrator -ErrorAction SilentlyContinue 8 | } 9 | -------------------------------------------------------------------------------- /Posh365/Private/Security/Test-DmarcRecordExists.ps1: -------------------------------------------------------------------------------- 1 | function Test-DmarcRecordExists { 2 | [CmdletBinding()] 3 | param ( 4 | [Parameter()] 5 | $DomainData 6 | ) 7 | $record = $DomainData.DMARC | Where-Object { $_.Strings -like '*v=DMARC1*' } -ErrorAction SilentlyContinue 8 | 9 | ($record -ne $null) 10 | } 11 | -------------------------------------------------------------------------------- /Posh365/Private/Security/Test-ExchangeOnlineDomain.ps1: -------------------------------------------------------------------------------- 1 | function Test-ExchangeOnlineDomain { 2 | [CmdletBinding()] 3 | param ( 4 | [Parameter()] 5 | $DomainData 6 | ) 7 | $isOffice365Tenant = "No" 8 | 9 | $msoidRecord = $DomainData.MSOID | Where-Object { $_.NameHost -like '*clientconfig.microsoftonline*' } -ErrorAction SilentlyContinue 10 | if ($msoidRecord) { $isOffice365Tenant = 'Possibly' } 11 | 12 | $txtVerificationRecord = $DomainData.TXT | Where-Object { $_.Strings -like 'MS=ms*' } -ErrorAction SilentlyContinue 13 | if ($txtVerificationRecord) { $isOffice365Tenant = 'Possibly' } 14 | 15 | $mdmRecord = $DomainData.ENTERPRISEREGISTRATION | Where-Object { $_.NameHost -eq 'enterpriseregistration.windows.net ' } -ErrorAction SilentlyContinue 16 | if ($mdmRecord) { $isOffice365Tenant = 'Likely' } 17 | 18 | $autoDiscoverRecord = $DomainData.AUTODISCOVER | Where-Object { $_.NameHost -eq 'autodiscover.outlook.com' } -ErrorAction SilentlyContinue 19 | if ($autoDiscoverRecord) { $isOffice365Tenant = 'Yes' } 20 | 21 | $spfRecord = $DomainData.TXT | Where-Object { $_.Strings -like '*spf.protection.outlook.com*' } -ErrorAction SilentlyContinue 22 | if ($spfRecord) { $isOffice365Tenant = 'Yes' } 23 | 24 | $mxRecords = $DomainData.MX | Where-Object { ($_.NameExchange -like '*mail.protection.outlook.com*') -or ($_.NameExchange -like '*eo.outlook.com') } -ErrorAction SilentlyContinue 25 | if ($mxRecords) { $isOffice365Tenant = 'Yes' } 26 | 27 | $isOffice365Tenant 28 | } 29 | -------------------------------------------------------------------------------- /Posh365/Private/Security/Test-MtaStsRecordExists.ps1: -------------------------------------------------------------------------------- 1 | function Test-MtaStsRecordExists { 2 | [CmdletBinding()] 3 | param ( 4 | [Parameter()] 5 | $DomainData 6 | ) 7 | $mtaRecord = $DomainData.MTASTS | Where-Object { $_.Strings -like "v=STSv1*" } -ErrorAction SilentlyContinue | Select-Object -ExpandProperty Strings -ErrorAction SilentlyContinue 8 | 9 | ($mtaRecord -ne $null) 10 | } 11 | -------------------------------------------------------------------------------- /Posh365/Private/Security/Test-O365DirectoryID.ps1: -------------------------------------------------------------------------------- 1 | function Test-O365DirectoryID { 2 | [CmdletBinding()] 3 | param ( 4 | [Parameter()] 5 | $DomainName 6 | ) 7 | try { 8 | $uri = "https://login.windows.net/$DomainName/.well-known/openid-configuration" 9 | 10 | $openIDResponse = Invoke-RestMethod -Uri $uri -ErrorAction Stop 11 | 12 | } 13 | catch { 14 | Write-Verbose "Couldn't retrieve federation data for domain: $DomainName" 15 | } 16 | 17 | if ($openIDResponse.token_endpoint) { 18 | $openIDResponse.token_endpoint.split('/')[3] 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Posh365/Private/Security/Test-O365Dkim.ps1: -------------------------------------------------------------------------------- 1 | function Test-O365Dkim { 2 | [CmdletBinding()] 3 | param ( 4 | [Parameter()] 5 | $DomainData 6 | ) 7 | $isOffice365Tenant = Test-ExchangeOnlineDomain $DomainData 8 | 9 | if ($isOffice365Tenant -eq 'No') { return "N/A" } 10 | 11 | if (($DomainData.O365DKIM.SELECTOR1 -ne $null) -and ($DomainData.O365DKIM.SELECTOR2 -ne $null)) { 12 | $True 13 | } 14 | else { 15 | $false 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Posh365/Private/Security/Test-O365DomainTenantName.ps1: -------------------------------------------------------------------------------- 1 | function Test-O365DomainTenantName { 2 | [CmdletBinding()] 3 | param ( 4 | [Parameter()] 5 | $DomainData 6 | ) 7 | $isOffice365Tenant = Test-ExchangeOnlineDomain $DomainData 8 | 9 | if ($isOffice365Tenant -eq 'No') { return "N/A" } 10 | 11 | $lowestPreferenceMX = $DomainData.MX | Where-Object { $_.NameExchange -ne $null } -ErrorAction SilentlyContinue | 12 | Sort-Object -Property Preference | Select-Object -First 1 -ErrorAction SilentlyContinue 13 | 14 | $nameExchange = $lowestPreferenceMX | Select-Object -ExpandProperty NameExchange -ErrorAction SilentlyContinue 15 | 16 | if ($nameExchange -eq $null) { return "Undetermined" } 17 | 18 | if ($nameExchange.Contains('mail.protection.outlook.com')) { 19 | $record = $nameExchange | Where-Object { $_ -like '*.mail.protection.outlook.com' } | Select-Object -First 1 20 | if ($record) { $record.Replace('.mail.protection.outlook.com', '') } 21 | } 22 | else { return "Undetermined" } 23 | } 24 | -------------------------------------------------------------------------------- /Posh365/Private/Security/Test-O365IsFederated.ps1: -------------------------------------------------------------------------------- 1 | function Test-O365IsFederated { 2 | [CmdletBinding()] 3 | param ( 4 | [Parameter()] 5 | $DomainData 6 | ) 7 | 8 | # Check if we have any federation data for this domain 9 | if ($DomainData.FEDERATION -eq $null) { return "N/A" } 10 | 11 | if ($DomainData.FEDERATION.NameSpaceType -eq 'Federated') { 12 | return $true 13 | } 14 | else { 15 | return $false 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Posh365/Private/Security/Test-SpfRecordExists.ps1: -------------------------------------------------------------------------------- 1 | function Test-SpfRecordExists { 2 | [CmdletBinding()] 3 | param ( 4 | [Parameter()] 5 | $domainData 6 | ) 7 | $record = $domainData.TXT | Where-Object { $_.Strings -like '*v=spf1*' } -ErrorAction SilentlyContinue 8 | 9 | if (($record | Measure-Object).Count -gt 1) { 10 | return "ERROR: MULTIPLE SPF RECORDS" 11 | } 12 | else { 13 | ($record -ne $null) 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Posh365/Private/SharePointandOneDrive/Invoke-LoadMethod.ps1: -------------------------------------------------------------------------------- 1 | Function Invoke-LoadMethod { 2 | param( 3 | [Parameter(Mandatory)] 4 | [Microsoft.SharePoint.Client.ClientObject]$Object, 5 | [Parameter(Mandatory)] 6 | [string]$PropertyName 7 | ) 8 | $ctx = $Object.Context 9 | $load = [Microsoft.SharePoint.Client.ClientContext].GetMethod("Load") 10 | $type = $Object.GetType() 11 | $clientLoad = $load.MakeGenericMethod($type) 12 | 13 | $Parameter = [System.Linq.Expressions.Expression]::Parameter(($type), $type.Name) 14 | $Expression = [System.Linq.Expressions.Expression]::Lambda( 15 | [System.Linq.Expressions.Expression]::Convert( 16 | [System.Linq.Expressions.Expression]::PropertyOrField($Parameter, $PropertyName), 17 | [System.Object] 18 | ), 19 | $($Parameter) 20 | ) 21 | $ExpressionArray = [System.Array]::CreateInstance($Expression.GetType(), 1) 22 | $ExpressionArray.SetValue($Expression, 0) 23 | $clientLoad.Invoke($ctx, @($Object, $ExpressionArray)) 24 | } -------------------------------------------------------------------------------- /Posh365/Public/ADConnect/Get-ADConnectError.ps1: -------------------------------------------------------------------------------- 1 | function Get-ADConnectError { 2 | <# 3 | .SYNOPSIS 4 | Provides in readable format, all AD Connect provisioning errors within MSOnline 5 | 6 | .DESCRIPTION 7 | Provides in readable format, all AD Connect provisioning errors within MSOnline 8 | 9 | .EXAMPLE 10 | Get-ADConnectError | Export-Csv .\ADConnectErrors.csv -notypeinformation 11 | 12 | .NOTES 13 | Connect to MSOnline first 14 | 15 | Connect-Cloud can be used to do this: 16 | Connect-Cloud contoso -msonline 17 | #> 18 | 19 | Param ( 20 | 21 | ) 22 | $ErrList = Get-MsolDirSyncProvisioningError -All 23 | 24 | foreach ($Err in $ErrList) { 25 | $ProvList = $Err.ProvisioningErrors 26 | foreach ($Prov in $ProvList) { 27 | [PSCustomObject]@{ 28 | DisplayName = $Err.DisplayName 29 | ImmutableId = $Err.ImmutableId 30 | ObjectType = $Err.ObjectType 31 | ErrorCategory = $Prov.ErrorCategory 32 | PropertyName = $Prov.PropertyName 33 | PropertyValue = $Prov.PropertyValue 34 | WhenStarted = $Prov.WhenStarted 35 | ProxyAddresses = @($Err.ProxyAddresses) -ne '' -join '|' 36 | ObjectId = $Err.ObjectId 37 | LastDirSyncTime = $Err.LastDirSyncTime 38 | } 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /Posh365/Public/ActiveDirectory/User/Convert-Id.ps1: -------------------------------------------------------------------------------- 1 | function Convert-Id { 2 | <# 3 | .SYNOPSIS 4 | Convert ImmutableID to ObjectGuid OR ObjectGuid to ImmutableID 5 | 6 | .DESCRIPTION 7 | Convert ImmutableID to ObjectGuid OR ObjectGuid to ImmutableID 8 | 9 | .PARAMETER Id 10 | Enter an ImmutableID or ObjectGuid 11 | 12 | .EXAMPLE 13 | Convert-Id -Id 3MK05obeZEm9/xvs8svAFw== 14 | 15 | .EXAMPLE 16 | Convert-Id -Id e6b4csdc-des6-4d34-bdfe-9adff2cbc017 17 | 18 | .NOTES 19 | General notes 20 | #> 21 | 22 | param ( 23 | [Parameter()] 24 | $Id 25 | ) 26 | 27 | end { 28 | try { 29 | $Guid = [GUID]$Id 30 | $Byte = $Guid.ToByteArray() 31 | [PSCustomObject]@{ 32 | Object = [system.convert]::ToBase64String($Byte) 33 | Type = 'immutableID' 34 | } 35 | } 36 | catch { 37 | if ($Decoded = [system.convert]::frombase64string($Id)) { 38 | if ($Guid = [GUID]$Decoded) { 39 | [PSCustomObject]@{ 40 | Object = $Guid.ToString() 41 | Type = 'ObjectGuid' 42 | } 43 | } 44 | else { 45 | Write-Warning "Not an ObjectGuid or ImmutableID" 46 | } 47 | } 48 | else { 49 | Write-Warning "Not an ObjectGuid or ImmutableID" 50 | } 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /Posh365/Public/AddressList/Get-ExchangeOfflineAddressBook.ps1: -------------------------------------------------------------------------------- 1 | function Get-ExchangeOfflineAddressBook { 2 | <# 3 | .SYNOPSIS 4 | Short description 5 | 6 | .DESCRIPTION 7 | Long description 8 | 9 | .PARAMETER OAB 10 | Offline Address Book 11 | 12 | .EXAMPLE 13 | Get-OfflineAddressBook | Get-ExchangeOfflineAddressBook 14 | 15 | .EXAMPLE 16 | Get-OfflineAddressBook | Get-ExchangeOfflineAddressBook | Export-Csv .\OABs.csv -notypeinformation 17 | 18 | .EXAMPLE 19 | Get-OfflineAddressBook -identity "Internal Mail Users" | Get-ExchangeOfflineAddressBook 20 | 21 | .NOTES 22 | General notes 23 | #> 24 | 25 | [CmdletBinding()] 26 | param ( 27 | 28 | [Parameter(ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)] 29 | $OABList 30 | ) 31 | begin { 32 | 33 | } 34 | process { 35 | foreach ($OAB in $OABList) { 36 | $OfflineAddressBook = New-Object -TypeName PSObject -Property @{ 37 | Name = $OAB.Name 38 | IsDefault = $OAB.IsDefault 39 | AddressLists = @($OAB.AddressLists) -ne '' -join '|' 40 | Identity = $OAB.Identity 41 | Guid = $OAB.Guid 42 | ExchangeVersion = $OAB.ExchangeVersion 43 | } 44 | $OfflineAddressBook | Select-Object 'Name', 'IsDefault', 'AddressLists', 'Identity', 'Guid', 'ExchangeVersion' 45 | } 46 | } 47 | end { 48 | 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /Posh365/Public/Azure/Get-AzureLoadBalancerReport.ps1: -------------------------------------------------------------------------------- 1 | 2 | function Get-AzureLoadBalancerReport { 3 | param ( 4 | [Parameter(Mandatory)] 5 | $LoadBalancer 6 | ) 7 | 8 | $MaxBackendPools = ($LoadBalancer.foreach( {$_.BackendAddressPools.count}) | Measure-Object -Maximum).Maximum 9 | $MaxFrontendIpConfigs = ($LoadBalancer.foreach( {$_.FrontendIpConfigurations.count}) | Measure-Object -Maximum).Maximum 10 | 11 | $LoadBalancer | Get-AzureLoadBalancerHelper -MaxBackendPools $MaxBackendPools -MaxFrontendIpConfigs $MaxFrontendIpConfigs 12 | 13 | } -------------------------------------------------------------------------------- /Posh365/Public/Azure/Get-AzureStorageReport.ps1: -------------------------------------------------------------------------------- 1 | function Get-AzureStorageReport { 2 | Param( 3 | [Parameter(Mandatory, ValueFromPipeline, ValueFromPipelineByPropertyName)] 4 | $StorageAcct 5 | ) 6 | begin { 7 | } 8 | process { 9 | foreach ($CurStorageAcct in $StorageAcct) { 10 | [PSCustomObject]@{ 11 | ResourceGroupName = $CurStorageAcct.ResourceGroupName 12 | StorageAccountName = $CurStorageAcct.StorageAccountName 13 | Location = $CurStorageAcct.Location 14 | StorageTier = $CurStorageAcct.Sku.Tier 15 | ReplicationType = $CurStorageAcct.Sku.Name 16 | } 17 | } 18 | } 19 | end { 20 | 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Posh365/Public/Azure/Get-AzureVMReport.ps1: -------------------------------------------------------------------------------- 1 | function Get-AzureVMReport { 2 | [CmdletBinding()] 3 | 4 | param( 5 | [Parameter(Mandatory)] 6 | $VM 7 | ) 8 | 9 | $MaxDataDisks = ($VM.foreach( {$_.StorageProfile.DataDisks.count}) | Measure-Object -Maximum).Maximum 10 | $MaxOsDisks = ($VM.foreach( {$_.StorageProfile.OsDisk.count}) | Measure-Object -Maximum).Maximum 11 | 12 | $VM | Get-AzureVMHelper -MaxDataDisks $MaxDataDisks -MaxOsDisks $MaxOsDisks 13 | } -------------------------------------------------------------------------------- /Posh365/Public/Azure/Get-AzureVNetReport.ps1: -------------------------------------------------------------------------------- 1 | function Get-AzureVNetReport { 2 | param ( 3 | [Parameter(Mandatory)] 4 | $VNet 5 | ) 6 | 7 | $MaxSubnets = ($VNet.foreach( {$_.Subnets.count}) | Measure-Object -Maximum).Maximum 8 | 9 | $VNet | Get-AzureVNetHelper -MaxSubnets $MaxSubnets 10 | 11 | } -------------------------------------------------------------------------------- /Posh365/Public/Azure/Get-AzureVPNReport.ps1: -------------------------------------------------------------------------------- 1 | function Get-AzureVPNReport { 2 | 3 | Param( 4 | [Parameter(Mandatory, ValueFromPipeline, ValueFromPipelineByPropertyName)] 5 | $VPNGateway, 6 | 7 | [Parameter(Mandatory)] 8 | [string] $ResourceGroupName 9 | ) 10 | begin { 11 | 12 | } 13 | process { 14 | 15 | foreach ($CurVpnGateway in $VPNGateway) { 16 | $id = $CurVpnGateway.IpConfigurations.PublicIPAddress.id 17 | $PublicIP = (Get-AzureRmPublicIpAddress -ResourceGroup $ResourceGroupName -Name ($id -split '/')[8]).IpAddress 18 | 19 | [PSCustomObject]@{ 20 | ResourceGroupName = $CurVpnGateway.ResourceGroupName 21 | Location = $CurVpnGateway.Location 22 | Name = $CurVpnGateway.Name 23 | ProvisioningState = $CurVpnGateway.ProvisioningState 24 | GatewayType = $CurVpnGateway.GatewayType 25 | VpnType = $CurVpnGateway.VpnType 26 | SkuTier = $CurVpnGateway.Sku.Tier 27 | BgpPeeringAddress = $CurVpnGateway.BgpSettings.BgpPeeringAddress 28 | PrivateIpAllocationMethod = $CurVpnGateway.IpConfigurations.PrivateIpAllocationMethod 29 | PublicIpAddress = $PublicIP 30 | } 31 | } 32 | } 33 | end { 34 | 35 | } 36 | } -------------------------------------------------------------------------------- /Posh365/Public/Azure/Get-DiscoveryAzure.ps1: -------------------------------------------------------------------------------- 1 | function Get-DiscoveryAzure { 2 | param ( 3 | [Parameter(Mandatory)] 4 | [string] $Tenant, 5 | 6 | [Parameter(Mandatory)] 7 | [string] $ReportPath, 8 | 9 | [Parameter()] 10 | [switch] $SkipLogin, 11 | 12 | [Parameter()] 13 | [switch] $SaveContext 14 | ) 15 | 16 | 17 | $TenantPath = Join-Path $ReportPath $Tenant 18 | if (-not (Test-Path $TenantPath)) { 19 | New-Item -Path $TenantPath -ItemType Directory -Force > $null 20 | } 21 | 22 | if (-not $SkipLogin) { 23 | Login-AzureRmAccount 24 | } 25 | 26 | $Sub = Get-AzureRmSubscription 27 | 28 | foreach ($CurSub in $Sub) { 29 | 30 | $SubId = $CurSub.Id 31 | $SubName = $CurSub.Name 32 | 33 | if ($CurSub.State -ne "Disabled") { 34 | Get-AzureInventory -SubId $SubId -SubName $SubName -ReportPath $TenantPath 35 | } 36 | } 37 | if (-not $SaveContext) { 38 | Get-AzureRmContext | Remove-AzureRmContext 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /Posh365/Public/AzureAD/Get-AzureActiveDirectoryDevice.ps1: -------------------------------------------------------------------------------- 1 | function Get-AzureActiveDirectoryDevice { 2 | param ( 3 | 4 | ) 5 | Get-AzureADDevice -All:$true | Select-Object @( 6 | 'DeviceOSType' 7 | 'DisplayName' 8 | 'DeviceOSVersion' 9 | 'DeviceTrustType' 10 | @{ 11 | Name = 'DirSyncEnabled' 12 | Expression = { [bool]$_.DirSyncEnabled } 13 | } 14 | 'ApproximateLastLogonTimeStamp' 15 | 'LastDirSyncTime' 16 | 17 | @{ 18 | Name = 'isManaged' 19 | Expression = { [bool]$_.isManaged } 20 | } 21 | 22 | 23 | @{ 24 | Name = 'isCompliant' 25 | Expression = { [bool]$_.isCompliant } 26 | } 27 | 'ProfileType' 28 | 'DeviceId' 29 | ) 30 | } 31 | -------------------------------------------------------------------------------- /Posh365/Public/AzureAD/Get-AzureUserOnPremisesOUs.ps1: -------------------------------------------------------------------------------- 1 | function Get-AzureUserOnPremisesOUs { 2 | [CmdletBinding()] 3 | param ( 4 | ) 5 | end { 6 | $AllUsers = Get-AzureADUser -All:$true 7 | $AllUsers | Select-Object @( 8 | @{ 9 | Name = 'Type' 10 | Expression = { 'User' } 11 | } 12 | @{ 13 | Name = 'OU' 14 | Expression = { Convert-DistinguishedToCanonical -DistinguishedName ($_.extensionproperty.onPremisesDistinguishedName -replace '^.+?,(?=(OU|CN)=)') } 15 | } 16 | ) | Where-Object { $_.OU } | Group-Object Type, OU | Select-Object @( 17 | 'Count' 18 | @{ 19 | Name = 'OU' 20 | Expression = { (($_.Name).split(','))[1].trim() } 21 | } 22 | @{ 23 | Name = 'Type' 24 | Expression = { (($_.Name).split(','))[0].trim() } 25 | } 26 | ) 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Posh365/Public/Compliance/Find-Spill.ps1: -------------------------------------------------------------------------------- 1 | function Find-Spill { 2 | [CmdletBinding()] 3 | param () 4 | do { 5 | $Splat = try { 6 | Invoke-Expression (Show-Command -NoCommonParameter -PassThru SpillFinder) -ErrorAction Stop 7 | } 8 | catch { 9 | Write-Host "Show-Command Error: $($_.Exception.Message)" -ForegroundColor Red 10 | return 11 | } 12 | $TenantPath = Join-Path -Path $Env:USERPROFILE -ChildPath ('.Posh365/Credentials/Graph/{0}' -f $Splat.Tenant) 13 | $TenantCred = Join-Path -Path $TenantPath -ChildPath ('{0}Cred.xml' -f $Splat.Tenant) 14 | $TenantConfig = Join-Path -Path $TenantPath -ChildPath ('{0}Config.xml' -f $Splat.Tenant) 15 | if (-not (Test-Path $TenantConfig) -or -not (Test-Path $TenantCred) ) { Export-GraphConfig -Tenant $Splat.Tenant } 16 | } until ($Splat.count -ge 1) 17 | if ($Splat.ContainsKey('OptionToDeleteMessages')) { 18 | Invoke-FindSpill @Splat | Out-GridView -PassThru -Title 'Choose Messages to Delete and Click OK' | Remove-GraphMailMessage 19 | } 20 | else { 21 | Invoke-FindSpill @Splat | Out-GridView -Title 'Messages found' 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Posh365/Public/Compliance/Get-ModifiedMailboxItem.ps1: -------------------------------------------------------------------------------- 1 | function Get-ModifiedMailboxItem { 2 | [CmdletBinding()] 3 | Param( 4 | [Parameter(Mandatory, ValueFromPipeline)] 5 | [Alias('UPN')] 6 | [ValidateNotNullOrEmpty()] 7 | [string] 8 | $UserPrincipalName 9 | ) 10 | process { 11 | Get-MailboxFolderStatistics -Identity $_ -IncludeOldestAndNewestItems | 12 | Sort-Object -Property OldestItemLastModifiedDate -Descending | 13 | Select-Object -Property @{ 14 | Name = 'UPN' 15 | Expression = { $UserPrincipalName } 16 | }, FolderPath, ItemsInFolder, OldestItemLastModifiedDate 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Posh365/Public/Connect/Connect-SharePointPNP.ps1: -------------------------------------------------------------------------------- 1 | function Connect-SharePointPNP { 2 | 3 | [CmdletBinding(SupportsShouldProcess = $true)] 4 | Param 5 | ( 6 | 7 | [Parameter(Mandatory)] 8 | [string] 9 | $Url 10 | 11 | ) 12 | end { 13 | [Net.ServicePointManager]::SecurityProtocol = [Net.ServicePointManager]::SecurityProtocol -bor [Net.SecurityProtocolType]::Tls12 14 | if ( -not (Get-Module -ListAvailable PnP.PowerShell)) { 15 | Install-Module PnP.PowerShell -Scope CurrentUser -Force -AllowClobber 16 | } 17 | Connect-PnPOnline -Url $Url -UseWebLogin 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Posh365/Public/Connect/Switch-AzureADModule.ps1: -------------------------------------------------------------------------------- 1 | function Switch-AzureADModule { 2 | param ( 3 | [Parameter()] 4 | [switch] 5 | $Preview 6 | ) 7 | [Net.ServicePointManager]::SecurityProtocol = [Net.ServicePointManager]::SecurityProtocol -bor [Net.SecurityProtocolType]::Tls12 8 | Get-Module 'AzureAD', 'AzureADPreview' -list | ForEach-Object { Remove-Item -Path $_.Path -Force } 9 | 10 | if ($Preview) { 11 | Install-Module -Name AzureADPreview -Scope CurrentUser -AllowPrerelease -Force 12 | } 13 | else { 14 | Install-Module -Name AzureAD -Scope CurrentUser -Force 15 | } 16 | } -------------------------------------------------------------------------------- /Posh365/Public/Discovery/Compare-List.ps1: -------------------------------------------------------------------------------- 1 | function Compare-List { 2 | param ( 3 | [Parameter(Mandatory)] 4 | [ValidateNotNull()] 5 | [System.IO.FileInfo] 6 | $ReferenceCsv, 7 | 8 | [Parameter(Mandatory)] 9 | [ValidateNotNull()] 10 | [System.IO.FileInfo] 11 | $DifferenceCsv, 12 | 13 | [Parameter()] 14 | [string] $FindInColumn = "UserPrincipalName" 15 | ) 16 | 17 | $dataSet1 = @{} 18 | Import-Csv $ReferenceCsv | ForEach-Object { 19 | $dataSet1.Add($_.$FindInColumn, $_) 20 | } 21 | 22 | $notFound = [System.Collections.Generic.HashSet[string]]::new() 23 | Import-Csv $DifferenceCsv | ForEach-Object { 24 | if (-not $dataSet1.Contains($_.$FindInColumn)) { 25 | [void]$notFound.Add($_.$FindInColumn) 26 | } 27 | } 28 | $notFound 29 | } 30 | # This needs to use to hashsets instead and you are doing nothing with the values of hashtable -------------------------------------------------------------------------------- /Posh365/Public/Discovery/Expand-IdFixReport.ps1: -------------------------------------------------------------------------------- 1 | function Expand-IdFixReport { 2 | <# 3 | .SYNOPSIS 4 | Adds OU column to idFIX report 5 | 6 | .DESCRIPTION 7 | Long description 8 | 9 | .PARAMETER ReportFile 10 | Parameter description 11 | 12 | .EXAMPLE 13 | Expand-IdFixReport -ReportFile .\idFix.csv |Export-PoshExcel .\IDFixWithOU.xlsx 14 | 15 | .NOTES 16 | General notes 17 | #> 18 | param ( 19 | [Parameter(Mandatory)] 20 | [string] $ReportFile 21 | ) 22 | 23 | $idFixReport = Import-Csv $ReportFile 24 | 25 | foreach ($id in $idFixReport) { 26 | [PSCustomObject]@{ 27 | ORGANIZATIONALUNIT = Convert-DistinguishedToCanonical -DistinguishedName ($id.DistinguishedName -replace '^.+?,(?=(OU|CN)=)') 28 | DISPLAYNAME = $id.DISTINGUISHEDNAME -replace '^CN=|,.*$' 29 | DISTINGUISHEDNAME = $id.DISTINGUISHEDNAME 30 | OBJECTCLASS = $id.OBJECTCLASS 31 | ATTRIBUTE = $id.ATTRIBUTE 32 | ERROR = $id.ERROR 33 | VALUE = $id.VALUE 34 | UPDATE = $id.UPDATE 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /Posh365/Public/Discovery/Get-DomainMatchingServicePrincipal.ps1: -------------------------------------------------------------------------------- 1 | function Get-DomainMatchingServicePrincipal { 2 | [CmdletBinding()] 3 | param ( 4 | 5 | ) 6 | end { 7 | $DomainList = '^(?:{0})$' -f ((Get-MsolDomain).name.foreach{ [regex]::Escape($_) } -join '|') 8 | $SPNList = Get-MsolServicePrincipal -All 9 | 10 | $SPNList.Where{ $_.ServicePrincipalNames -match $DomainList } | Select-Object @( 11 | @{ 12 | Name = 'DisplayName' 13 | Expression = { $_.DisplayName } 14 | } 15 | @{ 16 | Name = "AccountEnabled" 17 | Expression = { $_.AccountEnabled } 18 | } 19 | @{ 20 | Name = "ServicePrincipalName" 21 | Expression = { ($_.ServicePrincipalNames).Where{ $_ -match $DomainList } } 22 | } 23 | ) 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Posh365/Public/Discovery/Google/Export-GoogleAddress.ps1: -------------------------------------------------------------------------------- 1 | function Export-GoogleAddress { 2 | <# 3 | .SYNOPSIS 4 | Google's GAM shared mailbox dump is exported with relevant data to import into 365 5 | 6 | .DESCRIPTION 7 | Long description 8 | 9 | .PARAMETER SharedCsv 10 | Parameter description 11 | 12 | .EXAMPLE 13 | Export-GoogleAddress -SharedCsv C:\Scripts\Q\archive\QShared.csv 14 | 15 | .EXAMPLE 16 | Export-GoogleAddress -SharedCsv C:\Scripts\Q\archive\QShared.csv | Export-csv .\for365.csv -notypeinformation 17 | 18 | .NOTES 19 | EXAMPLE OF OUTPUT.... 20 | 21 | primaryEmail,name.familyName,name.fullName,name.givenName 22 | joe@contoso.com,smith,joe smith,joe 23 | jane@contoso.com,jones,jane jones,jane 24 | 25 | #> 26 | 27 | 28 | param ( 29 | 30 | [Parameter(Mandatory)] 31 | [string] $SharedCsv 32 | 33 | ) 34 | 35 | $CsvList = Import-Csv $SharedCsv 36 | $PropList = ($CsvList | Select-Object -first 1).psobject.properties.name.where{ 37 | $_ -match 'name.' -or $_ -match 'primaryEmail' 38 | } 39 | foreach ($Csv in $CsvList) { 40 | $PropArray = [System.Collections.Generic.List[string]]::new() 41 | foreach ($Prop in $PropList) { 42 | $PropArray.Add($Prop) 43 | } 44 | $Csv | Select $PropArray 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /Posh365/Public/EOP/Get-ATPAntiPhishRule.ps1: -------------------------------------------------------------------------------- 1 | function Get-ATPAntiPhishRule { 2 | [CmdletBinding()] 3 | param ( 4 | ) 5 | end { 6 | Get-AntiPhishRule | Select-Object @( 7 | 'Name' 8 | 'Priority' 9 | 'AntiPhishPolicy' 10 | 'Description' 11 | 'AuthenticationFailAction' 12 | 'MailboxIntelligenceProtectionAction' 13 | 'TargetedDomainProtectionAction' 14 | 'TargetedUserProtectionAction' 15 | 'PhishThresholdLevel' 16 | @{ 17 | Name = 'RecipientDomainIs' 18 | Expression = { @($_.RecipientDomainIs) -ne '' -join '|' } 19 | } 20 | @{ 21 | Name = 'ExceptIfRecipientDomainIs' 22 | Expression = { @($_.ExceptIfRecipientDomainIs) -ne '' -join '|' } 23 | } 24 | @{ 25 | Name = 'ExceptIfSentTo' 26 | Expression = { @($_.ExceptIfSentTo) -ne '' -join '|' } 27 | } 28 | @{ 29 | Name = 'ExceptIfSentToMemberOf' 30 | Expression = { @($_.ExceptIfSentToMemberOf) -ne '' -join '|' } 31 | } 32 | @{ 33 | Name = 'Exceptions' 34 | Expression = { @($_.Exceptions) -ne '' -join '|' } 35 | } 36 | 'Comments' 37 | 'WhenChanged' 38 | 'ExchangeObjectId' 39 | 'Guid' 40 | ) 41 | } 42 | } 43 | 44 | -------------------------------------------------------------------------------- /Posh365/Public/EOP/Get-ATPSafeAttachmentPolicy.ps1: -------------------------------------------------------------------------------- 1 | function Get-ATPSafeAttachmentPolicy { 2 | [CmdletBinding()] 3 | param ( 4 | ) 5 | end { 6 | Get-SafeAttachmentPolicy | Select-Object @( 7 | 'Name' 8 | 'RedirectAddress' 9 | 'Redirect' 10 | 'Action' 11 | 'ScanTimeout' 12 | 'ConfidenceLevelThreshold' 13 | 'OperationMode' 14 | 'Enable' 15 | 'ActionOnError' 16 | 'IsDefault' 17 | 'Identity' 18 | 'WhenChanged' 19 | 'WhenCreated' 20 | 'ExchangeObjectId' 21 | 'Guid' 22 | ) 23 | } 24 | } 25 | 26 | -------------------------------------------------------------------------------- /Posh365/Public/EOP/Get-ATPSafeLinksPolicy.ps1: -------------------------------------------------------------------------------- 1 | function Get-ATPSafeLinksPolicy { 2 | [CmdletBinding()] 3 | param ( 4 | ) 5 | end { 6 | Get-SafeLinksPolicy | Select-Object @( 7 | 'Name' 8 | 'IsEnabled' 9 | 'AllowClickThrough' 10 | 'DeliverMessageAfterScan' 11 | 'DisableUrlRewrite' 12 | 'DoNotAllowClickThrough' 13 | 'DoNotTrackUserClicks' 14 | 'EnableForInternalSenders' 15 | 'EnableSafeLinksForTeams' 16 | 'ScanUrls' 17 | 'TrackClicks' 18 | 'WhiteListedUrls' 19 | @{ 20 | Name = 'DoNotRewriteUrls' 21 | Expression = { @($_.DoNotRewriteUrls) -ne '' -join '|' } 22 | } 23 | @{ 24 | Name = 'ExcludedUrls' 25 | Expression = { @($_.ExcludedUrls) -ne '' -join '|' } 26 | } 27 | 'IsDefault' 28 | 'Guid' 29 | 'Identity' 30 | 'WhenChanged' 31 | 'WhenCreated' 32 | ) 33 | } 34 | } 35 | 36 | -------------------------------------------------------------------------------- /Posh365/Public/EOP/Get-EOPConnectionPolicy.ps1: -------------------------------------------------------------------------------- 1 | function Get-EOPConnectionPolicy { 2 | [CmdletBinding()] 3 | param ( 4 | ) 5 | end { 6 | Get-HostedConnectionFilterPolicy | Select-Object @( 7 | 'Name' 8 | 'Identity' 9 | 'EnableSafeList' 10 | 'IsDefault' 11 | 'IsValid' 12 | @{ 13 | Name = 'IPAllowList' 14 | Expression = { @($_.IPAllowList) -ne '' -join '|' } 15 | } 16 | @{ 17 | Name = 'IPBlockList' 18 | Expression = { @($_.IPBlockList) -ne '' -join '|' } 19 | } 20 | 'AdminDisplayName' 21 | 'DirectoryBasedEdgeBlockMode' 22 | 'ObjectState' 23 | 'OrganizationId' 24 | 'WhenChanged' 25 | 'WhenChangedUTC' 26 | 'WhenCreated' 27 | 'WhenCreatedUTC' 28 | 'ExchangeObjectId' 29 | 'Guid' 30 | 'Id' 31 | ) 32 | } 33 | } 34 | 35 | -------------------------------------------------------------------------------- /Posh365/Public/EOP/Get-EOPContentRule.ps1: -------------------------------------------------------------------------------- 1 | function Get-EOPContentRule { 2 | [CmdletBinding()] 3 | param ( 4 | ) 5 | 6 | Get-HostedContentFilterRule | Select-Object @( 7 | 'Name' 8 | 'State' 9 | 'Identity' 10 | 'AdminDisplayName' 11 | 'Priority' 12 | @{ 13 | Name = 'ExceptIfRecipientDomainIs' 14 | Expression = { @($_.ExceptIfRecipientDomainIs) -ne '' -join '|' } 15 | } 16 | @{ 17 | Name = 'ExceptIfSentTo' 18 | Expression = { @($_.ExceptIfSentTo) -ne '' -join '|' } 19 | } 20 | @{ 21 | Name = 'ExceptIfSentToMemberOf' 22 | Expression = { @($_.ExceptIfSentToMemberOf) -ne '' -join '|' } 23 | } 24 | @{ 25 | Name = 'RecipientDomainIs' 26 | Expression = { @($_.RecipientDomainIs) -ne '' -join '|' } 27 | } 28 | @{ 29 | Name = 'SentTo' 30 | Expression = { @($_.SentTo) -ne '' -join '|' } 31 | } 32 | @{ 33 | Name = 'SentToMemberOf' 34 | Expression = { @($_.SentToMemberOf) -ne '' -join '|' } 35 | } 36 | ) 37 | } 38 | -------------------------------------------------------------------------------- /Posh365/Public/EOP/Get-EOPOutboundSpamPolicy.ps1: -------------------------------------------------------------------------------- 1 | function Get-EOPOutboundSpamPolicy { 2 | [CmdletBinding()] 3 | param ( 4 | ) 5 | end { 6 | Get-HostedOutboundSpamFilterPolicy | Select-Object @( 7 | 'Name' 8 | 'Identity' 9 | 'ConfigurationType' 10 | 'ActionWhenThresholdReached' 11 | 'IsDefault' 12 | 'Enabled' 13 | 'NotifyOutboundSpam' 14 | @{ 15 | Name = 'NotifyOutboundSpamRecipients' 16 | Expression = { @($_.NotifyOutboundSpamRecipients) -ne '' -join '|' } 17 | } 18 | 'BccSuspiciousOutboundMail' 19 | @{ 20 | Name = 'BccSuspiciousOutboundAdditionalRecipients' 21 | Expression = { @($_.BccSuspiciousOutboundAdditionalRecipients) -ne '' -join '|' } 22 | } 23 | 'RecipientLimitExternalPerHour' 24 | 'RecipientLimitInternalPerHour' 25 | 'RecipientLimitPerDay' 26 | 'AdminDisplayName' 27 | 'DirectoryBasedEdgeBlockMode' 28 | 'ObjectState' 29 | 'OrganizationId' 30 | 'WhenChanged' 31 | 'WhenChangedUTC' 32 | 'WhenCreated' 33 | 'WhenCreatedUTC' 34 | 'Id' 35 | 'Guid' 36 | ) 37 | } 38 | } 39 | 40 | -------------------------------------------------------------------------------- /Posh365/Public/Forest/Convert-CanonicalToDistinguished.ps1: -------------------------------------------------------------------------------- 1 | function Convert-CanonicalToDistinguished { 2 | [cmdletbinding()] 3 | param( 4 | [Parameter(Mandatory = $true)] 5 | [ValidateNotNullOrEmpty()] 6 | [string] 7 | $CanonicalName 8 | ) 9 | end { 10 | $nameTranslate = New-Object -ComObject NameTranslate 11 | # $nameTranslate.Init(3, '') 12 | # To PS2: 13 | [__ComObject].InvokeMember('Init', 'InvokeMethod', $null, $nameTranslate, @(3, ''), $null, (Get-Culture), $null) 14 | # Get an identity using the canonicalName 15 | # $nameTranslate.Set(2, $canonicalName) 16 | # To PS2: 17 | [__ComObject].InvokeMember('Set', 'InvokeMethod', $null, $nameTranslate, @(2, $canonicalName), $null, (Get-Culture), $null) 18 | # Convert the identity to a DistinguishedName 19 | # $nameTranslate.Get(1) 20 | # To PS2: 21 | [__ComObject].InvokeMember('Get', 'InvokeMethod', $null, $nameTranslate, @(1), $null, (Get-Culture), $null) 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Posh365/Public/Forest/Convert-DistinguishedToCanonical.ps1: -------------------------------------------------------------------------------- 1 | function Convert-DistinguishedToCanonical { 2 | Param ( 3 | [Parameter(Mandatory, ValueFromPipeline)] 4 | [string[]] 5 | $DistinguishedName 6 | ) 7 | process { 8 | foreach ($dn in $DistinguishedName) { 9 | $d = $dn.Split(',') 10 | $arr = (@(($d | Where-Object { $_ -notmatch 'DC=' }) | ForEach-Object { $_.Substring(3) })) 11 | [array]::Reverse($arr) 12 | "{0}/{1}" -f (($d | Where-Object { $_ -match 'dc=' } | ForEach-Object { $_.Replace('DC=', '') }) -join '.'), ($arr -join '/') 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Posh365/Public/Format/Format-Vertical.ps1: -------------------------------------------------------------------------------- 1 | function Format-Vertical { 2 | [CmdletBinding()] 3 | param ( 4 | [Parameter(ValueFromPipeline)] 5 | [object[]] $Policy 6 | ) 7 | 8 | begin { 9 | $objects = [System.Collections.Generic.List[Object]]::new() 10 | } 11 | 12 | process { 13 | $objects.AddRange($Policy) 14 | } 15 | 16 | end { 17 | $propertyNames = $objects[0].PSObject.Properties.Name 18 | 19 | foreach ($name in $propertyNames) { 20 | $line = [Ordered]@{ 21 | Property = $name 22 | } 23 | 24 | foreach ($object in $objects) { 25 | $line[$object.DisplayName] = $object.$name 26 | } 27 | 28 | [PSCustomObject]$line 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /Posh365/Public/GitHub/Get-GitHubGist.ps1: -------------------------------------------------------------------------------- 1 | function Get-GitHubGist { 2 | <# 3 | .SYNOPSIS 4 | Returns all GISTs with the name you specify in a named GitHub account 5 | 6 | .DESCRIPTION 7 | Returns all GISTs with the name you specify in a named GitHub account 8 | 9 | .PARAMETER Username 10 | GitHub Username 11 | 12 | .PARAMETER Filename 13 | Name of the GIST name. This is named by the user before saving the GIST. 14 | Github does not mandate that the names are unique. 15 | This functions returns each that match the filename specified with this parameter 16 | 17 | .EXAMPLE 18 | Get-GitHubGist kevinblumenfeld -FileName test.xml 19 | 20 | .EXAMPLE 21 | (Get-GitHubGist kevinblumenfeld -FileName test.xml)[0] 22 | the most recent GIST named test.xml 23 | 24 | .NOTES 25 | General notes 26 | #> 27 | 28 | [CmdletBinding()] 29 | param ( 30 | [Parameter(Mandatory)] 31 | [string] 32 | $Username, 33 | 34 | [Parameter(Mandatory)] 35 | [string] 36 | $Filename 37 | ) 38 | $IdList = Get-GitHubGistID -Username $Username -Filename $Filename 39 | foreach ($Id in $IdList) { 40 | $Params = @{ 41 | Uri = "https://api.github.com/gists/${Id}" 42 | Method = 'Get' 43 | } 44 | (Invoke-RestMethod @Params).files.$Filename 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /Posh365/Public/Graph/GalSync/Get-GSGraphExchangeUser.ps1: -------------------------------------------------------------------------------- 1 | function Get-GSGraphExchangeUser { 2 | [CmdletBinding()] 3 | param ( 4 | 5 | [Parameter(Mandatory)] 6 | [string] $Tenant 7 | ) 8 | 9 | end { 10 | $ExchangeSet = [System.Collections.Generic.HashSet[string]]::new() 11 | (Get-GSGraphUserAll $Tenant).where{ 12 | $_.provisionedplans.service -eq 'exchange' -and $_.provisionedplans.capabilityStatus -eq 'enabled' 13 | } | ForEach-Object { $null = $ExchangeSet.Add($_.id) } 14 | $Script:ExchangeSet = $ExchangeSet 15 | } 16 | 17 | } -------------------------------------------------------------------------------- /Posh365/Public/Graph/Get-GraphUser.ps1: -------------------------------------------------------------------------------- 1 | function Get-GraphUser { 2 | [CmdletBinding()] 3 | param ( 4 | [Parameter()] 5 | $UserId 6 | ) 7 | if ([datetime]::UtcNow -ge $TimeToRefresh) { Connect-PoshGraphRefresh } 8 | $RestSplat = @{ 9 | Uri = 'https://graph.microsoft.com/beta/users/{0}' -f $UserId 10 | Headers = @{ "Authorization" = "Bearer $Token" } 11 | Method = 'Get' 12 | } 13 | Invoke-RestMethod @RestSplat -Verbose:$false 14 | 15 | } 16 | -------------------------------------------------------------------------------- /Posh365/Public/Graph/Get-GraphUserAll.ps1: -------------------------------------------------------------------------------- 1 | function Get-GraphUserAll { 2 | [CmdletBinding()] 3 | param ( 4 | [Parameter()] 5 | [switch] 6 | $IncludeGuests 7 | ) 8 | if (-not $IncludeGuests) { 9 | $uri = "https://graph.microsoft.com/beta/users/?`$filter=userType eq 'Member'" 10 | } 11 | else { $Uri = 'https://graph.microsoft.com/beta/users' } 12 | 13 | $RestSplat = @{ 14 | Uri = $Uri 15 | Headers = @{ "Authorization" = "Bearer $Token" } 16 | Method = 'Get' 17 | } 18 | do { 19 | if ([datetime]::UtcNow -ge $TimeToRefresh) { Connect-PoshGraphRefresh } 20 | $Response = Invoke-RestMethod @RestSplat -Verbose:$false 21 | $Response.value 22 | if ($Response.'@odata.nextLink' -match 'skip') { $Next = $Response.'@odata.nextLink' } 23 | else { $Next = $null } 24 | $RestSplat = @{ 25 | Uri = $Next 26 | Headers = @{ "Authorization" = "Bearer $Token" } 27 | Method = 'Get' 28 | } 29 | 30 | } until (-not $next) 31 | } 32 | -------------------------------------------------------------------------------- /Posh365/Public/Graph/Get-GraphUserContacts.ps1: -------------------------------------------------------------------------------- 1 | function Get-GraphUserContacts { 2 | [CmdletBinding()] 3 | param ( 4 | [Parameter(ValueFromPipeline)] 5 | $MailboxList 6 | ) 7 | process { 8 | foreach ($Mailbox in $MailboxList) { 9 | Write-Host "Mailbox: $($Mailbox.UserPrincipalName)" -ForegroundColor Green 10 | if ([datetime]::UtcNow -ge $TimeToRefresh) { Connect-PoshGraphRefresh } 11 | $RestSplat = @{ 12 | Uri = "https://graph.microsoft.com/v1.0/users/{0}/contacts?$top=1000" -f $Mailbox.UserPrincipalName 13 | Headers = @{ "Authorization" = "Bearer $Token" } 14 | Method = 'Get' 15 | } 16 | (Invoke-RestMethod @RestSplat -Verbose:$false).value 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Posh365/Public/Graph/Get-GraphUserList.ps1: -------------------------------------------------------------------------------- 1 | function Get-GraphUserList { 2 | [CmdletBinding()] 3 | param ( 4 | [Parameter(ValueFromPipeline, ValueFromPipelineByPropertyName)] 5 | [string[]] 6 | $UserPrincipalName 7 | ) 8 | begin { 9 | if (-not $MyInvocation.ExpectingInput -and -not $PSBoundParameters.ContainsKey('UserPrincipalName')) { Get-GraphUserAll } 10 | } 11 | process { 12 | foreach ($UPN in $UserPrincipalName) { 13 | if ([datetime]::UtcNow -ge $TimeToRefresh) { Connect-PoshGraphRefresh } 14 | $RestSplat = @{ 15 | Uri = 'https://graph.microsoft.com/beta/users/{0}' -f $UPN 16 | Headers = @{ "Authorization" = "Bearer $Token" } 17 | Method = 'Get' 18 | } 19 | try { Invoke-RestMethod @RestSplat -Verbose:$false -ErrorAction Stop } 20 | catch { Write-Host "Error: $UPN - $($_.Exception.Message)" -ForegroundColor Red } 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Posh365/Public/Graph/Get-TreePrintOut.ps1: -------------------------------------------------------------------------------- 1 | function Get-TreePrintout { 2 | [CmdletBinding()] 3 | param ( 4 | [Parameter()] 5 | $tree, 6 | 7 | [Parameter()] 8 | $Id, 9 | 10 | [Parameter()] 11 | $prefix 12 | ) 13 | foreach ($item in $tree.$Id) { 14 | [PSCustomObject]@{ 15 | DisplayName = $Item.DisplayName 16 | Mail = $Item.Mail 17 | UserPrincipalName = $Item.UserPrincipalName 18 | Folder = $Item.Folder 19 | Path = '{0} > {1}' -f $Prefix, $item.Folder 20 | ChildFolderCount = $Item.ChildFolderCount 21 | unreadItemCount = $Item.unreaditemCount 22 | totalItemCount = $Item.totalItemCount 23 | wellKnownName = $Item.wellKnownName 24 | ParentFolderId = $Item.ParentFolderId 25 | Id = $Item.Id 26 | } 27 | 28 | if ($tree.$($Item.Id).Count -gt 0) { 29 | Get-TreePrintout -tree $tree -Id $Item.Id -prefix ('{0} > {1}' -f $Prefix, $item.Folder) 30 | } 31 | } 32 | } 33 | 34 | -------------------------------------------------------------------------------- /Posh365/Public/Graph/GraphIdentities/Get-AzureADSP.ps1: -------------------------------------------------------------------------------- 1 | function Get-AzureADSP { 2 | [CmdletBinding()] 3 | param ( 4 | 5 | ) 6 | if ([datetime]::UtcNow -ge $TimeToRefresh) { 7 | Connect-PoshGraphRefresh 8 | } 9 | $RestSplat = @{ 10 | Uri = 'https://graph.microsoft.com/beta/servicePrincipals/' 11 | Headers = @{ "Authorization" = "Bearer $Token" } 12 | Method = 'Get' 13 | } 14 | Invoke-RestMethod @RestSplat -Verbose:$false | Select-Object -ExpandProperty Value 15 | } 16 | -------------------------------------------------------------------------------- /Posh365/Public/Graph/GraphIdentities/Get-GraphGroup.ps1: -------------------------------------------------------------------------------- 1 | function Get-GraphGroup { 2 | [CmdletBinding(DefaultParameterSetName = 'PlaceHolder')] 3 | param ( 4 | [Parameter(ParameterSetName = 'GroupID')] 5 | $GroupId, 6 | 7 | [Parameter(ParameterSetName = 'Name')] 8 | $Name 9 | ) 10 | 11 | if ([datetime]::UtcNow -ge $TimeToRefresh) { Connect-PoshGraphRefresh } 12 | switch ($PSCmdlet.ParameterSetName) { 13 | 'GroupID' { 14 | Get-GraphGroupData -GroupId $GroupId 15 | } 16 | 'Name' { 17 | Get-GraphGroupData -Name $Name | Select-Object -ExpandProperty Value 18 | } 19 | default { 20 | Get-GraphGroupData | Select-Object -ExpandProperty Value 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Posh365/Public/Graph/GraphIdentities/Get-GraphLocation.ps1: -------------------------------------------------------------------------------- 1 | function Get-GraphLocation { 2 | [CmdletBinding()] 3 | param ( 4 | [Parameter()] 5 | $Id 6 | ) 7 | if ([datetime]::UtcNow -ge $TimeToRefresh) { Connect-PoshGraphRefresh } 8 | $RestSplat = @{ 9 | Uri = 'https://graph.microsoft.com/v1.0/identity/conditionalAccess/namedLocations/{0}' -f $Id 10 | Headers = @{ "Authorization" = "Bearer $Token" } 11 | Method = 'Get' 12 | } 13 | Invoke-RestMethod @RestSplat -Verbose:$false 14 | 15 | } 16 | -------------------------------------------------------------------------------- /Posh365/Public/Graph/GraphIdentities/Get-GraphUnifiedRole.ps1: -------------------------------------------------------------------------------- 1 | function Get-GraphUnifiedRole { 2 | [CmdletBinding()] 3 | param ( 4 | ) 5 | if ([datetime]::UtcNow -ge $TimeToRefresh) { Connect-PoshGraphRefresh } 6 | $RestSplat = @{ 7 | Uri = 'https://graph.microsoft.com/beta/roleManagement/directory/roleDefinitions' 8 | Headers = @{ "Authorization" = "Bearer $Token" } 9 | Method = 'Get' 10 | } 11 | Invoke-RestMethod @RestSplat -Verbose:$false | Select-Object -expandproperty Value 12 | 13 | } 14 | -------------------------------------------------------------------------------- /Posh365/Public/Graph/New-GraphUser.ps1: -------------------------------------------------------------------------------- 1 | function New-GraphUser { 2 | [CmdletBinding()] 3 | param ( 4 | [Parameter(Mandatory)] 5 | [string] 6 | $Tenant, 7 | 8 | [Parameter(ValueFromPipeline)] 9 | $UserList 10 | ) 11 | process { 12 | foreach ($User in $UserList) { 13 | if ([datetime]::UtcNow -ge $TimeToRefresh) { Connect-PoshGraphRefresh } 14 | $Headers = @{ 15 | 'Authorization' = "Bearer $Token" 16 | 'Content-Type' = 'application/json' 17 | } 18 | $test = @{ 19 | 'accountEnabled' = $true 20 | 'mailnickname' = '' 21 | 'userPrincipalName' = '' 22 | 'displayName' = '' 23 | 'passwordProfile' = @{ 24 | 'password' = '' 25 | 'forceChangePasswordNextSignIn' = $true 26 | } 27 | } 28 | $RestSplat = @{ 29 | Uri = 'https://graph.microsoft.com/v1.0/users' 30 | Headers = $Headers 31 | Method = 'POST' 32 | Body = ($test | ConvertTo-Json) 33 | } 34 | try { Invoke-RestMethod @RestSplat -Verbose:$false -ErrorAction Stop } 35 | catch { Write-Host "Error: $($_.Exception.Message)" -ForegroundColor Red } 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /Posh365/Public/Graph/Remove-GraphMailMessage.ps1: -------------------------------------------------------------------------------- 1 | function Remove-GraphMailMessage { 2 | [CmdletBinding()] 3 | param ( 4 | [Parameter(ValueFromPipeline)] 5 | $MessageList 6 | ) 7 | process { 8 | foreach ($Message in $MessageList) { 9 | $RestSplat = @{ 10 | Uri = "https://graph.microsoft.com/v1.0/users/{0}/mailFolders/{1}/messages/{2}" -f $Message.UserPrincipalName, $Message.ParentFolderId, $Message.Id 11 | Headers = @{ "Authorization" = "Bearer $Token" } 12 | Method = 'Delete' 13 | ErrorAction = 'Stop' 14 | } 15 | try { $null = Invoke-RestMethod @RestSplat } 16 | catch { Write-Host "Error Deleting Message $($Message.UserPrincipalName): - $($_.Exception.Message)" -ForegroundColor Red } 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Posh365/Public/Group/Get-365MsolGroupMember.ps1: -------------------------------------------------------------------------------- 1 | function Get-365MsolGroupMember { 2 | param ( 3 | 4 | ) 5 | 6 | $Group = Get-MsolGroup -all 7 | 8 | foreach ($CurGroup in $Group) { 9 | $Member = Get-MsolGroupMember -GroupObjectId $CurGroup.ObjectId -All 10 | if (-not $CurGroup.LastDirSyncTime) { 11 | $LastDirSync = 'NotDirSynced' 12 | } 13 | else { 14 | $LastDirSync = ($CurGroup.LastDirSyncTime).ToLocalTime() 15 | } 16 | foreach ($CurMember in $Member) { 17 | [PSCustomObject]@{ 18 | GroupName = $CurGroup.DisplayName 19 | LastDirSync = $LastDirSync 20 | GroupType = $CurGroup.GroupType 21 | MemberCount = ($Member).count 22 | Member = $CurMember.DisplayName 23 | MemberEmail = $CurMember.EmailAddress 24 | } 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Posh365/Public/Group/Get-DistributionGroupMembershipHash.ps1: -------------------------------------------------------------------------------- 1 | function Get-DistributionGroupMembershipHash { 2 | <# 3 | .SYNOPSIS 4 | Creates a hash table from data returned from Get-DistributionGroupMembership 5 | 6 | .DESCRIPTION 7 | Creates a hash table from data returned from Get-DistributionGroupMembership 8 | 9 | .PARAMETER Recurse 10 | Reveals nested group membership 11 | 12 | .EXAMPLE 13 | "john@contoso.com" | Get-DistributionGroupMembershipHash -Recurse -Verbose 14 | 15 | .EXAMPLE 16 | Get-Content ./primaries.txt | Get-DistributionGroupMembershipHash -Recurse -Verbose 17 | 18 | #> 19 | [CmdletBinding(SupportsShouldProcess = $true)] 20 | param( 21 | [Parameter(Mandatory = $true, ValueFromPipeline = $True, ValueFromPipelineByPropertyName = $True)] 22 | [string[]]$Identity, 23 | 24 | [Parameter()] 25 | [switch]$Recurse 26 | ) 27 | begin { 28 | $GroupHash = @{} 29 | } 30 | process { 31 | foreach ($CurIdentity in $Identity) { 32 | Write-Verbose "Looking up memberships for '$CurIdentity'." 33 | if ($Recurse) { 34 | $GroupHash.$CurIdentity = $CurIdentity | Get-DistributionGroupMembership -Recurse 35 | } 36 | else { 37 | $GroupHash.$CurIdentity = $CurIdentity | Get-DistributionGroupMembership 38 | } 39 | } 40 | } 41 | end { 42 | $GroupHash 43 | } 44 | } -------------------------------------------------------------------------------- /Posh365/Public/Group/Unified/Get-UnifiedGroupOwnersMembersSubscribers.ps1: -------------------------------------------------------------------------------- 1 | function Get-UnifiedGroupOwnersMembersSubscribers { 2 | param ( 3 | 4 | ) 5 | end { 6 | Get-UnifiedGroup -ResultSize Unlimited | Select-Object @( 7 | 'DisplayName' 8 | @{ 9 | Name = 'EmailAddresses' 10 | Expression = { @($_.EmailAddresses) -ne '' -join '|' } 11 | } 12 | @{ 13 | Name = 'Members' 14 | Expression = { @((Get-UnifiedGroupLinks -Identity $_.Identity -LinkType Members).primarysmtpaddress) -ne '' -join '|' } 15 | } 16 | @{ 17 | Name = 'Subscribers' 18 | Expression = { @((Get-UnifiedGroupLinks -Identity $_.Identity -LinkType Subscribers).primarysmtpaddress) -ne '' -join '|' } 19 | } 20 | @{ 21 | Name = 'Owners' 22 | Expression = { @((Get-UnifiedGroupLinks -Identity $_.Identity -LinkType Owners).primarysmtpaddress) -ne '' -join '|' } 23 | } 24 | @{ 25 | Name = 'x500' 26 | Expression = { 'x500:{0}' -f $_.LegacyExchangeDN } 27 | } 28 | 'ExchangeObjectId' 29 | ) 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Posh365/Public/Import/Google/Export-GoogleForward.ps1: -------------------------------------------------------------------------------- 1 | 2 | function Export-GoogleForward { 3 | 4 | 5 | [CmdletBinding()] 6 | Param 7 | ( 8 | 9 | ) 10 | 11 | $AllGS = Get-GSUser -Filter * 12 | foreach ($All in $AllGS) { 13 | $fwd = Get-GSGmailAutoForwardingSettings -User $All.User | Select-Object -ExpandProperty EmailAddress 14 | [PSCustomObject]@{ 15 | Name = $All.Name.FullName 16 | User = $All.User 17 | Forward = $fwd 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Posh365/Public/Import/Google/Import-GoogleAliasToEXOGroup.ps1: -------------------------------------------------------------------------------- 1 | 2 | function Import-GoogleAliasToEXOGroup { 3 | $Group = Import-Csv .\Groups.csv 4 | $GroupsWithAliases = $Group | Where Aliases 5 | Add-Content -Path "C:\Scripts\AliasImportFailures.csv" -Value ("ERROR" + "," + "GROUP" + "," + "EMAIL") 6 | $GroupsWithAliases | ForEach-Object { 7 | $Name = $_.Name 8 | $Aliases = $_.Aliases 9 | Write-Host "GroupName:`t $Name" 10 | try { 11 | $DG = Get-DistributionGroup $Name -ErrorAction Stop 12 | $Aliases -split " " | ForEach-Object { 13 | $email = $_ 14 | try { 15 | $DG | Set-DistributionGroup -EmailAddresses @{add = $email} -ErrorAction Stop 16 | Write-Host "SUCCESS: $DGName`t$email" -ForegroundColor Green 17 | } 18 | catch { 19 | Write-Host "FAILED: $DGName`t$email" -ForegroundColor Red 20 | Add-Content -Path "C:\Scripts\AliasImportFailures.csv" -Value ("FAILEDADDEMAIL" + "," + "$DGName" + "," + "$Email") 21 | } 22 | } 23 | } 24 | catch { 25 | Add-Content -Path "C:\Scripts\AliasImportFailures.csv" -Value ("FAILEDGETGROUP" + "," + "$Name" + "," + "NOEMAIL") 26 | } 27 | $DGName = $DG.name 28 | } 29 | } -------------------------------------------------------------------------------- /Posh365/Public/Import/Import-365MsolUser.ps1: -------------------------------------------------------------------------------- 1 | function Import-365MsolUser { 2 | <# 3 | .SYNOPSIS 4 | Add New MsolUsers to Office 365 5 | #> 6 | [CmdletBinding()] 7 | param ( 8 | 9 | [Parameter(ValueFromPipeline = $true, Mandatory = $true)] 10 | [psobject] $MsolUser 11 | 12 | ) 13 | Begin { 14 | 15 | } 16 | Process { 17 | ForEach ($CurMsolUser in $MsolUser) { 18 | $Splat = @{ 19 | DisplayName = $CurMsolUser.DisplayName 20 | FirstName = $CurMsolUser.FirstName 21 | LastName = $CurMsolUser.LastName 22 | UserPrincipalName = $CurMsolUser.UserPrincipalName 23 | UsageLocation = $CurMsolUser.UsageLocation 24 | LicenseAssignment = $CurMsolUser.AccountSkuId 25 | Password = $CurMsolUser.Password 26 | } 27 | New-MsolUser @Splat 28 | } 29 | } 30 | End { 31 | 32 | } 33 | } -------------------------------------------------------------------------------- /Posh365/Public/Import/Import-AzureADUser.ps1: -------------------------------------------------------------------------------- 1 | function Import-AzureADUser { 2 | <# 3 | .SYNOPSIS 4 | Add New Azure AD User to Office 365 5 | #> 6 | [CmdletBinding()] 7 | param ( 8 | 9 | [Parameter(ValueFromPipeline = $true, Mandatory = $true)] 10 | [psobject] $AzureADUser 11 | 12 | ) 13 | Begin { 14 | 15 | } 16 | Process { 17 | ForEach ($CurAzureADUser in $AzureADUser) { 18 | $PasswordProfile = New-Object -TypeName Microsoft.Open.AzureAD.Model.PasswordProfile 19 | $PasswordProfile.Password = $CurAzureADUser.Password 20 | $Splat = @{ 21 | AccountEnabled = $True 22 | DisplayName = $CurAzureADUser.DisplayName 23 | MailNickName = $CurAzureADUser.Alias 24 | GivenName = $CurAzureADUser.FirstName 25 | Surname = $CurAzureADUser.LastName 26 | UserPrincipalName = $CurAzureADUser.UserPrincipalName 27 | UsageLocation = $CurAzureADUser.UsageLocation 28 | PasswordProfile = $PasswordProfile 29 | } 30 | New-AzureADUser @Splat 31 | } 32 | } 33 | End { 34 | 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /Posh365/Public/Import/Import-EXOGroupPermissions.ps1: -------------------------------------------------------------------------------- 1 | function Import-EXOGroupPermissions { 2 | <# 3 | .SYNOPSIS 4 | Applies permissions to Exchange Online Groups 5 | 6 | .DESCRIPTION 7 | Applies permissions to Exchange Online Groups 8 | 9 | .EXAMPLE 10 | Import-Csv .\contoso-EXOPermissions_All.csv | Import-EXOGroupPermissions 11 | 12 | #> 13 | 14 | [CmdletBinding()] 15 | Param 16 | ( 17 | [Parameter(Mandatory = $true, ValueFromPipeline = $true)] 18 | $Permission 19 | ) 20 | Begin { 21 | 22 | } 23 | Process { 24 | ForEach ($CurPermission in $Permission) { 25 | $type = $CurPermission.Permission 26 | switch ( $type ) { 27 | SendAs { 28 | Write-Verbose "Granting $($CurPermission.Granted) $($CurPermission.Permission) permission over group: $($CurPermission.Object)" 29 | Add-RecipientPermission -Identity $CurPermission.PrimarySmtpAddress -Trustee $CurPermission.GrantedSMTP -AccessRights SendAs -Confirm:$False 30 | } 31 | SendOnBehalf { 32 | Write-Verbose "Granting $($CurPermission.Granted) $($CurPermission.Permission) permission over group: $($CurPermission.Object)" 33 | Set-DistributionGroup $CurPermission.PrimarySmtpAddress -GrantSendOnBehalfTo $CurPermission.GrantedSMTP -Confirm:$False 34 | } 35 | } 36 | } 37 | } 38 | End { 39 | 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /Posh365/Public/ImportExcel/Import-PoshCsv.ps1: -------------------------------------------------------------------------------- 1 | function Import-PoshCsv { 2 | <# 3 | .SYNOPSIS 4 | Import a CSV and not worry if it is open or not 5 | 6 | .DESCRIPTION 7 | Import a CSV and not worry if it is open or not 8 | The data imported from the CSV will be from when it was last saved 9 | 10 | .PARAMETER Path 11 | The file path to the csv you wish to import 12 | example: c:\scripts\afile.csv 13 | 14 | .EXAMPLE 15 | Import-PoshCsv "c:\scripts\RawADUsers.csv" | Export-PoshExcel "c:\scripts\PrettyADUsers.xlsx" 16 | 17 | .NOTES 18 | General notes 19 | #> 20 | 21 | [CmdletBinding()] 22 | param ( 23 | [Parameter(Mandatory)] 24 | [ValidateNotNullOrEmpty()] 25 | [string] 26 | $Path 27 | ) 28 | end { 29 | try { 30 | Get-Content $Path -Raw -ErrorAction Stop | ConvertFrom-Csv 31 | } 32 | catch { 33 | Write-Warning "Error Importing Csv" 34 | Write-Warning $_.Exception.Message 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /Posh365/Public/Intune/Find-MemDevice.ps1: -------------------------------------------------------------------------------- 1 | function Find-MemDevice { 2 | <# 3 | .SYNOPSIS 4 | Loop till a mobile device is found and compliant 5 | 6 | .DESCRIPTION 7 | Loop till a mobile device is found and compliant 8 | 9 | .PARAMETER imei 10 | Phone's imei number 11 | 12 | .EXAMPLE 13 | Find-MemDevice -imei '673281231034555' 14 | 15 | .NOTES 16 | General notes 17 | #> 18 | param ( 19 | [Parameter(Mandatory)] 20 | $imei 21 | ) 22 | do { 23 | $Device = $null 24 | try { 25 | $Device = Get-MemDevice -imei $imei -ErrorAction Stop 26 | } 27 | catch { 28 | Write-Host 'Device not found ERROR!!!!' -ForegroundColor Red 29 | $_ | Select-Object * 30 | Start-Sleep 1 31 | continue 32 | } 33 | Start-Sleep 1 34 | if (-not $Device) { 35 | Write-Host 'Device not found' -ForegroundColor Red 36 | } 37 | elseif ($Device.complianceState -eq 'Compliant') { 38 | $Device | Select-Object *ID*, *NAME* 39 | Write-Host 'Device Found COMPLIANT!' -ForegroundColor Green 40 | } 41 | else { 42 | $Device | Select-Object *ID*,*NAME* 43 | Write-Host 'Device Found ' -ForegroundColor Green -NoNewline 44 | Write-Host 'NonCompliant' -ForegroundColor Red 45 | } 46 | } until ($Device.complianceState -eq 'Compliant') 47 | } -------------------------------------------------------------------------------- /Posh365/Public/Intune/Get-AADMemDevice.ps1: -------------------------------------------------------------------------------- 1 | function Get-AADMemDevice { 2 | [cmdletbinding(DefaultParameterSetName = 'PlaceHolder')] 3 | param ( 4 | 5 | [Parameter(Mandatory, ParameterSetName = 'SearchString')] 6 | $SearchString, 7 | 8 | [Parameter(Mandatory, ParameterSetName = 'ID')] 9 | $Id, 10 | 11 | [Parameter(Mandatory, ParameterSetName = 'OS')] 12 | [ValidateSet('IPhone', 'iOS', 'AndroidForWork', 'Windows')] 13 | $OS, 14 | 15 | [Parameter(Mandatory, ParameterSetName = 'Compliant')] 16 | [switch] 17 | $CompliantOnly, 18 | 19 | [Parameter(Mandatory, ParameterSetName = 'NonCompliant')] 20 | [switch] 21 | $NonCompliantOnly 22 | ) 23 | 24 | if ($SearchString) { 25 | Get-AADMemDeviceData -SearchString $SearchString | Select-Object -ExpandProperty Value 26 | } 27 | elseif ($Id) { 28 | Get-AADMemDeviceData -Id $ID 29 | } 30 | elseif ($OS) { 31 | Get-AADMemDeviceData -OS $OS | Select-Object -ExpandProperty Value 32 | } 33 | elseif ($CompliantOnly) { 34 | Get-AADMemDeviceData -CompliantOnly | Select-Object -ExpandProperty Value 35 | } 36 | elseif ($NonCompliantOnly) { 37 | Get-AADMemDeviceData -NonCompliantOnly | Select-Object -ExpandProperty Value 38 | } 39 | else { 40 | Get-AADMemDeviceData | Select-Object -ExpandProperty Value 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /Posh365/Public/Intune/Get-MemAuthenticationMethods.ps1: -------------------------------------------------------------------------------- 1 | function Get-MemAuthenticationMethods { 2 | [CmdletBinding()] 3 | param ( 4 | [Parameter(ValueFromPipelineByPropertyName)] 5 | [string] 6 | $UserPrincipalName 7 | ) 8 | process { 9 | foreach ($UPN in $UserPrincipalName) { 10 | if ([datetime]::UtcNow -ge $TimeToRefresh) { Connect-PoshGraphRefresh } 11 | $RestSplat = @{ 12 | Uri = 'https://graph.microsoft.com/beta/users/{0}/authentication/methods' -f $UPN 13 | Headers = @{ "Authorization" = "Bearer $Token" } 14 | Method = 'Get' 15 | } 16 | Invoke-RestMethod @RestSplat -Verbose:$false 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Posh365/Public/Intune/Get-MemGroupAppAssignment.ps1: -------------------------------------------------------------------------------- 1 | function Get-MemGroupAppAssignment { 2 | param ( 3 | [Parameter()] 4 | [switch] 5 | $IncludeUnassigned 6 | ) 7 | 8 | $AppList = Get-MemMobileAppData | Select-Object -ExpandProperty Value 9 | foreach ($App in $AppList) { 10 | foreach ($Assigned in $App.Assignments) { 11 | $Group = try { (Get-GraphGroup -ErrorAction Stop -GroupId $Assigned.Target.GroupId).displayName } catch { } 12 | if ($Group -or $IncludeUnassigned) { 13 | $Store = [regex]::matches($App.'@odata.type', '[^\.]*$').value[0] 14 | [PSCustomObject]@{ 15 | Group = $Group 16 | DisplayName = $App.DisplayName 17 | OS = if ($Store -like "*iOS*") { 'iOS' } 18 | elseif ($Store -like "*Android*") { 'Android' } 19 | elseif ($Store -like "*Windows*") { 'Windows' } 20 | else { $Store } 21 | Intent = $Assigned.Intent 22 | UninstallOnDeviceRemoval = $Assigned.Settings.uninstallOnDeviceRemoval 23 | VPN = $Assigned.Settings.vpnConfigurationId 24 | Store = $Store 25 | } 26 | } 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Posh365/Public/Intune/Get-MemMobileAppConfigTargeted.ps1: -------------------------------------------------------------------------------- 1 | function Get-MemMobileAppConfigTargeted { 2 | param ( 3 | 4 | ) 5 | $Excludes = @( 6 | 'assignments', 'apps', 'DisplayName', 'customSettings' 7 | 'assignments@odata.context', 'deploymentSummary@odata.context' 8 | 'apps@odata.context', 'deployedAppCount', 'isAssigned' 9 | ) 10 | Get-MemMobileAppConfigTargetedData | Select-Object -ExcludeProperty $Excludes -Property @( 11 | @{ 12 | Name = 'DisplayName' 13 | Expression = { $_.DisplayName } 14 | } 15 | @{ 16 | Name = 'Apps' 17 | Expression = { @(($_.Apps).id) -ne '' -join "`r`n" } 18 | } 19 | @{ 20 | Name = 'assignments' 21 | Expression = { @(($_.Assignments.Target.GroupID.foreach{ 22 | try { Get-GraphGroup -ErrorAction Stop -GroupId $_ } 23 | catch { } }).displayName) -ne '' -join "`r`n" } 24 | } 25 | @{ 26 | Name = 'CustomSettings' 27 | Expression = { @($_.CustomSettings.foreach{ '{0} --> {1}' -f $_.Name, $_.Value }) -ne '' -join "`r`n" } 28 | } 29 | @{ 30 | Name = 'deployedAppCount' 31 | Expression = { $_.deployedAppCount } 32 | } 33 | @{ 34 | Name = 'isAssigned' 35 | Expression = { $_.isAssigned } 36 | } 37 | '*' 38 | ) 39 | } -------------------------------------------------------------------------------- /Posh365/Public/Intune/Remove-AADMemMobileDevice.ps1: -------------------------------------------------------------------------------- 1 | function Remove-AADMemMobileDevice { 2 | param ( 3 | [Parameter(Mandatory, ValueFromPipelineByPropertyName)] 4 | $Id 5 | ) 6 | process { 7 | foreach ($i in $Id) { 8 | if ([datetime]::UtcNow -ge $TimeToRefresh) { Connect-PoshGraphRefresh } 9 | $RestSplat = @{ 10 | Uri = "https://graph.microsoft.com/beta/devices/{0}" -f $i 11 | Headers = @{ "Authorization" = "Bearer $Token" } 12 | Method = 'Delete' 13 | } 14 | Invoke-RestMethod @RestSplat -Verbose:$false 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Posh365/Public/Intune/Remove-MemMobileDevice.ps1: -------------------------------------------------------------------------------- 1 | function Remove-MemMobileDevice { 2 | param ( 3 | [Parameter(Mandatory, ValueFromPipelineByPropertyName)] 4 | $Id 5 | ) 6 | process { 7 | foreach ($i in $Id) { 8 | if ([datetime]::UtcNow -ge $TimeToRefresh) { Connect-PoshGraphRefresh } 9 | $RestSplat = @{ 10 | Uri = "https://graph.microsoft.com/beta/deviceManagement/managedDevices/{0}" -f $I 11 | Headers = @{ "Authorization" = "Bearer $Token" } 12 | Method = 'Delete' 13 | } 14 | Invoke-RestMethod @RestSplat -Verbose:$false 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Posh365/Public/Intune/Set-MemMobileDevice.ps1: -------------------------------------------------------------------------------- 1 | function Set-MemMobileDevice { 2 | param ( 3 | [Parameter(Mandatory, ParameterSetName = 'Action', ValueFromPipelineByPropertyName)] 4 | $Id, 5 | 6 | [Parameter(Mandatory, ParameterSetName = 'Action')] 7 | [ValidateSet('Retire')] 8 | $Action 9 | ) 10 | process { 11 | foreach ($i in $Id) { 12 | if ([datetime]::UtcNow -ge $TimeToRefresh) { Connect-PoshGraphRefresh } 13 | $RestSplat = @{ 14 | Uri = "https://graph.microsoft.com/beta/deviceManagement/managedDevices/{0}/retire" -f $i 15 | Headers = @{ "Authorization" = "Bearer $Token" } 16 | Method = 'Post' 17 | } 18 | Invoke-RestMethod @RestSplat -Verbose:$false 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Posh365/Public/Logging/Write-HostLog.ps1: -------------------------------------------------------------------------------- 1 | function Write-HostLog { 2 | param ( 3 | 4 | [Parameter()] 5 | [String]$Message, 6 | 7 | [Parameter()] 8 | [ValidateSet("Success", "Failed", "Neutral", "Information")] 9 | [String]$Status = "Information" 10 | 11 | ) 12 | $_ESC = "$([char]27)" 13 | $_FG = "$_ESC[38;5" 14 | $_BG = "$_ESC[48;5" 15 | $_Yellow = "$([char]27)[38;5;11m" 16 | $_Cyan = "$([char]27)[1;49;96m" 17 | $_White = "$([char]27)[38;5;3m" 18 | $_Red = "$([char]27)[91m" 19 | $_Green = "$([char]27)[38;5;2m" 20 | 21 | switch ($Status) { 22 | "Success" { $Color = $_Green } 23 | "Failed" { $Color = $_Red } 24 | "Neutral" { $Color = $_Cyan } 25 | Default { $Color = $_White } 26 | } 27 | 28 | $TimeStamp = "${_Yellow}[${_White}{0}${_Yellow}]${_Yellow}[${Color}{1}${_Yellow}]: ${Color}{2}" -f (Get-Date).ToString("HH:mm:ss"), $Status, $Message 29 | Write-host $TimeStamp 30 | } -------------------------------------------------------------------------------- /Posh365/Public/Logging/Write-HostProgress.ps1: -------------------------------------------------------------------------------- 1 | function Write-HostProgress { 2 | param ( 3 | [Parameter()] 4 | [String] 5 | $Message, 6 | 7 | [Parameter()] 8 | [ValidateSet("Success", "Failed", "Neutral", "Information")] 9 | [String] 10 | $Status = "Information", 11 | 12 | [Parameter()] 13 | [int] 14 | $Total, 15 | 16 | [Parameter()] 17 | [int] 18 | $Count 19 | ) 20 | $_ESC = "$([char]27)" 21 | $_FG = "$_ESC[38;5" 22 | $_BG = "$_ESC[48;5" 23 | $_Yellow = "$([char]27)[38;5;11m" 24 | $_Cyan = "$([char]27)[1;49;96m" 25 | $_White = "$([char]27)[38;5;3m" 26 | $_Red = "$([char]27)[91m" 27 | $_Green = "$([char]27)[38;5;2m" 28 | 29 | switch ($Status) { 30 | "Success" { $Color = $_Green } 31 | "Failed" { $Color = $_Red } 32 | "Neutral" { $Color = $_Cyan } 33 | Default { $Color = $_White } 34 | } 35 | $Pct = [int](($Count / $Total) * 100) 36 | $TimeStamp = "${_Yellow}[${_White}{0}%${_Yellow}]${_Yellow}[${_White}{1}${_Yellow}]${_Yellow}[${Color}{2}${_Yellow}]: ${Color}{3}" -f $Pct, (Get-Date).ToString("HH:mm:ss"), $Status, $Message 37 | Write-host $TimeStamp 38 | } 39 | -------------------------------------------------------------------------------- /Posh365/Public/MailFlow/Get-OutboundConnectorSummary.ps1: -------------------------------------------------------------------------------- 1 | function Get-OutboundConnectorSummary { 2 | [CmdletBinding()] 3 | param ( 4 | 5 | ) 6 | end { 7 | Get-OutboundConnector | Select-Object @( 8 | 'Name' 9 | 'Enabled' 10 | @{ 11 | Name = 'RecipientDomains' 12 | Expression = { @($_.RecipientDomains) -ne '' -join '|' } 13 | } 14 | @{ 15 | Name = 'SmartHosts' 16 | Expression = { @($_.SmartHosts) -ne '' -join '|' } 17 | } 18 | @{ 19 | Name = 'ValidationRecipients' 20 | Expression = { @($_.ValidationRecipients) -ne '' -join '|' } 21 | } 22 | 'AllAcceptedDomains' 23 | 'CloudServicesMailEnabled' 24 | 'Comment' 25 | 'ConnectorSource' 26 | 'ConnectorType' 27 | 'IsTransportRuleScoped' 28 | 'LastValidationTimestamp' 29 | 'RouteAllMessagesViaOnPremises' 30 | 'TestMode' 31 | 'TlsDomain' 32 | 'TlsSettings' 33 | 'UseMXRecord' 34 | 'WhenChangedUTC' 35 | 'WhenCreatedUTC' 36 | 'IsValid' 37 | 'IsValidated' 38 | 'Id' 39 | 'Identity' 40 | ) 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /Posh365/Public/Migration/Archive/Test-Preflight.ps1: -------------------------------------------------------------------------------- 1 | function Test-Preflight { 2 | param ( 3 | [Parameter()] 4 | [ValidateNotNullOrEmpty()] 5 | $MailboxCSV, 6 | 7 | [Parameter()] 8 | [switch] 9 | $UpnMatch 10 | ) 11 | end { 12 | 13 | $Mailbox = Import-Csv -Path $MailboxCSV 14 | 15 | $OGVBatch = @{ 16 | Title = 'Choose Batch(es)' 17 | OutputMode = 'Multiple' 18 | } 19 | 20 | $OGVUser = @{ 21 | Title = 'Choose User(s)' 22 | OutputMode = 'Multiple' 23 | } 24 | 25 | $BatchChoice = $Mailbox | Select-Object -ExpandProperty BatchName -Unique | Out-GridView @OGVBatch 26 | $UserChoice = $Mailbox | Where-Object { $_.BatchName -in $BatchChoice } | Out-GridView @OGVUser 27 | 28 | if ($UpnMatch) { 29 | $UserChoice | Test-UpnMatch 30 | } 31 | } 32 | } 33 | 34 | -------------------------------------------------------------------------------- /Posh365/Public/Migration/CloudData/Main/Set-MailboxFlag.ps1: -------------------------------------------------------------------------------- 1 | function Set-MailboxFlag { 2 | param ( 3 | [Parameter()] 4 | $ELCMailboxFlags = 24 5 | ) 6 | 7 | if (-not ($null = Get-Module ActiveDirectory -ListAvailable)) { 8 | Write-Host "ActiveDirectory module for PowerShell not found! Please run from a computer with the ActiveDirectory module" 9 | return 10 | } 11 | Import-Module ActiveDirectory -Force 12 | 13 | $PoshPath = (Join-Path -Path ([Environment]::GetFolderPath('Desktop')) -ChildPath Posh365 ) 14 | if (-not (Test-Path $PoshPath)) { 15 | $null = New-Item $PoshPath -type Directory -Force:$true -ErrorAction SilentlyContinue 16 | } 17 | $Result = Invoke-SetMailboxFlag -ELCMailboxFlags $ELCMailboxFlags 18 | $Result | Out-GridView -Title 'Results of Setting flag' 19 | $Result | Export-Csv (Join-Path $PoshPath 'RESULTS_SetMailboxFlag.csv') -NoTypeInformation -Append 20 | } -------------------------------------------------------------------------------- /Posh365/Public/Migration/CloudData/New-CloudData.ps1: -------------------------------------------------------------------------------- 1 | using namespace System.Management.Automation.Host 2 | function New-CloudData { 3 | 4 | [CmdletBinding()] 5 | param ( 6 | 7 | [Parameter()] 8 | [ValidateScript( { Test-Path $_ })] 9 | $FilePath, 10 | 11 | [Parameter(Mandatory)] 12 | [ValidateSet('Mailboxes', 'MailUsers', 'AzureADUsers')] 13 | $Type, 14 | 15 | [Parameter()] 16 | $SourceData 17 | ) 18 | 19 | while (-not $InitialDomain) { 20 | $InitialDomain = Select-CloudDataConnection -Type $Type -TenantLocation Target 21 | } 22 | if (-not $SourceData) { 23 | $SourceData = Import-Csv -Path $FilePath 24 | } 25 | Invoke-NewCloudData -ConvertedData $SourceData -Type $Type 26 | } 27 | -------------------------------------------------------------------------------- /Posh365/Public/Migration/MailboxMove/Base/Get-MailboxMove.ps1: -------------------------------------------------------------------------------- 1 | Function Get-MailboxMove { 2 | <# 3 | .SYNOPSIS 4 | Get Mailbox Moves 5 | 6 | .DESCRIPTION 7 | Get Mailbox Moves 8 | 9 | .PARAMETER IncludeCompleted 10 | Use this switch to view All mailbox moves that are not yet complete 11 | 12 | .EXAMPLE 13 | Get-MailboxMove 14 | 15 | .EXAMPLE 16 | Get-MailboxMove -IncludeCompleted 17 | 18 | .NOTES 19 | Connect to Exchange Online first. 20 | Connect-CloudMFA -Tenant Contoso -ExchangeOnline 21 | #> 22 | [CmdletBinding()] 23 | [Alias('GMM')] 24 | param 25 | ( 26 | [Parameter()] 27 | [switch] 28 | $IncludeCompleted 29 | ) 30 | 31 | if ($IncludeCompleted) { 32 | Invoke-GetMailboxMove | Out-GridView -Title "All mailbox moves" 33 | } 34 | else { 35 | Invoke-GetMailboxMove -NotCompleted | Out-GridView -Title "All mailbox moves that are not yet complete" 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /Posh365/Public/Migration/MailboxMove/Base/Resume-MailboxMove.ps1: -------------------------------------------------------------------------------- 1 | Function Resume-MailboxMove { 2 | <# 3 | .SYNOPSIS 4 | Resume Mailbox Move 5 | 6 | .DESCRIPTION 7 | Resume Mailbox Move 8 | 9 | .EXAMPLE 10 | Resume-MailboxMove 11 | 12 | .EXAMPLE 13 | Resume-MailboxMove -DontAutoComplete 14 | 15 | .NOTES 16 | General notes 17 | #> 18 | [CmdletBinding()] 19 | param 20 | ( 21 | [Parameter()] 22 | [switch] 23 | $DontAutoComplete 24 | ) 25 | 26 | $UserChoice = Get-MailboxMoveStatistics -PassThruData | Out-GridView -PassThru -Title 'Choose Mailbox Move(s) to Resume' 27 | if ($UserChoice) { 28 | Invoke-ResumeMailboxMove -UserChoice $UserChoice -DontAutoComplete:$DontAutoComplete | Out-GridView -Title "Results of Resume Mailbox Move" 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Posh365/Public/Migration/MailboxMove/Base/Suspend-MailboxMove.ps1: -------------------------------------------------------------------------------- 1 | function Suspend-MailboxMove { 2 | <# 3 | .SYNOPSIS 4 | Suspend Mailbox Move 5 | 6 | .DESCRIPTION 7 | Suspend Mailbox Move 8 | 9 | .EXAMPLE 10 | Suspend-MailboxMove 11 | 12 | .NOTES 13 | Connect to Exchange Online 14 | #> 15 | [CmdletBinding()] 16 | param 17 | ( ) 18 | 19 | $UserChoice = Get-MailboxMoveStatistics -PassThruData | Out-GridView -PassThru -Title 'Choose Mailbox Move(s) to Suspend' 20 | if ($UserChoice) { 21 | Invoke-SuspendMailboxMove -UserChoice $UserChoice | Out-GridView -Title "Results of Suspend Mailbox Move" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Posh365/Public/Migration/MailboxMove/BitTitan/Enter-BTCustomer.ps1: -------------------------------------------------------------------------------- 1 | function Enter-BTCustomer { 2 | [CmdletBinding()] 3 | Param 4 | ( 5 | 6 | ) 7 | end { 8 | $Select = @( 9 | 'CompanyName', 'PrimaryDomain', 'Updated', 'OrganizationId' 10 | ) 11 | $CustomerChoice = Invoke-EnterBTCustomer | Select-Object $Select | Out-GridView -Title "Choose the BitTitan customer you wish to work with" -OutputMode Single 12 | if ($CustomerChoice) { 13 | Write-Host "CompanyName: $($CustomerChoice.CompanyName)" 14 | $Script:BitTic = Get-BT_Ticket -Ticket $BitTic -OrganizationId $CustomerChoice.OrganizationId -Environment BT 15 | $Script:CustomerId = Get-BT_Customer -Ticket $BitTic -RetrieveAll:$true 16 | $host.ui.RawUI.WindowTitle = "BitTitan Project: *** $($CustomerChoice.CompanyName) ***" 17 | } 18 | else { 19 | Write-Host "Please run the command again and choose a customer" -ForegroundColor Red 20 | Return 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Posh365/Public/Migration/MailboxMove/BitTitan/Enter-MWProject.ps1: -------------------------------------------------------------------------------- 1 | function Enter-MWProject { 2 | [CmdletBinding()] 3 | Param 4 | ( 5 | 6 | ) 7 | end { 8 | $Select = @( 9 | 'Name', 'ProjectType', 'ExportType', 'ImportType', 'AdvancedOptions', 'FolderFilter', 'Id', 'OrganizationId' 10 | ) 11 | $Script:MWProject = Get-MWMailboxConnector | Select-Object $Select | Sort-Object -Property Name | Out-GridView -Title "Choose the MigrationWiz project you wish to work with" -OutputMode Single 12 | if ($MWProject) { 13 | Write-Host "MigrationWiz Project: $($MWProject.Name)" -ForegroundColor Magenta 14 | $host.ui.RawUI.WindowTitle = "MigrationWiz Project: *** $($MWProject.Name) ***" 15 | } 16 | else { 17 | Write-Host "Please run the command again and choose a customer" -ForegroundColor Red 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Posh365/Public/Migration/MailboxMove/BitTitan/Get-BTUser.ps1: -------------------------------------------------------------------------------- 1 | function Get-BTUser { 2 | [CmdletBinding()] 3 | Param 4 | ( 5 | 6 | ) 7 | end { 8 | Invoke-GetBTUserTrimmed | Out-GridView -Title "BitTitan Users" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /Posh365/Public/Migration/MailboxMove/BitTitan/Get-DeploymentProStatistics.ps1: -------------------------------------------------------------------------------- 1 | function Get-DeploymentProStatistics { 2 | [CmdletBinding()] 3 | Param 4 | ( 5 | [Parameter()] 6 | [switch] 7 | $AllModules, 8 | 9 | [Parameter()] 10 | [switch] 11 | $SkipUserRefresh, 12 | 13 | [Parameter()] 14 | [switch] 15 | $SkipDeviceRefresh 16 | ) 17 | end { 18 | $OGV = @{ 19 | Title = 'Choose Users and click OK to Return DeploymentPro Statistics' 20 | OutputMode = 'Multiple' 21 | } 22 | $UserHashSplat = @{ 23 | SkipUserRefresh = $SkipUserRefresh 24 | SkipDeviceRefresh = $SkipDeviceRefresh 25 | AllModules = $AllModules 26 | } 27 | foreach ($User in Invoke-GetBTUserTrimmed | Out-GridView @OGV) { 28 | $User | Invoke-GetDeploymentProStatistics @UserHashSplat | Out-GridView -Title "DeploymentPro Statistics" 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Posh365/Public/Migration/MailboxMove/BitTitan/Get-MWMailboxMove.ps1: -------------------------------------------------------------------------------- 1 | function Get-MWMailboxMove { 2 | [CmdletBinding()] 3 | Param 4 | ( 5 | 6 | ) 7 | end { 8 | Invoke-GetMWMailboxMove | Select-Object @( 9 | @{ 10 | Name = 'Source' 11 | Expression = 'ExportEmailAddress' 12 | } 13 | @{ 14 | Name = 'Target' 15 | Expression = 'ImportEmailAddress' 16 | } 17 | @{ 18 | Name = 'Categories' 19 | Expression = { If ($_.Categories) { $StarColor[$_.Categories] } else { "" } } 20 | } 21 | 'CreateDate' 22 | 'Id' 23 | ) | Out-GridView -Title "MigrationWiz Mailbox Moves" 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Posh365/Public/Migration/MailboxMove/BitTitan/Get-MWMailboxMovePasses.ps1: -------------------------------------------------------------------------------- 1 | function Get-MWMailboxMovePasses { 2 | [CmdletBinding()] 3 | Param 4 | ( 5 | 6 | ) 7 | end { 8 | Invoke-GetMWMailboxMove | Select-Object @( 9 | @{ 10 | Name = 'Source' 11 | Expression = 'ExportEmailAddress' 12 | } 13 | @{ 14 | Name = 'Target' 15 | Expression = 'ImportEmailAddress' 16 | } 17 | @{ 18 | Name = 'Categories' 19 | Expression = { if ($_.Categories) { $StarColor[$_.Categories] } else { "" } } 20 | } 21 | 'CreateDate' 22 | 'Id' 23 | ) | Out-GridView -Title "Choose Mailboxes to report on Migration Wiz Passes" -PassThru | 24 | Invoke-GetMWMailboxMovePasses | Sort-Object -Property Source, StartDate | Out-GridView -Title "Each MigrationWiz pass for each mailbox" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Posh365/Public/Migration/MailboxMove/BitTitan/Get-MWMailboxMoveStatistics.ps1: -------------------------------------------------------------------------------- 1 | function Get-MWMailboxMoveStatistics { 2 | [CmdletBinding()] 3 | Param 4 | ( 5 | 6 | ) 7 | end { 8 | Invoke-GetMWMailboxMove | Invoke-GetMWMailboxMoveStatistics | Out-GridView -Title "MigrationWiz Mailbox Move Stats" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /Posh365/Public/Migration/MailboxMove/BitTitan/New-MWMailboxMovePass.ps1: -------------------------------------------------------------------------------- 1 | function New-MWMailboxMovePass { 2 | [CmdletBinding()] 3 | param ( 4 | 5 | ) 6 | end { 7 | $MailboxChoice = Invoke-GetMWMailboxMove | Invoke-NewMWMailboxStatsandNoStats | Out-GridView -Title "Choose the users for whom to begin a Migration Move Pass" -OutputMode Multiple 8 | [int]$NumberofDays = Get-NumberOfDaysDecision 9 | if ($NumberofDays) { 10 | $ItemTypes = Get-MwItemType 11 | } 12 | if ($ItemTypes) { 13 | $ContinueDecision = Get-ContinueDecision 14 | if ($ContinueDecision -and $MailboxChoice) { 15 | $Value = [MigrationProxy.WebApi.MailboxItemTypes]::Mail 16 | # $Total = $Value -bor [MigrationProxy.WebApi.MailboxItemTypes]::Calendar 17 | $PassHash = @{ 18 | ItemTypes = $Value 19 | NumberofDays = $NumberofDays 20 | } 21 | $MailboxChoice | Invoke-NewMWMailboxMovePass @PassHash | Out-GridView -Title "Results of New Mailbox Move Pass" 22 | } 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Posh365/Public/Migration/MailboxMove/BitTitan/Remove-BTUser.ps1: -------------------------------------------------------------------------------- 1 | function Remove-BTUser { 2 | [CmdletBinding()] 3 | Param 4 | ( 5 | 6 | ) 7 | end { 8 | Invoke-RemoveBTUser | Out-GridView -Title "Results of Remove BitTitan User" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /Posh365/Public/Migration/MailboxMove/BitTitan/Set-DeploymentProSchedule.ps1: -------------------------------------------------------------------------------- 1 | function Set-DeploymentProSchedule { 2 | [CmdletBinding()] 3 | param ( 4 | 5 | ) 6 | end { 7 | Invoke-SetDeploymentProSchedule | Out-GridView -Title "Results of Set DeploymentPro Schedule" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /Posh365/Public/Migration/MailboxMove/BitTitan/Set-MWMailboxMoveForward.ps1: -------------------------------------------------------------------------------- 1 | function Set-MWMailboxMoveForward { 2 | [CmdletBinding()] 3 | Param 4 | ( 5 | [Parameter()] 6 | [switch] 7 | $DeliverAndForward 8 | ) 9 | end { 10 | $SetParams = @{ 11 | 'DeliverAndForward' = $DeliverAndForward 12 | } 13 | Invoke-SetMWMailboxMoveForward @SetParams | Out-GridView -Title "Results of Setting Mailbox Forwards for a MigrationWiz Mailbox Move" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Posh365/Public/Migration/MailboxMove/Connect/Connect-MailboxMove.ps1: -------------------------------------------------------------------------------- 1 | Function Connect-MailboxMove { 2 | <# 3 | .SYNOPSIS 4 | Connect to Exchange Online and Azure AD 5 | 6 | .DESCRIPTION 7 | Connect to Exchange Online and Azure AD 8 | 9 | .PARAMETER Tenant 10 | if contoso.onmicrosoft.com use "Contoso" 11 | 12 | .EXAMPLE 13 | Connect-CloudMFA -Tenant 14 | 15 | #> 16 | 17 | [CmdletBinding()] 18 | param 19 | ( 20 | [Parameter(Position = 0, Mandatory)] 21 | [string] $Tenant 22 | ) 23 | Connect-CloudMFA -Tenant $Tenant -ExchangeOnline -AzureAD 24 | } 25 | -------------------------------------------------------------------------------- /Posh365/Public/Migration/MailboxMove/Credential/Remove-MailboxMoveCredential.ps1: -------------------------------------------------------------------------------- 1 | function Remove-MailboxMoveCredential { 2 | <# 3 | .SYNOPSIS 4 | Erases credentials that are saved and encrypted on your computer 5 | These are the on-premises Exchange endpoint credentials. 6 | 7 | .DESCRIPTION 8 | Erases credentials that are saved and encrypted on your computer 9 | These are the on-premises Exchange endpoint credentials. 10 | 11 | .PARAMETER Tenant 12 | This is the tenant domain - where you are/were migrating to 13 | Example: If target tenant is contoso.mail.onmicrosoft.com use contoso 14 | 15 | .EXAMPLE 16 | Remove-MailboxMoveCredentials -Tenant Contoso 17 | 18 | .NOTES 19 | General notes 20 | #> 21 | 22 | param ( 23 | [Parameter(Mandatory)] 24 | [ValidateNotNullOrEmpty()] 25 | [string] 26 | $Tenant 27 | ) 28 | end { 29 | if ($Tenant -notmatch '.mail.onmicrosoft.com|\.onmicrosoft\.us') { 30 | $Tenant = '{0}.mail.onmicrosoft.com' -f $Tenant 31 | } 32 | $CredentialPath = "${env:\userprofile}\$Tenant.Migrations.Cred" 33 | Remove-Item $CredentialPath -ErrorAction SilentlyContinue 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Posh365/Public/Migration/MailboxMove/License/Get-MailboxMoveLicenseCount.ps1: -------------------------------------------------------------------------------- 1 | function Get-MailboxMoveLicenseCount { 2 | <# 3 | .SYNOPSIS 4 | Get a quick look at how many Office 365 skus are available and assigned 5 | 6 | .DESCRIPTION 7 | Get a quick look at how many Office 365 skus are available and assigned 8 | 9 | .EXAMPLE 10 | Get-MailboxMoveLicenseCount 11 | 12 | .NOTES 13 | Negative numbers represent when a sku is assigned/consumed but there are none available. 14 | Usually after a trial or if a company decided not to renew that sku 15 | #> 16 | 17 | [CmdletBinding()] 18 | param ( 19 | 20 | ) 21 | end { 22 | 'placeholder' | Set-CloudLicense -DisplayTenantsSkusAndOptionsFriendlyNames -ErrorAction SilentlyContinue 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Posh365/Public/Migration/MailboxMove/Permission/Remove-MailboxMovePermission.ps1: -------------------------------------------------------------------------------- 1 | function Remove-MailboxMovePermission { 2 | [CmdletBinding(DefaultParameterSetName = 'SharePoint')] 3 | param ( 4 | [Parameter(Mandatory, ParameterSetName = 'SharePoint')] 5 | [ValidateNotNullOrEmpty()] 6 | [string] 7 | $SharePointURL, 8 | 9 | [Parameter(Mandatory, ParameterSetName = 'SharePoint')] 10 | [ValidateNotNullOrEmpty()] 11 | [string] 12 | $ExcelFile 13 | ) 14 | end { 15 | 16 | $SetPermSplat = @{ 17 | 'PassThru' = $true 18 | 'Remove' = $true 19 | } 20 | switch ($PSBoundParameters.Keys) { 21 | 'SharePointURL' { $SetPermSplat.Add('SharePointURL', $SharePointURL) } 22 | 'ExcelFile' { $SetPermSplat.Add('ExcelFile', $ExcelFile) } 23 | 'MailboxCSV' { $SetPermSplat.Add('MailboxCSV', $MailboxCSV) } 24 | Default { } 25 | } 26 | $PermissionList = Get-MailboxMovePermission @SetPermSplat 27 | $PermissionList | Invoke-RemoveMailboxMovePermission | Out-GridView -Title 'Mailbox move permission remove results' 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Posh365/Public/OPP/Remove-OfficeLicense.ps1: -------------------------------------------------------------------------------- 1 | function Remove-OfficeLicense { 2 | <# 3 | 4 | .SYNOPSIS 5 | Remove Product Key and License from an existing Office Install 6 | 7 | .DESCRIPTION 8 | Remove Product Key and License from an existing Office Install 9 | Often used when moving from one Office 365 tenant to another. 10 | 11 | Verify which line number to use as product team may have made changes https://github.com/kevinblumenfeld/Posh365/issues/54 12 | 13 | .EXAMPLE 14 | Remove-OfficeLicense 15 | 16 | #> 17 | Start-Transcript 18 | 19 | $licrem = join-path $env:temp OfficeProPlusLicenseRemoved.txt 20 | if (-not (Test-Path $licrem)) { 21 | 22 | $license = cscript "C:\Program Files (x86)\Microsoft Office\Office16\OSPP.VBS" /dstatus 23 | 24 | $o365 = 'LICENSE NAME' 25 | 26 | for ($i = 0; $i -lt $license.Length; $i++) { 27 | 28 | if ($license[$i] -match $o365) { 29 | $i += 6 30 | $keyline = $license[$i] 31 | $prodkey = $keyline.substring($keyline.length - 5, 5) 32 | } 33 | } 34 | 35 | cscript "C:\Program Files (x86)\Microsoft Office\Office16\OSPP.VBS" /unpkey:$prodkey 36 | New-Item $licrem 37 | } 38 | } -------------------------------------------------------------------------------- /Posh365/Public/Okta/Remove-OktaUserfromApp.ps1: -------------------------------------------------------------------------------- 1 | function Remove-OktaUserfromApp { 2 | <# 3 | .SYNOPSIS 4 | Searches for specific Okta Users and removes (and deprovisions them) from a specific app 5 | 6 | .DESCRIPTION 7 | Searches for specific Okta Users and removes (and deprovisions them) from a specific app 8 | 9 | .EXAMPLE 10 | Remove-OktaUserfromApp -AppID 00u4m2pk9NMihnsWJ356 -ID 00d4em2pk9NMehesWJe3 11 | 12 | .EXAMPLE 13 | (Get-OktaAppUserReport -AppID 0oa497tfeAPQSU5sw356).id | Remove-OktaUserfromApp -AppID 0oa497tfeAPQSU5sw356 14 | 15 | #> 16 | Param ( 17 | 18 | [Parameter(Mandatory)] 19 | [string] $AppID, 20 | 21 | [Parameter(ValueFromPipeline, Mandatory)] 22 | $Id 23 | 24 | ) 25 | 26 | $Url = $OKTACredential.GetNetworkCredential().username 27 | $Token = $OKTACredential.GetNetworkCredential().Password 28 | 29 | $Headers = @{ 30 | "Authorization" = "SSWS $Token" 31 | "Accept" = "application/json" 32 | "Content-Type" = "application/json" 33 | } 34 | 35 | $RestSplat = @{ 36 | Uri = 'https://{0}.okta.com/api/v1/apps/{1}/users/{2}?sendEmail=true' -f $Url, $AppID, $Id 37 | Headers = $Headers 38 | Method = 'DELETE' 39 | } 40 | $Response = Invoke-WebRequest @RestSplat -Verbose:$false 41 | } 42 | -------------------------------------------------------------------------------- /Posh365/Public/Okta/Remove-UserfromOktaApp.ps1: -------------------------------------------------------------------------------- 1 | function Remove-UserfromOktaApp { 2 | <# 3 | .SYNOPSIS 4 | Remove user from Okta app 5 | 6 | .DESCRIPTION 7 | Remove user from Okta app 8 | 9 | .PARAMETER Login 10 | the users login to Okta 11 | 12 | .PARAMETER AppId 13 | The value assigned to the application by Okta 14 | 15 | .EXAMPLE 16 | 'user@contoso.com' | Remove-UserfromOktaApp -AppID '0oa2wf5crfrL9dEpJ234' -Verbose 17 | 18 | .NOTES 19 | General notes 20 | #> 21 | 22 | 23 | Param ( 24 | [Parameter(ValueFromPipeline, Mandatory)] 25 | [string] $Login, 26 | 27 | [Parameter(Mandatory)] 28 | [string] $AppId 29 | ) 30 | begin { 31 | 32 | $Url = $OKTACredential.GetNetworkCredential().username 33 | $Token = $OKTACredential.GetNetworkCredential().Password 34 | 35 | } 36 | process { 37 | Write-Verbose "Attemting to remove $Login from $AppId" 38 | $Id = (Get-SingleOktaUserReport -Login $Login).Id 39 | $Headers = @{ 40 | "Authorization" = "SSWS $Token" 41 | "Accept" = "application/json" 42 | "Content-Type" = "application/json" 43 | } 44 | $RestSplat = @{ 45 | Uri = "https://$Url.okta.com/api/v1/apps/{0}/users/{1}" -f $AppId, $Id 46 | Headers = $Headers 47 | Method = 'DELETE' 48 | } 49 | $null = Invoke-WebRequest @RestSplat -Verbose:$false 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /Posh365/Public/Okta/Report/Convert-OktaRateLimitToSleep.ps1: -------------------------------------------------------------------------------- 1 | function Convert-OktaRateLimitToSleep { 2 | Param ( 3 | 4 | [Parameter()] 5 | [long] $UnixTime, 6 | 7 | [Parameter()] 8 | $ApiTime 9 | 10 | ) 11 | 12 | $Offset = New-TimeSpan -Start $ApiTime -End (Get-Date) 13 | $CorrectedTime = (Get-Date).AddSeconds( - $Offset.TotalSeconds) 14 | $WhenToRequest = [timezone]::CurrentTimeZone.ToLocalTime(([datetime]'1/1/1970').AddSeconds($UnixTime)) 15 | $SleepTime = ((New-TimeSpan -Start $CorrectedTime -End $WhenToRequest).Seconds + 2) 16 | 17 | $SleepTime 18 | } -------------------------------------------------------------------------------- /Posh365/Public/Okta/Report/Get-OktaGroupUserMembershipReport.ps1: -------------------------------------------------------------------------------- 1 | function Get-OktaGroupUserMembershipReport { 2 | Param ( 3 | 4 | ) 5 | 6 | $GHash = Get-OktaGroupHash 7 | $M2GIDHash = Get-OktaMemberGroupIDHash 8 | $GroupID2Member = Get-OktaGroupMemberHash -Member2Group $M2GIDHash 9 | 10 | foreach ($Entry in $GroupID2Member.GetEnumerator()) { 11 | $GroupID = $Entry.Key 12 | $Member = $Entry.Value 13 | foreach ($CurMember in $Member) { 14 | [PSCustomObject]@{ 15 | Name = $GHash.$GroupID.Name 16 | Member = $CurMember 17 | ID = $GroupID 18 | Description = $GHash.$GroupID.Description 19 | Type = $GHash.$GroupID.Type 20 | Wdqn = $GHash.$GroupID.WindowsQualifiedDistinguishedName 21 | GroupType = $GHash.$GroupID.GroupType 22 | GroupScope = $GHash.$GroupID.GroupScope 23 | samAccountName = $GHash.$GroupID.samAccountName 24 | DN = $GHash.$GroupID.DistinguishedName 25 | } 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Posh365/Public/Okta/Report/Get-OktaUserGroupMembershipReport.ps1: -------------------------------------------------------------------------------- 1 | function Get-OktaUserGroupMembershipReport { 2 | Param ( 3 | [Parameter()] 4 | [string] $SearchString, 5 | 6 | [Parameter()] 7 | [string] $Login, 8 | 9 | [Parameter()] 10 | [switch] $RefreshGroupMemberHash 11 | ) 12 | 13 | if ($RefreshGroupMemberHash -or -not $M2GHash -or -not $groupId2NameHash) { 14 | $M2GHash = Get-OktaMemberGroupHash 15 | $Script:M2GHash = $M2GHash 16 | } 17 | 18 | if ($SearchString) { 19 | $userList = Get-OktaUserReport -SearchString $SearchString 20 | } 21 | elseif ($Login) { 22 | $userList = Get-OktaUserReport -Login $Login 23 | } 24 | else { 25 | $userList = Get-OktaUserReport 26 | } 27 | 28 | foreach ($User in $userList) { 29 | $groupList = $M2GHash[$User.Login] 30 | foreach ($Group in $groupList) { 31 | [PSCustomObject]@{ 32 | GroupName = $groupId2NameHash.$Group 33 | GroupId = $Group 34 | FirstName = $User.FirstName 35 | LastName = $User.LastName 36 | Login = $User.Login 37 | Email = $User.Email 38 | } 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /Posh365/Public/Options/Select-ADConnectServer.ps1: -------------------------------------------------------------------------------- 1 | function Select-ADConnectServer { 2 | param () 3 | $RootPath = $env:USERPROFILE + "\ps\" 4 | $User = $env:USERNAME 5 | 6 | if (!(Test-Path $RootPath)) { 7 | try { 8 | New-Item -ItemType Directory -Path $RootPath -ErrorAction STOP | Out-Null 9 | } 10 | catch { 11 | throw $_.Exception.Message 12 | } 13 | } 14 | $PDCEmulator = [System.DirectoryServices.ActiveDirectory.Domain]::GetComputerDomain().PdcRoleOwner.name 15 | while (! $ADConnect) { 16 | $ADConnect = Invoke-Command -ComputerName $PDCEmulator -ScriptBlock { ( Get-ADComputer -Filter { ( OperatingSystem -Like 'Windows*' ) -AND ( OperatingSystem -Like '*Server*' ) } ).DNSHostName } | 17 | Sort | Out-GridView -OutputMode Single -Title "SELECT THE AD CONNECT SERVER AND CLICK OK" 18 | } 19 | $ADConnect | Out-File ($RootPath + "$($user).ADConnectServer") -Force 20 | } 21 | -------------------------------------------------------------------------------- /Posh365/Public/Options/Select-DisplayNameFormat.ps1: -------------------------------------------------------------------------------- 1 | function Select-DisplayNameFormat { 2 | param () 3 | $RootPath = $env:USERPROFILE + "\ps\" 4 | $User = $env:USERNAME 5 | $DisplayNameFormat = $null 6 | 7 | if (!(Test-Path $RootPath)) { 8 | try { 9 | New-Item -ItemType Directory -Path $RootPath -ErrorAction STOP | Out-Null 10 | } 11 | catch { 12 | throw $_.Exception.Message 13 | } 14 | } 15 | 16 | while (!$DisplayNameFormat) { 17 | $DisplayNameFormat = "FirstName LastName", "LastName, FirstName" | Out-GridView -OutputMode Single -Title "SELECT `"DISPLAY NAME`" FORMAT" 18 | } 19 | if ($DisplayNameFormat -eq "FirstName LastName") { 20 | '$FirstName $LastName' | Out-File ($RootPath + "$($user).DisplayNameFormat") -Force 21 | } 22 | if ($DisplayNameFormat -eq "LastName, FirstName") { 23 | '$LastName, $FirstName' | Out-File ($RootPath + "$($user).DisplayNameFormat") -Force 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /Posh365/Public/Options/Select-DomainController.ps1: -------------------------------------------------------------------------------- 1 | function Select-DomainController { 2 | param () 3 | $RootPath = $env:USERPROFILE + "\ps\" 4 | $User = $env:USERNAME 5 | $DomainController = $null 6 | 7 | if (!(Test-Path $RootPath)) { 8 | try { 9 | New-Item -ItemType Directory -Path $RootPath -ErrorAction STOP | Out-Null 10 | } 11 | catch { 12 | throw $_.Exception.Message 13 | } 14 | } 15 | 16 | while (! $DomainController) { 17 | try { 18 | $DomainController = [System.DirectoryServices.ActiveDirectory.Forest]::GetCurrentForest().domains.DomainControllers.Name | 19 | Out-GridView -OutputMode Single -Title "SELECT A DOMAIN CONTROLLER AND CLICK OK" 20 | } 21 | catch { 22 | $DomainController = (([system.directoryservices.activedirectory.domain]::GetComputerDomain()).domaincontrollers).name | 23 | Out-GridView -OutputMode Single -Title "SELECT A DOMAIN CONTROLLER AND CLICK OK" 24 | } 25 | } 26 | $DomainController | Out-File ($RootPath + "$($user).DomainController") -Force 27 | } 28 | -------------------------------------------------------------------------------- /Posh365/Public/Options/Select-ExchangeServer.ps1: -------------------------------------------------------------------------------- 1 | function Select-ExchangeServer { 2 | param () 3 | $RootPath = $env:USERPROFILE + "\ps\" 4 | $User = $env:USERNAME 5 | $dn = $null 6 | $Ex = $null 7 | $EXCHServer = $null 8 | 9 | if (!(Test-Path $RootPath)) { 10 | try { 11 | New-Item -ItemType Directory -Path $RootPath -ErrorAction STOP | Out-Null 12 | } 13 | catch { 14 | throw $_.Exception.Message 15 | } 16 | } 17 | $dn = "DC=$(($env:USERDNSDOMAIN).replace('.',',DC='))" 18 | $Ex = [adsi]"LDAP://CN=Exchange Install Domain Servers,CN=Microsoft Exchange System Objects,$($dn)" | 19 | Select -ExpandProperty member 20 | while (! $EXCHServer) { 21 | $EXCHServer = ([regex]::Matches($Ex, '(?<=CN=).*?(?=\,)').groups.value) | 22 | Out-GridView -OutputMode Single -Title "SELECT AN EXCHANGE SERVER AND CLICK OK" 23 | } 24 | $EXCHServer | Out-File ($RootPath + "$($user).EXCHServer") -Force 25 | } 26 | -------------------------------------------------------------------------------- /Posh365/Public/Options/Select-Options.ps1: -------------------------------------------------------------------------------- 1 | function Select-Options { 2 | param () 3 | Select-ADConnectServer 4 | Select-DomainController 5 | Select-ExchangeServer 6 | Select-TargetAddressSuffix 7 | Select-DisplayNameFormat 8 | Select-SamAccountNameOptions 9 | } 10 | -------------------------------------------------------------------------------- /Posh365/Public/Options/Select-TargetAddressSuffix.ps1: -------------------------------------------------------------------------------- 1 | function Select-TargetAddressSuffix { 2 | param () 3 | $RootPath = $env:USERPROFILE + "\ps\" 4 | $User = $env:USERNAME 5 | $DomainFQDN = $null 6 | $RootDSE = $null 7 | $ConfigNC = $null 8 | $ADObjectSplat = $null 9 | $TargetAddressSuffix = $null 10 | 11 | 12 | if (!(Test-Path $RootPath)) { 13 | try { 14 | New-Item -ItemType Directory -Path $RootPath -ErrorAction STOP | Out-Null 15 | } 16 | catch { 17 | throw $_.Exception.Message 18 | } 19 | } 20 | $DomainFQDN = ([System.DirectoryServices.ActiveDirectory.Forest]::GetCurrentForest()).name 21 | $RootDSE = [ADSI]"LDAP://$DomainFqdn/RootDSE" 22 | $ConfigNC = $RootDSE.configurationNamingContext.ToString() 23 | 24 | $ADObjectSplat = @{ 25 | LDAPFilter = "(&(objectClass=msExchAcceptedDomain))" 26 | SearchBase = $ConfigNC 27 | Server = $DomainFqdn 28 | Properties = "msExchAcceptedDomainName" 29 | } 30 | while (! $TargetAddressSuffix) { 31 | $TargetAddressSuffix = Get-ADObject @ADObjectSplat | Select-Object -ExpandProperty msExchAcceptedDomainName| ? {$_ -like "*.mail.onmicrosoft.com"} | 32 | Out-GridView -OutputMode Single -Title "SELECT THE TARGET ADDRESS SUFFIX" 33 | } 34 | $TargetAddressSuffix | Out-File ($RootPath + "$($user).TargetAddressSuffix") -Force 35 | } -------------------------------------------------------------------------------- /Posh365/Public/PSGSuite/Get-PSGCalendar.ps1: -------------------------------------------------------------------------------- 1 | function Get-PSGCalendar { 2 | <# 3 | .SYNOPSIS 4 | Gets All users calendars in Google Workspace 5 | 6 | .DESCRIPTION 7 | Gets All users calendars in Google Workspace 8 | 9 | .EXAMPLE 10 | Get-PSGCalendar | Export-Csv .\Calendars.csv -notypeinformation 11 | 12 | .NOTES 13 | General notes 14 | #> 15 | [CmdletBinding()] 16 | Param ( 17 | 18 | ) 19 | 20 | $UserList = Get-GSUser -filter * 21 | 22 | foreach ($User in $UserList) { 23 | 24 | $CalendarList = Get-GSCalendar -User $User.User 25 | 26 | foreach ($Calendar in $CalendarList) { 27 | 28 | [PSCustomObject]@{ 29 | User = $User.User 30 | CalendarName = $Calendar.Summary 31 | AssignedUser = $Calendar.User 32 | CalendarEmail = $Calendar.Id 33 | AccessRole = $Calendar.AccessRole 34 | Hidden = $Calendar.Hidden 35 | Primary = $Calendar.Primary 36 | } 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /Posh365/Public/PSGSuite/Get-PSGCalendarACL.ps1: -------------------------------------------------------------------------------- 1 | function Get-PSGCalendarACL { 2 | [CmdletBinding()] 3 | Param ( 4 | 5 | ) 6 | $UserList = Get-GSUser -Filter * 7 | 8 | foreach ($User in $UserList) { 9 | $ACLList = Get-GSCalendarACL -User $User.User 10 | foreach ($ACL in $ACLList) { 11 | $Granted = $ACL.Id.replace('user:', '') 12 | if ($User.User -ne $Granted) { 13 | [PSCustomObject]@{ 14 | Name = $User.Name.FullName 15 | PrimaryEmail = $User.PrimaryEmail 16 | User = $ACL.User 17 | CalendarId = $ACL.CalendarId 18 | Granted = $Granted 19 | Role = $ACL.Role 20 | ETag = $ACL.ETag 21 | Kind = $ACL.Kind 22 | } 23 | } 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Posh365/Public/PSGSuite/Get-PSGGroup.ps1: -------------------------------------------------------------------------------- 1 | function Get-PSGGroup { 2 | [CmdletBinding()] 3 | Param 4 | ( 5 | 6 | ) 7 | $GroupList = Get-GSGroup -Filter * 8 | 9 | foreach ($Group in $GroupList) { 10 | $MemberList = Get-GSGroupMember -Identity $Group.Email 11 | $OwnerList = $MemberList.where{ $_.Role -eq 'OWNER' } 12 | $ManagerList = $MemberList.where{ $_.Role -eq 'MANAGER' } 13 | [PSCustomObject]@{ 14 | Name = $Group.Name 15 | Email = $Group.Email 16 | Aliases = @($Group.Aliases) -ne '' -join '|' 17 | Description = $Group.Description 18 | NonEditableAliases = @($Group.NonEditableAliases) -ne '' -join '|' 19 | MemberCount = $Group.DirectMembersCount 20 | Members = @($MemberList) -ne '' -join '|' 21 | ManagerCount = $ManagerList.Count 22 | Managers = @($ManagerList) -ne '' -join '|' 23 | OwnerCount = $OwnerList.Count 24 | Owners = @($OwnerList) -ne '' -join '|' 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /Posh365/Public/Roles/Get-MsolRoleReport.ps1: -------------------------------------------------------------------------------- 1 | function Get-MsolRoleReport { 2 | [CmdletBinding()] 3 | param ( 4 | ) 5 | Write-Verbose 'Retrieving Msol admin roles' 6 | $MsolRoleList = Get-MsolRole 7 | foreach ($MsolRole in $MsolRoleList) { 8 | Write-Verbose "Processing $($MsolRole.Name)" 9 | try { 10 | $RoleMemberList = Get-MsolRoleMember -RoleObjectId $MsolRole.ObjectId -ErrorAction Stop 11 | foreach ($RoleMember in $RoleMemberList) { 12 | [PSCustomObject]@{ 13 | 'Role' = $MsolRole.Name 14 | 'DisplayName' = $RoleMember.DisplayName 15 | 'EmailAddress' = $RoleMember.EmailAddress 16 | 'RoleMemberType' = $RoleMember.RoleMemberType 17 | 'LastDirSyncTime' = $RoleMember.LastDirSyncTime 18 | 'MFA_State' = ($RoleMember.StrongAuthenticationRequirements).State 19 | 'RoleDescription' = $MsolRole.Description 20 | } 21 | } 22 | } 23 | catch { 24 | 25 | } 26 | 27 | 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Posh365/Public/Roles/Update-RoleEntry.ps1: -------------------------------------------------------------------------------- 1 | Function Update-RoleEntry { 2 | <# 3 | .SYNOPSIS 4 | Function to modify a role by removing or adding Role Entries 5 | 6 | .DESCRIPTION 7 | 8 | (If no Action is passed we assume remove) 9 | $roleentry should be in the form Role\Roleentry e.g. MyRole\New-DistributionGroup 10 | 11 | .PARAMETER RoleEntry 12 | Parameter description 13 | 14 | .PARAMETER Action 15 | Parameter description 16 | 17 | .EXAMPLE 18 | An example 19 | 20 | .NOTES 21 | General notes 22 | #> 23 | 24 | Param( 25 | [Parameter()] 26 | $RoleEntry, 27 | 28 | [Parameter()] 29 | $Action 30 | ) 31 | 32 | Switch ($Action) { 33 | Add {Add-ManagementRoleEntry $RoleEntry -confirm:$false} 34 | Remove {Remove-ManagementRoleEntry $RoleEntry -confirm:$false} 35 | Default {Remove-ManagementRoleEntry $RoleEntry -confirm:$false} 36 | } 37 | } -------------------------------------------------------------------------------- /Posh365/Public/Security/Test-SPFRecord.ps1: -------------------------------------------------------------------------------- 1 | function Test-SPFRecord { 2 | [CmdletBinding()] 3 | param ( 4 | [Parameter()] 5 | $DomainName 6 | ) 7 | $Message = Invoke-TestSPFRecord -Domain $DomainName 8 | $ResultHash = [ordered]@{ } 9 | 10 | if ($message -like "*pass*") { 11 | $ResultHash.Add('Result', 'PASS') 12 | } 13 | else { 14 | $ResultHash.Add('Result', 'FAIL') 15 | } 16 | $Detail = [regex]::Matches($Message, "(?<=Results - )[^<]*").value 17 | if ($Detail) { 18 | $ResultHash.Add('Detail', $Detail) 19 | } 20 | else { 21 | $ResultHash.Add('Detail', 'PASS') 22 | } 23 | [PSCustomObject]$ResultHash 24 | } 25 | -------------------------------------------------------------------------------- /Posh365/Public/SharePointPNP/Add-PoshPnPFile.ps1: -------------------------------------------------------------------------------- 1 | function Add-PoshPnPFile { 2 | [CmdletBinding()] 3 | param ( 4 | [Parameter(Mandatory)] 5 | [ValidateNotNullOrEmpty()] 6 | [string] 7 | $SharePointURL, 8 | 9 | [Parameter(Mandatory)] 10 | [ValidateScript( { Test-Path $_ })] 11 | [string] 12 | $FilePath, 13 | 14 | [Parameter()] 15 | [ValidateNotNullOrEmpty()] 16 | [string] 17 | $SubURL 18 | ) 19 | end { 20 | Connect-SharePointPNP -Url $SharePointURL 21 | $SPFolder = "Shared Documents/{0}" -f $SubURL 22 | try { 23 | Add-PnPFile -Path $FilePath -Folder $SPFolder -ErrorAction Stop 24 | } 25 | catch { 26 | Write-Host "Error getting file from SharePoint" 27 | $_ 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Posh365/Public/Sync/Sync-AD.ps1: -------------------------------------------------------------------------------- 1 | function Sync-AD { 2 | 3 | Param () 4 | <# 5 | .SYNOPSIS 6 | Force Replication on each Domain Controller in the Forest 7 | 8 | .EXAMPLE 9 | 10 | Sync-AD 11 | 12 | #> 13 | 14 | ### Force Replication on each Domain Controller in the Forest ### 15 | $session = New-PSSession -ComputerName ($env:LOGONSERVER).Split("\")[2] 16 | Invoke-Command -Session $session -ScriptBlock {((Get-ADForest).Domains | % { Get-ADdomainController -Filter * -Server $_ }).hostname | % {repadmin /syncall /APeqd $_}} 17 | Remove-PSSession $session 18 | } --------------------------------------------------------------------------------