Make sure your Azure ARM VM’s are not a threat

The script below will deploy or un-deploy the Azure antimalware extension from all VM’s in a resource group. You need to ensure the anySettings and SqlSettings are correct for your world.

[cmdletbinding()]
param (
    $rgname="release4.11.0.1",
    [bool]$adding = $true
)
 
# Get-AzureVMAvailableExtension | fl -Property Publisher, ExtensionName
 
$location="north europe"
$extName="IaasAntimalware"
$extType="IaaSAntimalware"
$extPublisherName="Microsoft.Azure.Security"
 
 
$anySetting = @"
{
"AntimalwareEnabled": true, 
"RealtimeProtectionEnabled": true,
"ScheduledScanSettings": {
       "isEnabled": true,
       "day": 1,
       "time": 120,
       "scanType": "Quick"
       },
"Exclusions": {}
}
"@
 
$sqlSetting = @"
{
"AntimalwareEnabled": true, 
"RealtimeProtectionEnabled": true, 
"ScheduledScanSettings": {        
       "isEnabled": true, 
       "day": 1, 
       "time": 120, 
       "scanType": "Quick"  
       },        
       "Exclusions": {
             "Extensions": ".mdf;.ldf",
             "Paths": "D:\\;E:\\",
             "Processes": "excludedproc1.exe;excludedproc2.exe"    
             }
       }
"@
 
 
$allVersions= (Get-AzureRmVMExtensionImage -Location $location -PublisherName "$extPublisherName" -Type "$extType").Version
$versionString = $allVersions[($allVersions.count)-1].Split(".")[0] + "." + $allVersions[($allVersions.count)-1].Split(".")[1]
 
 
$vms = get-azurermvm -ResourceGroupName $rgname
 
$vms | % {
    $thisVm = $_
 
    $whichSetting="Any"
    $setting = $anySetting
 
    if($thisVm.Name -like "*-sql") {
        $setting = $sqlSetting
        $whichSetting="SQL"
    }
    if($adding) {
 
    write-host ("ADDING $whichsetting setting to " + $thisVm.Name)
 
    Set-AzureRmVMExtension `
            -ResourceGroupName $rgname `
            -VMName $thisVm.Name `
            -Name "$extName" `
            -Publisher "$extPublisherName" `
            -TypeHandlerVersion "$versionString" `
            -ExtensionType "$extType" `
            -Location "$location" `
            -SettingString "$setting"
    }
    else {
        write-host ("REMOVING FROM " + $thisVm.Name)
        Remove-AzureRmVMExtension -ResourceGroupName $rgname -VMName $thisVm.Name -Name "$extName"
    }
}

SharePoint on-line : simple 2013 workflow to send an email

Struggled for a while with this.

  • Download latest SharePoint designer 2013 (some early releases were buggy I am told)
  • Apply any SharePoint designer updates (Had an issue with designer not able to load visio)
  • Make sure the “Acount” Designer is using is your 0n-line account not your desktop account
  • Connect to an site collection (Not your admin site collection :-))
  • Enable site feature “Workflows can use app permissions”
  • Grant app permissions in your site collection see this (http://msdn.microsoft.com/en-us/library/jj822159.aspx)
  • Create a (in my case) site workflow
  • Add an app step
  • Inside the app step Include a send email action, send it to yourself
  • Publish the workflow
  • Go to site settings -> Site content -> site workflows
  • Execute your workflow
  • Check your inbox of the email address specified in your Profile

That’s all folks.

 

Search fix (Simple single server farm only)

I am constantly having issues with three things on SharePoint 2013 farms

  • Search
  • UP Synch
  • Managed metadata

So to search.  Often following a reboot the search admin screen will show one component or another in a non ideal state.  Red cross, Yellow warning triangle etc.

googling will show you many and various ways to fix some / all or none of these issues, re create index, flush SharePoint Caches, re provision Search host, and the list goes on and on and on…

For times when all these fail me, I have crafted this simple script to surgically take out a broken component and replace it with a shiney new one.  It is intended for single server with simple search topology and if you use it you are responsible for ensuring the code is fit for ‘your’ purpose.

I think the script is self explanatory.

 

[cmdletbinding()]
param (
    [Parameter(Mandatory=$true)]
    $component # Crawl, Admin, Query, Content, Analytics, Index
)
 
write-host "ONLY USE ON A SIMPLE, SINGLE SERVER FARM,  IF THIS IS THE CASE, COMMENT OUT NEXT LINE AND RE RUN"
break
 
# Grab the Search Service Instance
#
$Sinstance = Get-SPEnterpriseSearchServiceInstance -Identity $env:COMPUTERNAME
 
# Grab active topology
#
$ssa = Get-SPEnterpriseSearchServiceApplication
$active = Get-SPEnterpriseSearchTopology -SearchApplication $ssa -Active
 
# Create a clone of active to work with
#
$clone = New-SPEnterpriseSearchTopology -SearchApplication $ssa -Clone –SearchTopology $active
 
# grab component giving us trouble
#
$problem = Get-SPEnterpriseSearchComponent -SearchTopology $clone | ? {$_.Name -like "$component*"}
$problem
 
# Remove troublesome component from clone
#
if($problem.GetType().ToString() -eq "System.Object[]") {
    $problem | Remove-SPEnterpriseSearchComponent -Identity $_ -SearchTopology $clone -Confirm:$false
}
else {
    Remove-SPEnterpriseSearchComponent -Identity $problem -SearchTopology $clone -Confirm:$false
}
 
switch($component) {
    "Crawl" {
        New-SPEnterpriseSearchCrawlComponent -SearchTopology $clone -SearchServiceInstance $Sinstance
    }
 
    "Admin" {
        New-SPEnterpriseSearchAdminComponent -SearchTopology $clone -SearchServiceInstance $Sinstance
    }
 
    "Query" {
        New-SPEnterpriseSearchQueryProcessingComponent -SearchTopology $clone -SearchServiceInstance $Sinstance
    }
 
    "Content" {
        New-SPEnterpriseSearchContentProcessingComponent  -SearchTopology $clone -SearchServiceInstance $Sinstance
    }
 
    "Analytics" {
        New-SPEnterpriseSearchAnalyticsProcessingComponent  -SearchTopology $clone -SearchServiceInstance $Sinstance
    }
 
    "Index" {
        New-SPEnterpriseSearchIndexComponent  -SearchTopology $clone -SearchServiceInstance $Sinstance    
    }
 
    default {
        write-host "Dont understand" $component
    }
}
 
# Make clone active
#
Set-SPEnterpriseSearchTopology -Identity $clone
 
# Clear out Inactive topologies
#
get-SPEnterpriseSearchTopology -SearchApplication $ssa | ? {$_.state -ine "Active" } | Remove-SPEnterpriseSearchTopology -Confirm:$false

scripted “re creation” of User Profile Service app from powershell as spfarm account after deleting the existing UPSA.

Thanks to Brian Lala and AutospInstaller for the inspiration and start-process syntax.

  • Ensure UAC is OFF
  • Run a PowerShell window as administrator
  • Paste the script below into your.ps1 file and run it
$ErrorActionPreference="stop"
 
$script = {
Add-PSSnapin microsoft.sharepoint.powershell -ea SilentlyContinue
$ErrorActionPreference="stop"
$setNetbiosNames=$true
$prefix="hostname"
$tld="domain.dev"
$mshPort="80"
 
#
 
$upServiceAppName="User Profile Service Application"
$upAppPool="SharePoint Hosted Services"
$upDbServer="UPS"
 
$upProfileDBServer=$upDbServer
$upProfileDB=("$prefix" + "_Profile")
 
$upSyncDBServer=$upDbServer
$upSyncDB=("$prefix" + "_Sync")
 
$upSocialDBServer=$upDbServer
$upSocialDB=("$prefix" + "_Social")
 
$upSyncInstance="$prefix"
 
$upMySiteHostUrl=("http://$prefix" + "-mysites." + "$tld" + ":" + "$mshport" + "/")
$upManagedPath="Personal"
 
 
 
$upsapp = Get-SPServiceApplication | ? {$_.TypeName -like "User Profile Service Application"}
 
if($upsapp -eq $null) {
    #write-host "Delete pre existing User Profile timer jobs"
 
    #Get-SPTimerJob | where {$_.name -match "User Profile Service.*"} |  % {
    #    write-host "deleting timer job:" $_.Name
    #    $_.Delete()
    # }
 
    write-host "Create UPSA"
 
    try {
        $upsapp = New-SPProfileServiceApplication `
                    -ApplicationPool $upAppPool `
                    -MySiteHostLocation $upMySiteHostUrl `
                    -Name $upServiceAppName `
                    -ProfileDbName $upProfileDB `
                    -ProfileDbServer $upProfileDbServer `
                    -ProfileSyncDbServer $upSyncDbServer `
                    -ProfileSyncDbName $upSyncDB `
                    -SocialDbName $upSocialDb `
                    -SocialDbServer $upSocialDbServer
 
 
        if($setNetbiosName) {
            write-host "Enable NETBIOS domain names"
 
            $upsapp.NetBIOSDomainNamesEnabled=1
            $upsapp.update()
        }
 
        $upsapp
    }
    catch {
        write-host $_
    }
 
}
else {
    write-host "Pre existing User Profile Service Application"
}
 
if($upsapp -ne $null) {
    write-host "Create UPSA Proxy"
 
    $upsAppProxy = Get-SPServiceApplicationProxy | ? {$_.TypeName -like "User Profile Service Application Proxy"}
 
    if($upsAppProxy -eq $null) {
 
        try {
 
            $upsAppProxy = New-SPProfileServiceApplicationProxy `
                            -ServiceApplication $upsapp.Id `
                            -Name $upServiceAppName
 
            $upsAppProxy
        }
        catch {
            write-host $_
        }
    }
}
else {
    write-host "Pre existing UPSA Proxy"
}
 
 
}
 
 
 
 
 
# this runs the script defined above under spfarm user account
# orginally sourced from Brian Lala autoSP-Installer for the "Start-process" syntax, Thanks Brian :-)
# See Brian T if it does not work for you
#
$secpasswd = ConvertTo-SecureString "p@55w0rd" -AsPlainText -Force
$farmCredential = New-Object System.Management.Automation.PSCredential ("domain\spfarm", $secpasswd)
 
$scriptFile = "$env:TEMP\UPCreate-Script.ps1"
write-output $script | out-file $scriptFile
 
Start-Process  -WorkingDirectory $PSHOME -FilePath "powershell.exe" -Credential $farmCredential -ArgumentList "-Command Start-Process -WorkingDirectory `"'$PSHOME'`" -FilePath `"'powershell.exe'`" -ArgumentList `"'$scriptFile'`" -Verb Runas " -Wait
 
 
 
 
$msg = "UP SA Creation done`n`n"
 
$msg += "You need to start the UP Sync service in `"Services on a server`"`n"
$msg += "Create a Sync connection, if you get error in create, try to use a new name for connection`n"
$msg += "Ensure UP Service account has Admin and full control of UP SA`n"
$msg += "Ensure msh app pool account has Admin and full control of UP SA`n"
$msg += "Ensure app pool account has Admin and full control of UP SA`n"
$msg += "Ensure sp content account has Admin = read people data in UP SA`n"
$msg += "Ensure sp farm account has Admin and full control of UP SA`n"
$msg += "Ensure setup (you) account has Admin and full control of UP SA`n"
$msg += "Configure service application associations and ensure UP SA is associated"
 
$msg += "Run a full sync`n"
 
write-host $msg

Update all SharePoint 2010 service account passwords from one script

Nice to do this in one script, take note of additional steps after the script has run.

You must of course set the values between ### YOU NEED TO SET THESE and
### STOP SETTING NOW to those appropriate to your farm.

You will note that this script allows for a typical set of farm accounts
as required by a Least Privilege Service Accounts setup. You may add modify
or remove accounts as you require.

add-pssnapin microsoft.sharepoint.powershell -erroraction silentlycontinue
 
function Set-AdUserPwd
{
[CmdletBinding()]
Param(
    [string[]]$users,
    [string]$password
)
 
    write-host "Change AD passwords for system accounts"
 
    $users | % {
 
        $thisAccount = $_
 
        write-host "`tChange password for" $thisAccount
 
        $oUser = [adsi]"LDAP://$thisAccount" 
        $ouser.psbase.invoke("SetPassword",$password)
        $ouser.psbase.CommitChanges()
    }
 
    write-host "All done."
 
}
 
function ChangePasswordForManagedAccounts()
{
[CmdletBinding()]
param(
    [string] $newPassword,
    [string[]]$accounts,
    [bool] $UseExisting
)
 
    $newPw = ConvertTo-SecureString $newPassword -asPlainText -Force
 
    write-host "Change Managed account passwords"
 
    $accounts | % {
        $thisAccount = $_
 
        write-host "`tChange password for managed account" $thisAccount
 
        if($useExisting)
        {
            Set-SPManagedAccount    -identity $thisAccount `
                                    -ExistingPassword $newPw `
                                    -UseExistingPassword:$true `
                                    -Confirm:$false `
 
        }
        else
        {
            Set-SPManagedAccount    -identity $thisAccount `
                                    -Confirmpassword  $newPw `
                                    -Newpassword  $newPw `
                                    -Confirm:$false `
                                    -SetNewPassword:$true
        }
    }
 
    write-host "All done."
}
 
function DefaultContentAccessAccountPassword()
{
[CmdletBinding()]
param(
    [string] $searchAppName,
    [string] $account,
    [string] $password
)
    write-host "Change Default content access account password for" $account
 
    $searchapp = Get-SPEnterpriseSearchServiceApplication -Identity $searchAppName
    $c = New-Object Microsoft.Office.Server.Search.Administration.Content($searchapp)
 
    $c.SetDefaultGatheringAccount(
        $account,
        (ConvertTo-SecureString $password -AsPlainText -force))
}
 
#
# ### YOU NEED TO SET THESE
#
$systemAccounts = @(
                    "cn=sql-svc,ou=YOUR_OU,dc=YOUR_DOMAIN,dc=com",
                    "cn=SpUps,ou=YOUR_OU,dc=YOUR_DOMAIN,dc=com",
                    "cn=SPServices,ou=YOUR_OU,dc=YOUR_DOMAIN,dc=com",
                    "cn=SPSearch,ou=YOUR_OU,dc=YOUR_DOMAIN,dc=com",
                    "cn=SPObjCacheSuper,ou=YOUR_OU,dc=YOUR_DOMAIN,dc=com",
                    "cn=SPObjCacheRead,ou=YOUR_OU,dc=YOUR_DOMAIN,dc=com",
                    "cn=SPMySiteAppPool,ou=YOUR_OU,dc=YOUR_DOMAIN,dc=com",
                    "cn=SPFarm,ou=YOUR_OU,dc=YOUR_DOMAIN,dc=com",
                    "cn=SPContent,ou=YOUR_OU,dc=YOUR_DOMAIN,dc=com",
                    "cn=SPAppPool,ou=YOUR_OU,dc=YOUR_DOMAIN,dc=com",
)
 
$managedAccounts = @(
                    "YOUR_NETBIOS_DOMAIN\SPFarm",
                    "YOUR_NETBIOS_DOMAIN\SPServices",
                    "YOUR_NETBIOS_DOMAIN\SPAppPool",
                    "YOUR_NETBIOS_DOMAIN\SPMySiteAppPool",
                    "YOUR_NETBIOS_DOMAIN\SPSearch"
)
 
$searchAppName = "Search Service Application"
$farmAccount = "YOUR_NETBIOS_DOMAIN\SPFarm"
$defaultSearchContentAccount = "YOUR_NETBIOS_DOMAIN\SPContent"
 
$theNewPassword = "L3tM31n"   
 
#
# ### STOP SETTING NOW
#
 
clear-host
 
# Change system account passwords in AD
#
set-AdUserPwd -users $systemAccounts -password $theNewPassword
 
# Managed account passwords
#
ChangePasswordForManagedAccounts -newPassword $theNewPassword -accounts $managedAccounts -UseExisting $true
 
# Default content access account
#
DefaultContentAccessAccountPassword -SearchAppName $searchAppName -account $defaultSearchContentAccount -password $theNewPassword
 
# Farm account
#
#
write-host "Change farm account password" $farmAccount
 
stsadm -o updatefarmcredentials -userlogin $farmAccount -password $theNewPassword
 
# its all over now
#
write-host "Remember to edit SQL service startup account password in `"Services`""
write-host "Remember to Restart profile sync service on central admin in `"Services on a server`""
write-host "Check out if SharePoint tracing service is running as a system account in `"Services`" make it local system"
write-host "All done."

SharePoint 2010 Service Application Groups

IMHO, Microsoft obviously rushed the release of SharePoint 2010 and there are quite a few unfinished areas at the very least in the UI.

Try to create more than one custom Service Application Group in Central admin for example. You just cant do it, as far as I can see.

The good news is, powershell SharePoint CmdLets allow you to fill this gap. I crafted this in a bit of a hurry, but it does the job.

$PSSnapin = Add-PsSnapin Microsoft.SharePoint.PowerShell -ErrorAction SilentlyContinue
 
 
$AppProxyGroupFriendlyName = "New Custom Proxy group"
$ProxyDisplayNamesToAddToGroup = @(
                    "State Service Application Proxy",
                    "MyApp Taxonomy",
                    "Secure Store Service Proxy",
                    "Web Analytics Service Application",
                    "Application Discovery and Load Balancer Service Application Proxy_aa187b7a-cc28-448a-b232-4c9f0713d0bb",
                    "WSS Usage Application"
                    )
 
# Grab our new ApplicationProxyGroup
#
$appProxyGroup = get-SPServiceApplicationProxyGroup | where-object {$_.FriendlyName -eq $AppProxyGroupFriendlyName}
 
if(-not $appProxyGroup) {
    write-host "Creating" $AppProxyGroupFriendlyName
    New-SPServiceApplicationProxyGroup -Name $AppProxyGroupFriendlyName
}
 
 
 
# Get each of the application proxies to be used by this group
#
$ProxyDisplayNamesToAddToGroup | % {
    $thisProxy = $_
    $appProxy = Get-SPServiceApplicationProxy | where-object {$_.DisplayName -eq $thisProxy}
 
    if($appProxyGroup.Contains($appProxy)) {
        # Already present
        write-host $thisProxy "already present"
    }
    else {
        write-host "Adding" $thisProxy
        $appProxyGroup.Add($appProxy)
    }
}
 
# Show the proxies in the new group
#
$appProxyGroup = Get-SPServiceApplicationProxyGroup -Identity $AppProxyGroupFriendlyName
$appProxyGroup.DefaultProxies | Format-list -Property DisplayName

Script the DCOM fix in SharePoint

I got fed up with fixing this so I put together a powershell script to sort
it all out for me.

You will need to install SetAcl and DcomPerm.

Paste the script below into a file e.g. FixDcom.ps1
Fire up a powershell window (As Administrator) and execute the script

As ever, all at your own risk.

$PortalSiteOwner="domain\username"
$PortalAccount="domain\username"
$SPFarmAccount="domain\username"
 
$SetAcl="WhereYouInstalledSetAcl.exe"
$backupFileName="$here\RegPerms-Dconfig.bak"
$RegKeyOwner="$PortalSiteOwner"
 
# SETACL
#
 
# Backup the existing perms
#
$args = "-on", "HKCR\AppID\{61738644-F196-11D0-9953-00C04FD919C1}",
 "-ot", "reg", "-actn", "list", "-lst", "f:sddl;w:d,s,o,g;i:y;s:b",
 "-bckp", "$backupFileName"
& $SetAcl $args
 
 
 
 
# Take ownership
#
$args = "-on", "HKCR\AppID\{61738644-F196-11D0-9953-00C04FD919C1}", "-ot",
 "reg", "-actn", "setowner", "-ownr", "n:$RegKeyOwner;s:n"
& $SetAcl $args
 
# Assign full control
#
$args = "-on", "HKCR\AppID\{61738644-F196-11D0-9953-00C04FD919C1}", "-ot",
 "reg", "-actn", "ace", "-ace", "n:$RegKeyOwner;p:full"
& $SetAcl $args
 
# DCOMFIG
#
 
Write-Host "THIS WILL FAIL IF YOU DO NOT HAVE REGISTRY ACCESS TO"
Write-Host "HKCR:\AppID\{61738644-F196-11D0-9953-00C04FD919C1} REGISTRY KEY" 
 
$argz = @( "-al", "{61738644-F196-11D0-9953-00C04FD919C1}", "set" ,
 "__USER__HERE__" ,"permit", "level:l")
 
$argz[3] = "$SpfarmAccount"
& "$AssetsPath\dcomperm.exe" $argz
 
$argz[3] = "$PortalAccount"
& "$AssetsPath\dcomperm.exe" $argz
 
# Restore original permissions
#
$args = "-on", "HKCR\AppID\{61738644-F196-11D0-9953-00C04FD919C1}", "-ot",
 "reg", "-actn", "restore", "-bckp", "$backupFileName"
& $SetAcl $args

So this is what it is doing;

  • Use SetAcl to make a backup of the registry permissions on the …919C1 registry key
  • Use SetAcl to take ownership of the …919C1 registry key
  • Use SetAcl to assign full control of the …919C1 registry key
  • Use Dcomperm to Grant local activation to SP Farm account
  • Use Dcomperm to grant loccal activation to Portal app pool account
  • Use SetAcl to restore the originla permissions to the … 919C1 registry key

Enjoy.

>Scripted WinNT user creation

>Well, I seem to spend most of my life these days building some new virtual environment to develop against MOSS (Biztalk is a distant memory, I understand thats all about to change though)

I nearly always need to create some degree of system accounts to have my build comply with best practice, very tedious in MOSS as you need quite a few system accounts.

I came up with this script which I use to automate the account creation process in a predictable repeatable way

This flavour works with WinNT provider on windows server 2003 and XP, it will run on a Vista box if you choose to ‘run as administrator’

So, edit the createWinNTusers.vbs file to specify the name of the computer, the name of a single group the names of the users you want to create and the password they will all share, then

Usage is :-
cscript createWinNTusers.vbs [create clean]

The create parameter causes users to be created along with a group to contain them.
The clean parameter causes the users and group to be deleted.

Hope someone finds it usefull.