Get SharePoint Users and Groups Info

This script uses the SharePoint commands to gather all the users and groups with access to your Central Administration SP site.
It mails the report using SMTP and it will upload the report to a SharePoint site.
This script must be run as a Farm Administrator to get complete results.

It puts it out in a HTML format. It is usefull for those security audits that come up from time to time.
The is adapted from the code I found here which puts out the results in a quasi XML format.
:

#Function to send out email 
function sendMail($emailTo,$outFile) 
{ 
    $smtpServer = "smtp.org" #<-- Your SMTP mail server
    $emailFrom = "$machineName@yourdomain.com"  
    $subject = "$MachineName SharePoint Users Info - $date" 
    $body = "See Attached."  
	
	If ($outFile -eq $null) {
		# no attachement
		$body += $Results
        Send-MailMessage -From $emailFrom -To $emailTo -Subject $subject  -Body $body -SmtpServer $smtpServer 
	}
	Else
	{
		# with $outfile as attachement
        Send-MailMessage -From $emailFrom -To $emailTo -Subject $subject  -Body $body -Attachments $outFile -SmtpServer $smtpServer
    }
} 

function DisplayWeb #-web SPWeb -depth int -parentWeb SPWeb
{
   if($args[0].HasUniquePerm -eq "True")
  {
    $UserAccess = DetermineUserAccess $args[0] ($args[1] + 1)
  }
  

  if($args[0].Webs -ne $Null)
  {
    # RECURSIVELY SEARCH SUBWEBS
    foreach ($spSubWeb in $args[0].Webs)
    {
      $subWeb = DisplayWeb $spSubWeb ($args[1] + 2)
      $spSubWeb.Dispose()
    }
    # END CONTAINED SUBSITES ENTITY
   
  }

  # END SITE ENTITY
  Return $subWeb
}

function DisplayMissingParametersMessage
{
  #Write-Output "You are missing a parameter for 'Site URL'"
  $script:siteURL = Read-Host "Enter Site URL"
}
<#
This report must be run as a Farm Administrator to get complete results.
The report will mail itself to a person or group and upload the report file to a 
SharePoint site. ("http://sharepoint/Shared%20Documents")
:: Usage:
.\SP Security Report.ps1' "http://ServerName:51234" <-- Change the server name as appropriate.


#>
############
# MAIN
############

Add-PsSnapin Microsoft.SharePoint.PowerShell -ErrorAction SilentlyContinue

#IF MISSING PARM FOR SITE URL, ASK FOR INPUT TO FILL
if($args.length -eq 0)
{
  DisplayMissingParametersMessage
}

[string]$siteUrl = $args[0]
[string]$searchScope = $args[1]
[string]$userToFind = $args[2]

#Import-module active*
$server = $env:computername
$date = ( get-date ).ToString('MM-dd-yyyy')
$MachineName = $env:COMPUTERNAME
$u = @()
$rootSite = New-Object Microsoft.SharePoint.SPSite($siteUrl)
$spWebApp = $rootSite.WebApplication

#IF SEARCH SCOPE SPECIFIED FOR SITE, ONLY SEARCH SITE
if($searchScope -eq "-site")
{
  DisplaySiteCollection $rootSite 1
}
#ELSE SEARCH ENTIRE WEB APP
else
{
  #DisplayWebApplication $spWebApp 1
}

# Create Webpage Header
$z = "<!DOCTYPE html PUBLIC `"-//W3C//DTD XHTML 1.0 Strict//EN`"  `"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd`">"
$z = $z + "<html xmlns=`"http://www.w3.org/1999/xhtml`">"
$z = "<head><style>"
$z = $z + "TABLE{border-width: 2px;border-style: solid;border-color: black;border-collapse: collapse;}"
$z = $z + "TH{border-width: 2px;padding: 4px;border-style: solid;border-color: black;background-color:lightblue;text-align:left;font-size:14px}"
$z = $z + "TD{border-width: 1px;padding: 4px;border-style: solid;border-color: black;font-size:12px}"
$z = $z + "</style></head><body>"
$z = $z + "<H4>SharePoint Users Report for $env:COMPUTERNAME Central Admin $date</H4>"
$z = $z + "<table><colgroup><col/><col/><col/><col/><col/><col/><col/></colgroup>"
$z = $z + "<tr><th>Web App</th><th>Web</th><th>Site Collection</th><th>Site User</th><th>SPGroup</th><th>SPGroupMembers</th><th>Local Group</th></tr>"
$MainWebApp = $spWebApp
$MainDisplayWeb = DisplayWeb 
$subSite = @()

ForEach ($site in $SpWebApp){
$MainSiteCollection = @()
$a = $site.Sites 
	forEach ($a1 in $a) {
	$sSite = $a1.ToString().split("=")
		$SubSite = $subSite + $sSite[1]
	$MainSiteCollection = "$MainSiteCollection $sSite <br>"
	}
}

$z = $z + "<tr><td>$MainWebApp</td><td>$MainDisplayWeb</td><td>$MainSiteCollection</td><td></td></tr>"

ForEach ($site in $SubSite){
$siteUser = @()
$u1 = @()
$SPGroups = @()
$MainSPGroupMembers = @()
$rSite = New-Object Microsoft.SharePoint.SPSite($site)
$x = $rSite.rootweb
$x1 = $x.users

ForEach ($i in $x1) { 
$u = $i.UserLogin
$u2 = $u.ToString().split(".")
$u1 = "$u1  $u2 <br>"
$siteUser = "$u1<br>"
 }
foreach($group in $rsite.RootWeb.SiteGroups)
{	
    $b = $group.Name 
    $sGroup = $b.ToString().split(".")
	$SPGroup = $sGroup[0]
	$SPGroups = ($SPGroup)
	$LocalGrp = @()
	$lgn = @()
	$lgm = @()
	$MemberName = @()
	$x1 = @()
	$x = $null
	foreach ($user in $group.Users)
    {    
		$D = $user.UserLogin
			$D1 = $D.ToString().split(".")
			$D2 = $D.ToString().split("\")
			$SPGroupMembers = "$D1"
			$MainSPGroupMembers = ("$MainSPGroupMembers $SPGroupMembers <br>")
		If ($User.IsDomainGroup) {
			$x = $user
			$lgn = $x
			$x1 = $x1 + $x 
			forEach ($x2 in $x1) {
			$Lgm = $Null
			$y = $Null
			$gName = $x2.ToString().split("\")
			$groupName = $gName[1]
			  #BEGIN - CODE ADAPTED FROM SCRIPT CENTER SAMPLE CODE REPOSITORY
			  #http://www.microsoft.com/technet/scriptcenter/scripts/powershell/search/users/srch106.mspx
			  #GET AD GROUP FROM DIRECTORY SERVICES SEARCH
			  $strFilter = "(&(objectCategory=Group)(name="+($groupName)+"))"
			  $objDomain = New-Object System.DirectoryServices.DirectoryEntry
			  $objSearcher = New-Object System.DirectoryServices.DirectorySearcher
			  $objSearcher.SearchRoot = $objDomain
			  $objSearcher.Filter = $strFilter
				$colProplist = ("name","member")
				foreach ($i in $colPropList)
					{
					$catcher = $objSearcher.PropertiesToLoad.Add($i)
					}
						$colResults = $objSearcher.FindAll()

				#END - CODE ADAPTED FROM SCRIPT CENTER SAMPLE CODE REPOSITORY
				  foreach ($objResult in $colResults)
				  {
					foreach ($member in $objResult.Properties.member)
					{
					  $indMember = [adsi] "LDAP://$member"
					    $y = $domain + ($indMember.Name) 
						$Lgm = ("$Lgm <tr><td>$y</td></tr>")
						}
					 }
			}	
			$LocalGrp = ("$LocalGrp <TABLE><td><strong>$lgn</strong></td><td>$Lgm</td></tr></TABLE>")
			}
	}
	$lgnlgm = $Localgrp
	$z = $z + "<tr><td></td><td>$site</td><td></td><td>$siteUser</td><td>$SPGroups</td><td>$MainSPGroupMembers</td><td>$lgnlgm</td><tr>"
	}
	$rSite.Dispose()
}

# Create Table
$surl = $siteUrl.ToString().split("/")
$s = "CA"
# $s = $surl[2]
# $s = ($s -replace ":", "-") 
$MainWebApp = $spWebApp
$MainDisplayWeb = DisplayWeb
$z = $z + "</table></body></html>"

# Adjust Path
$OutFileName = ("G:\Reports\" + $server + "-" + $s + "-SharePoint Security Report-" + $date + ".html")
#
Out-File -FilePath $OutFileName -InputObject $z -Encoding ASCII	
#End Table
$OutFileItem = Get-Item -Path $OutFileName
Write-Host " Report available here: $OutFileItem" -Foregroundcolor Yellow
sendMail user@yourmai.com $OutFileItem #<--- Change email address

# upload the report to a SharePoint site
$userName = Read-Host "Enter your username"
$password = Read-Host "Enter your password"
 
 $path = "G:\Reports"; #<--- Change directory
 $destination = "http://sharepoint/Shared Documents"; 
 $securePasssword = ConvertTo-SecureString $password -AsPlainText -Force;
 $credentials = New-Object System.Management.Automation.PSCredential ($userName, $securePasssword);
 #$credentials = [System.Net.CredentialCache]::DefaultCredentials; 
 $webclient = New-Object System.Net.WebClient;
 $webclient.Credentials = $credentials; 
 Get-ChildItem $path | Where-Object {$_.Extension -eq ".html"} | 
 ForEach-Object { $webclient.UploadFile($destination + "/" + $_.Name, "PUT", $_.FullName); 
 }
#CLEANUP
$rootSite.Dispose()

Advertisements

Get the SSL Certs by Web Site

I need to check several Web servers for sites that might have an expiring certification.
This pulls the information and adds it to an Excel Spreadsheet.
Note that this only works on 2008 servers.

$date = Get-Date
$rDate = (Get-Date -format "MM-dd-yyyy")
$strPath = "C:\Scripts\PS1\serverinfo-$rDate.xlsx" 
$xl = New-Object -comobject Excel.Application 
$xl.Visible = $True
$xl.DisplayAlerts = $False

$wb = $a.Workbooks.Add() 
$ws = $b.Worksheets.Item(1) 
$ws.Name = $rDate
$ws.Cells.Item(1,1) = "Machine Name" 
$ws.Cells.Item(1,2) = "FriendlyName" 
$ws.Cells.Item(1,3) = "NotAfter" 
$ws.Cells.Item(1,4) = "Issuer" 

$xRow = 2
$cert = dir IIS:\SslBindings | ? {$_.Port -eq 443} | Select *
foreach ($i in $cert) { 
$x = $i.thumbprint
$y = get-item cert:\LocalMachine\My\$x
$FN = $y.FriendlyName
$NA = $y.NotAfter
$IS = $y.Issuer
$ws.Cells.Item($xRow,1) =$comp 
$ws.Cells.Item($xRow,2) =$FN 
$ws.Cells.Item($xRow,3) =$NA 
$ws.Cells.Item($xRow,4) =$IS 
$xRow++
}

This version pulls the info and puts it into a Tab delimited file. I had to run this on each individule server
due to some restriction in my enviroment.

$comp = $env:computername
$strPath = "C:\Scripts\PS1\Certificates\$comp-CertInfo.csv"  # <-- You might want to point this at a share
$date = Get-Date
$rDate = (Get-Date -format "MM-dd-yyyy")
IF(Test-Path $strPath) { Remove-Item $strPath }
Add-Content -Path $strPath "Certificate Inventory `t$rDate`n"
Add-Content -Path $strPath "Machine Name`tFriendlyName `tNotAfter `tIssuer"

$OS = Get-WmiObject Win32_OperatingSystem
$osVer = $os.version
If ($osVer -like "6*") {
$cert = dir IIS:\SslBindings | ? {$_.Port -eq 443} | Select *
foreach ($i in $cert) { 
$x = $i.thumbprint
$y = get-item cert:\LocalMachine\My\$x
$FN = $y.FriendlyName
$NA = $y.NotAfter
$IS = $y.Issuer
Add-Content -Path $strPath "$comp `t$FN `t$NA `t$IS `n";
	}
}
Notepad $strPath

Automates a SharePoint 2010 installation

###### Start Posh Script ######## 

<#
.Script Name
New-SPInstallation.ps1 

.SYNOPSIS
Automates a SharePoint 2010 installation.

.DESCRIPTION
The script automates a SharePoint 2010 installation.
Requires that the binaries are installed on the server.

.PARAMETER databaseName
Name of the configuration database.

.PARAMETER databaseServer
Name of the database server.

.PARAMETER centralAdminDatabase
Name of the Central Administration content database.

.PARAMETER port
Port to use.

.PARAMETER windowsAuthProvider
NTLM or Kerberos, default set to NTLM.

.PARAMETER userName
Farm Administrator account in the format ‘domain\username’.

.PARAMETER password
Pasword for the Farm Administrator account.

.PARAMETER passPhrase
Farm password, used to add new machines to the farm.
#>

param(
[string]$databaseName,
[string]$databaseServer,
[string]$centralAdminDatabase,
[string]$port,
[string]$windowsAuthProvider = "NTLM",
[string]$userName,
[string]$password,
[string]$passPhrase
)
Add-PSSnapin Microsoft.SharePoint.Powershell
$Host.Runspace.ThreadOptions = "ReuseThread"

# Converting password strings to secure strings
$securePassword = ConvertTo-SecureString -String $password -AsPlainText -Force
$securePassPhrase = ConvertTo-SecureString -String $passPhrase -AsPlainText -Force

# Creating a PSCredential object
$psCredentials = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $userName, $securePassword

# New Configuration Database
New-SPConfigurationDatabase -DatabaseName $databaseName -DatabaseServer $databaseServer -AdministrationContentDatabaseName $centralAdminDatabase -Passphrase $securePassPhrase -FarmCredentials $psCredentials

# Install help files
Install-SPHelpCollection -All

# Install services
Install-SPService

# Install Features
Install-SPFeature -AllExistingFeatures

# Create a new Central Administration
New-SPCentralAdministration -Port $port -WindowsAuthProvider $windowsAuthProvider

# Copy shared application data
Install-SPApplicationContent

###### End Posh Script ######## 

We can run this script by typing the following:

New-SPInstallation.ps1 -databaseName “My config DB” `
-databaseServer “SqlServer01” `
-centralAdminDatabase “My Admin_ContentDB” -port 5057 `
-username “ps\admin” `
-password “SecretP@assword” -passphrase “JoinDoain”

Using Central ISE Snippet Repository

Using Central ISE Snippet Repository

In a previous tip we illustrated that ISE code snippets (press CTRL+J to view them) are plain ps1xml-files that you can manage in File Explorer. By default, the PowerShell 3.0 ISE editor loads snippets from your private cache folder.

Imagine you and your colleagues set up a network drive to share useful snippets. Instead of manually checking this folder and manually copying the snippets from this folder onto your local machine, you can also tell the ISE editor to load the snippets directly from the central repository. Here is a sample:

 

$snippetPath = Join-Path (Split-Path $profile.CurrentUserCurrentHost) "Snippets"

$snippetPath

Get-ChildItem -Path $snippetPath -Filter *.ps1xml |

ForEach-Object {

$psise.CurrentPowerShellTab.Snippets.Load($_.FullName)

This sample loads the snippets from your private local folder, so it shows what ISE does by default. Simply assign another path to $snippetPath to load the snippets from another folder. This could be your central team repository, and it could also be a USB stick you are carrying around with you that holds your favorite snippets.

As it turns out, this is the code executed behind the scenes by Import-IseSnippet. In fact, all *-IseSnippet commands are functions, and you can view the source code like this:

$path = "$pshome\modules\ise\ise.psm1"

ise $path

http://powershell.com/cs/blogs/tips/archive/2013/05/07/using-central-ise-snippet-repository.aspx

Accessing Latest Log File Entries

Sometimes you may just be interested in the last couple of entries in a log file. Here’s a simple yet fast way of outputting only the last x lines from a text log:
# Show last 5 lines of windowsupdate.log file

$logs = Get-Content -Path $env:windir\windowsupdate.log -ReadCount 0
$logs[-5..-1]

This example would return only the last (newest) five lines from the windowsupdate.log file.
It’s pretty fast because Get-Content uses –ReadCount 0, reading in even large text files very fast. The result is a text array with the text lines read in. In the example, only the last 5 lines are output (index -5 through -1). However, $logs will hold the complete log file content which may take considerable memory. So in PowerShell 3.0, there is a more efficient approach:
# Show last 5 lines of windowsupdate.log file

Get-Content -Path $env:windir\windowsupdate.log -ReadCount 0 -Tail 5

Here, only the number of lines specified with –Tail are returned, so there is no need for a text array to store all the other text lines found in the log file.

From: “Powershell Tip Of The Day”
http://powershell.com/cs/blogs/tips/archive/2013/04/26/accessing-latest-log-file-entries.aspx

powershell commands by noun

Here is a handy article on how to get a list of all the available Powershell commndlets on your machine in a nicely sorted list.

http://jdhitsolutions.com/blog/2013/04/friday-fun-powershell-commands-by-noun/?utm_source=feedburner&utm_medium=feed&utm_campaign=Feed%3A+JeffsScriptingBlogAndMore+%28The+Lonely+Administrator%29&utm_content=Google+Feedfetcher#utm_source=feed&utm_medium=feed&utm_campaign=feed?utm_source=rss&utm_medium=rss&utm_campaign=friday-fun-powershell-commands-by-noun

get-command -CommandType cmdlet | sort noun,verb | format-table -group noun

Finding Group members in AD

This is a simple script that will pull up the names of the members of a given group in AD. I use Excell to collect all the names.

 

$group = Read-Host "Enter group name to find"
$row = 2
$as = Get-ADGroup $group | Get-ADGroupMember

$xlSummaryAbove = 0 
$xlSortValues = $xlPinYin = 1 
$xlAscending = 1 
$xlDescending = 2
$xl = New-Object -comobject excel.application 
$xl.Visible = $true 
$wb = $xl.Workbooks.Add() 
$ws = $wb.Worksheets.Item(1) 
$row = 2
 $ws.Cells.Item(1,1) = 'First Name'
 $ws.Cells.Item(1,2) = 'Last Name'
 $ws.Cells.Item(1,3) = 'EMail Address'
 $ws.Cells.Item(1,4) = 'samAccountName'
 $range = $ws.range('A1:D1')
 $range.font.bold = 'true' 
foreach ($item in $as) { 
$name = Get-ADUser $item.samAccountName
 $ws.Cells.Item($row,1) = $name.GivenName
 $ws.Cells.Item($row,2) = $name.surname
 $ws.Cells.Item($row,3) = $item.name
 $ws.Cells.Item($row,4) = $name.samAccountName 
 $row++
  }

# one-column sort --> works 
$range1 = $ws.range('A2:D2500')
$range2 = $ws.range('B2')
[void]$range1.sort($range2, $xlAscending)
[void]$range1.entireColumn.Autofit()