Archive

Posts Tagged ‘Powershell’

SharePoint 2010: Adding SAML Claim permission for All Authenticated Users using PowerShell.

February 1, 2017 Leave a comment

I recently had to convert one of my SharePoint 2010 Web Applications from using Windows Claims/NTLM to use SAML Claims, removing the need for NTLM authentication by using a Claims Provider (ADFS) for authentication. When doing so permissions on the SALM Claims Web Application broke because it was still leveraging the Windows Claims Permissions. Since the NTLM permission was removed at the Web Application level, and to meet the DISA STIG requirement Anonymous Access permissions were also removed; this in return restricted access to users who used to have “read” rights to the Portal. To fix this problem I had to grant the “read” permissions for the SAML Claims ‘All Authenticated Users’ to all Site Collections / Sites so these users can once again gain access. Below is how I accomplished this using PowerShell.

————————————————————————–

$webApp = Get-SPWebApplication "[WEB APPLICATION URL]"
$sts = Get-SPTrustedIdentityTokenIssuer "[CLAIMS PROVIDER TOKEN ISSUER NAME]"

$PermLevels = @{}

"URL `t" + "userName `t" + "userLogin `t" + "userEmail `t" + "permissionLevel `t" + "SAMLClaim" >> User_Permissions_AllAuthenticatedUsers.csv

foreach ($web in $webApp | Get-SPSite -Limit All | Get-SPWeb -Limit All)
{

	foreach ($role in $web.Roles)
	{
		$permmask = $role.PermissionMask
		$permname = $role.Name
		$PermLevels.Add("$permmask", "$permname")
		trap [Exception] {continue}
	}
	foreach ($perm in $web.Permissions)
	{
		$permmaskcurrent = $perm.PermissionMask
		$level = $PermLevels.Get_Item("$permmaskcurrent")

		if ($perm.Member.Name -like "*All Authenticated Users*")
		{
				#CLAIM PRINCIPAL FOR ROLE
				$claimPrincipal = New-SPClaimsPrincipal -ClaimValue $perm.Member.Name -ClaimType "http://schemas.microsoft.com/ws/2008/06/identity/claims/role" -TrustedIdentityTokenIssuer $sts
				
				
				$newUser = New-SPUser -UserAlias $claimPrincipal.ToEncodedString() -Web $web

				$account = $web.EnsureUser($newUser)
			
				if ($level -eq "Limited Access")
				{
					$level = "Read"
					$role = $web.RoleDefinitions[$level]
					$assignment = New-Object Microsoft.SharePoint.SPRoleAssignment($account)
					$assignment.RoleDefinitionBindings.Add($role)
					$web.RoleAssignments.Add($assignment)
				}
				else
				{
					$role = $web.RoleDefinitions[$level]
					$assignment = New-Object Microsoft.SharePoint.SPRoleAssignment($account)
					$assignment.RoleDefinitionBindings.Add($role)
					$web.RoleAssignments.Add($assignment)
				}
				
				$web.Url + "`t" + $perm.Member.Name + "`t" + $perm.Member.UserLogin + "`t" + $perm.Member.Email + "`t" + $level + "`t" + $account >> User_Permissions_AllAuthenticatedUsers.csv

		}
	}
}

————————————————————————–

The above script loops through all the Site Collections and Sites to search for the Windows Claim for ‘All Authenticated Users’ once it finds an instance where the ‘All Authenticated Users’ permissions is used it adds the SAML Claim for ‘All Authenticated Users’

This script does not clean up/remove the old Windows Claims permission for the ‘All Authenticated Users’ I did that just incase the Web Application needs to be extended to once again support Windows Claims/NTLM authentication.

I will later blog about how to add the ‘All Authenticated Users’ SAML Claim to Groups, and also how to add indivdual SAML Claim permissions to users by granting their SAML Token for email.

Hopefully this is helpful for those that are struggling to reprovision their Windows Claims permissions to SAML Claims.

SharePoint 2010: Enable (Page) Output Cache Settings using PowerShell

January 25, 2017 Leave a comment

To optimize performance in SharePoint 2010, there are a few settings you can do to help with page load times and optimizing SharePoint Cache.

The three main ways to do this is:

1. BLOB Cache
2. Object Cache
3. Page Output Cache

In my environment we are not leveraging BLOB cache, and Object Cache is already enabled by default. Though you can optimize it for your SP environment.

However the Page Output Cache is not enabled by default.

Below is a PowerShell script I created that enables the Page Output Cache at the Site Collection Level for a Web Application.

$webapp = Get-SPWebApplication [URL OF WEB APPLICATION]

foreach ($web in $webapp.Sites)
{
$cacheSettings = New-Object Microsoft.SharePoint.Publishing.SiteCacheSettingsWriter($web.url)
$cacheSettings.EnableCache = $true
$cacheSettings.Update();
Write-Host “Updated Page Output Cache Settings…” $web.Url
}

Options:

#Default Page Output Cache Profile. The Cache Profile Id is built off the Cache Profile List (Site Actions – Site Settings – Site Collection Cache Profiles (under Site Collection Administration))

SetAnonymousPageCacheProfileId($web.Url, 1)
SetAuthenticatedPageCacheProfileId($web.Url, 2);

#Page Output Cache Policy
$cacheSettings.AllowPublishingWebPageOverrides = $true;
$cacheSettings.AllowLayoutPageOverrides = $true;
$cacheSettings.EnableDebuggingOutput = $true;

SharePoint 2010: Getting SharePoint Claims Web Applications to Work With None-Claims Aware Applications / Services

February 19, 2016 Leave a comment

I recently ran into an issue with an in house solution that was developed in Visual Studio leveraging .NET and C# which made SOAP Web Service calls to SharePoint to populate form data from SharePoint lists.  This solution worked fine in my SharePoint 2007 environment that utilized Classic Authentication.  However after upgrading to SharePoint 2010 and switching the authentication type to Claims broke the ability for the solution to make successful SOAP Web Service calls to SharePoint.

So instead of me having to completely reengineer the in-house solution to be claims aware I took a different approach.

For me to successfully get this to work I had to do a few things.

ONE
1.  Extend the Claims Web Application to a new zone (intranet) that used Integrated  Windows Authentication (NTLM).  Give the Web Application a new name.  I used (SharePoint – Portal_NTLM)

Since extending the Web Application will keep the same Authentication mode of Claims as of the default primary Web Application I still had a little bit of work left to do.  I had to essentially “trick” the extended Web Application to think it was using Classic Authentication instead of Claims.

Since extending the Web Application creates a new web.config file I had to modify this file on each WFE Server for the new extended web app.  This is usually found in c:\inetpub\wwwroot\wss\VirtualDirectories\Extended Web Application

Open up the Web.Config File and search for the following lines
<add key=”aspnet:AllowAnonymousImpersonation” value=”true” />
Change to
<add key=”aspent:AllowAnonymousImpersonation” value=”false” />

Search for the following lines:
<authentication mode=”Forms”>
Change to
<authentication mode=”Windows”>

Make the changes to all web.config files and save.

TWO
Since the Default Web Application leveraged CLAIMS with Kerberos Authentication, and the Extended Web Application leveraged CLAIMS (hacked “Windows” in web.config) and NTLM Authentication the service account that ran the Application Pool for the Default Web Application did not have the necessary rights to call SOAP Web Services from within the in-house solution.  If I were to change the  Pass-Through Authentication in IIS for the Extended Site to use the “Connect As” and manually enter in the Farm Account and Password the in-house solution executed successfully, but I ran into another issue with NINTEX Workflows.  Since changing the Pass-Through Authentication to use “Connect As” it was using the Farm Account which when authenticating to SharePoint was signing in as the “System Account”  which broke the NINTEX Workflows from automatically kicking off because it was expecting a dedicated service account.

Since the Extended Web Application leveraged the same Application Pool as the Default (Main) Web Application I had to create a new Application Pool which used the Farm Account as the Identity.

For me to create a new Application Pool I had to do a few things.

I leveraged PowerShell to create a new Application Pool and associated that new Application Pool with the new extended web application:

Below is the PowerShell to create a new Application Pool and associate it with the extended Web Application.

Before you execute this PowerShell script make sure you write down the name of the original Web Application Pool name for the Default (Main) Web Application. *This will be important later*

————————————————————–

$WebAppURL = http://portal/extendedwebapp
$NewAppPoolName = “SharePoint – Portal_NTLM”
$NewAppPoolUserName = “DOMAIN\FarmAccount”

$Farm = Get-SPFarm
$Service = $Farm.Services | where {$_.TypeName -eq “Microsoft SharePoint Foundation Web Application”}
$Password = Read-Host -Prompt “Please enter your password” -AsSecureString
$NewAppPool = New-Object Microsoft.SharePoint.Administration.SPApplicationPool($NewAppPoolName,$Service)
$NewAppPool.CurrentIdentityType = “SpecificUser”
$NewAppPool.Username = $NewAppPoolUserName
$NewAppPool.SetPassword($Password)
$NewAppPool.Provision()
$NewAppPool.Update($true)

$NewAppPool = $Service.ApplicationPools[$NewAppPoolName]
$WebApp = Get-SPWebApplication $WebAppURL
$WebApp.ApplicationPool = $NewAppPool
$WebApp.ProvisionGlobally()
$WebApp.Update()

————————————————————–

After associating the new Extended Web Application to the new Application Pool I ran into one other problem.  Since the Extended Web Application shares the same Application Pool with the default (Main) Web Application, when doing this  it also re-associate the default (Main) Web Application with the new Application Pool.  Remember the note I mentioned up above “Before you execute this PowerShell script make sure you write down the name of the original Web Application Pool name for the Default (Main) Web Application. *This will be important later*”.   There is where this will now come into handy.  If your default (Main) Web Application utilizes Kerberos Authentication and the App Pool User Identity is different then that of the new Application Pool Identity you will run into problems.

To fix this problem you have to re-associate the default (Main) Web Application with its original App Pool.   To do this you basically run the same PowerShell script above minus the creation of the new Application Pool as follows:

————————————————————–
$Farm = Get-SPFarm
$Service = $Farm.Services | where {$_.TypeName -eq “Microsoft SharePoint Foundation Web Application”}
$NewAppPool = $Service.ApplicationPools[NAME OF DEFAULT APPLICATION POOL]
$WebApp = Get-SPWebApplication “URL OF THE DEFAULT WEB APPLICATON”
$WebApp.ApplicationPool = $NewAppPool
$WebApp.ProvisionGlobally()
$WebApp.Update()

————————————————————–

Now after running this script you will run into one last problem.  As mentioned above since the Extended Web Application shares the same Web Application Pool as the Default (Main) Web Application the Application Pool will again change for the Extended Web Application to use the Web Application Pool of the Default (Main) Web Application.  This is because the schema for the Web Application’s Application Pool lives within the ConfigDB.

If you execute the following two PowerShell lines below you will see which Web Applications are associated with which Web Application Pools:

$Farm = Get-SPFarm
$Service = $Farm.Services | where {$_.TypeName -eq “Microsoft SharePoint Foundation Web Application”}
$Service

You will notice that both the Default (Main) and the Extended Web Application are associated with the same Application Pool in the Config Database.  There is no way around associating the Extended Web Application to a new Application Pool and keeping the Default (Main) Web Application the same in the ConfigDB.  So you have to basically tell IIS to use a different Web Application Pool which basically bypasses what is associated in the ConfigDB.

Since now that there is a new Application Pool in IIS, you can now then manually re-associate the Extended Web Application Site to that new Web Application Pool.  This can only be done in IIS.  If you were to run the same two PowerShell scripts above you will still see the Extended Web Application is associated with the Default (Main) Web Application Pool, but will be assigned the new one in IIS.

Now the only problem with this is if you ever have to do any configuration of the Extended Web Application that might cause the reset of the Application Pool in IIS you have to again manually go back into IIS and re-associate the right Application pool to the Extended Web Application.

This was the way I was able to get an Extended Web Application to use Classic Authentication with NTLM from a Claims Authentication with Kerberos Web Application.

SharePoint 2010: Get List of All Relative and Absolute URL’s in a Web Application using PowerShell

December 23, 2015 Leave a comment

In the process of configuring SharePoint 2010 to use ADFS Authentication I needed to extend the Web Application so that our external partners who are federated can access the portal with ADFS claims in a different zone, while our internal / non-federated users can still access the portal using Windows Auth with Kerberos.  When doing this you have to make sure there are no Absolute URL’s that might break the user experience.  Below is a PowerShell script I generated to search a Web Application for Relative and Absolute URLs so clean up can be performed before switching over to ADFS.

#GET WEB APPLICATION
$webApp = Get-SPWebApplication https://portal.com

#URL SEARCH STRING FOR ABSOLUTE URL
$searchURL = “*http*”

#CREATE .CSV FILE WITH HEADINGS FOR HYPERLINKS
“siteURL `t” + “Heading `t” + “hyperlink `t” + “Path” >> HYPERLINKS.csv

#FOREACH LOOP – LOOPS THROUGH ALL WEBS AND SUBSITES OF WEB APPLICATION
foreach ($web in $webApp | Get-SPSite -Limit All | Get-SPWeb -Limit All)

{
#GET PUBLISHING WEB FOR ALL WEBS IN WEB APPLICATION

$pubWeb = [Microsoft.SharePoint.Publishing.PublishingWeb]::GetPublishingWeb($web)
#GET GLOBAL NAVIGATION NODES
$nav = $pubWeb.Navigation.GlobalNavigationNodes
#GET QUICK LAUNCH NAVIGATION NODES

$nodes = $web.Navigation.QuickLaunch

#FOREACH LOOP – LOOPS THROUGH ALL GLOBAL NAVIGATION HEADINGS.
foreach ($qlHeading in $nav)

{
#GET GLOBAL NAVIGATION HEADING CHILDREN.

$qlLibraries = $qlHeading.Children

#FOREACH LOOP – LOOPS THROUGH ALL CHILDREN (LINKS) IN GLOBAL NAVIGATION HEADINGS.
foreach ($lib in $qlLibraries)

{
#IF STATEMENT TO CHECK IF HYPERLINK IS NOT NULL.

if ($lib.Url -ne $null)
{
write-host $qlHeading.Title
write-host $lib.Url
#IF STATEMENT TO CHECK HYPERLINK TO SEE IF IT MATCHES searchURL string.
if ($lib.Url -like $searchURL)

{
#IF HYPERLINK MATCHES THE $searchURL STRING THEN STORE “AbsoluteURL” STRING IN $path VARIABLE.

$path = “AbsoluteURL”
}
else
#IF HYPERLINK DOES NOT MATCH THE $searchURL  STRING THEN STORE “RelativeURL” STRING IN $path VARIABLE.

{
$path = “RelativeURL”
}
#WRITE GLOBAL NAVIGATION NODE RESULTS TO HYPERLINKS.csv FILE.

$web.Url + “`t” + $qlHeading.Title + “`t” + $lib.Url + “`t” + $path >> HYPERLINKS.csv
}
}
}
#FOREACH LOOP – LOOPS THROUGH ALL QUICK LAUNCH NAVIGATION NODES

foreach ($node in $nodes)
{
write-host $node.Title
write-host $node.Url
#IF STATEMENT TO CHECK HYPERLINK TO SEE IF IT MATCHES searchURL string.
if ($node.Url -like $searchURL)
{
#IF HYPERLINK MATCHES THE $searchURL STRING THEN STORE “AbsoluteURL” STRING IN $path VARIABLE.

$path = “AbsoluteURL”
}
else
{
#IF HYPERLINK DOES NOT MATCH THE $searchURL  STRING THEN STORE “RelativeURL” STRING IN $path VARIABLE.

$path = “RelativeURL”
}
#WRITE QUICK LAUNCH NAVIGATION NODE RESULTS TO HYPERLINKS.csv FILE.

$web.Url + “`t” + $qlHeading.Title + “`t” + $lib.Url + “`t” + $path >> HYPERLINKS.csv
}
}

Query SharePoint 2010 HTTPRequest Pages for JQuery References Utilizing PowerShell

September 23, 2015 Leave a comment

I had a request from a customer who needed me to do a HTTP inline search query on a specific web application for all references of JQuery that was being utilized on all Site Collections and Sites within that Web Application.  Since the Web Application had over 1300 sites I needed to turn to PowerShell to iterate through all Sites, stream through the HTTPRequst pages and generate separate reports where JQuery references were found.

Below is how I accomplished this task using Powershell

————————————————————————————
Add-PSSnappin “Microsoft.SharePoint.PowerShell” -ErrorAction SilentlyContinue

$WebApp = Get-SPWebApplication(“URL OF WEB APPLICATION“)

$results = “PATH TO STORE HTTPRequest PAGE STREAMS
$JQueryResults = “PATH TO STORE JQUERY RESULTS FROM PAGE STREAMS

foreach ($site in $WebApp.Sites)
{
foreach ($web in $site.AllWebs)
{
[net.httpWebRequest] $request = [net.WebRequest]::create($web.Url)
$request.TimeOut = 600000
$request.UseDefaultCredentials = $true
[net.httpWebResponse] $response = $request.getResponse()
$responseURI = $response.ResponseURI
$responseAbsoluteURI = $responseURI.AbsoluteUri
$responseStream = $response.getResponseStream()
$streamReader = New-Object IO.StreamReader($responseStream)

$pathResults = $Results + “results_” + $web.Title + “.txt”
$result = $streamReader.ReadToEnd() >> $pathResults

$find = select-string -Path $pathResults -pattern “Jquery”
$jqueryPath = $JQueryResults + “jqueryresults_” + $web.Title + “.txt”
$web.Title >> $jqueryPath
$responseAbsoluteURI >> jqueryPath
“” >> $jqueryPath
$find  -replace [regex]::Escape($pathResults) >> $jqueryPath
}
}
————————————————————————————

 

 

Query CRM/TMT Database for Disabled Users / Generate Report / Email Utilizing PowerShell

September 22, 2015 Leave a comment

Working for the Department of Defense (DoD) I have the pleasure to work with many technologies that many people don’t.  This would be the case here for CRM/TMT.  I had a weekly request to query the CRM/TMT database to generate a report for all users within TMT whose accounts were disabled so that our CRM / TMT engineer could parse these accounts out.  So instead of manually executing a T-SQL query every week I turned to PowerShell to do all the heavy lifting, and automate the process.  Below is how I accomplish that.

On the SQL server where the TMT/CRM database lives I created a SQL Server Agent Job using PowerShell.

———————————————————————————————————
$Server = “SQL SERVER\INSTANCE
$Database = “CRMTMT_DATABASE
$query = “select b.ava_spidentity, max(a.createdon) lasacessdate from Audit
a inner join SystemUserExtensionBase b on a.ObjectId = b.SystemUserId
inner join systemuserbase c on b.SystemUserId = c.SystemUserId where a.Operation = 4 and c.isDisabled = 0
group by b.ava_spidentity”

$today = Get-Date
$filedate =$today.toString(‘MM-dd-yyyy’)

$extractfile = “PATH OF CRM REPORTS\CRM-DisabledAccounts_” + $filedate + “.csv”

$connectionTemplate = “Data Source={0};Integrated Security=SSPI;Initial Catalog={1};”
$connectionString = [string]::Format($connectionTemplate, $Server, $Database)
$connection = New-Object System.Data.SqlClient.sqlConnection
$connection.ConnectionString = $connectionString

$command = New-Object System.Data.SqlClient.SqlCommand
$command.CommandText = $query
$command.Connection = $connection

$SqlAdapter = New-Object System.Data.SqlClient.SqlDataAdapter
$SqlAdapter.SelectCommand = $command
$DataSet = New-Object System.Data.DataSet
$SqlAdapter.Fill($DataSet)
$connection.Close()

$DataSet.Table[0] | Export-Csv $extractfile

—————————————————————————————————

On the server that will run the Task Scheduler Job and Send the Email via SMTP Services.

Create a new Task Schedule job and create a .ps1 file with the script below

—————————————————————————————————

$CRMDirectory = “\\PATH TO CRM REPORT ON SQL
$getCRMReports = Get-ChildItem $CRMDirectory
$getCRMReports | Copy-Item “\\LOCAL PATH TO COPY CRM REPORT
Get-ChildItem  “\\PATH TO CRM REPORTS ON SQL” | Remove-Item -Force

$directory = “\\LOCAL PATH WHERE CRM REPORTS WHERE COPIED
$GetLatestCRMDisabledList = Get-ChildItem $directory

$attachment = “LOCAL PATH OF CRM REPORTS\” + $GetLastestCRMDisabledList

att1 = New-Object Net.Mail.Attachment($attachment)
$email = New-Object System.Net.Mail.MailMessage
$email.From = “EMAIL OF SENDER
$email.To.Add = “EMAIL TO RECEIVER
$email.Subject = “EMAIL SUBJECT
$email.Body = “EMAIL BODY
$email.Attachments.Add($att1)
$SmtpServer = “IP / NAME OF SMTP SERVER’
$Smtp = New-Object Net.Mail.SmtpClient($smtpServer)
$Smtp.Send($email)

Get-ChildItem “\\LOCAL PATH OF CRM REPORTS” | Remove-Item -force

—————————————————————————————————-

I set the task schedule to run once a week on Thursdays, and call it a day.

Set SQL 2012 DBs to Read Only using PowerShell

September 9, 2015 Leave a comment

I needed to set all my SharePoint 2010 Content DBs to Read-Only within SQL for my DR COOP environment but I did not want to have to go to each DBs Properties-Options-ReadOnly setting since I have quite a few SharePoint Content DBs so I wrote a PowerShell script to help me out.

For those that are interested on how I accomplish this.

—————————————————————–

#Load SQL Server SMO assemblies
[System.Reflection.Assembly]::LoadWithPartialName(‘Microsoft.SqlServer.Smo’) | out-null
#Make Connection to SQL Server/Instance
$sqlServer = New-Object (‘Microsoft.SqlServer.Management.Smo.Server’) “NAME OF SQL SERVER/INSTANCE”
#Grab all user DBs
$dbs = $sqlServer.databases

#Foreach loop to loop through all user dbs attached in SQL
foreach ($db in $dbs)
{
#If statement to search for only user dbs with SPContent as part of its name, and exclude the CA database.  Here you would substitute SPContent for the naming convention of your DBs.
if ($db.Name -like “*SPContent_*” -and $db.Name -notlike “*SPContent_Admin*”)
{
$dbname = $db.Name
$DBObject = $sqlServer.Databases[$dbname]
#Kill all the DBs processes to allow for database alter
Write-Host “Killing $dbname Proccess”
$sqlServer.KillAllProcesses($dbname)
#Set db object to ReadOnly set flag as $false; if you want to revert back set flag to $true (read/write)
Write-Host “Setting $dbname to Read-Only”
$DBObject.DatabaseOptions.ReadOnly = $false
#Alter DB Object
$DBObject.Alter()
}
}
Write-Host “Done’

——————————————————————