├── Scripts
├── SharePoint.Sandbox.ListSolutionsFromTenant
│ ├── Get-SPOnlineSandboxSolutionList.ps1
│ └── README.MD
├── SharePoint.Hybrid.Search.Configuration
│ ├── Documentation
│ │ └── Hybrid Configuration Wizard.docx
│ ├── readme.md
│ └── HybridWizard.ps1
├── README.md
├── SharePoint.Hybrid.CloudSSA.Configuration
│ ├── DetectWorkFlowConnection.ps1
│ ├── WorkflowManagerfixUp.ps1
│ ├── DetectProviderHostedAddIns.ps1
│ ├── AuthenticationRealmFixUp.ps1
│ ├── readme.md
│ ├── SPHybridValidation.ps1
│ └── CreateHybridCloudSSA.ps1
├── SharePoint.SiteColProvisioning.Configuration
│ ├── definetenantadminsite.ps1
│ ├── allowtenantapiv16.ps1
│ ├── allowtenantapiv15.ps1
│ └── readme.md
├── readme-template.md
├── AzureAD.Principals.Expire
│ ├── Principals.ps1
│ └── readme.md
└── SharePoint.LowTrustACS.Configuration
│ ├── LowTrustConfigurationSession.ps1
│ ├── Connect-SPFarmToAAD.psm1
│ └── readme.md
├── .github
├── PULL_REQUEST_TEMPLATE.md
├── ISSUE_TEMPLATE.md
└── CONTRIBUTING.md
├── README.md
├── LICENSE
└── .gitignore
/Scripts/SharePoint.Sandbox.ListSolutionsFromTenant/Get-SPOnlineSandboxSolutionList.ps1:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sharepoint/sp-admin-scripts/master/Scripts/SharePoint.Sandbox.ListSolutionsFromTenant/Get-SPOnlineSandboxSolutionList.ps1
--------------------------------------------------------------------------------
/Scripts/SharePoint.Hybrid.Search.Configuration/Documentation/Hybrid Configuration Wizard.docx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sharepoint/sp-admin-scripts/master/Scripts/SharePoint.Hybrid.Search.Configuration/Documentation/Hybrid Configuration Wizard.docx
--------------------------------------------------------------------------------
/Scripts/README.md:
--------------------------------------------------------------------------------
1 | # Patterns and Practices - Scripts #
2 | Different kind of automation scripts for SharePoint and Office 365 in general. See readme from specific folders for exact details.
3 |
4 | 
5 |
6 | # "Sharing is caring" #
7 |
8 |
--------------------------------------------------------------------------------
/Scripts/SharePoint.Hybrid.CloudSSA.Configuration/DetectWorkFlowConnection.ps1:
--------------------------------------------------------------------------------
1 | <#
2 | .synopsis
3 | Script determines whether A Workflow Manager Service Application Proxy Connection is deployed to the local farm.
4 | .example
5 | .\DetectWorkFlowConnection.ps1
6 | #>
7 | if ((Get-PSSnapin -Name "Microsoft.SharePoint.PowerShell" -ErrorAction SilentlyContinue) -eq $null)
8 | {
9 | Add-PSSnapin -Name "Microsoft.SharePoint.PowerShell"
10 | }
11 | cls
12 |
13 | $workflowproxy = Get-SPWorkflowServiceApplicationProxy
14 |
15 | if ($workflowproxy)
16 | {
17 | Write-Output "Workflow Manager Connection Detected. Use documented remediation steos to update it after hybrid deployment"
18 | }
19 | else
20 | {
21 | Write-Output "No Workflow Manager Connection Detected. Remediation not required"
22 | }
--------------------------------------------------------------------------------
/.github/PULL_REQUEST_TEMPLATE.md:
--------------------------------------------------------------------------------
1 | | Q | A |
2 | | --------------- | --------------------------------------- |
3 | | Bug fix? | no - yes? |
4 | | New feature? | no - yes? |
5 | | New script? | no - yes? |
6 | | Related issues? | fixes #X, partially #Y, mentioned in #Z |
7 |
8 | ## What's in this Pull Request?
9 |
10 | > Please describe the changes in this PR. Sample description or details around bugs which are being fixed.
11 | >
12 | > _(DELETE THIS PARAGRAPH AFTER READING)_
13 |
14 | ## Guidance
15 |
16 | > *Please update this PR information accordingly. We'll use this as part of our release notes in monthly communications.*
17 | >
18 | > *Please target your PR to `master` branch.*
19 | >
20 | > _(DELETE THIS PARAGRAPH AFTER READING)_
21 |
--------------------------------------------------------------------------------
/Scripts/SharePoint.SiteColProvisioning.Configuration/definetenantadminsite.ps1:
--------------------------------------------------------------------------------
1 | param
2 | (
3 | [Parameter(Mandatory=$true)][ValidateNotNullOrEmpty()]
4 | [String]$siteColUrl
5 | )
6 | #
7 | # Set admin site type property to the site collection using PS for any site collection type.
8 | # This is needed to be set for the site collection which is used as the
9 | # "Connection point" for the CSOM when site collections are created in on-prem
10 | #
11 |
12 | $snapin = Get-PSSnapin | Where-Object {$_.Name -eq 'Microsoft.SharePoint.Powershell'}
13 | if ($snapin -eq $null)
14 | {
15 | Write-Host "Loading SharePoint Powershell Snapin"
16 | Add-PSSnapin "Microsoft.SharePoint.Powershell"
17 | }
18 |
19 | $site = get-spsite -Identity $siteColUrl
20 | $site.AdministrationSiteType = [Microsoft.SharePoint.SPAdministrationSiteType]::TenantAdministration
21 |
22 | Write-Host "Site $siteColUrl set to AdministrationSiteType" $site.AdministrationSiteType
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 | # Contributing
3 |
4 | This project welcomes contributions and suggestions. Most contributions require you to agree to a
5 | Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us
6 | the rights to use your contribution. For details, visit https://cla.microsoft.com.
7 |
8 | When you submit a pull request, a CLA-bot will automatically determine whether you need to provide
9 | a CLA and decorate the PR appropriately (e.g., label, comment). Simply follow the instructions
10 | provided by the bot. You will only need to do this once across all repos using our CLA.
11 |
12 | This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/).
13 | For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or
14 | contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments.
15 |
--------------------------------------------------------------------------------
/Scripts/readme-template.md:
--------------------------------------------------------------------------------
1 | # Title of the Script (SEO friendly) #
2 |
3 | ## Summary ##
4 |
5 | Description of the script
6 |
7 | ### Applies to ###
8 |
9 | - OneDrive
10 | - Potentially SharePoint if applies there as well
11 |
12 | ### Prerequisites ###
13 |
14 | - if any
15 |
16 | ### Solution ###
17 | Solution | Author(s)
18 | ---------|----------
19 | Name of the solution | name (company name)
20 |
21 | ### Version history ###
22 | Version | Date | Comments
23 | ---------| -----| --------
24 | 1.0 | February 8th 2026 | Initial release
25 |
26 | ### Disclaimer ###
27 |
28 | **THIS SCRIPT IS PROVIDED *AS IS* WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.**
29 |
30 | ----------
31 |
32 | # Introduction
33 |
34 | Description of the script and what it does with potential set of additional links, images and other references.
35 |
36 |
--------------------------------------------------------------------------------
/Scripts/AzureAD.Principals.Expire/Principals.ps1:
--------------------------------------------------------------------------------
1 | <#
2 | .Synopsis
3 | This cmdlet will list out all the expired service principals
4 |
5 | Goals
6 | · Prevent expired client id
7 |
8 |
9 | .EXAMPLE
10 |
11 | -------------------------- EXAMPLE 01 --------------------------
12 | Get-ExpiredServicePrincipals
13 |
14 | #>
15 |
16 | function Get-ExpiredServicePrincipals {
17 | #filter out Microsoft and WorkFlow
18 | $applist = Get-MsolServicePrincipal -all | Where-Object -FilterScript { ($_.DisplayName -notlike "*Microsoft*") -and ($_.DisplayName -notlike "*WorkFlow*") }
19 | $today = get-date
20 |
21 | foreach ($appentry in $applist) {
22 | $pc = Get-MsolServicePrincipalCredential -AppPrincipalId $appentry.AppPrincipalId -ReturnKeyValues $false | Where-Object { ($_.Type -ne "Other") -and ($_.Type -ne "Asymmetric") -and ($_.EndDate -lt $today)}
23 | if($pc){
24 | Write-Host $appentry.DisplayName, $appentry.AppPrincipalId , $pc[0].EndDate.DateTime
25 | }
26 | }
27 | }
28 |
29 |
30 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) Microsoft Corporation. All rights reserved.
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE
22 |
--------------------------------------------------------------------------------
/Scripts/SharePoint.SiteColProvisioning.Configuration/allowtenantapiv16.ps1:
--------------------------------------------------------------------------------
1 | param
2 | (
3 | [Parameter(Mandatory=$true)][ValidateNotNullOrEmpty()]
4 | [String]$WebApplicationUrl
5 | )
6 | #
7 | # Enable the remote site collection creation for on-prem in web application level
8 | # If this is not done, unknon object exception is raised by the CSOM code
9 | #
10 | $snapin = Get-PSSnapin | Where-Object {$_.Name -eq 'Microsoft.SharePoint.Powershell'}
11 | if ($snapin -eq $null)
12 | {
13 | Write-Host "Loading SharePoint Powershell Snapin"
14 | Add-PSSnapin "Microsoft.SharePoint.Powershell"
15 | }
16 |
17 | $webapp=Get-SPWebApplication $WebApplicationUrl
18 | $newProxyLibrary = New-Object "Microsoft.SharePoint.Administration.SPClientCallableProxyLibrary"
19 | $newProxyLibrary.AssemblyName = "Microsoft.Online.SharePoint.Dedicated.TenantAdmin.ServerStub, Version=16.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c"
20 | $newProxyLibrary.SupportAppAuthentication = $true
21 | $webapp.ClientCallableSettings.ProxyLibraries.Add($newProxyLibrary)
22 | $webapp.SelfServiceSiteCreationEnabled=$true
23 | $webapp.Update()
24 | Write-Host "Successfully added TenantAdmin ServerStub to ClientCallableProxyLibrary for web application" $WebApplicationUrl
25 | # Reset the memory of the web application
26 | Write-Host "IISReset..."
27 | Restart-Service W3SVC,WAS -force
28 | Write-Host "IISReset complete on this server, remember other servers in farm as well."
--------------------------------------------------------------------------------
/Scripts/SharePoint.SiteColProvisioning.Configuration/allowtenantapiv15.ps1:
--------------------------------------------------------------------------------
1 | param
2 | (
3 | [Parameter(Mandatory=$true)][ValidateNotNullOrEmpty()]
4 | [String]$WebApplicationUrl
5 | )
6 | #
7 | # Enable the remote site collection creation for on-prem in web application level
8 | # If this is not done, unknon object exception is raised by the CSOM code
9 | #
10 | $snapin = Get-PSSnapin | Where-Object {$_.Name -eq 'Microsoft.SharePoint.Powershell'}
11 | if ($snapin -eq $null)
12 | {
13 | Write-Host "Loading SharePoint Powershell Snapin"
14 | Add-PSSnapin "Microsoft.SharePoint.Powershell"
15 | }
16 |
17 | $webapp=Get-SPWebApplication $WebApplicationUrl
18 | $newProxyLibrary = New-Object "Microsoft.SharePoint.Administration.SPClientCallableProxyLibrary"
19 | $newProxyLibrary.AssemblyName = "Microsoft.Online.SharePoint.Dedicated.TenantAdmin.ServerStub, Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c"
20 | $newProxyLibrary.SupportAppAuthentication = $true
21 | $webapp.ClientCallableSettings.ProxyLibraries.Add($newProxyLibrary)
22 | $webapp.SelfServiceSiteCreationEnabled=$true
23 | $webapp.Update()
24 | Write-Host "Successfully added TenantAdmin ServerStub to ClientCallableProxyLibrary for web application" $WebApplicationUrl
25 | # Reset the memory of the web application
26 | Write-Host "IISReset..."
27 | Restart-Service W3SVC,WAS -force
28 | Write-Host "IISReset complete on this server, remember other servers in farm as well."
29 |
--------------------------------------------------------------------------------
/Scripts/SharePoint.Hybrid.Search.Configuration/readme.md:
--------------------------------------------------------------------------------
1 | # Hybrid Configuration Wizard #
2 |
3 | ### Summary ###
4 |
5 | This script is for use in configuring an outbound search hybrid experience between SharePoint 2013 Server and SharePoint Online. In preliminary testing this also works with TAP builds of SharePoint 2016.
6 |
7 | See following blog post for additional details
8 | - [Cloud Hybrid Search Service Application](http://blogs.msdn.com/b/spses/archive/2015/09/15/cloud-hybrid-search-service-application.aspx)
9 |
10 | *work in progress*
11 |
12 | ### Applies to ###
13 | - SharePoint 2013 on-premises
14 | - SharePoint 2016 on-premises
15 |
16 | ### Prerequisites ###
17 | Any special pre-requisites?
18 |
19 | ### Solution ###
20 | Solution | Author(s)
21 | ---------|----------
22 | Hybrid Configuration Wizard | Manas Biswas (Microsoft), Neil Hodgkinson (Microsoft)
23 |
24 | ### Version history ###
25 | Version | Date | Comments
26 | ---------| -----| --------
27 | 1.0 | November 20th 2015 | Initial release
28 |
29 | ### Disclaimer ###
30 | **THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.**
31 |
32 |
33 | ----------
34 |
35 | # For detailed description of scenarios and steps, please refer to following documentation in the repository.#
36 |
37 | ## Hybrid Configuration Wizard ##
38 | Located under the *Documents* folder. Contains similar information as the mentioned blog post.
39 |
40 |
--------------------------------------------------------------------------------
/Scripts/AzureAD.Principals.Expire/readme.md:
--------------------------------------------------------------------------------
1 | # Azure Active Directory Principals #
2 |
3 | ### Summary ###
4 | This script will assist you discovery of Client ID's that have expired in your Azure Active Directory Tenant
5 |
6 | *work in progress*
7 |
8 | ### Applies to ###
9 | - SharePoint 2013 on-premises - Low Trust Configuration
10 | - SharePoint 2016 on-premises - Low Trust Configuration
11 | - SharePoint Online MT and Dedicated Services
12 |
13 | ### Prerequisites ###
14 | [Microsoft Online Services Sign-In](https://www.microsoft.com/en-us/download/details.aspx?id=39267) Assistant is installed
15 | [Microsoft Online Services PowerShell Module](http://go.microsoft.com/fwlink/p/?linkid=236297) is installed
16 |
17 |
18 | ### Solution ###
19 | Solution | Author(s)
20 | ---------|----------
21 | Principals | Frank Marasco (Microsoft)
22 |
23 | ### Version history ###
24 | Version | Date | Comments
25 | ---------| -----| --------
26 | 1.0 | April 19th 2016 | Initial release
27 |
28 | ### Disclaimer ###
29 | **THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.**
30 |
31 |
32 | ----------
33 |
34 | ## Execution ##
35 |
36 | Connect-MSolService
37 |
38 | 
39 |
40 | Get-ExpiredServicePrincipals
41 |
42 | 
43 |
44 |
45 | ## Resources ##
46 | Replace an expiring client secret in a SharePoint Add-in](https://msdn.microsoft.com/en-us/library/office/dn726681.aspx)
47 |
48 |
--------------------------------------------------------------------------------
/Scripts/SharePoint.LowTrustACS.Configuration/LowTrustConfigurationSession.ps1:
--------------------------------------------------------------------------------
1 |
2 | param
3 | (
4 | [Parameter(Mandatory=$true)][ValidateNotNullOrEmpty()] [String]$PFXFile,
5 | [Parameter(Mandatory=$true)][ValidateNotNullOrEmpty()] [String]$PFXPassword,
6 | [Parameter(Mandatory=$true)][ValidateNotNullOrEmpty()] [String]$ConnectSPFarmToAADModulePath
7 | )
8 |
9 | #Load the PS module when needed
10 | $snapin = Get-PSSnapin | Where-Object {$_.Name -eq 'Microsoft.SharePoint.Powershell'}
11 | if ($snapin -eq $null)
12 | {
13 | Write-Host "Loading SharePoint Powershell Snapin"
14 | Add-PSSnapin "Microsoft.SharePoint.Powershell"
15 | }
16 |
17 | #Import the signing certificate and reset the timer service
18 | $stsCertificate = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2 $PFXFile, $PFXPassword, 20
19 | Set-SPSecurityTokenServiceConfig –ImportSigningCertificate $stsCertificate -confirm:$false
20 | iisreset
21 | net stop SPTimerV4
22 | net start SPTimerV4
23 |
24 | #Load the custom module with the Connect-SPFarmToAAD command
25 | Import-Module ("{0}\Connect-SPFarmToAAD.psm1" -f $ConnectSPFarmToAADModulePath)
26 | ls function:\ | where {$_.Name -eq "Connect-SPFarmToAAD"}
27 |
28 | Write-Host
29 | Write-Host "Use the Connect-SPFarmToAAD cmdlet to realize the low trust connection between your on-premises farm and your Office 365 tenant." -ForegroundColor Green
30 | Write-Host "See below for typical sample usages:"
31 |
32 | Write-Host "Connect-SPFarmToAAD –AADDomain 'MyO365Domain.onmicrosoft.com' –SharePointOnlineUrl https://MyO365Domain.sharepoint.com" -ForegroundColor Cyan
33 | Write-Host "Connect-SPFarmToAAD –AADDomain 'MyO365Domain.onmicrosoft.com' –SharePointOnlineUrl https://MyO365Domain.sharepoint.com –SharePointWeb https://fabrikam.com" -ForegroundColor Cyan
34 | Write-Host "Connect-SPFarmToAAD –AADDomain 'MyO365Domain.onmicrosoft.com' –SharePointOnlineUrl https://MyO365Domain.sharepoint.com –SharePointWeb http://northwind.com -AllowOverHttp" -ForegroundColor Cyan
35 | Write-Host "Connect-SPFarmToAAD –AADDomain 'MyO365Domain.onmicrosoft.com' –SharePointOnlineUrl https://MyO365Domain.sharepoint.com –SharePointWeb http://northwind.com –AllowOverHttp –RemoveExistingACS –RemoveExistingSTS –RemoveExistingSPOProxy –RemoveExistingAADCredentials" -ForegroundColor Cyan
36 | Write-Host "More information can be found at https://msdn.microsoft.com/en-us/library/office/dn155905.aspx"
37 | Write-Host
--------------------------------------------------------------------------------
/Scripts/SharePoint.Hybrid.CloudSSA.Configuration/WorkflowManagerfixUp.ps1:
--------------------------------------------------------------------------------
1 | <#
2 | .synopsis
3 | This script will detect the details of the workflow manager proxy on the farm and recreate the proxy connection
4 | .description
5 | This script will detect the details of the workflow manager proxy on the farm and recreate the proxy connection
6 | The proxy connection needs to be recreated due tot he change in AuthentivationRealm ID caused by hybrid deployment.
7 |
8 | Run the script as a farm and local admin on a SharePoint server.
9 |
10 | .example
11 | .\WorkflowManagerfixUp.ps1
12 | #>
13 |
14 | if ((Get-PSSnapin -Name "Microsoft.SharePoint.PowerShell" -ErrorAction SilentlyContinue) -eq $null)
15 | {
16 | Add-PSSnapin -Name "Microsoft.SharePoint.PowerShell"
17 | }
18 | cls
19 |
20 |
21 | function Update-WorkflowManagerProxyConnection
22 | {
23 |
24 | $workflowproxy = Get-SPWorkflowServiceApplicationProxy
25 | try
26 | {
27 | $webapp = get-spwebapplication
28 | }
29 | catch {}
30 |
31 | if ($webapp)
32 | {
33 | $webappurl = $webapp[0].url
34 | try
35 | {
36 | $Site=get-spsite $webappurl
37 | }
38 | catch {}
39 |
40 | if ($site)
41 | {
42 | $workflowaddress = $workflowproxy.GetWorkflowServiceAddress($site)
43 | $workflowscopename = $workflowproxy.GetWorkflowScopeName($site)
44 | $TrimScope = '/'+$workflowscopename+'/'
45 | $wfmaddress = $workflowaddress.TrimEnd($Trimscope)
46 | }
47 | Else
48 | {
49 | Write-Warning "There is no site collection at the root of the web application. Create a site collection at $webappurl to fix the workflow manager connection"
50 | }
51 | }
52 | else
53 | {
54 | Write-Warning "There are no web applications on this farm. Workflow Manager cannot be conencted to a farm with no web applications"
55 | }
56 |
57 | write-Warning "Deleting the Workflow proxy connection to $wfmaddress"
58 | $workflowproxy.delete()
59 |
60 | try
61 | {
62 | write-output "Recreating the Workflow manager proxy connection to $wfmaddress"
63 | Register-SPWorkflowService -SPSite $Site -WorkflowHostUri $wfmaddress -Force
64 | }
65 | catch
66 | {
67 | Write-Error "Failed to create the proxy connection to $wfmaddress . Please repair this connection manually before attempting to progress any workflow on this farm"
68 | }
69 | }
70 |
71 | Update-WorkflowManagerProxyConnection
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE.md:
--------------------------------------------------------------------------------
1 | > Use the following form to submit an issue only if it's related to samples in this repo. If you have an issue related to the OneDrive or its documentation, please submit the issue at [https://github.com/OneDrive/onedrive-api-docs/issues/new](https://github.com/OneDrive/onedrive-api-docs/issues/new). This will help us respond to your issue faster.
2 | >
3 | > ----
4 | >
5 | > Thank you for reporting an issue or suggesting an enhancement. We appreciate your feedback - to help the team to understand your needs, please complete the below template to ensure we have the necessary details to assist you.
6 | >
7 | > _(DELETE THIS PARAGRAPH AFTER READING)_
8 |
9 | ## Category
10 |
11 | - [ ] Question
12 | - [ ] Bug
13 | - [x] Enhancement
14 |
15 | > For the above list, an empty checkbox is [ ] as in [SPACE]. A checked checkbox is [x] with no space between the brackets. Use the `PREVIEW` tab at the top right to preview the rendering before submitting your issue.
16 | >
17 | > _(DELETE THIS PARAGRAPH AFTER READING)_
18 |
19 | ## Expected or Desired Behavior
20 |
21 | > _If you are reporting a bug, please describe the expected behavior. If you are suggesting an enhancement please describe thoroughly the enhancement, how it can be achieved, and expected benefit._
22 | >
23 | > _(DELETE THIS PARAGRAPH AFTER READING)_
24 |
25 | ## Observed Behavior
26 |
27 | > _If you are reporting a bug, please describe the behavior you expected to occur when performing the action. If you are making a suggestion, you can delete this section._
28 | >
29 | > _(DELETE THIS PARAGRAPH AFTER READING)_
30 |
31 | ## Steps to Reproduce
32 |
33 | > _If you are reporting a bug please describe the steps to reproduce the bug in sufficient detail to allow testing. Only way to fix things properly, is to have sufficient details to reproduce it. If you are making a suggestion, you can delete this section._
34 | >
35 | > _(DELETE THIS PARAGRAPH AFTER READING)_
36 |
37 | ## Submission Guidelines
38 |
39 | > - All suggestions or bugs are welcome, please let us know what's on your mind.
40 | > - If you are reporting an issue around any of the samples, please ensure that you have clear reference on the sample and possibly script file, which should be fixed.
41 | > - Remember to include sufficient details and context.
42 | > - If you have multiple suggestions or bugs please submit them in separate bugs so we can track resolution.
43 | >
44 | > _(DELETE THIS PARAGRAPH AFTER READING)_
45 |
46 | Thanks for your contribution! Sharing is caring.
47 |
--------------------------------------------------------------------------------
/Scripts/SharePoint.Hybrid.CloudSSA.Configuration/DetectProviderHostedAddIns.ps1:
--------------------------------------------------------------------------------
1 | <#
2 | .Synopsis
3 | Script locates Provider Hosted AddIn Instance on the local farm and reports the AddIn name and site url .
4 | .Description
5 | Searches for provider hosted addins and need to be ran with a farm admin account
6 | .example
7 | .\DetectProviderHosterAddIns.ps1
8 | #>
9 |
10 | if ((Get-PSSnapin -Name "Microsoft.SharePoint.PowerShell" -ErrorAction SilentlyContinue) -eq $null)
11 | {
12 | Add-PSSnapin -Name "Microsoft.SharePoint.PowerShell"
13 | }
14 | cls
15 |
16 | function Find-AppInstances
17 | {
18 |
19 | #SUMMARY Get all app instances in each of the web applications
20 | $AppsforRemediation = @()
21 | $webApplications = Get-SPWebApplication
22 |
23 | foreach($webapp in $webapplications)
24 | {
25 | foreach($site in $webApp.Sites)
26 | {
27 | try{
28 | foreach($web in $site.AllWebs)
29 | {
30 | $appInstance = Get-SPAppInstance -Web $web.Url | ? {$_.LaunchUrl -notlike "~appWebUrl*"} | select Title, AppPrincipalId
31 | if($appInstance -ne $null)
32 | {
33 | foreach ($instance in $appInstance)
34 | {
35 | $tmp = $instance.AppPrincipalId.Split('|@',[System.StringSplitOptions]::RemoveEmptyEntries)
36 | $appInfo = $instance.Title + " - " + $tmp[$tmp.Count - 2] + " - " + $web.Url
37 |
38 | $AppsforRemediation+=(,($instance.Title, $tmp[$tmp.Count - 2], $web.Url))
39 | }
40 | }
41 | }
42 | }
43 | catch
44 | {
45 | # Typically this scenario would only arise when the Admin executing the script is not a farm admin, or the site is a Fast Site creation Master template site which is inaccessible by default.
46 | Write-Output ""
47 | write-warning "Unable to enumerate webs at Site: $site.url : If this is expected then ignore this message"
48 | Write-Output ""
49 | }
50 | }
51 | }
52 | }
53 |
54 | Find-AppInstances
55 |
56 | if($AppsforRemediation.Count -gt 0)
57 | {
58 | $AppCount = $AppsforRemediation.Count
59 | Write-Output ""
60 | Write-Output "Provider Hosted App Instances Discovered: $AppCount Total PHAs"
61 |
62 | for ($i = 0; $i -lt $AppCount; $i++)
63 | {
64 |
65 | $appTitle = $AppsforRemediation[$i][0]
66 | $clientID = $AppsforRemediation[$i][1]
67 | $targetWeb = Get-SPWeb $AppsforRemediation[$i][2]
68 | $appweb = $targetWeb.Url
69 |
70 | Write-Output ""
71 | Write-Output "Provider Hosted App $appTitle discovered on site $appweb"
72 | }
73 | }
74 | Else
75 | {
76 | Write-Output ""
77 | Write-Output "No Provider Hosted App Instances Discovered: Remediation not required"
78 | }
--------------------------------------------------------------------------------
/Scripts/SharePoint.SiteColProvisioning.Configuration/readme.md:
--------------------------------------------------------------------------------
1 | # PowerShell to enable site collection creation with CSOM #
2 |
3 | ### Summary ###
4 | Scripts and instructions that explain how to enable CSOM based site collection creation in on-premises SharePoint 2013 or 2016.
5 |
6 | ### Applies to ###
7 | - SharePoint 2013 on-premises
8 | - SharePoint 2016 on-premises
9 | - SharePoint 2019 on-premises
10 |
11 | ### Prerequisites ###
12 | Capability is introduced in April 2014 CU for SP2013 and is included in SharePoint 2016 and SharePoint 2019.
13 |
14 | ### Solution ###
15 | Solution | Author(s)
16 | ---------|----------
17 | Site Collection provisioning scripts | Vesa Juvonen, Bert Jansen (**Microsoft**)
18 |
19 | ### Version history ###
20 | Version | Date | Comments
21 | ---------| -----| --------
22 | 1.1 | July 3rd 2018 | Adding notes on the SharePoint 2019
23 | 1.0 | February 8th 2016 | Initial release
24 |
25 | ### Disclaimer ###
26 | **THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.**
27 |
28 |
29 | ----------
30 |
31 | # Introduction
32 | In order to enable site collection using the CSOM CreateSite method you need to run the below two scripts on your SharePoint on-premises farm (SP2013, SP2016, SP2019).
33 |
34 | > **Important.** If you are enabling this capability in SharePoint 2019 farm, you can skip Step #1.
35 |
36 | ## Step 1: Flag a site as "tenant admin" site (SharePoint 2013, SharePoint 2016)
37 |
38 | The `CreateSite` CSOM operation will server side use the multi-tenant CreateSite API's which has as consequence that these API's will need a tenant admin site to function. Luckily you do not to setup the multi-tenant features in your environment, but rather simply **mark** a site as tenant admin site by setting it's `AdministrationSiteType` property to `SPAdministrationSiteType.TenantAdministration`. This site can be **any** site collection, but it's recommended to create a separate site collection with a meaningful name (e.g. TenantAdmin) as this will avoid accidental deletion.
39 |
40 | You can do this by running the `definetenantadminsite.ps1` script like shown below:
41 |
42 | ```PowerShell
43 | .\definetenantadminsite.ps1 -siteColUrl https://portal2016b4327.pnp.com/sites/tenantadmin
44 | ```
45 |
46 | This will result in the following output:
47 |
48 | ```
49 | Loading SharePoint Powershell Snapin
50 | Site https://portal2016b4327.pnp.com/sites/tenantadmin set to AdministrationSiteType TenantAdministration
51 | ```
52 |
53 |
54 | ## Step 2: Prepare the web application(s) to enable the CreateSite CSOM method
55 |
56 | Each web application for which you want to be able to create site collections using the `CreateSite` CSOM method needs to be prepared by:
57 |
58 | - Adding the TenantAdmin CSOM stub to the list of allowed client callable proxy libraries
59 | - Enabling self service site collection creation
60 |
61 | You can perform the above 2 steps by running `allowtenantapiv15.ps1` when you're working with SharePoint 2013 or `allowtenantapiv16.ps1` when you're using SharePoint 2016 or SharePoint 2019 version..
62 |
63 | **Note:**
64 | This will perform an IISReset on the server you run this. **Don't forget to perform an IISReset on the other servers in the farm.**
65 |
66 |
67 | ```PowerShell
68 | .\allowtenantapiv16.ps1 -WebApplicationUrl https://portal2016b4327.pnp.com
69 | ```
70 |
71 | This will result in the following output:
72 |
73 | ```
74 | Successfully added TenantAdmin ServerStub to ClientCallableProxyLibrary for web application https://portal2016b4327.pnp.com
75 | IISReset...
76 | WARNING: Waiting for service 'World Wide Web Publishing Service (W3SVC)' to stop...
77 | WARNING: Waiting for service 'Windows Process Activation Service (WAS)' to stop...
78 | IISReset complete on this server, remember other servers in farm as well.
79 | ```
80 | To finalize this step you'll need to perform an IISReset on all the other servers in the farm.
81 |
82 |
83 |
--------------------------------------------------------------------------------
/Scripts/SharePoint.Hybrid.CloudSSA.Configuration/AuthenticationRealmFixUp.ps1:
--------------------------------------------------------------------------------
1 | <#
2 | .Synopsis
3 | Script fixes the scenario where a hybrid workload has been onboarded to a farm and the result is broken PHAs.
4 | .Description
5 | This scripts will fix the PHAs and need to be ran with a farm admin account
6 | .EXAMPLE
7 | .\AuthenticationRealmFixUp.ps1
8 | Reports the PHAs that need to be fixed an the location where they are fixe
9 | #>
10 |
11 | if ((Get-PSSnapin -Name "Microsoft.SharePoint.PowerShell" -ErrorAction SilentlyContinue) -eq $null)
12 | {
13 | Add-PSSnapin -Name "Microsoft.SharePoint.PowerShell"
14 | }
15 | cls
16 |
17 | function Find-AppInstances{
18 |
19 | #SUMMARY Get all app instances in each of the web applications
20 | $AppsforRemediation = @()
21 | $webApplications = Get-SPWebApplication
22 |
23 | foreach($webapp in $webapplications)
24 | {
25 | foreach($site in $webApp.Sites)
26 | {
27 | try
28 | {
29 | foreach($web in $site.AllWebs)
30 | {
31 | $appInstance = Get-SPAppInstance -Web $web.Url | ? {$_.LaunchUrl -notlike "~appWebUrl*"} | select Title, AppPrincipalId
32 | if($appInstance -ne $null)
33 | {
34 | foreach ($instance in $appInstance)
35 | {
36 | $tmp = $instance.AppPrincipalId.Split('|@',[System.StringSplitOptions]::RemoveEmptyEntries)
37 | $appInfo = $instance.Title + " - " + $tmp[$tmp.Count - 2] + " - " + $web.Url
38 |
39 | $AppsforRemediation+=(,($instance.Title, $tmp[$tmp.Count - 2], $web.Url))
40 | }
41 | }
42 | }
43 | }
44 | catch
45 | {
46 | # Typically this scenario would only arise when the Admin executing the script is not a farm admin, or the site is a Fast Site creation Master template site which is inaccessible by default.
47 | Write-Output ""
48 | write-warning "Unable to enumerate webs at Site: $site.url : If this is expected then ignore this message"
49 | Write-Output ""
50 | }
51 | }
52 | }
53 | }
54 |
55 |
56 | function Repair-TrustedSecurityTokenIssuer {
57 |
58 | #SUMMARY Fix up the SPTrustedSecurityTokenIssuers with the new SPAuthenticationRealmID to match the Office365
59 |
60 |
61 | $NewRealm = Get-SPAuthenticationRealm
62 | $sts = Get-SPTrustedSecurityTokenIssuer | ? {$_.Name -ne 'EvoSTS-Trust' -and $_.Name -ne 'ACS_STS'} | Select RegisteredIssuerName
63 | $realm = $sts | ?{$_.RegisteredIssuerName -ne $null} | %{$($($_.RegisteredIssuerName).toString().split('@',2)[1]).toString()} | ?{$_ -ne '*' -and $_ -ne $newRealm}
64 |
65 | if($Realm.count -gt 0)
66 | {
67 | try{
68 | $TempRealm = '*@$($NewRealm)'
69 | $Issuers = Get-SPTrustedSecurityTokenIssuer | ?{$_.Name -ne 'EvoSTS-Trust' -and $_.Name -ne 'ACS_STS' -and $_.RegisteredIssuerName -ne $null -and $_.RegisteredIssuerName -notlike '*@`*' -and $_.RegisteredIssuerName -notlike $TempRealm}
70 |
71 | $Guid = [guid]::NewGuid()
72 | foreach ($Issuer in $Issuers)
73 | {
74 | $NameCopy = $Issuer.Name
75 | $NewIssuerName = $Guid
76 | $IssuerCertificate = $Issuer.SigningCertificate
77 | $OldRegisteredIssuerID = $Issuer.RegisteredIssuerName
78 | $IssuerID = $OldRegisteredIssuerID.Split('@')[0]
79 | $NewRegisteredIssuerName = $IssuerID + '@' + $NewRealm
80 |
81 | $NewIssuer = New-SPTrustedSecurityTokenIssuer -Name $NewIssuerName -Certificate $IssuerCertificate -RegisteredIssuerName $NewRegisteredIssuerName -IsTrustBroker
82 | Remove-SPTrustedSecurityTokenIssuer $Issuer -Confirm:$false
83 | $NewIssuer.Name = $NameCopy
84 | $NewIssuer.Update()
85 | }
86 | }
87 | Catch{
88 | Write-Output ""
89 | Write-Error "Failed to update SharePoint Trusted Security Token Issuer for $NewIssuerName. Investigate and correct before re-running the script else PHAs depending on this Issuer will fail"
90 | }
91 | }
92 | }
93 |
94 |
95 | function Repair-AppPermissions{
96 |
97 | $AppCount = $AppsforRemediation.count
98 |
99 | for ($i = 0; $i -lt $AppCount; $i++)
100 | {
101 |
102 | $appTitle = $AppsforRemediation[$i][0]
103 | $clientID = $AppsforRemediation[$i][1]
104 | $targetWeb = Get-SPWeb $AppsforRemediation[$i][2]
105 | $appweb = $targetWeb.Url
106 | $Scope = 'Site'
107 | $Right = 'FullControl'
108 | $authRealm = Get-SPAuthenticationRealm -ServiceContext $targetWeb.Site
109 | $AppIdentifier = $clientID + '@' + $authRealm
110 | Write-Output ""
111 | Write-Output "Repairing Permissions for $appTitle on site $appweb"
112 |
113 | $regprincipal = Register-SPAppPrincipal -NameIdentifier $AppIdentifier -Site $targetWeb -DisplayName $appTitle
114 | $appPrincipal = Get-SPAppPrincipal -Site $targetWeb -NameIdentifier $AppIdentifier
115 | Set-SPAppPrincipalPermission -Site $targetWeb -AppPrincipal $appPrincipal -Scope $Scope -Right $Right
116 |
117 | }
118 |
119 | }
120 |
121 |
122 |
123 | Find-AppInstances
124 |
125 | if($AppsforRemediation.Count -gt 0){
126 |
127 | Write-Output ""
128 | Write-Output "Provider Hosted App Instances Discovered: $AppCount Total PHAs"
129 |
130 |
131 | Write-Output ""
132 | Write-Output "Repairing the SPAuthenticationrealmID"
133 |
134 | Repair-TrustedSecurityTokenIssuer
135 |
136 | Write-Output ""
137 | Write-Output "Repairing the Individual App Permissions"
138 |
139 | Repair-AppPermissions
140 |
141 | }
142 | else
143 | {
144 | Write-Output ""
145 | Write-Output "There are no remediation actions required on this farm"
146 | }
147 |
148 |
--------------------------------------------------------------------------------
/Scripts/SharePoint.Hybrid.CloudSSA.Configuration/readme.md:
--------------------------------------------------------------------------------
1 | # Cloud Search Service Application and Supporting Scripts for Deployment and Configuration #
2 |
3 | ## Summary ##
4 | This section of the PnP tools repository contains a series of scripts to help deploy and configure hybrid scenarios for SharePoint and Office 365 SharePoint Online. The following scripts are available
5 |
6 | ### CreateHybridCloudSSA.ps1 ###
7 |
8 | This script is designed for configuring a SharePoint Server farm with a hybrid Cloud Search Service Application
9 |
10 | It requires the following variables:
11 |
12 | *SearchApplicationPoolAccountName - this is the account for the search app pool. If there is an existing local SSA that same account can be reused. Note that this account must be a managed SharePoint service account.
13 |
14 | *DatabaseServer - this is the name of an existing SharePoint database server.
15 |
16 | *SearchServer1 - this is the name of the first new server for Hybrid Search services. This server must already be added to the farm and should not host any SharePoint roles other than what was created when the server was added.
17 |
18 | *SearchServer2 - this is the name of the second new server for Hybrid Search services. The presence of this server is optional if the customer does not have a highly available SharePoint farm. This server must already be added to the farm and should not host any SharePoint roles other than what was created when the server was added.
19 |
20 | The authors recommend that two servers be used to ensure high availability of the service application.
21 |
22 |
23 | #### Applies to ####
24 | - SharePoint 2016 on-premises
25 | - SharePoint 2013 on-premises
26 |
27 | #### Prerequisites ####
28 | Any special pre-requisites?
29 |
30 | #### Solution ####
31 | Solution | Author(s)
32 | ---------|----------
33 | Hybrid Cloud Search Service Application Configuration Wizard | Neil Hodgkinson (Microsoft), Marcus Tiongson (Microsoft), Manas Biswas (Microsoft)
34 |
35 | #### Version history ####
36 | Version | Date | Comments
37 | ---------| -----| --------
38 | 1.0 | October 3rd 2016 | Initial release
39 |
40 |
41 | ### SpHybridValidation.ps1 ###
42 |
43 | This script take a single input of the global admin credentials and validates the local farm hybrid connection to the tenant.
44 |
45 | #### Applies to ####
46 | - SharePoint 2016 on-premises
47 | - SharePoint 2013 on-premises
48 |
49 | #### Prerequisites ####
50 | Any special pre-requisites?
51 |
52 | #### Solution ####
53 | Solution | Author(s)
54 | ---------|----------
55 | Sp Hybrid Configuration Validation | Neil Hodgkinson (Microsoft), Manas Biswas (Microsoft)
56 |
57 | #### Version history ####
58 | Version | Date | Comments
59 | ---------| -----| --------
60 | 1.0 | October 3rd 2016 | Initial release
61 |
62 |
63 | ### DetectWorkflowConnection.ps1 ###
64 |
65 | This script requires no inputs and simply detects the presence of a WorkFlow Manager Connection on the local farm.
66 |
67 | #### Applies to ####
68 | - SharePoint 2016 on-premises
69 | - SharePoint 2013 on-premises
70 |
71 | #### Prerequisites ####
72 | Any special pre-requisites?
73 |
74 | #### Solution ####
75 | Solution | Author(s)
76 | ---------|----------
77 | Provider Hosted Add Ins Detection | Neil Hodgkinson (Microsoft)
78 |
79 | #### Version history ####
80 | Version | Date | Comments
81 | ---------| -----| --------
82 | 1.0 | October 3rd 2016 | Initial release
83 |
84 |
85 | ### DetectProviderHostedAddIns.ps1 ###
86 |
87 | This script requires no inputs and simply detects the presence of Provider Hosted Addins on the local farm, reporting back the AddIn name and the web url of each instance deployed to the farm. It then repairs the TrustedSecurityTokenIssuer registration in the farm and regenerates the App Principals and permission for each app instance.
88 |
89 | #### Applies to ####
90 | - SharePoint 2016 on-premises
91 | - SharePoint 2013 on-premises
92 |
93 | #### Prerequisites ####
94 | Any special pre-requisites?
95 |
96 | #### Solution ####
97 | Solution | Author(s)
98 | ---------|----------
99 | Provider Hosted Add Ins Detection | Neil Hodgkinson (Microsoft)
100 |
101 | #### Version history ####
102 | Version | Date | Comments
103 | ---------| -----| --------
104 | 1.0 | October 3rd 2016 | Initial release
105 |
106 |
107 |
108 |
109 | ### AuthenticationRealmFixUp.ps1 ###
110 |
111 | This script requires no inputs and simply detects the presence of Provider Hosted Addins on the local farm, reporting back the AddIn name and the web url of each instance deployed to the farm.
112 |
113 | #### Applies to ####
114 | - SharePoint 2016 on-premises
115 | - SharePoint 2013 on-premises
116 |
117 | #### Prerequisites ####
118 | Any special pre-requisites?
119 |
120 | #### Solution ####
121 | Solution | Author(s)
122 | ---------|----------
123 | Provider Hosted Add Ins Detection | Neil Hodgkinson (Microsoft)
124 |
125 | #### Version history ####
126 | Version | Date | Comments
127 | ---------| -----| --------
128 | 1.0 | October 3rd 2016 | Initial release
129 |
130 |
131 | ### WorkFlowManagerFixUp.ps1 ###
132 |
133 | This script requires no inputs and simply regenerates the WorkFlow Manager Connection on the local farm.
134 |
135 | #### Applies to ####
136 | - SharePoint 2016 on-premises
137 | - SharePoint 2013 on-premises
138 |
139 | #### Prerequisites ####
140 | Any special pre-requisites?
141 |
142 | #### Solution ####
143 | Solution | Author(s)
144 | ---------|----------
145 | Provider Hosted Add Ins Detection | Neil Hodgkinson (Microsoft)
146 |
147 | #### Version history ####
148 | Version | Date | Comments
149 | ---------| -----| --------
150 | 1.0 | October 3rd 2016 | Initial release
151 |
152 |
153 |
154 |
155 | ### Disclaimer ###
156 | **THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.**
157 | ----------
158 |
159 | ### For detailed description of scenarios and steps, please refer to following documentation in the repository.
160 |
161 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 | ##
4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
5 |
6 | # User-specific files
7 | *.suo
8 | *.user
9 | *.userosscache
10 | *.sln.docstates
11 |
12 | # User-specific files (MonoDevelop/Xamarin Studio)
13 | *.userprefs
14 |
15 | # Build results
16 | [Dd]ebug/
17 | [Dd]ebugPublic/
18 | [Rr]elease/
19 | [Rr]eleases/
20 | x64/
21 | x86/
22 | bld/
23 | [Bb]in/
24 | [Oo]bj/
25 | [Ll]og/
26 |
27 | # Visual Studio 2015/2017 cache/options directory
28 | .vs/
29 | # Uncomment if you have tasks that create the project's static files in wwwroot
30 | #wwwroot/
31 |
32 | # Visual Studio 2017 auto generated files
33 | Generated\ Files/
34 |
35 | # MSTest test Results
36 | [Tt]est[Rr]esult*/
37 | [Bb]uild[Ll]og.*
38 |
39 | # NUNIT
40 | *.VisualState.xml
41 | TestResult.xml
42 |
43 | # Build Results of an ATL Project
44 | [Dd]ebugPS/
45 | [Rr]eleasePS/
46 | dlldata.c
47 |
48 | # Benchmark Results
49 | BenchmarkDotNet.Artifacts/
50 |
51 | # .NET Core
52 | project.lock.json
53 | project.fragment.lock.json
54 | artifacts/
55 | **/Properties/launchSettings.json
56 |
57 | # StyleCop
58 | StyleCopReport.xml
59 |
60 | # Files built by Visual Studio
61 | *_i.c
62 | *_p.c
63 | *_i.h
64 | *.ilk
65 | *.meta
66 | *.obj
67 | *.iobj
68 | *.pch
69 | *.pdb
70 | *.ipdb
71 | *.pgc
72 | *.pgd
73 | *.rsp
74 | *.sbr
75 | *.tlb
76 | *.tli
77 | *.tlh
78 | *.tmp
79 | *.tmp_proj
80 | *.log
81 | *.vspscc
82 | *.vssscc
83 | .builds
84 | *.pidb
85 | *.svclog
86 | *.scc
87 |
88 | # Chutzpah Test files
89 | _Chutzpah*
90 |
91 | # Visual C++ cache files
92 | ipch/
93 | *.aps
94 | *.ncb
95 | *.opendb
96 | *.opensdf
97 | *.sdf
98 | *.cachefile
99 | *.VC.db
100 | *.VC.VC.opendb
101 |
102 | # Visual Studio profiler
103 | *.psess
104 | *.vsp
105 | *.vspx
106 | *.sap
107 |
108 | # Visual Studio Trace Files
109 | *.e2e
110 |
111 | # TFS 2012 Local Workspace
112 | $tf/
113 |
114 | # Guidance Automation Toolkit
115 | *.gpState
116 |
117 | # ReSharper is a .NET coding add-in
118 | _ReSharper*/
119 | *.[Rr]e[Ss]harper
120 | *.DotSettings.user
121 |
122 | # JustCode is a .NET coding add-in
123 | .JustCode
124 |
125 | # TeamCity is a build add-in
126 | _TeamCity*
127 |
128 | # DotCover is a Code Coverage Tool
129 | *.dotCover
130 |
131 | # AxoCover is a Code Coverage Tool
132 | .axoCover/*
133 | !.axoCover/settings.json
134 |
135 | # Visual Studio code coverage results
136 | *.coverage
137 | *.coveragexml
138 |
139 | # NCrunch
140 | _NCrunch_*
141 | .*crunch*.local.xml
142 | nCrunchTemp_*
143 |
144 | # MightyMoose
145 | *.mm.*
146 | AutoTest.Net/
147 |
148 | # Web workbench (sass)
149 | .sass-cache/
150 |
151 | # Installshield output folder
152 | [Ee]xpress/
153 |
154 | # DocProject is a documentation generator add-in
155 | DocProject/buildhelp/
156 | DocProject/Help/*.HxT
157 | DocProject/Help/*.HxC
158 | DocProject/Help/*.hhc
159 | DocProject/Help/*.hhk
160 | DocProject/Help/*.hhp
161 | DocProject/Help/Html2
162 | DocProject/Help/html
163 |
164 | # Click-Once directory
165 | publish/
166 |
167 | # Publish Web Output
168 | *.[Pp]ublish.xml
169 | *.azurePubxml
170 | # Note: Comment the next line if you want to checkin your web deploy settings,
171 | # but database connection strings (with potential passwords) will be unencrypted
172 | *.pubxml
173 | *.publishproj
174 |
175 | # Microsoft Azure Web App publish settings. Comment the next line if you want to
176 | # checkin your Azure Web App publish settings, but sensitive information contained
177 | # in these scripts will be unencrypted
178 | PublishScripts/
179 |
180 | # NuGet Packages
181 | *.nupkg
182 | # The packages folder can be ignored because of Package Restore
183 | **/[Pp]ackages/*
184 | # except build/, which is used as an MSBuild target.
185 | !**/[Pp]ackages/build/
186 | # Uncomment if necessary however generally it will be regenerated when needed
187 | #!**/[Pp]ackages/repositories.config
188 | # NuGet v3's project.json files produces more ignorable files
189 | *.nuget.props
190 | *.nuget.targets
191 |
192 | # Microsoft Azure Build Output
193 | csx/
194 | *.build.csdef
195 |
196 | # Microsoft Azure Emulator
197 | ecf/
198 | rcf/
199 |
200 | # Windows Store app package directories and files
201 | AppPackages/
202 | BundleArtifacts/
203 | Package.StoreAssociation.xml
204 | _pkginfo.txt
205 | *.appx
206 |
207 | # Visual Studio cache files
208 | # files ending in .cache can be ignored
209 | *.[Cc]ache
210 | # but keep track of directories ending in .cache
211 | !*.[Cc]ache/
212 |
213 | # Others
214 | ClientBin/
215 | ~$*
216 | *~
217 | *.dbmdl
218 | *.dbproj.schemaview
219 | *.jfm
220 | *.pfx
221 | *.publishsettings
222 | orleans.codegen.cs
223 |
224 | # Including strong name files can present a security risk
225 | # (https://github.com/github/gitignore/pull/2483#issue-259490424)
226 | #*.snk
227 |
228 | # Since there are multiple workflows, uncomment next line to ignore bower_components
229 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
230 | #bower_components/
231 |
232 | # RIA/Silverlight projects
233 | Generated_Code/
234 |
235 | # Backup & report files from converting an old project file
236 | # to a newer Visual Studio version. Backup files are not needed,
237 | # because we have git ;-)
238 | _UpgradeReport_Files/
239 | Backup*/
240 | UpgradeLog*.XML
241 | UpgradeLog*.htm
242 | ServiceFabricBackup/
243 | *.rptproj.bak
244 |
245 | # SQL Server files
246 | *.mdf
247 | *.ldf
248 | *.ndf
249 |
250 | # Business Intelligence projects
251 | *.rdl.data
252 | *.bim.layout
253 | *.bim_*.settings
254 | *.rptproj.rsuser
255 |
256 | # Microsoft Fakes
257 | FakesAssemblies/
258 |
259 | # GhostDoc plugin setting file
260 | *.GhostDoc.xml
261 |
262 | # Node.js Tools for Visual Studio
263 | .ntvs_analysis.dat
264 | node_modules/
265 |
266 | # Visual Studio 6 build log
267 | *.plg
268 |
269 | # Visual Studio 6 workspace options file
270 | *.opt
271 |
272 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
273 | *.vbw
274 |
275 | # Visual Studio LightSwitch build output
276 | **/*.HTMLClient/GeneratedArtifacts
277 | **/*.DesktopClient/GeneratedArtifacts
278 | **/*.DesktopClient/ModelManifest.xml
279 | **/*.Server/GeneratedArtifacts
280 | **/*.Server/ModelManifest.xml
281 | _Pvt_Extensions
282 |
283 | # Paket dependency manager
284 | .paket/paket.exe
285 | paket-files/
286 |
287 | # FAKE - F# Make
288 | .fake/
289 |
290 | # JetBrains Rider
291 | .idea/
292 | *.sln.iml
293 |
294 | # CodeRush
295 | .cr/
296 |
297 | # Python Tools for Visual Studio (PTVS)
298 | __pycache__/
299 | *.pyc
300 |
301 | # Cake - Uncomment if you are using it
302 | # tools/**
303 | # !tools/packages.config
304 |
305 | # Tabs Studio
306 | *.tss
307 |
308 | # Telerik's JustMock configuration file
309 | *.jmconfig
310 |
311 | # BizTalk build output
312 | *.btp.cs
313 | *.btm.cs
314 | *.odx.cs
315 | *.xsd.cs
316 |
317 | # OpenCover UI analysis results
318 | OpenCover/
319 |
320 | # Azure Stream Analytics local run output
321 | ASALocalRun/
322 |
323 | # MSBuild Binary and Structured Log
324 | *.binlog
325 |
326 | # NVidia Nsight GPU debugger configuration file
327 | *.nvuser
328 |
329 | # MFractors (Xamarin productivity tool) working folder
330 | .mfractor/
331 |
--------------------------------------------------------------------------------
/.github/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contribution Guidance
2 |
3 | If you'd like to contribute to this repository, please read the following guidelines. Contributors are more than welcome to share your learnings with others from centralized location.
4 |
5 | ## Code of Conduct
6 |
7 | This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/).
8 | For more information, see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments.
9 |
10 | ## Question or Problem?
11 |
12 | Please do not open GitHub issues for general support questions as the GitHub list should be used for script requests and bug reports. This way we can more easily track actual issues or bugs from the scripts and keep the general discussion separate from the actual script samples.
13 |
14 | ## Typos, Issues, Bugs and contributions
15 |
16 | Whenever you are submitting any changes to the SharePoint repositories, please follow these recommendations.
17 |
18 | * Always fork repository to your own account for applying modifications
19 | * Do not combine multiple changes to one pull request, please submit for example any samples and documentation updates using separate PRs
20 | * If you are submitting multiple samples, please create specific PR for each of them
21 | * If you are submitting typo or documentation fix, you can combine modifications to single PR where suitable
22 |
23 | ## Sample Naming and Structure Guidelines
24 |
25 | When you are submitting a new sample, it has to follow up below guidelines
26 |
27 | * You will need to have a README file for your contribution, which is based on [provided template](../samples/README-template.md) under the scripts folder. Please copy this template and update accordingly. README has to be named as README.md with capital letters.
28 | * Please include as much as possible information on the exact use case of your script. More information will help on others to understand the value of your script. You can add links and images as needed.
29 |
30 | * README template contains specific tracking image as a final entry in the page with img tag by default to https://telemetry.sharepointpnp.com/sp-admin-scripts/scripts/readme-template. This is transparent image, which is used to track popularity of individual samples in GitHub.
31 |
32 | * Updated the image src element according with repository name and folder information. If your sample is for example in samples folder and named as known-folder-move, src element should be updated as https://telemetry.sharepointpnp.com/sp-admin-scripts/script/known-folder-move
33 |
34 | * When you are submitting a new script, please name the sample solution folder accordingly
35 | * Do not use words "sample", "script" or "SharePoint" in the folder or sample name - these are scripts for SharePoint management, so no reason to repeat that in the name
36 |
37 | * Do not use period/dot in the folder name of the provided sample
38 |
39 | ## Submitting Pull Requests
40 |
41 | Here's a high level process for submitting new samples or updates to existing ones.
42 |
43 | 1. Sign the Contributor License Agreement (see below)
44 | 1. Fork this repository [SharePoint/sp-admin-scripts](https://github.com/SharePoint/sp-admin-scripts) to your GitHub account
45 | 1. Create a new branch off the `master` branch for your fork for the contribution
46 | 1. Include your changes to your branch
47 | 1. Commit your changes using descriptive commit message * These are used to track changes on the repositories for monthly communications
48 | 1. Create a pull request in your own fork and target `master` branch
49 | 1. Fill up the provided PR template with the requested details
50 |
51 | Before you submit your pull request consider the following guidelines:
52 |
53 | * Make sure you have a link in your local cloned fork to the [SharePoint/sp-admin-scripts](https://github.com/SharePoint/sp-admin-scripts):
54 |
55 | ```shell
56 | # check if you have a remote pointing to the Microsoft repo:
57 | git remote -v
58 |
59 | # if you see a pair of remotes (fetch & pull) that point to https://github.com/SharePoint/sp-admin-scripts, you're ok... otherwise you need to add one
60 |
61 | # add a new remote named "upstream" and point to the Microsoft repo
62 | git remote add upstream https://github.com/SharePoint/sp-admin-scripts.git
63 | ```
64 |
65 | * Make your changes in a new git branch:
66 |
67 | ```shell
68 | git checkout -b my-awesome-script-name master
69 | ```
70 |
71 | * Ensure your fork is updated and not behind the upstream **sp-admin-scripts** repo. Refer to these resources for more information on syncing your repo:
72 | * [GitHub Help: Syncing a Fork](https://help.github.com/articles/syncing-a-fork/)
73 | * [Keep Your Forked Git Repo Updated with Changes from the Original Upstream Repo](http://www.andrewconnell.com/blog/keep-your-forked-git-repo-updated-with-changes-from-the-original-upstream-repo)
74 | * For a quick cheat sheet:
75 |
76 | ```shell
77 | # assuming you are in the folder of your locally cloned fork....
78 | git checkout master
79 |
80 | # assuming you have a remote named `upstream` pointing official **sp-admin-scripts** repo
81 | git fetch upstream
82 |
83 | # update your local master to be a mirror of what's in the main repo
84 | git pull --rebase upstream master
85 |
86 | # switch to your branch where you are working, say "my-awesome-script-name"
87 | git checkout my-awesome-script-name
88 |
89 | # update your branch to update it's fork point to the current tip of master & put your changes on top of it
90 | git rebase master
91 | ```
92 |
93 | * Push your branch to GitHub:
94 |
95 | ```shell
96 | git push origin my-awesome-script-name
97 | ```
98 |
99 | ## Merging your Existing Github Projects with this Repository
100 |
101 | If the sample you wish to contribute is stored in your own Github repository, you can use the following steps to merge it with the this repository:
102 |
103 | * Fork the `sp-admin-scripts` repository from GitHub
104 | * Create a local git repository
105 |
106 | ```shell
107 | md sp-admin-scripts
108 | cd sp-admin-scripts
109 | git init
110 | ```
111 |
112 | * Pull your forked copy of sp-admin-scripts into your local repository
113 |
114 | ```shell
115 | git remote add origin https://github.com/yourgitaccount/sp-admin-scripts.git
116 | git pull origin dev
117 | ```
118 |
119 | * Pull your other project from github into the scripts folder of your local copy of sp-admin-scripts
120 |
121 | ```shell
122 | git subtree add --prefix=scripts/projectname https://github.com/yourgitaccount/projectname.git master
123 | ```
124 |
125 | * Push the changes up to your forked repository
126 |
127 | ```shell
128 | git push origin master
129 | ```
130 |
131 | ## Signing the CLA
132 |
133 | Before we can accept your pull requests you will be asked to sign electronically Contributor License Agreement (CLA), which is prerequisite for any contributions to PnP repository. This will be one time process, so for any future contributions you will not be asked to re-sign anything. After the CLA has been signed, our PnP core team members will have a look on your submission for final verification of the submission. Please do not delete your development branch until the submission has been closed.
134 |
135 | You can find Microsoft CLA from the following address - https://cla.microsoft.com.
136 |
137 | Thank you for your contribution.
138 |
139 | > Sharing is caring.
--------------------------------------------------------------------------------
/Scripts/SharePoint.LowTrustACS.Configuration/Connect-SPFarmToAAD.psm1:
--------------------------------------------------------------------------------
1 | function Connect-SPFarmToAAD
2 | {
3 | param(
4 | [Parameter(Mandatory)][String] $AADDomain,
5 | [Parameter(Mandatory)][String] $SharePointOnlineUrl,
6 | #Specify this parameter if you don't want to use the default SPWeb returned
7 | [Parameter()][String] $SharePointWeb,
8 | [Parameter()][System.Management.Automation.PSCredential] $O365Credentials,
9 | #Use these switches if you're replacing an existing connection to AAD.
10 | [Parameter()][Switch] $RemoveExistingACS,
11 | [Parameter()][Switch] $RemoveExistingSTS,
12 | [Parameter()][Switch] $RemoveExistingSPOProxy,
13 | #Use this switch if you're replacing the Office 365 SharePoint site.
14 | [Parameter()][Switch] $RemoveExistingAADCredentials,
15 | #Use this switch if you don't want to use SSL when you launch your app.
16 | [Parameter()][Switch] $AllowOverHttp
17 | )
18 | #Prompt for credentials right away.
19 | if (-not $O365Credentials)
20 | {
21 | $O365Credentials = Get-Credential -Message "Admin credentials for $AADDomain"
22 | }
23 |
24 | Add-PSSnapin Microsoft.SharePoint.PowerShell
25 | #Import the Microsoft Online Services Sign-In Assistant.
26 | Import-Module -Name MSOnline
27 | #Import the Microsoft Online Services Module for Windows Powershell.
28 | Import-Module MSOnlineExtended �force -verbose
29 | #Set values for Constants.
30 | New-Variable -Option Constant -Name SP_APPPRINCIPALID -Value '00000003-0000-0ff1-ce00-000000000000' | Out-Null
31 | New-Variable -Option Constant -Name ACS_APPPRINCIPALID -Value '00000001-0000-0000-c000-000000000000' | Out-Null
32 | New-Variable -Option Constant -Name ACS_APPPROXY_NAME -Value ACS
33 | New-Variable -Option Constant -Name SPO_MANAGEMENT_APPPROXY_NAME -Value 'SPO Add-in Management Proxy'
34 | New-Variable -Option Constant -Name ACS_STS_NAME -Value ACS-STS
35 |
36 | # Use following values for AAD_METADATAEP_FSTRING depending on the environment where your Office 365 tenant is hosted
37 | # Default: https://accounts.accesscontrol.windows.net/{0}/metadata/json/1
38 | # Germany: https://login.microsoftonline.de/{0}/metadata/json/1
39 | # China: https://accounts.accesscontrol.chinacloudapi.cn/{0}/metadata/json/1
40 |
41 | New-Variable -Option Constant -Name AAD_METADATAEP_FSTRING -Value 'https://accounts.accesscontrol.windows.net/{0}/metadata/json/1'
42 | New-Variable -Option Constant -Name SP_METADATAEP_FSTRING -Value '{0}/_layouts/15/metadata/json/1'
43 | #Get the default SPWeb from the on-premises farm if no $SharePointWeb parameter is specified.
44 | if ([String]::IsNullOrEmpty($SharePointWeb))
45 | {
46 | $SharePointWeb = Get-SPSite | Select-Object -First 1 | Get-SPWeb | Select-Object -First 1 | % Url
47 | }
48 |
49 | #Configure the realm ID for local farm so that it matches the AAD realm.
50 | $ACSMetadataEndpoint = $AAD_METADATAEP_FSTRING -f $AADDomain
51 | $ACSMetadata = Invoke-RestMethod -Uri $ACSMetadataEndpoint
52 | $AADRealmId = $ACSMetadata.realm
53 |
54 | Set-SPAuthenticationRealm -ServiceContext $SharePointWeb -Realm $AADRealmId
55 |
56 | $LocalSTS = Get-SPSecurityTokenServiceConfig
57 | $LocalSTS.NameIdentifier = '{0}@{1}' -f $SP_APPPRINCIPALID,$AADRealmId
58 | $LocalSTS.Update()
59 |
60 | #Allow connections over HTTP if the switch is specified.
61 | if ($AllowOverHttp.IsPresent -and $AllowOverHttp -eq $True)
62 | {
63 | $serviceConfig = Get-SPSecurityTokenServiceConfig
64 | $serviceConfig.AllowOAuthOverHttp = $true
65 | $serviceConfig.AllowMetadataOverHttp = $true
66 | $serviceConfig.Update()
67 | }
68 |
69 | #Step 1: Set up the ACS proxy in the on-premises SharePoint farm. Remove the existing ACS proxy
70 | #if the switch is specified.
71 | if ($RemoveExistingACS.IsPresent -and $RemoveExistingACS -eq $True)
72 | {
73 | Get-SPServiceApplicationProxy | ? DisplayName -EQ $ACS_APPPROXY_NAME | Remove-SPServiceApplicationProxy -RemoveData -Confirm:$false
74 | }
75 | if (-not (Get-SPServiceApplicationProxy | ? DisplayName -EQ $ACS_APPPROXY_NAME))
76 | {
77 | $AzureACSProxy = New-SPAzureAccessControlServiceApplicationProxy -Name $ACS_APPPROXY_NAME -MetadataServiceEndpointUri $ACSMetadataEndpoint -DefaultProxyGroup
78 | }
79 |
80 | #Remove the existing security token service if the switch is specified.
81 | if ($RemoveExistingSTS.IsPresent)
82 | {
83 | Get-SPTrustedSecurityTokenIssuer | ? Name -EQ $ACS_STS_NAME | Remove-SPTrustedSecurityTokenIssuer -Confirm:$false
84 | }
85 | if (-not (Get-SPTrustedSecurityTokenIssuer | ? DisplayName -EQ $ACS_STS_NAME))
86 | {
87 | $AzureACSSTS = New-SPTrustedSecurityTokenIssuer -Name $ACS_STS_NAME -IsTrustBroker -MetadataEndPoint $ACSMetadataEndpoint
88 | }
89 |
90 | #Update the ACS Proxy for OAuth authentication.
91 | $ACSProxy = Get-SPServiceApplicationProxy | ? Name -EQ $ACS_APPPROXY_NAME
92 | $ACSProxy.DiscoveryConfiguration.SecurityTokenServiceName = $ACS_APPPRINCIPALID
93 | $ACSProxy.Update()
94 |
95 | #Retrieve the local STS signing key from JSON metadata.
96 | $SPMetadata = Invoke-RestMethod -Uri ($SP_METADATAEP_FSTRING -f $SharePointWeb)
97 | $SPSigningKey = $SPMetadata.keys | ? usage -EQ "Signing" | % keyValue
98 | $CertValue = $SPSigningKey.value
99 |
100 | #Connect to Office 365.
101 | Connect-MsolService -Credential $O365Credentials
102 | #Remove existing connection to an Office 365 SharePoint site if the switch is specified.
103 | if ($RemoveExistingAADCredentials.IsPresent -and $RemoveExistingAADCredentials -eq $true)
104 | {
105 | $msolserviceprincipal = Get-MsolServicePrincipal -AppPrincipalId $SP_APPPRINCIPALID
106 | [Guid[]] $ExistingKeyIds = Get-MsolServicePrincipalCredential -ObjectId $msolserviceprincipal.ObjectId -ReturnKeyValues $false | % {if ($_.Type -ne "Other") {$_.KeyId}}
107 | Remove-MsolServicePrincipalCredential -AppPrincipalId $SP_APPPRINCIPALID -KeyIds $ExistingKeyIds
108 | }
109 | #Step 2: Upload the local STS signing certificate
110 | New-MsolServicePrincipalCredential -AppPrincipalId $SP_APPPRINCIPALID -Type Asymmetric -Value $CertValue -Usage Verify
111 |
112 | #Step 3: Add the service principal name of the local web application, if necessary.
113 | $indexHostName = $SharePointWeb.IndexOf('://') + 3
114 | $HostName = $SharePointWeb.Substring($indexHostName)
115 | $NewSPN = '{0}/{1}' -f $SP_APPPRINCIPALID, $HostName
116 | $SPAppPrincipal = Get-MsolServicePrincipal -AppPrincipalId $SP_APPPRINCIPALID
117 | if ($SPAppPrincipal.ServicePrincipalNames -notcontains $NewSPN)
118 | {
119 | $SPAppPrincipal.ServicePrincipalNames.Add($NewSPN)
120 | Set-MsolServicePrincipal -AppPrincipalId $SPAppPrincipal.AppPrincipalId -ServicePrincipalNames $SPAppPrincipal.ServicePrincipalNames
121 | }
122 |
123 | #Remove the existing SharePoint Online proxy if the switch is specified.
124 | if ($RemoveExistingSPOProxy.IsPresent -and $RemoveExistingSPOProxy -eq $True)
125 | {
126 | Get-SPServiceApplicationProxy | ? DisplayName -EQ $SPO_MANAGEMENT_APPPROXY_NAME | Remove-SPServiceApplicationProxy -RemoveData -Confirm:$false
127 | }
128 | #Step 4: Add the SharePoint Online proxy
129 | if (-not (Get-SPServiceApplicationProxy | ? DisplayName -EQ $SPO_MANAGEMENT_APPPROXY_NAME))
130 | {
131 | $spoproxy = New-SPOnlineApplicationPrincipalManagementServiceApplicationProxy -Name $SPO_MANAGEMENT_APPPROXY_NAME -OnlineTenantUri $SharePointOnlineUrl -DefaultProxyGroup
132 | }
133 | }
--------------------------------------------------------------------------------
/Scripts/SharePoint.Hybrid.CloudSSA.Configuration/SPHybridValidation.ps1:
--------------------------------------------------------------------------------
1 | <#
2 | .synopsis
3 | Script does several checks on the farm and Office 365 if a hybrid connection can be setup
4 | .description
5 | This script needs to be ran on a SharePoint server that has access to internet
6 | .example
7 | .\SPHybridValidation.ps1
8 | #>
9 |
10 | if ((Get-PSSnapin -Name "Microsoft.SharePoint.PowerShell" -ErrorAction SilentlyContinue) -eq $null)
11 | {
12 | Add-PSSnapin -Name "Microsoft.SharePoint.PowerShell"
13 | }
14 | cls
15 |
16 | #Connect to the O365 Tenant
17 | Write-Host "Please Conenct to the Microsoft Online tenant you wish to validate this on premises farm with" -ForegroundColor Yellow
18 | Connect-MsolService
19 |
20 | #Validate Certificate is not expired - checks all Msol Principals not just current farm
21 | Write-Host "Validating MSOL Principals still within valid date range" -ForegroundColor Yellow
22 | Write-Host
23 | Write-Host "Collecting All MSOL Principals" -ForegroundColor Yellow
24 | $MsolSPC = Get-MsolServicePrincipalCredential -AppPrincipalId "00000003-0000-0ff1-ce00-000000000000" -ReturnKeyValues:$false|ft startdate,enddate ,keyid -autosize
25 | Write-Host
26 | # Validate that the local STS Signing Certificate matches a valid Microsoft Online Service Principal
27 | Write-Host "Validating that the local STS Signing Certificate matches a valid Microsoft Online Service Principal" -ForegroundColor Yellow
28 |
29 | $StsThumbprint = (Get-SPSecurityTokenServiceConfig).LocalLoginProvider.SigningCertificate.thumbprint
30 | #Changed to /sharepoint
31 | $StsCertificate = get-item -Path CERT:\localmachine\SharePoint\$StsThumbprint
32 | $StsCertificateBin = $StsCertificate.GetRawCertData()
33 | $StsCredentialValue = [System.Convert]::ToBase64String($StsCertificateBin)
34 | $MsolServicePrincipalCredential = Get-MsolServicePrincipalCredential -AppPrincipalId "00000003-0000-0ff1-ce00-000000000000" -ReturnKeyValues $true | Where-Object {$_.Value -eq $StsCredentialValue}
35 |
36 | if($MsolServicePrincipalCredential)
37 | {
38 | # Check for valid date
39 | if($MsolServicePrincipalCredential.EndDate -gt (get-date) -and $MsolServicePrincipalCredential.StartDate -lt (get-date))
40 | {
41 | Write-Host
42 | write-host "Msol Service Principal is found and is Valid until :"$MsolServicePrincipalCredential.EndDate -ForegroundColor Green
43 | }
44 | Else
45 | {
46 | Write-Host
47 | write-host "Msol Service Principal is found but expired on " + $MsolServicePrincipalCredential.EndDate + " You should update the ACS trust certificates for hybrid workloads to function" -ForegroundColor Yellow
48 | }
49 | }
50 | else
51 | {
52 | Write-Host
53 | Write-host "No matching Msol Service Principal found for the local farm. Hybrid workloads will not function correctly on this farm" -foregroundcolor Red
54 | }
55 |
56 | #Validate SPNs setup properly in WAAD
57 | Write-Host
58 | Write-Host "Validating that the Microsoft online Service Principal Names are correct" -ForegroundColor Yellow
59 |
60 | $apps = (Get-MsolServicePrincipal -AppPrincipalId "00000003-0000-0ff1-ce00-000000000000").serviceprincipalnames
61 |
62 | $webapps = Get-SPWebApplication
63 | $foundmatch = $false
64 | Foreach($WebApp in $WebApps)
65 | {
66 | $webappurl = (($WebApp.url).split(":")).split("//")
67 |
68 | Foreach($app in $apps)
69 | {
70 | $spn = ((($app).split("/")) -replace "\*.", "")
71 |
72 | if(($webappurl[3] -match $spn[1]) -and ($spn[1] -ne $null ))
73 | {
74 | Write-Host
75 | write-host "It seems the local farm has a matching SPN and URL combination " $webappurl[3] " matched with " $spn[1] " on this farm" -ForegroundColor Green
76 | write-host "This is required for hybrid scenarios requiring outbound OAuthN" -ForegroundColor Green
77 | $foundmatch=$true
78 | }
79 | }
80 | }
81 | if($foundmatch = $false)
82 | {
83 | Write-Host
84 | write-host "No matching SPN and URL combinations found on this farm" -ForegroundColor Red
85 | }
86 |
87 | # Validate Directory Synchronization
88 | Write-Host "Checking Directory Synchronization is Operational" -ForegroundColor Yellow
89 | $msolcompany = Get-MsolCompanyInformation
90 | $IsDirSyncEnabled = $msolcompany.DirectorySynchronizationEnabled
91 |
92 | Write-Host "Directory Sync Enabled Status" $IsDirSyncEnabled -ForegroundColor Green
93 | Write-Host
94 |
95 | $LastDirsynctime = $msolcompany.LastDirSyncTime
96 | Write-Host "Last Directory Sync Time" $LastDirsynctime -ForegroundColor Green
97 | Write-Host
98 |
99 | Write-Host "Checking license state of users" -ForegroundColor Yellow
100 | $licensed = Get-MsolUser | where-object {$_.IsLicensed -eq $true}
101 | $unlicensed = get-msoluser -UnlicensedUsersOnly
102 | $licenses = (MSOnline\Get-MsolSubscription).TotalLicenses
103 |
104 | Write-Host "Total number of licensed users is " $licensed.count -ForegroundColor Green
105 | Write-Host "Total number of unlicensed users is " $unlicensed.count -ForegroundColor Green
106 | Write-Host "Total number of purchased licenses is " $licenses -ForegroundColor Green
107 | Write-Host
108 |
109 | #Validate Service Applications
110 | Write-Host "Checking On Premises Services" -ForegroundColor Yellow
111 | $upa=Get-SPServiceApplication | where-object {$_.TypeName -match "User profile Service Application"}
112 | if ($upa -ne $null -and $upa.Status -eq "online")
113 | {
114 | Write-Host ("User Profile Service Application is available with status ") $upa.status -ForegroundColor Green
115 | }
116 | elseif ($upa -ne $null -and $upa.Status -ne "online")
117 | {
118 | Write-Host ("User Profile Service Application is availble but status is ") $upa.status -ForegroundColor Red
119 | }
120 | else
121 | {
122 | Write-Host ("User Profile Service Application is not available. ") $upa.status -ForegroundColor Red
123 | }
124 | Write-Host
125 | $app=Get-SPServiceApplication | where-object {$_.TypeName -match "App Management Service Application"}
126 |
127 | if ($app -ne $null -and $app.Status -eq "online")
128 | {
129 | Write-Host ("App Management Service Application is available with status ") $app.status -ForegroundColor Green
130 | }
131 | elseif ($app -ne $null -and $app.Status -ne "online")
132 | {
133 | Write-Host ("App Management Service Application is available but status is ") $app.status -ForegroundColor Red
134 | }
135 | else
136 | {
137 | Write-Host ("App Management Service Application is not available. ") $app.status -ForegroundColor Red
138 | }
139 | Write-Host
140 | Write-Host "Checking On Proxies" -ForegroundColor Yellow
141 |
142 | #Validate ACS Proxy
143 |
144 | $proxy =Get-SPServiceApplicationProxy | ? {$_.TypeName -eq "Azure Access Control Service Application Proxy"}
145 | if ($proxy -ne $null -and $proxy.Status -eq "online")
146 | {
147 | Write-Host ("ACS proxy is available with status ") $proxy.status -ForegroundColor Green
148 | }
149 | elseif ($proxy -ne $null -and $proxy.Status -ne "online")
150 | {
151 | Write-Host ("ACS proxy is available but status is ") $proxy.status -ForegroundColor Red
152 | }
153 | else
154 | {
155 | Write-Host ("ACS proxy is not available. ") -ForegroundColor Red
156 | }
157 |
158 | Write-Host
159 | # Validate SPO proxy
160 | $spoProxy = Get-SPServiceApplicationProxy | ? {$_.TypeName -eq "SharePoint Online Application Principal Management Service Application Proxy"}
161 | if ($spoproxy -ne $null -and $spoproxy.Status -eq "online")
162 | {
163 | Write-Host ("SPO proxy is available with status ") $spoProxy.status -ForegroundColor Green
164 | }
165 | elseif ($spoproxy -ne $null -and $spoproxy.Status -ne "online")
166 | {
167 | Write-Host ("SPO proxy is available but status is ") $spoProxy.status -ForegroundColor Red
168 | }
169 | else
170 | {
171 | Write-Host ("SPO proxy is not available. ") -ForegroundColor Red
172 | }
--------------------------------------------------------------------------------
/Scripts/SharePoint.Sandbox.ListSolutionsFromTenant/README.MD:
--------------------------------------------------------------------------------
1 | # Sandbox solutions inventory script for SharePoint Online #
2 | This script can be used to analyze what kind of sandbox solutions exists in specific SharePoint Online tenant. You will need to use tenant administrator account to connect to SharePoint Online and script will generate a list of sandbox solutions to separate txt file, which can be imported to Excel for further analyses.
3 |
4 | >**Note**: This script is relatively simple and does not use multi-threading, so execution in larger tenants might take a while. We are looking for further enhancing the script with multi-threading support, if there's demand for this. Also community contributions on this side are more than welcome.
5 |
6 | Output file has following columns
7 | * URL of the site collection
8 | * Name of the sandbox solution
9 | * Author field from the sandbox solution - who uploaded the file. If value contains a comma, it will be removed in output
10 | * Created field from the sandbox solution - when solution was uploaded
11 | * Status field - 1=Activated, 0=Not activated
12 | * HasAssemblies field - 1=solution has assemblies , 0=solution does not have assemblies
13 | * SolutionHash field - hash of the solution. If solution is exactly the same cross site collections, has is the same. If solution has small adjustments or it's different version regardless of the wsp name matching, it's a different solution
14 |
15 | Example output file, which can be easily imported to Excel for further analyses
16 | ```PowerShell
17 | SiteURL,WSPName,Author,CreatedDate,Activated,HasAssemblies,SolutionHash
18 | https://contoso.sharepoint.com/sites/635993483643159661,MyCoolWebPart.wsp,Vesa Juvonen,07/27/2016 00:55:22,0,1,IEYyOmzpYRAWRTLIuh0VbtUQFNJEsNxP6vVbECvVIY0=
19 | https://contoso.sharepoint.com/sites/devpub,PnPRocks.wsp,System Account,07/27/2016 01:03:36,0,1,4KmaeOO1r7vw8/MDBuEmBzKMUtXxYhvc42vv/mw+Nnw=
20 | https://contoso.sharepoint.com/sites/team,WhosReadingThese.wsp,Vesa Juvonen,06/07/2016 12:58:05,1,0,l8oO15G6LKX61wbTHZCCGyzNxZhYC3bbz5F+KsMbWYU=
21 | https://contoso.sharepoint.com/sites/team,HiMom.wsp,Vesa Juvonen,06/22/2016 12:41:04,1,1,cdLgVhgD3uZCuoSl0VF/wBBF903ldJQJAG7sZWcAojw=
22 | https://contoso.sharepoint.com/sites/team,WhatsUp.wsp,Vesa Juvonen,07/27/2016 00:47:54,0,0,tRB8KTZc6VTzJ6rGqtYCeFMozMroeIksQO2Bg0RJzcw=
23 | https://contoso.sharepoint.com/sites/team,MrVanRules.wsp,Vesa Juvonen,07/29/2016 22:26:43,1,1,a48UeIRwd8HTReQ+UNnvH9w3NIKu2u4hYXK412riFgg=
24 | https://contoso.sharepoint.com/sites/templatesite,RememberIgniteOnSeptember.wsp,Vesa Juvonen,07/27/2016 00:50:50,0,1,DsZBtAYAHjfNtHL8qytqI3//VwzSL3kR7rgkOG03Hl0=
25 | https://contoso.sharepoint.com/sites/templatesite,WhatsUp.wsp,Vesa Juvonen,07/27/2016 00:56:32,1,0,MZ8BAIfCKdDhUx2rzQi9TlhVZ1lBn6f1F4/7+q0WekE=
26 | https://contoso.sharepoint.com/sites/visiodemos,UsefullForYouGiveFeedback.wsp,Provisioning User 0,03/24/2014 21:44:25,1,0,xoCOeSDyhnYAY6nkXNpDpCL0A5TbLUTU4qX0q25ZFgE=
27 |
28 | ```
29 |
30 | **What will be reported?**
31 | Scripts reports all sandbox solution from solution gallery regardless if they contain code behind or regardless how they were created. Here's different kind of sandbox solutions, which you can have in the report.
32 | * Site templates
33 | * Design Manager Packages
34 | * InfoPath Forms with code behind
35 | * Custom solutions created with Visual Studio (web parts, web templates, event receivers)
36 |
37 |
38 | >**Note**: This is an **Open Source** project, and any contribution from the community
39 | is more than welcome. Feel free to review the code and submit any [Issues](https://github.com/OfficeDev/PnP-Tools/issues) or [Pull Requests](https://github.com/OfficeDev/PnP-Tools/pulls), using GitHub. If you want to assist the community on this journey around sandbox solutions, we are looking for example improvements on identifying sandbox solution type, code behind existence or to add multi-threading support.
40 |
41 | # Setup Instructions #
42 | In order to get list of sandbox solutions using this script, you'll need to:
43 | * [Download the files included in this solution](#download)
44 | * [Setup software requirements](#requirements)
45 | * [Execute the *Get-SPOnlineSandboxSolutionList* cmdlet](#execute)
46 |
47 |
48 | ## Download the files
49 | You can download the script file manually or you can download
50 | a ZIP file with all the content from PnP-Tools repository, simply following
51 | this link.
52 | Within the ZIP file, under the /Scripts/SharePoint.Sandbox.ListSolutionsFromTenant folder, you will
53 | find all the required files.
54 |
55 |
56 | ## Setup software requirements
57 | This scripts requires SharePoint Online PowerShell commands, which you can install
58 | from the following link:
59 |
60 | * [SharePoint PowerShell commands](https://www.microsoft.com/en-us/download/details.aspx?id=35588)
61 |
62 |
63 | ## Execute the *Get-SPOnlineSandboxSolutionList* cmdlet
64 | Once you have installed the SharePoint PowerShell commands, you can simply open a
65 | PowerShell console, go to the path where you stored the files and execute the *Get-SPOnlineSandboxSolutionList*
66 | cmdlet, which is included in the
67 | Get-SPOnlineSandboxSolutionList.ps1 script file of this solution.
68 |
69 | The *Get-SPOnlineSandboxSolutionList* cmdlet accepts the following three parameters:
70 | * **AdminUrl**: it is a mandatory parameter, which declares the URL of the admin site for the tenant where the sandbox solution scan will be performed. It has to be provided as a full URL, like for example: https://contoso-admin.sharepoint.com
71 | * **Credentials**: it is an optional parameter, which defines the user credentials that will be used to authenticate against both the target Site Collection and the infrastructure Site Collection, if any. Should be the credentials of a user, who is Site Collection Administrator for the target Site Collections. If you don't provide this parameter, the script will directly prompt you for credentials.
72 | * **Delimiter**: it is an optional parameter, by default is ',' and can be used to specify a different separation character for CSV output.
73 |
74 | Here you can see a couple of examples about how to invoke the *Get-SPOnlineSandboxSolutionList.ps1* script:
75 |
76 | ###EXAMPLE 1
77 | ```PowerShell
78 | PS C:\> .\Get-SPOnlineSandboxSolutionList.ps1 -AdminUrl "https://contoso-admin.sharepoint.com"
79 | ```
80 |
81 | The example above performs as sandbox solution scan in contoso tenant with admin URL https://contoso-admin.sharepoint.com. The user's credentials are not provided, so the cmdlet will directly prompt the user.
82 |
83 | ###EXAMPLE 2
84 | ```PowerShell
85 | PS C:\> .\Get-SPOnlineSandboxSolutionList.ps1 -AdminUrl "https://contoso-admin.sharepoint.com" -Delimiter ';'
86 | ```
87 |
88 | This example above shows how to specify a custom character as delimiter for CSV output
89 |
90 |
91 | ###EXAMPLE 3
92 | ```PowerShell
93 | PS C:\> $creds = Get-Credential
94 | PS C:\> .\Get-SPOnlineSandboxSolutionList.ps1 -AdminUrl "https://contoso-admin.sharepoint.com" -Credentials $creds
95 | ```
96 |
97 | The example above performs as sandbox solution scan in contoso tenant with admin URL https://contoso-admin.sharepoint.com. The user's credentials are provided through the *$creds* variable.
98 |
99 |
100 | --
101 |
102 | ### Applies to ###
103 | - Office 365 Multi Tenant (MT)
104 |
105 | ### Prerequisites ###
106 | Following software installation packages have to be downloaded and installed on the machine where script will execute
107 | - [SharePoint Online Client Components SDK](https://www.microsoft.com/en-us/download/details.aspx?id=42038)
108 | - [SharePoint Online Management Shell](https://www.microsoft.com/en-us/download/details.aspx?id=35588)
109 | - [SharePoint PowerShell CmdLets](https://www.microsoft.com/en-us/download/details.aspx?id=35588)
110 |
111 | ### **Note** ###
112 | `You will need to use tenant administrator credentials to be able to list site collections from target tenant.
113 | This account must have as well access to all site collections, in order to be able to access their solutions gallery.`
114 |
115 | ### Script ###
116 | Script | Author(s)
117 | ---------|----------
118 | SharePoint.Sandbox.ListSolutionsFromTenant | Karine Bosch (Microsoft), Vesa Juvonen (Microsoft), Daniel Budimir (Microsoft), Massimo Prota (Rapid Circle)
119 |
120 | ### Version history ###
121 | Version | Date | Comments
122 | ---------| -----| --------
123 | 1.3 | August 9th 2016 | Added hash of the solution as output
124 | 1.2 | August 4th 2016 | Added possibility to specify CSV delimiter, headers to output, better ClientContext handling
125 | 1.1 | August 3rd 2016 | Added HasAssemblies to output
126 | 1.0 | August 3rd 2016 | Initial release
127 |
128 | ### Disclaimer ###
129 | **THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.**
130 |
131 |
132 |
133 |
134 |
--------------------------------------------------------------------------------
/Scripts/SharePoint.LowTrustACS.Configuration/readme.md:
--------------------------------------------------------------------------------
1 | # PowerShell to enable low trust authentication model at on-premises #
2 |
3 | ### Summary ###
4 |
5 | This document and scripts explain how to setup low trust authentication between your SharePoint 2013/2016 on-premises farm and an Office 365 tenant.
6 |
7 | ### Applies to ###
8 |
9 | - SharePoint 2013 on-premises
10 | - SharePoint 2016 on-premises
11 |
12 | ### Prerequisites ###
13 | - [An Office 365 tenant which you'll use for the low trust association](https://msdn.microsoft.com/en-us/library/office/fp179924.aspx)
14 | - [Setup app management in your on-premises farm](https://msdn.microsoft.com/en-us/library/office/fp179923.aspx)
15 |
16 | ### Solution ###
17 | Solution | Author(s)
18 | ---------|----------
19 | Enable low trust in on-premises | Vesa Juvonen, Bert Jansen (**Microsoft**)
20 |
21 | ### Version history ###
22 | Version | Date | Comments
23 | ---------| -----| --------
24 | 1.0 | February 8th 2016 | Initial release
25 |
26 | ### Disclaimer ###
27 | **THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.**
28 |
29 |
30 | ----------
31 |
32 | # Introduction
33 | This document and scripts explain how to setup low trust authentication between your SharePoint 2013/2016 on-premises farm and an Office 365 tenant. Setting up low trust for your on-premises farms will allow you to use Azure ACS as OAuth broker for your on-premises environment and as such run your apps and client side applications in the same manner as you would do for SharePoint Online.
34 |
35 | The [detailed steps for this task are documented in MSDN](https://msdn.microsoft.com/en-us/library/office/dn155905.aspx), you can consider this document as a shortened and easier set of instructions.
36 |
37 | Below chapters describe the individual steps needed to make this happen
38 |
39 | ## Step 1: Obtain a new signing certificate for the on-premises SharePoint Token Service (STS)
40 | You’ll need to replace the default security token service (STS) certificate of your on-premises installation of SharePoint 2013/2016 with your own certificate. This section describes how to obtain this certificate by making use of [makecert.exe which is available as part of the Windows SDK](https://msdn.microsoft.com/library/windows/desktop/aa386968.aspx). If you do not want to use makecert.exe you can also use IIS Manager to create a certificate as described [here](https://msdn.microsoft.com/en-us/library/office/dn155905.aspx).
41 |
42 | Using `makecert.exe` allows you to choose a certificate with a longer lifetime which means less maintenance on your low trust setup. In below sample we create our own trusted root authority and then individual certs that have our trusted root authority as issuer. See [Mike O'Brien's blog](http://www.mikeobrien.net/blog/creating-self-signed-wildcard/) for more details.
43 |
44 | Import detail for the token signing certificate is that it **requires a key length of at least 2048** which is in below command provided via the **len** parameter.
45 |
46 | Navigate to folder **C:\Program Files (x86)\Microsoft SDKs\Windows\v7.1A\Bin** and execute the following commands:
47 |
48 | ```Cmd
49 | #creates the trusted root authority
50 | ./makecert.exe -n "CN=PnP Development Root CA,O=PnP,OU=Development,L=Bree,S=Limburg,C=Belgium" -pe -ss Root -sr LocalMachine -sky exchange -m 120 -a sha256 -len 2048 -r
51 |
52 | #creates the token signing cert
53 | ./makecert.exe -n "CN=STSTokenSigning" -pe -ss My -sr LocalMachine -sky exchange -m 120 -in "PnP Development Root CA" -is Root -ir LocalMachine -len 2048 -a sha256 -eku 1.3.6.1.5.5.7.3.1
54 | ```
55 |
56 | **Note:**
57 | You can create these certificates an any machine that has `makecert.exe` available, no need to deploy the SDK to your SharePoint servers.
58 |
59 | Once you've created the token signing certificate you'll need to export it to a PFX file via the following steps:
60 | - Start `mmc.exe`
61 | - Load the **Certificates** snap-in for the **Computer Account**
62 | - Locate the created token signing certificate in the **Personal --> Certificates** node, right-click and choose the **Export** task
63 | - Choose to export the **private key**
64 | - The PFX option will be pre-selected, chech the "Include all certificates in the certification path if possible" and deselect the other options
65 | - Select the **Password** check box and provide a password
66 | - Provide a name and path for the PFX file (use .pfx extension)
67 | - Press **Finish**
68 | - Copy the created pfx file to your SharePoint 2013/2016 server or a share that you can reach from that server
69 |
70 |
71 | ## Step 2: Install the binary dependencies and download the custom PowerShell module
72 | Before you can load and execute the needed module in step 3 you'll need to first install the following two dependencies on the SharePoint 2013/2016 server you're executing these steps on:
73 | - [The 64-bit edition of Microsoft Online Services Sign-In Assistant](https://www.microsoft.com/en-us/download/details.aspx?id=41950)
74 | - [Microsoft Online Services Module for Windows Powershell (64-bit)](http://go.microsoft.com/fwlink/p/?linkid=236297)
75 |
76 | Once that's done you'll need to copy the `Connect-SPFarmToAAD.psm1` PowerShell module from the scripts folder to a folder or file share on the file system.
77 |
78 | ## Step 3: Apply the new signing certificate and setup the low trust association
79 |
80 | ### What if you're connecting to an Office 365 tenant which lives in the Germany or China environment?
81 | If your Office 365 tenant is hosted in either the Germany or China Office 365 environment then you'll need to adjust the `Connect-SPFarmToAAD.psm1` script as outlined below:
82 |
83 | ```PowerShell
84 | ...
85 |
86 | # Use following values for AAD_METADATAEP_FSTRING depending on the environment where your Office 365 tenant is hosted
87 | # Default: https://accounts.accesscontrol.windows.net/{0}/metadata/json/1
88 | # Germany: https://login.microsoftonline.de/{0}/metadata/json/1
89 | # China: https://accounts.accesscontrol.chinacloudapi.cn/{0}/metadata/json/1
90 |
91 | New-Variable -Option Constant -Name AAD_METADATAEP_FSTRING -Value 'https://accounts.accesscontrol.windows.net/{0}/metadata/json/1'
92 | ...
93 | ```
94 |
95 |
96 | ### Setup the low trust association
97 | Start this step by running the `LowTrustConfigurationSession.ps1` script and provide as input:
98 | - **PFXFile**: the location to the PFX file created in step 1
99 | - **PFXPassword**: the password of the PFX file created in step 1
100 | - **ConnectSPFarmToAADModulePath**: the path to the module named `Connect-SPFarmToAAD.psm1` downloaded in step 2
101 |
102 | This script will perform the following tasks:
103 | - Set the new STS signing certificate
104 | - Reset the SharePoint Timer service
105 | - Import the `Connect-SPFarmToAAD.psm1` module
106 |
107 | ```PowerShell
108 | .\LowTrustConfigurationSession.ps1 -PFXFile "\\dc1\admin\certificates\STSTokenSigning.pfx" -PFXPassword "****" -ConnectSPFarmToAADModulePath "\\dc1\admin\lowtrust"
109 | ```
110 |
111 | Once the above is done you've setup a session that's ready for the final step, performing the actual low trust configuration. You can do this by issuing the `Connect-SPFarmToAAD` cmdlet like shown in below samples:
112 |
113 | ```PowerShell
114 | Connect-SPFarmToAAD –AADDomain 'MyO365Domain.onmicrosoft.com' –SharePointOnlineUrl https://MyO365Domain.sharepoint.com –SharePointWeb https://fabrikam.com
115 |
116 | Connect-SPFarmToAAD –AADDomain 'MyO365Domain.onmicrosoft.com' –SharePointOnlineUrl https://MyO365Domain.sharepoint.com –SharePointWeb http://northwind.com -AllowOverHttp
117 |
118 | Connect-SPFarmToAAD –AADDomain 'MyO365Domain.onmicrosoft.com' –SharePointOnlineUrl https://MyO365Domain.sharepoint.com –SharePointWeb http://northwind.com –AllowOverHttp –RemoveExistingACS –RemoveExistingSTS –RemoveExistingSPOProxy –RemoveExistingAADCredentials
119 | ```
120 |
121 | The final steps are the doing an IISReset all the farm servers + perform a SharePoint Timer Server restart on all the servers of the farm except the one where you did run the `Connect-SPFarmToAAD` cmdlet as that was already done.
122 |
123 | If you want to also enable low trust on other web applications you do not need to repeat the above procedure but rather use below PowerShell script:
124 |
125 | ```PowerShell
126 | $SPAppPrincipal = Get-MsolServicePrincipal -AppPrincipalId 00000003-0000-0ff1-ce00-000000000000
127 | $id = "00000003-0000-0ff1-ce00-000000000000/"
128 |
129 | Get-SPWebApplication | ForEach-Object {
130 | $hostName = $_.Url.substring($_.Url.indexof("//") + 2)
131 | $hostName = $hostName.Remove($hostName.Length - 1, 1)
132 |
133 | $NewSPN = $id + $hostName
134 |
135 | Write-Host "Adding SPN for" $NewSPN
136 |
137 | if ($SPAppPrincipal.ServicePrincipalNames -notcontains $NewSPN) {
138 | $SPAppPrincipal.ServicePrincipalNames.Add($NewSPN)
139 | Set-MsolServicePrincipal -AppPrincipalId $SPAppPrincipal.AppPrincipalId -ServicePrincipalNames $SPAppPrincipal.ServicePrincipalNames
140 | }
141 | }
142 | ```
143 |
144 |
--------------------------------------------------------------------------------
/Scripts/SharePoint.Hybrid.CloudSSA.Configuration/CreateHybridCloudSSA.ps1:
--------------------------------------------------------------------------------
1 | <#
2 | .Synopsis
3 | This script is designed specifically to deploy a hybrid cloud Search Service Application to a SharePoint Server farm
4 |
5 | .description
6 | This script is designed specifically to deploy a hybrid cloud Search Service Application to a SharePoint Server farm
7 | All components are configured on the services selected
8 | Change the script if you have more services or want certain components on certain servers
9 |
10 | It requires the following variables:
11 | *SearchApplicationPoolAccountName - this is the account for the search app pool. If there is an existing local SSA that same account can be reused. Note that this account must be a managed SharePoint service account
12 | *DatabaseServer - this is the name of an existing SharePoint database server
13 | *SearchServer1 - this is the name of the first new server for Hybrid Search services. This server must already be added to the farm and should not host any SharePoint roles other than what was created when the server was added
14 | *SearchServer2 - this is the name of the second new server for Hybrid Search services. The presence of this server is optional if the customer does not have a highly available SharePoint farm. This server must already be added to the farm and should not host any SharePoint roles other than what was created when the server was added
15 | The Authors recommend that two servers be used for high availability of the search service application
16 |
17 | .example
18 | .\CreateHybridCloudSSA.ps1 -SearchApplicationPoolAccountName "appoolname" -DatabaseServer "spsql" -SearchServer1 "spba01" -SearchServer2 "SPfe01"
19 | #>
20 |
21 |
22 | Param(
23 | [Parameter(Mandatory=$true)][string] $SearchApplicationPoolAccountName,
24 | [Parameter(Mandatory=$true)][string] $DatabaseServer,
25 | [Parameter(Mandatory=$true)][string] $SearchServer1,
26 | [Parameter(Mandatory=$false)][string] $SearchServer2
27 | )
28 |
29 | #==============================================================
30 | #Set name constants
31 | #==============================================================
32 | Add-PSSnapin Microsoft.SharePoint.Powershell
33 | $SearchServiceApplicationName = "HybridSearchServiceApplication"
34 | $DatabaseName = "HybridSearchServiceApplication"
35 |
36 | #==============================================================
37 | #Search Application Pool
38 | #==============================================================
39 | Write-Host -ForegroundColor DarkGray "Checking if Search Application Pool exists"
40 | $SPServiceApplicationPool = Get-SPServiceApplicationPool -Identity $SearchServiceApplicationName -ErrorAction SilentlyContinue
41 |
42 | if (!$SPServiceApplicationPool)
43 | {
44 | Write-Host -ForegroundColor Yellow "Creating Search Application Pool"
45 | $SPServiceApplicationPool = New-SPServiceApplicationPool -Name $SearchServiceApplicationName -Account $SearchApplicationPoolAccountName -Verbose
46 | }
47 |
48 | #==============================================================
49 | #Search Service Application
50 | #==============================================================
51 | Write-Host -ForegroundColor DarkGray "Checking if SSA exists"
52 | $SearchServiceApplication = Get-SPEnterpriseSearchServiceApplication -Identity $SearchServiceApplicationName -ErrorAction SilentlyContinue
53 | if (!$SearchServiceApplication)
54 | {
55 | Write-Host -ForegroundColor Yellow "Creating Search Service Application"
56 | $SearchServiceApplication = New-SPEnterpriseSearchServiceApplication -Name $SearchServiceApplicationName -ApplicationPool $SPServiceApplicationPool.Name -DatabaseServer $DatabaseServer -DatabaseName $DatabaseName -CloudIndex $true
57 | }
58 |
59 | Write-Host -ForegroundColor DarkGray "Checking if SSA Proxy exists"
60 | $SearchServiceApplicationProxy = Get-SPEnterpriseSearchServiceApplicationProxy -Identity ($SearchServiceApplicationName + "_Proxy") -ErrorAction SilentlyContinue
61 | if (!$SearchServiceApplicationProxy)
62 | {
63 | Write-Host -ForegroundColor Yellow "Creating SSA Proxy"
64 | New-SPEnterpriseSearchServiceApplicationProxy -Name ($SearchServiceApplicationName + "_Proxy") -SearchApplication $SearchServiceApplicationName
65 | }
66 |
67 | #==============================================================
68 | #Start Search Service Instance on Server1
69 | #==============================================================
70 | $SearchServiceInstanceServer1 = Get-SPEnterpriseSearchServiceInstance $SearchServer1
71 | Write-Host -ForegroundColor DarkGray "Checking if SSI is Online on SearchServer1"
72 | if($SearchServiceInstanceServer1.Status -ne 'Online')
73 | {
74 | Write-Host -ForegroundColor Yellow "Starting Search Service Instance"
75 | Start-SPEnterpriseSearchServiceInstance -Identity $SearchServiceInstanceServer1
76 | While ($SearchServiceInstanceServer1.Status -ne 'Online')
77 | {
78 | Start-Sleep -s 5
79 | Write-Host "Sleeping for 5 seconds"
80 | $SearchServiceInstanceServer1 = Get-SPEnterpriseSearchServiceInstance -Identity $SearchServer1
81 | }
82 | Write-Host -ForegroundColor Yellow "SSI on SearchServer1 is started"
83 | }
84 |
85 | #==============================================================
86 | #Start Search Service Instance on Server2 (if specified)
87 | #==============================================================
88 | If ($SearchServer2)
89 | {
90 | $SearchServiceInstanceServer2 = Get-SPEnterpriseSearchServiceInstance $SearchServer2
91 | Write-Host -ForegroundColor DarkGray "Checking if SSI is Online on SearchServer2"
92 | if($SearchServiceInstanceServer2.Status -ne 'Online')
93 | {
94 | Write-Host -ForegroundColor Yellow "Starting Search Service Instance"
95 | Start-SPEnterpriseSearchServiceInstance -Identity $SearchServiceInstanceServer2
96 | While ($SearchServiceInstanceServer2.Status -ne 'Online')
97 | {
98 | Start-Sleep -s 5
99 | Write-Host "Sleeping for 5 seconds"
100 | $SearchServiceInstanceServer2 = Get-SPEnterpriseSearchServiceInstance -Identity $SearchServer2
101 | }
102 | Write-Host -ForegroundColor Yellow "SSI on SearchServer2 is started"
103 | }
104 |
105 | }
106 | #==============================================================
107 | #Cannot make changes to topology in Active State.
108 | #Create new topology to add components
109 | #==============================================================
110 |
111 | $InitialSearchTopology = $SearchServiceApplication | Get-SPEnterpriseSearchTopology -Active
112 | $NewSearchTopology = $SearchServiceApplication | New-SPEnterpriseSearchTopology
113 |
114 | #==============================================================
115 | #Search Service Application Components on SearchServer1
116 | #Creating all components except Index (created later)
117 | #==============================================================
118 | New-SPEnterpriseSearchAnalyticsProcessingComponent -SearchTopology $NewSearchTopology -SearchServiceInstance $SearchServiceInstanceServer1
119 | New-SPEnterpriseSearchContentProcessingComponent -SearchTopology $NewSearchTopology -SearchServiceInstance $SearchServiceInstanceServer1
120 | New-SPEnterpriseSearchQueryProcessingComponent -SearchTopology $NewSearchTopology -SearchServiceInstance $SearchServiceInstanceServer1
121 | New-SPEnterpriseSearchCrawlComponent -SearchTopology $NewSearchTopology -SearchServiceInstance $SearchServiceInstanceServer1
122 | New-SPEnterpriseSearchAdminComponent -SearchTopology $NewSearchTopology -SearchServiceInstance $SearchServiceInstanceServer1
123 |
124 | #==============================================================
125 | #Search Service Application Components on SearchServer2 (if specified)
126 | #Creating all components except Index (created later)
127 | #==============================================================
128 | If ($SearchServer2)
129 | {
130 | New-SPEnterpriseSearchAnalyticsProcessingComponent -SearchTopology $NewSearchTopology -SearchServiceInstance $SearchServiceInstanceServer2
131 | New-SPEnterpriseSearchContentProcessingComponent -SearchTopology $NewSearchTopology -SearchServiceInstance $SearchServiceInstanceServer2
132 | New-SPEnterpriseSearchQueryProcessingComponent -SearchTopology $NewSearchTopology -SearchServiceInstance $SearchServiceInstanceServer2
133 | New-SPEnterpriseSearchCrawlComponent -SearchTopology $NewSearchTopology -SearchServiceInstance $SearchServiceInstanceServer2
134 | New-SPEnterpriseSearchAdminComponent -SearchTopology $NewSearchTopology -SearchServiceInstance $SearchServiceInstanceServer2
135 | }
136 | #==============================================================
137 | #Index Components with replicas on SearchServer1 and SearchServer2 (if specified)
138 | #==============================================================
139 |
140 | New-SPEnterpriseSearchIndexComponent -SearchTopology $NewSearchTopology -SearchServiceInstance $SearchServiceInstanceServer1 -IndexPartition 0
141 | New-SPEnterpriseSearchIndexComponent -SearchTopology $NewSearchTopology -SearchServiceInstance $SearchServiceInstanceServer1 -IndexPartition 1
142 |
143 | If ($SearchServer2)
144 | {
145 | New-SPEnterpriseSearchIndexComponent -SearchTopology $NewSearchTopology -SearchServiceInstance $SearchServiceInstanceServer2 -IndexPartition 0
146 | New-SPEnterpriseSearchIndexComponent -SearchTopology $NewSearchTopology -SearchServiceInstance $SearchServiceInstanceServer2 -IndexPartition 1
147 | }
148 |
149 | $NewSearchTopology.Activate()
150 |
151 | #=================================================
152 |
153 | $ssa = Get-SPEnterpriseSearchServiceApplication | ?{$_.CloudIndex -eq $true}
154 | Get-SPEnterpriseSearchTopology -Active -SearchApplication $ssa
155 | Get-SPEnterpriseSearchStatus -SearchApplication $ssa -Text |ft Name, state,Partition,Host -AutoSize
156 | $ssa.CloudIndex
--------------------------------------------------------------------------------
/Scripts/SharePoint.Hybrid.Search.Configuration/HybridWizard.ps1:
--------------------------------------------------------------------------------
1 | <# Disclaimer
2 |
3 | Microsoft provides programming examples for illustration only, without warranty either expressed or
4 | implied, including, but not limited to, the implied warranties of merchantability and/or fitness
5 | for a particular purpose.
6 |
7 | This sample assumes that you are familiar with the programming language being demonstrated and the
8 | tools used to create and debug procedures. Microsoft support professionals can help explain the
9 | functionality of a particular procedure, but they will not modify these examples to provide added
10 | functionality or construct procedures to meet your specific needs. if you have limited programming
11 | experience, you may want to contact a Microsoft Certified Partner or the Microsoft fee-based consulting
12 | line at (800) 936-5200.
13 |
14 | # Added to Github PnP-Tools Repository
15 |
16 | # HYBRID CONFIGURATION WIZARD #
17 | # 20/11/2015 - Release v0.9
18 | # 20/11/2015 - Added pre req checks and more graceful exit
19 | # 11/11/2015 - Fixed up dirsync report format; Make http call to spsite after iisreset, single domain name url fixed, debug text cleanup
20 | # 09/04/2015 - Implemented Form.Focus, added cleanup option (not quite ready) and fixed Wizard Exit on Completion
21 | # 20/03/2015 - Changed text boxes to labels. Added Dirsync check and local admin check. Removed IISReset Warning and updated Start/Exit button behaviour
22 | # 09/01/2015 - Fixed problem installing .MSI files
23 | # 18/12/2014 - V0.3 released for testing
24 | # 10/12/2014 - Self Signed Cert bug fixed by implementing a -1 day to start date
25 | # 09/12/2014 - Fixed certificate export bug - missing move to root auth section
26 | # 09/12/2014 - Added code to remove existing certs from my and root if same self signed name is used.
27 | # 08/12/2014 - Added multiple error checking for failed SPO logins
28 | # 05/12/2014 - Fixed naming conventions for functions
29 |
30 | # Version Control
31 |
32 | #Update this version number for each release
33 | #>
34 |
35 | $HWVersion = " v0.9"
36 |
37 | #Useful references - PowerShell forms and Controls - http://technet.microsoft.com/en-us/library/ff730941.aspx
38 | Add-PSSnapin Microsoft.SharePoint.PowerShell -EA 0
39 | Add-Type -AssemblyName System.Windows.Forms
40 |
41 | #region FunctionDefs
42 |
43 | ######################################################################
44 | # Import-ModulesAndConnect #
45 | # Prompts for O365 tenant login creds #
46 | ######################################################################
47 | function Import-ModulesAndConnect()
48 | {
49 | Write-Host "Entering Import-Modules and Connect"
50 |
51 | Update-WizardProgress "Importing required PowerShell Modules and Connecting to O365"
52 |
53 | # Import MSOnline Modules
54 | # To Add - if msol modules are not available we need to add a section to prompt for download and install
55 |
56 | #Import the Microsoft Online Services Sign-In Assistant.
57 | Import-Module -Name MSOnline
58 | #Import the Microsoft Online Services Module for Windows Powershell.
59 | Import-Module MSOnlineExtended –force
60 | $O365Creds = ""
61 | $ExitConnect = $false
62 | #We are going to use the $error output to track the last error message to see if it corresponds to an invalid login attempt
63 | $error.Clear()
64 | do
65 | {
66 | $error.Clear()
67 | $O365Creds = Get-Credential -Message "Tenant Admin credentials"
68 | Connect-MsolService -Credential $O365Creds
69 | $Theuser = $O365Creds.UserName
70 | If ($error[0].Exception -match "The user name or password is incorrect")
71 | {
72 | Update-WizardProgress "Login Unsuccessful"
73 | $O365Connected = $false, $Theuser
74 | $ExitConnect = $false
75 | }
76 | else
77 | {
78 | Update-WizardProgress "Logged into MSOL as $TheUser"
79 | $O365Connected = $true, $Theuser
80 | $ExitConnect = $true
81 | }
82 |
83 | if ($ExitConnect -eq $false)
84 | {
85 | Update-WizardProgress "Connection to MSOL failed - Try Again?"
86 |
87 | $msgBox = Show-MessageBox "You failed to authenticate to Office 365 as a global admin.`nWould you like to try again?" -YesNo
88 |
89 | # Checking if user wants to exit the login attempt
90 | if ($msgbox -eq "No")
91 | {
92 | $ExitConnect = $true
93 | }
94 | else
95 | {
96 | $ExitConnect = $false
97 | }
98 | }
99 | }
100 | until ($ExitConnect -eq $true)
101 |
102 |
103 | #Check for dirsync active - warn if not
104 | #Report last time sync - warn is last dirsync time > 24 hours
105 |
106 | $msolcompany = Get-MsolCompanyInformation
107 | $IsDirSyncEnabled = $msolcompany.DirectorySynchronizationEnabled
108 | $LastDirsynctime = $msolcompany.LastDirSyncTime
109 | $thedate = Get-Date
110 |
111 | $SyncDelay = (get-date) - ($msolcompany.LastDirSyncTime)
112 | $SyncDelayDays = $SyncDelay.Days
113 | $SyncDelayHours = $SyncDelay.Hours
114 | $SyncDelayMinutes = $SyncDelay.Minutes
115 |
116 | if ($IsDirSyncEnabled -eq $true)
117 | {
118 | Update-WizardProgress "Dirsync is enabled for the O365 Tenancy"
119 | Write-Host "Dirsync is enabled for the O365 Tenancy"
120 | Update-WizardProgress "Last Dirsync was $SyncDelayHours hours and $SyncDelayMinutes minutes ago"
121 | Write-Host "Last Dirsync was $SyncDelayHours hours and $SyncDelayMinutes minutes ago"
122 |
123 | if($SyncDelay.Days -gt 0)
124 | {
125 | Show-MessageBox -Title "Dirsync Warning" "Your Dirsync process has not completed for $SyncDelayDays Days and $SyncDelayHours Hours`nYou can continue with the Wizard but it is recommended you investigate and fix and errors with the sync process as soon as possible" -Warning | out-null
126 | Update-WizardProgress "Dirsync Warning - Over 24 Hours since last sync"
127 | }
128 | }
129 | else
130 | {
131 | Show-MessageBox -Title "Dirsync Critcal" "Dirsync is not enabled for the Tenancy!`n`nYou can continue with the Wizard but it is required that you complete this process to enable hybrid user experiences" -Critical | out-null
132 | Update-WizardProgress "Dirsync is NOT enabled for the O365 Tenancy"
133 | }
134 |
135 | return $O365Connected
136 |
137 | }
138 |
139 | ######################################################################
140 | # Register-ServicePrincipalO365 #
141 | # Registers the service principal for O365 using the certificate #
142 | # $spo_appid = Standared SPO App ID GUID #
143 | # $cred_value = Base64 encoding of the STS.cer certificate #
144 | ######################################################################
145 | function Register-ServicePrincipalO365($spo_appid, $cred_value)
146 | {
147 | write-host "Entering Register-ServicePrincipalO365 with parameters" $spo_appid $cred_value
148 |
149 | Update-WizardProgress "Registering Service App Principal"
150 |
151 | #Register the On-Premise STS as Service Principal in Office 365
152 |
153 | New-MsolServicePrincipalCredential -AppPrincipalId $spo_appid -Type asymmetric -Usage Verify -Value $cred_Value
154 | $spocontextID = (Get-MsolCompanyInformation).ObjectID
155 | $spoappprincipalID = (Get-MsolServicePrincipal -ServicePrincipalName $spo_appid).ObjectID
156 | $sponameidentifier = "$spoappprincipalID@$spocontextID"
157 |
158 | $SPO365 = $spocontextID, $sponameidentifier
159 |
160 | return $SPO365
161 | }
162 |
163 | ######################################################################
164 | # Establish-ACSTrust #
165 | # Creates the ACS proxy and Adds ACS as security token issues #
166 | # $sp_site = defines the site for app prinicpal registeration #
167 | # $spo_name_identifier = SPOID and Tenant ContextID #
168 | # $spo_context_ID = Establishes Authentication Realm #
169 | ######################################################################
170 | function Establish-ACSTrust($SPSite, $spo_name_identifier, $spo_context_ID)
171 | {
172 | write-host "Entering Establish_ACSTrust with parameters" $spsite $spo_name_identifier $spo_context_ID
173 |
174 | Update-WizardProgress "Establishing ACS Trust and Deploying Proxy"
175 |
176 | #First we remove old ACS Proxy and SecurityTokenIssues
177 | $OldACSProxy = Get-SPServiceApplicationProxy | ? {$_.typename -match "Azure Access Control Service Application Proxy"} | Remove-SPServiceApplicationProxy
178 | $OldTSTI = Get-SPTrustedSecurityTokenIssuer | ? {$_.name -match "ACS"} | Remove-SPTrustedSecurityTokenIssuer
179 |
180 | #Finally Establish in the On-Premise Farm a Trust with the ACS
181 |
182 | $rootsite = Get-SPSite $SPSite
183 |
184 | $appPrincipal = Register-SPAppPrincipal -site $rootsite.rootweb -nameIdentifier $spo_name_identifier -displayName "SharePoint Online" #Error here
185 | Set-SPAuthenticationRealm -realm $spo_context_ID
186 | New-SPAzureAccessControlServiceApplicationProxy -Name "ACS" -MetadataServiceEndpointUri "https://accounts.accesscontrol.windows.net/metadata/json/1/" -DefaultProxyGroup
187 | New-SPTrustedSecurityTokenIssuer -MetadataEndpoint "https://accounts.accesscontrol.windows.net/metadata/json/1/" -IsTrustBroker -Name "ACS"
188 | }
189 |
190 | ######################################################################
191 | # Manage-STSCertificate #
192 | # Sequence of steps to implement selected Certificates Process #
193 | # Options are SelfSigned, Default or Public #
194 | # v1 = SelfSigned only #
195 | # $spoapplid = SPO App ID GUID #
196 | # $spcname = on premises SP domain name for SPN #
197 | ######################################################################
198 | function Manage-STSCertificate($spoapplid, $SPSite, $CommonName)
199 | {
200 | Write-Host "Entering manage-stscertificate with parameters $spoapplid $SPSite $commonname"
201 |
202 | Update-WizardProgress "Beginning Certificate Management Process"
203 |
204 | $indexHostName = $SPSite.IndexOf('://') + 3
205 | $HostName = $SPSite.Substring($indexHostName)
206 | $indexHostName = $HostName.IndexOf('/')
207 | if ($indexhostName -ge 0) {
208 | $HostName = $HostName.Substring(0,$indexHostName)
209 | }
210 |
211 | $partfqdn = $Hostname.Indexof('.')
212 |
213 | # Check for single part domain name, ie http://spweb as this will result in $partfqdn value of -1
214 | if($partfqdn -lt 0)
215 | {
216 | $Hostname = "*" + $Hostname
217 | }
218 | else
219 | {
220 | $Hostname = "*" + $Hostname.Substring($partfqdn) ##substring error here
221 | }
222 |
223 | $NewSPN = '{0}/{1}' -f $spoapplid, $HostName
224 |
225 | $SPAppPrincipal = Get-MsolServicePrincipal -AppPrincipalId $spoapplid
226 | if ($SPAppPrincipal.ServicePrincipalNames -notcontains $NewSPN)
227 | {
228 | $SPAppPrincipal.ServicePrincipalNames.Add($NewSPN)
229 | Set-MsolServicePrincipal -AppPrincipalId $SPAppPrincipal.AppPrincipalId -ServicePrincipalNames $SPAppPrincipal.ServicePrincipalNames
230 | }
231 |
232 | $UpdateWizardProgress = "SPN in O365 configured for $Hostname"
233 |
234 | Update-WizardProgress $UpdateWizardProgress
235 |
236 | if($radiobuttonUsePublicAuthoritySi.Checked)
237 | {
238 | #Use Public Authority Certificate
239 | }
240 |
241 | if($radiobuttonUseNewSelfSignedSTSC.Checked)
242 | {
243 | #Use Auto Generated Self Signed Certificate
244 |
245 | Update-WizardProgress "New selfsigned certificate selected"
246 | $CertPass = read-host -Prompt "Please enter the password to secure the self signed certificate" -AsSecureString
247 | Update-WizardProgress "Creating selfsigned certificate and adding to trusted root store"
248 | $CreateCert = Add-SelfSignedCertificate $CommonName
249 | Update-WizardProgress "Updating Farm Secure Token Service with new Certificate"
250 | $UpdateFarmSTS = Update-FarmSTS $CommonName $CertPass
251 | Update-WizardProgress "Generating Credentials for O365 S2S trust"
252 | $CredentialValue = Convert-CertsForUpload $CommonName $CertPass
253 | Update-WizardProgress "Registering the Service App Principal"
254 | $RegServiceAppPrin = Register-ServicePrincipalO365 $spoapplid $CredentialValue
255 |
256 | $spo_contextID = $RegServiceAppPrin[0]
257 | $spo_nameidentifier = $RegServiceAppPrin[1]
258 | Update-WizardProgress "Setting up the S2S trust and deploying ACS Proxy"
259 | $EstablishACSTrust = Establish-ACSTrust $SPSite $spo_nameidentifier $spo_contextID
260 |
261 | #At this Point Hybrid identity setup is complete for NewSelfSignedCertificate
262 |
263 | Update-WizardProgress "Hybrid Certificate Management process is complete"
264 | Write-Host "Hybrid Certificate Management process is complete"
265 | }
266 |
267 | if($radiobuttonUseBuiltInSharePoint.Checked)
268 | {
269 | #Use Built In STS Certificate
270 |
271 | Update-WizardProgress"Built in certificate selected"
272 | #$sp_site = $labelOnPremisesSharePoin.Text # future where user gets option to choose which on prem site to configure
273 | Update-WizardProgress"Exporting Default STS Cert"
274 | $LocalCertCred = Export-LocalSTSCert
275 | #Register the Service Principal
276 | Update-WizardProgress"Registering the Service App Principal"
277 | $RegServiceAppPrin = Register-ServicePrincipalO365 $spoapplid $LocalCertCred
278 |
279 | $spo_contextID = $RegServiceAppPrin[0]
280 | $spo_nameidentifier = $RegServiceAppPrin[1]
281 | Update-WizardProgress"Setting up the S2S trust and deploying ACS Proxy"
282 | $EstablishACSTrust = Establish-ACSTrust $SPSite $spo_nameidentifier $spo_contextID
283 |
284 | #At this Point Hybrid identity setup is complete for ExportingTheDefaultCertificate
285 |
286 | Update-WizardProgress "Hybrid Certificate Management process is complete"
287 | Write-Host "Hybrid Certificate Management process is complete"
288 | }
289 | }
290 |
291 | ######################################################################
292 | # Export-LocalSTSCert #
293 | # Exports local STS Cert and converts for use as CredValue #
294 | # for settings up the trust #
295 | ######################################################################
296 | function Export-LocalSTSCert()
297 | {
298 | #Uses the local signing key for upload to O365 instead of creating a new one
299 | $SPSigningCert = (Get-SPSecurityTokenServiceConfig).LocalLoginProvider.SigningCertificate
300 | $ExportedCert = $SPSigningCert.Export([System.Security.Cryptography.X509Certificates.X509ContentType]::Cert)
301 | $CertValue = [System.Convert]::ToBase64String($ExportedCert,[System.Base64formattingoptions]::InsertLineBreaks)
302 |
303 | return $CertValue
304 | }
305 |
306 | ######################################################################
307 | # Update-FarmSTS #
308 | # Updates the Farm STS with the specified certificate #
309 | # $commonname = Certificate common name #
310 | # $CertSecret = Password to use to secure the certificate #
311 | ######################################################################
312 | function Update-FarmSTS($commonname, $SecCertSecret)
313 | {
314 | write-host "Entering Update-FarmSTS with parameters $commonname $SecCertSecret"
315 | #$SecCertSecret = ConvertTo-SecureString $CertSecret -AsPlainText -Force
316 | #Export the required certificates for Updating STS and Uploading to ACS
317 |
318 | $certstore = dir Cert:\LocalMachine\Root `
319 | | where-object {$_.Subject -eq "CN=$commonname"} `
320 | | foreach-object{
321 | [system.IO.file]::WriteAllBytes( "$home\$($_.subject).pfx", ($_.Export('PFX', $SecCertSecret)) )
322 | [system.IO.file]::WriteAllBytes( "$home\$($_.subject).cer", ($_.Export('CER', $SecCertSecret)) )
323 | }
324 |
325 | $pfxcertname = "$home\CN=$commonname"+".pfx"
326 |
327 | $pfxCertificate = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2 $pfxcertname, $SecCertSecret, 20
328 | Set-SPSecurityTokenServiceConfig -ImportSigningCertificate $pfxCertificate
329 |
330 | #Restart IIS so STS Picks up the New Certificate
331 | Update-WizardProgress "The IIS Services and the SharePoint Timer Service are now going to be recycled."
332 |
333 | & iisreset
334 | & net stop SPTimerV4
335 | & net start SPTimerV4
336 |
337 | #(Get-SPSecurityTokenServiceConfig).LocalLoginProvider.SigningCertificate #DEBUG ONLY
338 | }
339 |
340 | ######################################################################
341 | # Convert-CertsforUpload #
342 | # Converts Certificate to Base 64 for use as App Principal Cred #
343 | # $LocalDN = Certificate common name #
344 | # $CertSecret = Password to use to secure the certificate #
345 | ######################################################################
346 | function Convert-CertsForUpload($LocalCN, $CertSecret)
347 | {
348 | #Do Some Conversions With the Certificates to Base64
349 | #Return $credValue for use in Adding App Principal
350 |
351 | $stscertpfx = "$home\CN=$LocalCN.pfx"
352 | $stscertpassword = $CertSecret
353 | $stscertcer = "$home\CN=$LocalCN.cer"
354 |
355 | $pfxCertificate = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2 -ArgumentList $stscertpfx,$stscertpassword
356 | $pfxCertificateBin = $pfxCertificate.GetRawCertData()
357 | $cerCertificate = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2
358 | $cerCertificate.Import($stscertcer)
359 | $cerCertificateBin = $cerCertificate.GetRawCertData()
360 | $credValue = [System.Convert]::ToBase64String($cerCertificateBin)
361 |
362 | Return $credValue
363 | }
364 |
365 | ######################################################################
366 | # Add-SelfSignedCertificate #
367 | # Adds a Self Signed Certificate to the Local Machine Personal Store #
368 | # $commonname defines the certificate subject to be used #
369 | ######################################################################
370 | function Add-SelfSignedCertificate($commonname)
371 | {
372 |
373 | #Remove and existing certificates with the same common name from personal and root stores
374 | #Need to be very wary of this as could break something
375 |
376 | $certs = dir Cert:\LocalMachine\my | ?{$_.Subject -eq "CN=$commonname"}
377 | $mystore = get-item Cert:\LocalMachine\My
378 | $mystore.open("ReadWrite")
379 | Foreach($acert in $certs) { $mystore.Remove($acert) }
380 | $mystore.close()
381 |
382 | $certs = dir Cert:\LocalMachine\Root | ?{$_.Subject -eq "CN=$commonname"}
383 | $rootstore = get-item Cert:\LocalMachine\Root
384 | $rootstore.open("ReadWrite")
385 | Foreach($acert in $certs) { $rootstore.Remove($acert) }
386 | $rootstore.close()
387 |
388 | $name = new-object -com "X509Enrollment.CX500DistinguishedName.1"
389 | $name.Encode("CN=$CommonName", 0)
390 |
391 | $key = new-object -com "X509Enrollment.CX509PrivateKey.1"
392 | $key.ProviderName = "Microsoft RSA SChannel Cryptographic Provider"
393 | $key.KeySpec = 1
394 | $key.Length = 2048 # Modified to 2048
395 | $key.SecurityDescriptor = "D:PAI(A;;0xd01f01ff;;;SY)(A;;0xd01f01ff;;;BA)(A;;0x80120089;;;NS)"
396 | $key.MachineContext = 1
397 | $key.ExportPolicy = 1 # This is required to allow the private key to be exported
398 | $key.Create()
399 |
400 | $serverauthoid = new-object -com "X509Enrollment.CObjectId.1"
401 | $serverauthoid.InitializeFromValue("1.3.6.1.5.5.7.3.1")
402 | $ekuoids = new-object -com "X509Enrollment.CObjectIds.1"
403 | $ekuoids.add($serverauthoid)
404 | $ekuext = new-object -com "X509Enrollment.CX509ExtensionEnhancedKeyUsage.1"
405 | $ekuext.InitializeEncode($ekuoids)
406 |
407 | $cert = new-object -com "X509Enrollment.CX509CertificateRequestCertificate.1"
408 | $cert.InitializeFromPrivateKey(2, $key, "")
409 | $cert.Subject = $name
410 | $cert.Issuer = $cert.Subject
411 | $cert.NotBefore = get-date
412 | $cert.NotBefore = $cert.NotBefore.AddDays(-1) # Make the certificate valid to the previous day.
413 | $cert.NotAfter = $cert.NotBefore.AddDays(720)
414 | $cert.X509Extensions.Add($ekuext)
415 | $cert.Encode()
416 |
417 | $enrollment = new-object -com "X509Enrollment.CX509Enrollment.1"
418 | $enrollment.InitializeFromRequest($cert)
419 | $certdata = $enrollment.CreateRequest(0)
420 | $enrollment.InstallResponse(2, $certdata, 0, "")
421 |
422 | $newcert = dir Cert:\LocalMachine\my | ?{$_.Subject -eq "CN=$commonname"}
423 | #$thecert = "Cert:\localmachine\my\$newcert"
424 | $store = get-item Cert:\LocalMachine\Root
425 | $store.open("ReadWrite")
426 | $store.add($newcert)
427 | $store.close()
428 | }
429 |
430 | ######################################################################
431 | # Show-MessageBox #
432 | # Supports alert boxes with various button combinations #
433 | # $Msg = Message to send #
434 | # $Title = Alert box title #
435 | # Various button option in parameters
436 | ######################################################################
437 | function Show-MessageBox()
438 | {
439 | Param(
440 | [Parameter(Mandatory=$True)][Alias('M')][String]$Msg,
441 | [Parameter(Mandatory=$False)][Alias('T')][String]$Title = "",
442 | [Parameter(Mandatory=$False)][Alias('OC')][Switch]$OkCancel,
443 | [Parameter(Mandatory=$False)][Alias('OCI')][Switch]$AbortRetryIgnore,
444 | [Parameter(Mandatory=$False)][Alias('YNC')][Switch]$YesNoCancel,
445 | [Parameter(Mandatory=$False)][Alias('YN')][Switch]$YesNo,
446 | [Parameter(Mandatory=$False)][Alias('RC')][Switch]$RetryCancel,
447 | [Parameter(Mandatory=$False)][Alias('C')][Switch]$Critical,
448 | [Parameter(Mandatory=$False)][Alias('Q')][Switch]$Question,
449 | [Parameter(Mandatory=$False)][Alias('W')][Switch]$Warning,
450 | [Parameter(Mandatory=$False)][Alias('I')][Switch]$Informational)
451 |
452 | #Set Message Box Style
453 | IF($OkCancel){$Type = 1}
454 | Elseif($AbortRetryIgnore){$Type = 2}
455 | Elseif($YesNoCancel){$Type = 3}
456 | Elseif($YesNo){$Type = 4}
457 | Elseif($RetryCancel){$Type = 5}
458 | Else{$Type = 0}
459 |
460 | #Set Message box Icon
461 | If($Critical){$Icon = 16}
462 | ElseIf($Question){$Icon = 32}
463 | Elseif($Warning){$Icon = 48}
464 | Elseif($Informational){$Icon = 64}
465 | Else{$Icon = 0}
466 |
467 | #Loads the WinForm Assembly, Out-Null hides the message while loading.
468 | [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms") | Out-Null
469 |
470 | #Display the message with input
471 | $Answer = [System.Windows.Forms.MessageBox]::Show($MSG , $TITLE, $Type, $Icon)
472 |
473 | #Return Answer
474 | Return $Answer
475 | }
476 |
477 | ######################################################################
478 | # Check-FarmAdmin #
479 | # Checks if current user is a farm admin and returns true or false #
480 | ######################################################################
481 | function Check-FarmAdmin()
482 | {
483 | #Must return true else send message to use different user and exit app
484 |
485 | #(Get-SPFarm).DefaultServiceAccount.Name
486 | $FarmAdmin = (Get-Spfarm).CurrentUserIsAdministrator()
487 | Return $FarmAdmin
488 | }
489 |
490 | ######################################################################
491 | # Get-SPFarmAdministrators #
492 | # Returns the farm adminstrators group membership #
493 | ######################################################################
494 | function Get-SPfarmAdministrators()
495 | {
496 | $adminwebapp = Get-SPwebapplication -includecentraladministration | where {$_.IsAdministrationWebApplication}
497 | $adminsite = Get-SPweb($adminwebapp.Url)
498 | $AdminGroupName = $adminsite.AssociatedOwnerGroup
499 | $farmAdministratorsGroup = $adminsite.SiteGroups[$AdminGroupName]
500 | return $farmAdministratorsGroup.users
501 | }
502 |
503 | ######################################################################
504 | # Validate-ServiceApps #
505 | # Checks if the required service applications are deployed #
506 | # Checks if the required service application instances are enabled #
507 | # Warning or Error message is delivered to user #
508 | ######################################################################
509 | function Validate-ServiceApps()
510 | {
511 | #Create Response to Required Service App Check"
512 | $ServiceCheck = ""
513 | $ServiceStatus = 1
514 |
515 | #Validate User Profile Service Application Status
516 | $upa=Get-SPServiceApplication | where-object {$_.TypeName -match "User profile"}
517 | if ($upa.status -eq "Online") { $ServiceCheck = "UPA Service Application Check Successful`r`n" }
518 | else
519 | {
520 | $ServiceCheck = "UPA Service Application Check Failed`r`n"
521 | $ServiceStatus = 0
522 | }
523 | #$upa | Out-Null
524 |
525 | #validate userprofile service instance status
526 | $upaservinst = Get-SPServiceInstance | where-object{$_.typename -match "User Profile Service" -AND $_.status -eq "Online"}
527 | if($upaservinst) { $ServiceCheck = $ServiceCheck + "UPA Service Instance Check Successful`r`n" }
528 | else
529 | {
530 | $ServiceCheck = $ServiceCheck + "UPA Service Instance Check Failed`r`n"
531 | $ServiceStatus = 0
532 | }
533 |
534 | #validate user profile sync service instance status
535 | $upasyncinst = Get-SPServiceInstance | where-object{$_.typename -match "User Profile Synchronization Service" -AND $_.status -eq "Online"}
536 | if($upasyncinst) { $ServiceCheck = $ServiceCheck + "UPA Sync Service Instance Check Successful`r`n" }
537 | else
538 | {
539 | if($upa.NoILMUsed -eq $true) { $ServiceCheck = $ServiceCheck + "Sync Service is disabled, ensure you have run AD import synchronization `r`n" }
540 | else
541 | {
542 | #We cannot yet determine the difference between internal and external FIM so do not fail just in case - see windows service on sync machine
543 | $ServiceCheck = $ServiceCheck + "UPA Sync Service Instance Check Failed - Check UPA Import Config `r`n"}
544 | }
545 |
546 | #Validate Search Service Application Status
547 | $ssa=Get-SPServiceApplication | where-object {$_.TypeName -match "Search Service"}
548 | if ($ssa.status -eq "Online") { $ServiceCheck = $ServiceCheck + "Search Service Application Check Successful`r`n" }
549 | else
550 | {
551 | $ServiceCheck = "Search Service Application Check Failed`r`n"
552 | $ServiceStatus = 0
553 | }
554 |
555 | #Validate Search Admin Service Application Status
556 | $sas=Get-SPServiceApplication | where-object {$_.TypeName -match "Search Admin"}
557 | if ($sas.status -eq "Online") { $ServiceCheck = $ServiceCheck + "Search Admin Service Application Check Successful`r`n" }
558 | else
559 | {
560 | $ServiceCheck = "Search Admin Service Application Check Failed`r`n"
561 | $ServiceStatus = 0
562 | }
563 |
564 | #validate Search host controller service instance status
565 | $shcservinst = Get-SPServiceInstance | where-object {$_.typename -match "Search Host Controller Service" -AND $_.status -eq "Online"}
566 | if($shcservinst) { $ServiceCheck = $ServiceCheck + "Search Host Controller Service Instance Check Successful`r`n" }
567 | else
568 | {
569 | $ServiceCheck = $ServiceCheck + "Search Host Controller Service Instance Check Failed`r`n"
570 | $ServiceStatus = 0
571 | }
572 |
573 | #validate SharePoint Server Search service instance status
574 | $seaservinst = Get-SPServiceInstance | where-object{$_.typename -match "SharePoint Server Search" -AND $_.status -eq "Online"}
575 | if($seaservinst) { $ServiceCheck = $ServiceCheck + "SharePoint Server Search Service Instance Check Successful`r`n" }
576 | else
577 | {
578 | $ServiceCheck = $ServiceCheck + "SharePoint Server Search Service Instance Check Failed`r`n"
579 | $ServiceStatus = 0
580 | }
581 |
582 | #validate Search Query and Site Settings Service instance status
583 | $sqsservinst = Get-SPServiceInstance | where-object{$_.typename -match "Search Query and Site Settings Service" -AND $_.status -eq "Online"}
584 | if($sqsservinst) { $ServiceCheck = $ServiceCheck + "Search Query and Site Settings Service Instance Check Successful`r`n" }
585 | else
586 | {
587 | $ServiceCheck = $ServiceCheck + "Search Query and Site Settings Service Instance Check Failed`r`n"
588 | $ServiceStatus = 0
589 | }
590 |
591 | #Validate Subscription Settings Application Status
592 | $sss=Get-SPServiceApplication | where-object {$_.TypeName -match "Subscription"}
593 | if ($sss.status -eq "Online") { $ServiceCheck = $ServiceCheck + "Subscription Settings Service Application Check Successful`r`n" }
594 | else
595 | {
596 | $ServiceCheck = "Subscription Settings Service Application Check Failed`r`n"
597 | $ServiceStatus = 0
598 | }
599 |
600 | #Validate Microsoft SharePoint Foundation Subscription Settings Service Instance Status
601 | $sfsservinst = Get-SPServiceInstance | where-object{$_.typename -match "Microsoft SharePoint Foundation Subscription Settings Service" -AND $_.status -eq "Online"}
602 | if($sfsservinst) { $ServiceCheck = $ServiceCheck + "SharePoint Subscription Settings Service Instance Check Successful`r`n" }
603 | else
604 | {
605 | $ServiceCheck = $ServiceCheck + "SharePoint Subscription Settings Service Instance Check Failed`r`n"
606 | $ServiceStatus = 0
607 | }
608 |
609 | #Validate App Management Application Status
610 | $app=Get-SPServiceApplication | where-object {$_.TypeName -match "App Management"}
611 | if ($app.status -eq "Online") { $ServiceCheck = $ServiceCheck + "App Management Service Application Check Successful`r`n" }
612 | else
613 | {
614 | $ServiceCheck = "App Management Service Application Check Failed`r`n"
615 | $ServiceStatus = 0
616 | }
617 |
618 | #Validate App Management Service Instance Status
619 | $samservinst = Get-SPServiceInstance | where-object{$_.typename -match "App Management Service" -AND $_.status -eq "Online"}
620 | if($samservinst) { $ServiceCheck = $ServiceCheck + "App Management Service Instance Check Successful`r`n" }
621 | else
622 | {
623 | $ServiceCheck = $ServiceCheck + "App Management Service Instance Check Failed`r`n"
624 | $ServiceStatus = 0
625 | }
626 |
627 | #Validate Security Token Service Application Status
628 | $sts=Get-SPServiceApplication | where-object {$_.TypeName -match "Security Token"}
629 | if ($sts.status -eq "Online") { $ServiceCheck = $ServiceCheck + "Security Token Service Check Successful`r`n" }
630 | else
631 | {
632 | $ServiceCheck = "Security Token Service Check Failed`r`n"
633 | $ServiceStatus = 0
634 | }
635 |
636 | if ($ServiceStatus -eq 1) { Show-MessageBox "All Required Services are deployed and Online `r`n$ServiceCheck" | out-null }
637 | else
638 | {
639 | Show-MessageBox "Services not correctly setup `r `n$ServiceCheck" -Critical | out-null
640 | Show-MessageBox "Wizard will now exit!" | Out-Null
641 | }
642 | return $ServiceStatus, $ServiceCheck
643 | }
644 |
645 | <#
646 | ######################################################################
647 | # DEPRECATED FUNCTION #
648 | # Prepares the server by deploying the MSOL/ADCRL pieces #
649 | # Recycles services after deployment #
650 | ######################################################################
651 | function Deprecated-Prepare-Environment(){
652 |
653 | ## Future - look for new version of MSOL/IDCRL online and download/update if required/prompted ##
654 |
655 | $scriptFolder = "C:\scripts\Resources"
656 |
657 | $MSOIdCRLRegKey = Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\MSOIdentityCRL" -ErrorAction SilentlyContinue
658 | if($MSOIdCRLRegKey -eq $null)
659 | {
660 | Update-WizardProgress "Installing Office Single Sign On Assistant"
661 | #Install-MSI (Get-AbsolutePath "\msoidcli_64.msi")
662 | Start-Process "$scriptFolder\msoidcli_64.msi" -ArgumentList " /q /norestart" -Wait
663 | Update-WizardProgress "Successfully installed!"
664 | }
665 | else
666 | {
667 | Update-WizardProgress "Office Single Sign On Assistant already Installed"
668 | }
669 | $MSOLPSRegKey = Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\MSOnlinePowershell" -ErrorAction SilentlyContinue
670 | if($MSOLPSRegKey -eq $null)
671 | {
672 | Update-WizardProgress "Installing Active Directory PowerShell"
673 | Start-Process "$scriptFolder\AdministrationConfig-EN.msi" -ArgumentList " /q /norestart" -wait
674 | Update-WizardProgress "Creating Taskbar Shortcuts"
675 | #New-Shortcut -ShortcutName "AAD PowerShell" -IconPath ($scriptFolder + "\AzurePS.ico") -ApplicationPath "C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -NoExit -Command ""Import-Module MSOnline"""
676 | Update-WizardProgress "Successfully installed!"
677 | }
678 | else
679 | {
680 | Update-WizardProgress "Azure Active Directory Powershell already Installed"
681 | }
682 |
683 | Update-WizardProgress "Restarting MSO IDCRL Service"
684 | Stop-Service -Name msoidsvc -Force -WarningAction SilentlyContinue -ErrorAction SilentlyContinue
685 | $svc = Get-Service msoidsvc
686 | $svc.WaitForStatus("Stopped")
687 | Start-Service -Name msoidsvc
688 | $svc = Get-Service msoidsvc
689 | $svc.WaitForStatus("Running")
690 | Update-WizardProgress "MSO IDCRL Service Restarted!"
691 |
692 | }
693 | #>
694 |
695 | ######################################################################
696 | # Checks the Server for the AAD PowerShell and Sign In Assistant #
697 | # Recycles services if they are deployed #
698 | # Raises error and exits if they are not installed #
699 | ######################################################################
700 | function Prepare-Environment()
701 | {
702 | $MSOIdCRLRegKey = Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\MSOIdentityCRL" -ErrorAction SilentlyContinue
703 | if ($MSOIdCRLRegKey -eq $null)
704 | {
705 | Write-Host "Office Single Sign On Assistant required, see http://www.microsoft.com/en-us/download/details.aspx?id=39267." -Foreground Red
706 | Update-WizardProgress "Office Single Sign on Assistant not found"
707 | }
708 | else
709 | {
710 | Write-Host "Found Office Single Sign On Assistant!" -Foreground Green
711 | Update-WizardProgress "Office Single Sign on Assistant found"
712 | }
713 |
714 | $MSOLPSRegKey = Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\MSOnlinePowershell" -ErrorAction SilentlyContinue
715 | if ($MSOLPSRegKey -eq $null)
716 | {
717 | Write-Host "AAD PowerShell required, see http://go.microsoft.com/fwlink/p/?linkid=236297." -Foreground Red
718 | Update-WizardProgress "AAD PowerShell not found"
719 | }
720 | else
721 | {
722 | Write-Host "Found AAD PowerShell!" -Foreground Green
723 | Update-WizardProgress "AAD PowerShell found"
724 | }
725 |
726 | if ($MSOIdCRLRegKey -eq $null -or $MSOLPSRegKey -eq $null)
727 | {
728 | Update-WizardProgress "Please manually install the prerequisites."
729 | throw "Manual installation of prerequisites required."
730 | }
731 |
732 | Write-Host "Configuring Azure AD settings..." -Foreground Yellow
733 |
734 | $regkey = "HKLM:\SOFTWARE\Microsoft\MSOnlinePowerShell\Path"
735 | Set-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\MSOIdentityCRL" -Name "ServiceEnvironment" -Value "Production"
736 | Set-ItemProperty -Path $regkey -Name "WebServiceUrl" -Value "https://provisioningapi.microsoftonline.com/provisioningwebservice.svc" #$PROVISIONINGAPI_WEBSERVICEURL
737 | Set-ItemProperty -Path $regkey -Name "FederationProviderIdentifier" -Value "microsoftonline.com"
738 |
739 | Write-Host "Restarting MSO IDCRL Service..." -Foreground Yellow
740 | Update-WizardProgress "Restarting MSO IDCRL Service"
741 |
742 | # Service takes time to get provisioned, retry restart.
743 | for ($i = 1; $i -le 10; $i++)
744 | {
745 | try
746 | {
747 | Stop-Service -Name msoidsvc -Force -WarningAction SilentlyContinue -ErrorAction SilentlyContinue
748 | $svc = Get-Service msoidsvc
749 | $svc.WaitForStatus("Stopped")
750 | Start-Service -Name msoidsvc
751 | }
752 | catch
753 | {
754 | Write-Host "Failed to start msoidsvc service, retrying..."
755 | Update-WizardProgress "Failed to start msoidsvc service, retrying..."
756 | Start-Sleep -seconds 2
757 | continue
758 | }
759 | Write-Host "Service Restarted!" -Foreground Green
760 | Update-WizardProgress "Service Restrated"
761 | break
762 | }
763 | }
764 |
765 | ######################################################################
766 | # Validate-MSOLDomain #
767 | # Checks for domains added to the tenant and prompts to use dirsync #
768 | ######################################################################
769 | function Validate-MSOLDomain()
770 | {
771 | $domainlist = ""
772 | $domains = get-msoldomain | ?{$_.name -notmatch "onmicrosoft.com"}
773 |
774 | foreach ($domain in $domains)
775 | {
776 | $domainlist = $domainlist + $domain.name + "`n"
777 | }
778 | $updatetxt = "The following domain(s) are associated with your tenant. Please ensure you have completed the Azure AD Sync process for these domains. `n `n$domainlist`n"
779 | Update-WizardProgress $updatetxt
780 |
781 | $spodomains = get-msoldomain | ?{$_.name -match "onmicrosoft.com"}
782 | $firstspodomainname=$spodomains[0].name
783 | $thespotenantdomain=$firstspodomainname.split(".")
784 | $SPORootSite="https://" + $thespotenantdomain[0] +".sharepoint.com"
785 | $labelSPOTenantURL.text = $SPORootSite
786 |
787 | #Need to isolate a domain for later when adding an SPN - Grab the first returned SPWeb and use that
788 | #Might need to consider adding a selection for the web app into here
789 |
790 | $SharePointWeb = Get-SPSite | Select-Object -First 1 | Get-SPWeb | Select-Object -First 1 | % Url
791 | $labelOnPremisesSharePoin.Text = $SharePointWeb
792 | return $SharePointWeb
793 | }
794 |
795 | ######################################################################
796 | # Creates new query rule and search result source #
797 | # #
798 | ######################################################################
799 | function New-SCSearchResultSourceAndQueryRule($siteUrl, $remoteUrl, $resultSourceName, $queryRuleName)
800 | {
801 |
802 | #$sspApp = Get-SPEnterpriseSearchServiceApplication | select -first 1
803 | #$SearchServiceApplicationName = $sspApp.Name
804 | $RootSiteCollection = Get-SPSite $siteUrl -ErrorAction SilentlyContinue
805 |
806 | #-----------------------------------------------------
807 | # Get the Search Service application
808 | #-----------------------------------------------------
809 | # Select the first search service application in case there are multiple - can add choices later
810 | $SearchServiceApplication = Get-SPEnterpriseSearchServiceApplication | select -first 1 # -Identity $SearchServiceApplicationName -ErrorAction SilentlyContinue
811 | $FederationManager = New-Object Microsoft.Office.Server.Search.Administration.Query.FederationManager($SearchServiceApplication)
812 |
813 | #--------------------------------------------------------------------------
814 | # The below line creates a Search Object owner at the site collection level
815 | # and this can be changed to Search Application or Site level by passing
816 | # different SearchObjectLevel argument.
817 | #--------------------------------------------------------------------------
818 | $SearchOwner = New-Object Microsoft.Office.Server.Search.Administration.SearchObjectOwner –ArgumentList @([Microsoft.Office.Server.Search.Administration.SearchObjectLevel]::SPSite,$RootSiteCollection.RootWeb)
819 | $Query = "{searchTerms}"
820 | $ResultSource = $FederationManager.GetSourceByName($resultSourceName,$SearchOwner)
821 |
822 | if($ResultSource)
823 | {
824 | Update-WizardProgress "Result Source : $ResultSourceName exist - appending remote url to name"
825 | $resultsourcename = $resultsourcename + "-" + $remoteurl
826 | }
827 |
828 | Update-WizardProgress "Creating Result Source : $ResultSourceName"
829 |
830 | $resultSource = $FederationManager.CreateSource($SearchOwner)
831 | $resultSource.Name = $resultSourceName
832 | $resultSource.CreateQueryTransform($queryProperties, $query)
833 | $resultSource.ConnectionUrlTemplate = $remoteUrl
834 | $resultSource.ProviderId = $FederationManager.ListProviders()["Remote SharePoint Provider"].Id
835 | $ResultSource.Activate()
836 | $resultSource.Commit()
837 |
838 |
839 | #-------------------------------------------------------------------
840 | # Configure a Query Rule
841 | #-------------------------------------------------------------------
842 |
843 | #$QueryRuleConditionTerm = "test"
844 | $QueryRuleManager = New-Object Microsoft.Office.Server.Search.Query.Rules.QueryRuleManager($SearchServiceApplication)
845 |
846 | # Create a search object filter using a $SearchOwner object (Site collection level - in this case)
847 | $SearchObjectFilter = New-Object Microsoft.Office.Server.Search.Administration.SearchObjectFilter($SearchOwner)
848 |
849 | $QueryRules = $QueryRuleManager.GetQueryRules($SearchObjectFilter)
850 | ForEach($Rule in $QueryRules)
851 | {
852 | if($Rule.DisplayName -eq $queryRuleName)
853 | {
854 | Update-WizardProgress "Query Rule : $QueryRuleName already exist. Appending remoteurl to name."
855 | $queryrulename = $queryrulename + "-" + $remoteurl
856 | }
857 | }
858 |
859 | Update-WizardProgress "Creating Query Rule : $QueryRuleName"
860 |
861 | $QueryRules = $QueryRuleManager.GetQueryRules($SearchObjectFilter)
862 |
863 | # Create a new rule as a active one.
864 | $QueryRule = $QueryRules.CreateQueryRule($QueryRuleName,$null,$null,$true)
865 |
866 | # Set the Query Rule condition...
867 | #[string[]] $QueryRuleTerms = @($QueryRuleConditionTerm)
868 | #$QueryRuleConditions = $QueryRule.QueryConditions
869 | #$QueryRuleCondition = $QueryRuleConditions.CreateKeywordCondition($QueryRuleTerms,$true)
870 |
871 | #Bind it to the Result Source...
872 | #$QuerySourceContextCondition = $QueryRule.CreateSourceContextCondition($ResultSource)
873 |
874 | # Set the Query Condition action to change ranked results...
875 | #$QueryRuleAction = $QueryRule.CreateQueryAction([Microsoft.Office.Server.Search.Query.Rules.QueryActionType]::ChangeQuery)
876 | #$QueryRuleAction.QueryTransform.OverrideProperties = new-object Microsoft.Office.Server.Search.Query.Rules.QueryTransformProperties
877 | #$QueryRuleAction.QueryTransform.SourceId = $ResultSource.Id
878 |
879 | # define a custom sorting - Order by FileName
880 | #$QueryRuleSortCollection = New-Object Microsoft.Office.Server.Search.Query.SortCollection
881 | #$QueryRuleSortCollection.Add("FileName", [Microsoft.Office.Server.Search.Query.SortDirection]::Descending)
882 |
883 | #$QueryRule.ChangeQueryAction.QueryTransform.OverrideProperties["SortList"] = [Microsoft.Office.Server.Search.Query.SortCollection]$QueryRuleSortCollection
884 | #$QueryRule.ChangeQueryAction.QueryTransform.QueryTemplate = "{searchTerms}"
885 |
886 | $difqueryblock = $QueryRule.CreateQueryAction("CreateResultBlock")
887 | $difqueryblock.ResultTitle.DefaultLanguageString = "Results from {searchTerms}"
888 |
889 | #look into changing the number of returned items within the result block
890 | $difqueryblock.QueryTransform.SourceId = $resultSource.Id
891 | $difqueryblock.QueryTransform.QueryTemplate = "{searchTerms}"
892 | $difqueryblock.AlwaysShow = $true
893 |
894 | $QueryRule.Update()
895 | }
896 |
897 | ##################################################
898 | #Update-WizardProgress #
899 | #Adds status messages to the progress check box #
900 | ##################################################
901 | function Update-WizardProgress($update)
902 | {
903 | $progress = $textboxWizardProgress.text + "`r`n"
904 | $progress = $progress + $update
905 | $textboxWizardProgress.Text = $progress
906 |
907 | $textboxWizardProgress.SelectionStart= $textboxWizardProgress.TextLength
908 | $textboxWizardProgress.ScrollToCaret()
909 | }
910 |
911 | ##########################################
912 | # CHECK IF CURRENT USER IS A LOCAL ADMIN #
913 | # Todo: check all farm servers #
914 | ##########################################
915 | function Check-IsLocalAdmin
916 | {
917 | $identity = [System.Security.Principal.WindowsIdentity]::GetCurrent()
918 | $principal = new-object System.Security.Principal.WindowsPrincipal($identity)
919 | $admin = [System.Security.Principal.WindowsBuiltInRole]::Administrator
920 | $principal.IsInRole($admin)
921 | }
922 |
923 | ##########################################
924 | # CLEAN UP HYBRID CONFIGURATION #
925 | # 1. REMOVE SPN #
926 | # 2. REMOVE ACS PROXY #
927 | # 3. LOOK FOR AND REMOVE DEFAULT RESULT #
928 | # SOURCE AND QUERY RULE #
929 | ##########################################
930 | function Remove-HybridConfiguration($SPSite)
931 | {
932 | $app = Get-MsolServicePrincipal -AppPrincipalId "00000003-0000-0ff1-ce00-000000000000"
933 | $app.ServicePrincipalNames
934 |
935 | $indexHostName = $SPSite.IndexOf('://') + 3
936 | $HostName = $SPSite.Substring($indexHostName)
937 | $indexHostName = $HostName.IndexOf('/')
938 | if ($indexhostName -ge 0) {
939 | $HostName = $HostName.Substring(0,$indexHostName)
940 | }
941 |
942 | $partfqdn = $Hostname.Indexof('.')
943 |
944 | # Check for single part domain name, ie http://spweb as this will result in $partfqdn value of -1
945 | if($partfqdn -lt 0)
946 | {
947 | $Hostname = $Hostname #No change since single name website
948 | }
949 | else
950 | {
951 | $Hostname = "*" + $Hostname.Substring($partfqdn)
952 | }
953 |
954 | # Loop through the service principal names and clean up the one matching the local SharePoint url
955 |
956 | for ($i = 0; $i -lt $app.ServicePrincipalNames.count; $i++)
957 | {
958 | if($app[$i] -match $Hostname)
959 | {
960 | $app.ServicePrincipalNames.RemoveAt($i)
961 | }
962 | }
963 |
964 | Set-MsolServicePrincipal -AppPrincipalId $app.AppPrincipalId -ServicePrincipalNames $app.ServicePrincipalNames
965 |
966 | # Remove the ACS Proxy - will remove them all so be careful
967 | Get-SPServiceApplicationProxy | ? {$_.TypeName -eq "Azure Access Control Service Application Proxy"} | Remove-SPServiceApplicationProxy
968 | Update-WizardProgress "Azure ACS Proxy has been removed"
969 |
970 | #Remove the TrustedSecurityTokenIssuer based on metadata endpoint
971 | Get-SPTrustedSecurityTokenIssuer |?{$_.MetadataEndPoint -eq "https://accounts.accesscontrol.windows.net/metadata/json/1/"} | Remove-SPTrustedSecurityTokenIssuer
972 |
973 | Update-WizardProgress "Trusted Security Token Issuer has been removed"
974 | }
975 |
976 | ##########################################
977 | # WARMS UP THE ROOT SITE #
978 | # After IISRESET #
979 | ##########################################
980 | function Warmup-SPSite()
981 | {
982 | $Warmup = get-spsite -Limit 1
983 | $warmupurl = $warmup.Url
984 |
985 | Update-WizardProgress "Warming up site $warmupurl after IISRESET"
986 | Write-Host "Warming up site $warmupurl after IISRESET"
987 |
988 | $WarmItUp = Invoke-WebRequest -Uri $warmupurl -UseDefaultCredentials
989 | }
990 |
991 | #endregion
992 |
993 | ######################################################################
994 | # mainflow #
995 | # Main program execution flow #
996 | ######################################################################
997 | function mainflow()
998 | {
999 |
1000 | $spsite= ""
1001 | $spoappid="00000003-0000-0ff1-ce00-000000000000"
1002 | $Update = ""
1003 | $wizstatus=$true
1004 | $wizstatusmsg = ""
1005 | #############################################################
1006 | # CHECK IF CURRENT USER IS A LOCAL ADMIN ON ALL FARM SERVERS#
1007 | # REQUIRED #
1008 | #############################################################
1009 |
1010 | $Isboxadmin = Check-IsLocalAdmin
1011 |
1012 | If($Isboxadmin -eq $false)
1013 | {
1014 | Update-WizardProgress "Is User Local Admin returns FALSE"
1015 | Show-MessageBox "You are not logged in as a Local Machine administrator account.`nPlease ensure you are logged in with an account that has local machine admin rights and is a SharePoint Farm Administrator then re-start this wizard`n`nThe Hybrid Wizard will now Exit!`n" -Critical | out-null
1016 | #Show-MessageBox "Wizard will now exit!" | out-null
1017 | $wizstatus=$false
1018 | $wizstatusmsg = "`nLocal Admin Check Failed"
1019 | }
1020 | Else
1021 | {
1022 | Show-MessageBox "Current User is Local Machine Admin`nPlease ensure the user is a local admin on all other farm servers before proceeding" | out-null
1023 | Update-WizardProgress "Is User Local Admin returns TRUE"
1024 | }
1025 |
1026 | ################################################
1027 | #CHECK CURRENT USER IS A MEMBER OF FARM ADMINS.#
1028 | #IF NOT THE DISPLAY LIST OF ADMINS AND EXIT #
1029 | # REQUIRED #
1030 | ################################################
1031 |
1032 | $IsFarmAdmin = Check-FarmAdmin
1033 | if($IsFarmAdmin){}
1034 | else
1035 | {
1036 | $farmadmins = Get-SPfarmAdministrators | ? {$_.Name -notmatch "BUILTIN"}
1037 |
1038 | $listoffarmadmins = ""
1039 | foreach ($farmadmin in $farmadmins)
1040 | {
1041 | $listoffarmadmins = $listoffarmadmins + $farmadmin.Name + "`n"
1042 | }
1043 | Update-WizardProgress "Is User Farm Admin returns FALSE"
1044 | Show-MessageBox "You are not logged in as a farm administrator account. Please login as one of the following accounts and rerun this wizard `n`n$listoffarmadmins" -Critical | out-null
1045 |
1046 | $wizstatus=$false
1047 | $wizstatusmsg = $wizstatusmsg + "`nFarm Admin Check Failed"
1048 | #Show-MessageBox "Wizard will now exit!" | out-null
1049 | #break
1050 | }
1051 | Update-WizardProgress "Is User Farm Admin returns TRUE"
1052 |
1053 | #######################################################
1054 | #VALIDATE ALL REQUIRED SERVICE APPLICATIONS ARE ONLINE#
1055 | #IF NOT THE DISPLAY LIST OF APP STATUSES AND QUIT #
1056 | # REQUIRED #
1057 | #######################################################
1058 |
1059 | $validateserviceapps = Validate-ServiceApps
1060 |
1061 | Update-WizardProgress $validateserviceapps[1]
1062 | if($validateserviceapps[0] -eq 0)
1063 | {
1064 | try
1065 | {
1066 | #$MainForm.Close()
1067 | Update-WizardProgress "Service Application minimum configuration is not setup correctly"
1068 | $wizstatus=$false
1069 | $wizstatusmsg = $wizstatusmsg + "`nService Application Check Failed "
1070 | }
1071 | catch [Exception] { }
1072 | }
1073 | Update-WizardProgress "All Service Application minimum requirements are met"
1074 |
1075 |
1076 | #######################################################
1077 | #CHECK FOR MSOL AND IDCRL INSTALLED #
1078 | #REQUIREMENTs .NET 3.5SP1 .NET 4.5 #
1079 | # REQUIRED #
1080 | #######################################################
1081 | try
1082 | {
1083 | $prepareenv = prepare-environment
1084 | }
1085 | catch
1086 | {
1087 | Update-WizardProgress "Prerequisite Software not met. Exiting Wizard. Please refer to the pre requisites section of the documentation"
1088 | Write-Host "Prerequisite Software not met. Exiting Wizard. Please refer to the pre requisites section of the documentation"
1089 | $wizstatus=$false
1090 | $wizstatusmsg = $wizstatusmsg + "`nPrerequisite Software Check Failed "
1091 |
1092 | #$MainForm.close()
1093 | #[environment]::exit(0)
1094 | #break
1095 | }
1096 |
1097 |
1098 | #######################################################
1099 | # Check if all Required Checks Passed or Failed #
1100 | # #
1101 | #######################################################
1102 |
1103 | if($wizstatus -eq $false)
1104 | {
1105 | Update-WizardProgress $wizstatusmsg
1106 | Write-Host $wizstatusmsg
1107 | Show-MessageBox "Required Checks Failed`n$wizstatusmsg `nThe wizard cannot continue until these errors are remediated" -Critical
1108 |
1109 | $mainform.close()
1110 |
1111 | #[environment]::exit(0)
1112 | pause
1113 | }
1114 |
1115 |
1116 | #######################################################
1117 | #IMPORT MSOL AND IDCRL MODULES #
1118 | #CONNECT TO O365 TENANT #
1119 | #######################################################
1120 |
1121 | $connect = Import-ModulesAndConnect
1122 |
1123 | if ($connect[0] -eq $true) { Update-WizardProgress "continue login success" }
1124 | else { Update-WizardProgress "quit failed login" }
1125 |
1126 | #######################################################
1127 | #VALIDATE MSOLDOMAIN #
1128 | #The $SharePointWeb will match the tenant root site #
1129 | #######################################################
1130 |
1131 | $SharePointWeb = Validate-MSOLDomain
1132 |
1133 | if($SharePointWeb -eq "") { break } #Started seeing some odd WCF errors causing blank Urls and we must stop if this happens
1134 |
1135 | # We can test for clean up here since $SharePointWeb will match the SPN we want to remove (hopefully)
1136 |
1137 | #######################################################
1138 | #REMOVE HYBRID CONFIG if Selected #
1139 | #######################################################
1140 |
1141 | if($checkboxcleanuphybridstatus.checked)
1142 | {
1143 | Remove-HybridConfiguration $SharePointWeb
1144 | Update-WizardProgress "Hybrid Configuration Removed - Exiting Wizard"
1145 | Break
1146 | }
1147 |
1148 | #######################################################
1149 | #MANAGE STS CERTIFICATE #
1150 | #Lot goes on here to set cert for ACS trust and SPN #
1151 | #######################################################
1152 |
1153 | $spoappid="00000003-0000-0ff1-ce00-000000000000"
1154 | $CommonName = $textboxSelfSignedCertCN.Text
1155 | $stscertificate = Manage-STSCertificate $spoappid $SharePointWeb $CommonName
1156 |
1157 | #######################################################
1158 | #WARM UP WEB APP #
1159 | #Hits the first site collection from get-spsite #
1160 | #######################################################
1161 |
1162 | Warmup-spsite
1163 |
1164 | #######################################################
1165 | #CREATE RESULT SOURCE #
1166 | #Uses Certificate Common Name as ResultSource Name #
1167 | #Uses Certificate Common Name as the Query Rule Name #
1168 | #######################################################
1169 |
1170 | New-SCSearchResultSourceAndQueryRule $labelOnPremisesSharePoin.text $labelSPOTenantURL.Text $textboxSelfSignedCertCN.Text $textboxSelfSignedCertCN.Text
1171 |
1172 | Update-WizardProgress "Hybrid wizard setup is completed - Please test to validate success"
1173 |
1174 | $buttonStart.Enabled=$true
1175 | $buttonStart.Text = "Exit Wizard"
1176 | #ALL DONE
1177 |
1178 | #GUI
1179 | #Things to Capture
1180 | #LocalCN for SelfSignedCert
1181 | #Use New SelfSigned STS Cert or Use Existing STS Cert or public
1182 | #On Premises Site Url
1183 | #SPO Url of Tenant
1184 | #Check for Farm Account and Local Admin or prompt for admin creds
1185 | }
1186 |
1187 | #region Generate Wizard Form
1188 |
1189 | Add-Type -AssemblyName System.Windows.Forms
1190 |
1191 | #region Generated Form Objects
1192 | #----------------------------------------------
1193 | [System.Windows.Forms.Application]::EnableVisualStyles()
1194 | $MainForm = New-Object 'System.Windows.Forms.Form'
1195 | $groupbox1 = New-Object 'System.Windows.Forms.GroupBox'
1196 | $radiobuttonUsePublicAuthoritySi = New-Object 'System.Windows.Forms.RadioButton'
1197 | $radiobuttonUseNewSelfSignedSTSC = New-Object 'System.Windows.Forms.RadioButton'
1198 | $radiobuttonUseBuiltInSharePoint = New-Object 'System.Windows.Forms.RadioButton'
1199 | $labelOnPremisesSharePoint = New-Object 'System.Windows.Forms.Label'
1200 | $labelSPOTenantURLegHttpsw = New-Object 'System.Windows.Forms.Label'
1201 | $labelSPOTenantURL = New-Object 'System.Windows.Forms.Label'
1202 | $labelOnPremisesSharePoin = New-Object 'System.Windows.Forms.Label'
1203 | $textboxSelfSignedCertCN = New-Object 'System.Windows.Forms.TextBox'
1204 | $textboxPubAuthSignedCertCN = New-Object 'System.Windows.Forms.TextBox'
1205 | $labelHybridConfigurationW = New-Object 'System.Windows.Forms.Label'
1206 | $buttonStart = New-Object 'System.Windows.Forms.Button'
1207 | $InitialFormWindowState = New-Object 'System.Windows.Forms.FormWindowState'
1208 | $textboxWizardProgress = New-Object 'System.Windows.Forms.TextBox'
1209 | $checkboxcleanuphybridstatus = new-object 'System.Windows.Forms.CheckBox'
1210 | $labelcleanuphybridstatus = new-object 'System.Windows.Forms.Label'
1211 | $labelcontactinfo = new-object 'System.Windows.Forms.Label'
1212 |
1213 | #endregion Generated Form Objects
1214 |
1215 | #----------------------------------------------
1216 | # User Generated Script
1217 | #----------------------------------------------
1218 |
1219 | $OnLoadFormEvent={
1220 | #TODO: Initialize Form Controls here
1221 | $MainForm.Focused
1222 | }
1223 |
1224 | $Form_FormClosing={
1225 | # Capture form closing event ie user clicked red X. Prompt for validation and cancel event if user has exietd by mistake
1226 |
1227 | If ($wizstatus -eq $false)
1228 | {
1229 | #Pre requisites failed so kill form
1230 | [environment]::exit(0)
1231 | }
1232 |
1233 | $closeme = Show-MessageBox "Do you want to close down the Wizard?" -YesNo
1234 |
1235 | If ($closeme -eq "Yes") {}
1236 | Else
1237 | {
1238 | $_.Cancel = $true # $_.Cancel actually cancels the FormClosing Event and so FormClosed never fires
1239 | Show-MessageBox "Carry on regardless"
1240 | }
1241 | }
1242 |
1243 | $buttonStart_Click={
1244 | #$buttonStart.Text = "Exit Wizard" #debug
1245 |
1246 | if($buttonStart.Text -eq "Exit Wizard")
1247 | {
1248 | $MainForm.close()
1249 | [environment]::exit(0)
1250 | break
1251 | }
1252 |
1253 | $buttonStart.Text = "Running"
1254 | $buttonStart.Enabled=$false
1255 | mainflow
1256 | }
1257 |
1258 | $buttonStart_MouseHover={
1259 | $buttonStart.BackColor = 'Blue'
1260 | }
1261 |
1262 | $Form_StateCorrection_Load=
1263 | {
1264 | #Correct the initial state of the form to prevent the .Net maximized form issue
1265 | $MainForm.WindowState = $InitialFormWindowState
1266 | }
1267 |
1268 | $Form_StoreValues_Closing=
1269 | {
1270 | #Store the control values
1271 | $script:MainForm_radiobuttonUsePublicAuthoritySi = $radiobuttonUsePublicAuthoritySi.Checked
1272 | $script:MainForm_radiobuttonUseNewSelfSignedSTSC = $radiobuttonUseNewSelfSignedSTSC.Checked
1273 | $script:MainForm_radiobuttonUseBuiltInSharePoint = $radiobuttonUseBuiltInSharePoint.Checked
1274 | $script:MainForm_textbox1 = $textbox1.Text
1275 | }
1276 |
1277 | $Form_Cleanup_FormClosed=
1278 | {
1279 | #Remove all event handlers from the controls
1280 | try
1281 | {
1282 | $radiobuttonUseBuiltInSharePoint.remove_CheckedChanged($radiobuttonUseBuiltInSharePoint_CheckedChanged)
1283 | $labelSPOTenantURLegHttpsw.remove_Click($labelSPOTenantURLegHttpsw_Click)
1284 | $buttonStart.remove_Click($buttonStart_Click)
1285 | $MainForm.remove_Load($OnLoadFormEvent)
1286 | $MainForm.remove_Load($Form_StateCorrection_Load)
1287 | $MainForm.remove_Closing($Form_StoreValues_Closing)
1288 | $MainForm.remove_FormClosed($Form_Cleanup_FormClosed)
1289 | }
1290 | catch [Exception]
1291 | { }
1292 | }
1293 |
1294 | #region Generated Form Code
1295 | #----------------------------------------------
1296 | $MainForm.SuspendLayout()
1297 | $groupbox1.SuspendLayout()
1298 | #
1299 | #region MainForm
1300 | #
1301 | $MainForm.Controls.Add($groupbox1)
1302 | $MainForm.Controls.Add($labelOnPremisesSharePoint)
1303 | $MainForm.Controls.Add($labelSPOTenantURLegHttpsw)
1304 | $MainForm.Controls.Add($labelSPOTenantURL)
1305 | $MainForm.Controls.Add($labelOnPremisesSharePoin)
1306 | $MainForm.Controls.Add($labelHybridConfigurationW)
1307 | $MainForm.Controls.Add($buttonStart)
1308 | $MainForm.Controls.Add($textboxWizardProgress)
1309 | $MainForm.Controls.Add($checkboxcleanuphybridstatus)
1310 | $MainForm.Controls.Add($labelcleanuphybridstatus)
1311 | $Mainform.Controls.Add($labelcontactinfo)
1312 | $MainForm.Name = "MainForm"
1313 | $MainForm.StartPosition = 'CenterScreen'
1314 | $MainForm.Text = "Hybrid Configuration Wizard" + $HWVersion
1315 | $MainForm.add_Load($OnLoadFormEvent)
1316 | $MainForm.Size = "650,650"
1317 | #
1318 | #endregion Mainform
1319 |
1320 | #region groupbox1
1321 | #
1322 | $groupbox1.Controls.Add($radiobuttonUsePublicAuthoritySi)
1323 | $groupbox1.Controls.Add($radiobuttonUseNewSelfSignedSTSC)
1324 | $groupbox1.Controls.Add($radiobuttonUseBuiltInSharePoint)
1325 | $groupbox1.Controls.Add($textboxSelfSignedCertCN)
1326 | $groupbox1.Controls.Add($textboxPubAuthSignedCertCN)
1327 | $groupbox1.Location = '13, 193'
1328 | $groupbox1.Name = "groupbox1"
1329 | $groupbox1.Size = '538, 138'
1330 | $groupbox1.TabIndex = 6
1331 | $groupbox1.TabStop = $False
1332 | $groupbox1.Text = "STS Certificate Replacement"
1333 | #
1334 | # radiobuttonUsePublicAuthoritySi
1335 | #
1336 | $radiobuttonUsePublicAuthoritySi.Font = "Microsoft Sans Serif, 8pt"
1337 | $radiobuttonUsePublicAuthoritySi.Location = '15, 87'
1338 | $radiobuttonUsePublicAuthoritySi.Name = "radiobuttonUsePublicAuthoritySi"
1339 | $radiobuttonUsePublicAuthoritySi.Size = '270, 24'
1340 | $radiobuttonUsePublicAuthoritySi.TabIndex = 5
1341 | $radiobuttonUsePublicAuthoritySi.TabStop = $True
1342 | $radiobuttonUsePublicAuthoritySi.Text = "Use Public Authority Signed STS Cert"
1343 | $radiobuttonUsePublicAuthoritySi.UseVisualStyleBackColor = $True
1344 | $radiobuttonUsePublicAuthoritySi.Enabled = $False
1345 | #
1346 | # radiobuttonUseNewSelfSignedSTSC
1347 | #
1348 | $radiobuttonUseNewSelfSignedSTSC.Font = "Microsoft Sans Serif, 8pt"
1349 | $radiobuttonUseNewSelfSignedSTSC.Location = '15, 56'
1350 | $radiobuttonUseNewSelfSignedSTSC.Name = "radiobuttonUseNewSelfSignedSTSC"
1351 | $radiobuttonUseNewSelfSignedSTSC.Size = '270, 24'
1352 | $radiobuttonUseNewSelfSignedSTSC.TabIndex = 4
1353 | $radiobuttonUseNewSelfSignedSTSC.TabStop = $True
1354 | $radiobuttonUseNewSelfSignedSTSC.Text = "Use New Self Signed STS Cert"
1355 | $radiobuttonUseNewSelfSignedSTSC.UseVisualStyleBackColor = $True
1356 | $radiobuttonUseNewSelfSignedSTSC.Checked = $True
1357 | #
1358 | # radiobuttonUseBuiltInSharePoint
1359 | #
1360 | $radiobuttonUseBuiltInSharePoint.Font = "Microsoft Sans Serif, 8pt"
1361 | $radiobuttonUseBuiltInSharePoint.Location = '15, 26'
1362 | $radiobuttonUseBuiltInSharePoint.Name = "radiobuttonUseBuiltInSharePoint"
1363 | $radiobuttonUseBuiltInSharePoint.Size = '270, 24'
1364 | $radiobuttonUseBuiltInSharePoint.TabIndex = 3
1365 | $radiobuttonUseBuiltInSharePoint.TabStop = $True
1366 | $radiobuttonUseBuiltInSharePoint.Text = "Use Built In SharePoint STS Cert"
1367 | $radiobuttonUseBuiltInSharePoint.UseVisualStyleBackColor = $True
1368 | $radiobuttonUseBuiltInSharePoint.add_CheckedChanged($radiobuttonUseBuiltInSharePoint_CheckedChanged)
1369 | #
1370 | # textboxNewSelfSignedCertCN
1371 | #
1372 | $textboxSelfSignedCertCN.Font = "Microsoft Sans Serif, 8pt"
1373 | $textboxSelfSignedCertCN.Location = '300, 56'
1374 | $textboxSelfSignedCertCN.Name = "textboxSelfSignedCertCN"
1375 | $textboxSelfSignedCertCN.Size = '200, 20'
1376 | $textboxSelfSignedCertCN.TabIndex = 8
1377 | $textboxSelfSignedCertCN.Text = "HybridWizard"
1378 | #
1379 | # textboxPubAuthSignedCertCN
1380 | #
1381 | $textboxPubAuthSignedCertCN.Font = "Microsoft Sans Serif, 8pt"
1382 | $textboxPubAuthSignedCertCN.Location = '300, 87'
1383 | $textboxPubAuthSignedCertCN.Name = "textboxPubAuthSignedCertCN"
1384 | $textboxPubAuthSignedCertCN.Size = '200, 20'
1385 | $textboxPubAuthSignedCertCN.TabIndex = 7
1386 | $textboxPubAuthSignedCertCN.Text = "Coming Soon"
1387 | $textboxPubAuthSignedCertCN.Enabled = $False
1388 | #
1389 | # labelOnPremisesSharePoint
1390 | #
1391 | $labelOnPremisesSharePoint.Font = "Microsoft Sans Serif, 8pt"
1392 | $labelOnPremisesSharePoint.Location = '12, 136'
1393 | $labelOnPremisesSharePoint.Name = "labelOnPremisesSharePoint"
1394 | $labelOnPremisesSharePoint.Size = '228, 38'
1395 | $labelOnPremisesSharePoint.TabIndex = 5
1396 | $labelOnPremisesSharePoint.Text = "On Premises SharePoint Url"
1397 | #
1398 | # labelSPOTenantURLegHttpsw
1399 | #
1400 | $labelSPOTenantURLegHttpsw.Font = "Microsoft Sans Serif, 8pt"
1401 | $labelSPOTenantURLegHttpsw.Location = '12, 95'
1402 | $labelSPOTenantURLegHttpsw.Name = "labelSPOTenantURLegHttpsw"
1403 | $labelSPOTenantURLegHttpsw.Size = '228, 38'
1404 | $labelSPOTenantURLegHttpsw.TabIndex = 4
1405 | $labelSPOTenantURLegHttpsw.Text = "SPO Tenant URL"
1406 | #$labelSPOTenantURLegHttpsw.add_Click($labelSPOTenantURLegHttpsw_Click)
1407 | #
1408 | # labelSPOTenantURL
1409 | #
1410 | $labelSPOTenantURL.Font = "Microsoft Sans Serif, 8pt"
1411 | $labelSPOTenantURL.Location = '246, 95'
1412 | $labelSPOTenantURL.Name = "labelSPOTenantURL"
1413 | $labelSPOTenantURL.Size = '260, 20'
1414 | $labelSPOTenantURL.TabIndex = 3
1415 | $labelSPOTenantURL.Text = "Not Connected Yet"
1416 | #
1417 | # labelOnPremisesSharePoin
1418 | #
1419 | $labelOnPremisesSharePoin.Font = "Microsoft Sans Serif, 8pt"
1420 | $labelOnPremisesSharePoin.Location = '246, 130'
1421 | $labelOnPremisesSharePoin.Name = "labelOnPremisesSharePoin"
1422 | $labelOnPremisesSharePoin.Size = '260, 20'
1423 | $labelOnPremisesSharePoin.TabIndex = 6
1424 | $labelOnPremisesSharePoin.Text = "Not Connected Yet"
1425 | #
1426 | # labelHybridConfigurationW
1427 | #
1428 | $labelHybridConfigurationW.Font = "Microsoft Sans Serif, 15.75pt"
1429 | $labelHybridConfigurationW.Location = '12, 9'
1430 | $labelHybridConfigurationW.Name = "labelHybridConfigurationW"
1431 | $labelHybridConfigurationW.Size = '543, 58'
1432 | $labelHybridConfigurationW.TabIndex = 2
1433 | $labelHybridConfigurationW.Text = "Hybrid Configuration Wizard"
1434 | $labelHybridConfigurationW.TextAlign = 'MiddleCenter'
1435 | #
1436 | # labelcleanuphybridstatus
1437 | #
1438 | $labelcleanuphybridstatus.Font = "Microsoft Sans Serif, 8pt"
1439 | $labelcleanuphybridstatus.ForeColor = "Red"
1440 | $labelcleanuphybridstatus.Location = '60,350'
1441 | $labelcleanuphybridstatus.Size = '500,58'
1442 | $labelcleanuphybridstatus.TabIndex = 10
1443 | $labelcleanuphybridstatus.Text = "Select this box to Cleanup Existing Hybrid Config (Coming Soon)"
1444 | #$labelcleanuphybridstatus.TextAlign = 'Left'
1445 | # $labelcleanuphybridstatus.Enabled = $false
1446 | #
1447 | # checkboxcleanuphybridstatus
1448 | $checkboxcleanuphybridstatus.Font = "Microsoft Sans Serif, 8pt"
1449 | $checkboxcleanuphybridstatus.Location = '30,350'
1450 | #
1451 | $checkboxcleanuphybridstatus.Size = '20,20'
1452 | $checkboxcleanuphybridstatus.TabIndex = 10
1453 | $checkboxcleanuphybridstatus.Enabled = $false
1454 | #
1455 | # textboxWizardProgress
1456 | #
1457 | $textboxWizardProgress.Font = "Microsoft Sans Serif, 8pt"
1458 | $textboxWizardProgress.Location = '13, 390'
1459 | $textboxWizardProgress.Name = "textboxWizardProgress"
1460 | $textboxWizardProgress.Size = '543, 150'
1461 | $textboxWizardProgress.TabIndex = 2
1462 | $textboxWizardProgress.Text = "Hybrid Configuration Wizard Progress`r`n"
1463 | $textboxWizardProgress.TextAlign = 'Left'
1464 | $textboxWizardProgress.Multiline = $true
1465 | $textboxWizardProgress.ScrollBars = "Vertical"
1466 | $textboxWizardProgress.AcceptsReturn = "true"
1467 | $textboxWizardProgress.WordWrap = "true"
1468 | $textboxWizardProgress.AutoScrollOffset = 1
1469 | #
1470 | # buttonStart
1471 | #
1472 | $buttonStart.Location = '268, 550'
1473 | $buttonStart.Name = "buttonStart"
1474 | $buttonStart.Size = '75, 20'
1475 | $buttonStart.TabIndex = 0
1476 | $buttonStart.Text = "Start"
1477 | $buttonStart.UseVisualStyleBackColor = $True
1478 | $buttonStart.add_Click($buttonStart_Click)
1479 | $buttonStart.Cursor = "Hand"
1480 | $groupbox1.ResumeLayout()
1481 | $MainForm.ResumeLayout()
1482 |
1483 | #
1484 | #Contact Info
1485 | #
1486 | $labelcontactinfo
1487 | $labelcontactinfo.Font = "Microsoft Sans Serif, 10pt"
1488 | $labelcontactinfo.ForeColor = "Red"
1489 | $labelcontactinfo.Location = '20,580'
1490 | $labelcontactinfo.Size = '500,58'
1491 | $labelcontactinfo.TabIndex = 12
1492 | $labelcontactinfo.Text = "Send feedback via the comments on the blog at (https://blogs.msdn.com/spses)"
1493 |
1494 |
1495 | #Save the initial state of the form
1496 | $InitialFormWindowState = $MainForm.WindowState
1497 | #Init the OnLoad event to correct the initial state of the form
1498 | $MainForm.add_Load($Form_StateCorrection_Load)
1499 | #Clean up the control events
1500 | $MainForm.add_FormClosed($Form_Cleanup_FormClosed)
1501 | #Store the control values when form is closing
1502 | $MainForm.add_Closing($Form_FormClosing)
1503 | #Show the Form
1504 | return $MainForm.ShowDialog()
1505 | #endregion Generated Form Code
1506 | #endregion Generate Wizard Form
--------------------------------------------------------------------------------