Solved

Create Web Site multiple Enviroments - Ps Script.

Posted on 2011-03-04
16
1,664 Views
Last Modified: 2012-06-22
Dear,

 I need your help to fix a problem I have with this script. This script is used to create a website in IIS 7.5 in all environments (DEV - QA - PRD).
 This script uses a xml to read all necessary information.
Do not work local or remotes servers.

 This is the error:
 Error

Powershell Script:
 
#This script requires WINRM installed on all servers
#Can be installed with this command: Enable-PSRemoting

#The lists of the servers where the script will be executed
$intServers = "Server1","Server2"
$qasServers = "Server1","Server2"
$prdServers = "Server1PRD","Server2PRD"

### GLOBAL FUNCTIONS ###
function CheckUserPassword($username, $password)
{
    try
    {
        [System.Reflection.Assembly]::LoadWithPartialName("System.DirectoryServices.AccountManagement")  | Out-Null

        $userSplit = $username.split("\") 

        $ctype = [System.DirectoryServices.AccountManagement.ContextType]::Domain
        $context = New-Object -TypeName System.DirectoryServices.AccountManagement.PrincipalContext -ArgumentList $ctype, $userSplit[0]
        try
        {
            $isValid = $context.ValidateCredentials($userSplit[1], $password)
            return $isValid
        }
        finally
        {
            $context.Dispose()
        }
    }
    catch
    {
        return $false
    }
}

function CheckGroupExists($groupName)
{
    if ($groupName -eq "Authenticated Users")
    {
        return $true
    }

    try
    {
        [System.Reflection.Assembly]::LoadWithPartialName("System.DirectoryServices.AccountManagement")  | Out-Null

        $groupSplit = $groupName.split("\") 

        $ctype = [System.DirectoryServices.AccountManagement.ContextType]::Domain
        $context = New-Object -TypeName System.DirectoryServices.AccountManagement.PrincipalContext -ArgumentList $ctype, $groupSplit[0]
        try
        {
            $group = [System.DirectoryServices.AccountManagement.GroupPrincipal]::FindByIdentity($context, $groupName)
            return ($group -ne $null)
        }
        finally
        {
            $context.Dispose()
        }
    }
    catch
    {
        return $false
    }
}



#Create Logs directory
if (-not (Test-Path ".\Logs\"))
{
    New-Item -Path ".\Logs\" -Type Directory | Out-Null
}

#Start logging
$scriptName = ([System.IO.Path]::GetFileNameWithoutExtension($myInvocation.MyCommand.Definition ))
Start-Transcript -Path (".\Logs\$scriptName-{0:yyyyMMdd-hhmmss}.txt" -f (Get-Date))
try
{

    ############## Parameters ###################
    try
    {
        $xmlFilename = [System.IO.Path]::Combine([System.IO.Path]::GetDirectoryname($myInvocation.MyCommand.Definition), "site_creation_shared.xml")
        [xml]$xml = Get-Content $xmlFilename
    }
    catch
    {
        Write-Error "Error in the xml file: $_" -ErrorAction Stop
    }

    $siteName = $xml.Site.Name
    $impersonate = [System.Convert]::ToBoolean($xml.Site.Impersonate)

    #App pool settings
    $managedRuntimeVersion = $xml.Site.ManagedRuntimeVersion
    $x64Bits = [System.Convert]::ToBoolean($xml.Site.x64Bits)
    $integratedMode = [System.Convert]::ToBoolean($xml.Site.IntegratedMode)
    $writeAccessAppPoolAccount = [System.Convert]::ToBoolean($xml.Site.WriteAccessAppPoolAccount)
    $writeAccessSiteUsersGroup = [System.Convert]::ToBoolean($xml.Site.WriteAccessSiteUsersGroup)
    
    #Host Headers (CNames)
    $intHostHeader = $xml.Site.Int.HostHeader
    $qasHostHeader = $xml.Site.Qas.HostHeader
    $prdHostHeader = $xml.Site.Prd.HostHeader

    #AppPool Identities (Service Account)
    $intAppPoolAccount = $xml.Site.Int.AppPoolAccount
    $intAppPoolPassword = $xml.Site.Int.AppPoolPassword

    $qasAppPoolAccount = $xml.Site.Qas.AppPoolAccount
    $qasAppPoolPassword = $xml.Site.Qas.AppPoolPassword

    $prdAppPoolAccount = $xml.Site.Prd.AppPoolAccount
    $prdAppPoolPassword = $xml.Site.Prd.AppPoolPassword

    #Users Groups
    $intSiteUsersGroup = $xml.Site.Int.SiteUsersGroup
    $qasSiteUsersGroup = $xml.Site.Qas.SiteUsersGroup
    $prdSiteUsersGroup = $xml.Site.Prd.SiteUsersGroup
    
    #Logs Readers Group
    $intLogsReadersGroup = $xml.Site.Int.LogsReadersGroup
    $qasLogsReadersGroup = $xml.Site.Qas.LogsReadersGroup
    $prdLogsReadersGroup = $xml.Site.Prd.LogsReadersGroup

    #Developers group
    $siteDevelopersGroup = $xml.Site.DevelopersGroup

    #Log settings (Except Password)
    Write-Host "#############################"
    Write-Host "Site settings"
    Write-Host "#############################"
    Write-Host "Name: $siteName"
    Write-Host "x64Bits: $x64Bits"
    Write-Host "Integrated Mode: $integratedMode"
    Write-Host "Managed Runtime Version: $managedRuntimeVersion"
    Write-Host "WriteAccessAppPoolAccount: $writeAccessAppPoolAccount"
    Write-Host "WriteAccessSiteUsersGroup: $writeAccessSiteUsersGroup"
    Write-Host "Impersonate: $impersonate"
    Write-Host "Developers Group: $siteDevelopersGroup"

    Write-Host 
    Write-Host "#############################"
    Write-Host "Int settings"
    Write-Host "#############################"
    Write-Host "Host header: $intHostHeader"
    Write-Host "AppPool Account: $intAppPoolAccount"
    Write-Host "Site Users Group: $intSiteUsersGroup"
    Write-Host "Logs Readers Group: $intLogsReadersGroup" 

    Write-Host 
    Write-Host "#############################"
    Write-Host "Qas settings"
    Write-Host "#############################"
    Write-Host "Host header: $qasHostHeader"
    Write-Host "AppPool Account: $qasAppPoolAccount"
    Write-Host "Site Users Group: $qasSiteUsersGroup"
    Write-Host "Logs Readers Group: $qasLogsReadersGroup" 

    Write-Host 
    Write-Host "#############################"
    Write-Host "Prd settings"
    Write-Host "#############################"
    Write-Host "Host header: $prdHostHeader"
    Write-Host "AppPool Account: $prdAppPoolAccount"
    Write-Host "Site Users Group: $prdSiteUsersGroup"
    Write-Host "Logs Readers Group: $prdLogsReadersGroup" 
    Write-Host
    
    Write-Host "#############################"
    Write-Host "Check users and groups"
    Write-Host "#############################"
    
    $usersAndGroupOK = $true
    
    $check = CheckUserPassword $intAppPoolAccount $intAppPoolPassword
    Write-Host $intAppPoolAccount " = " $check
    $usersAndGroupOK = $check -and $usersAndGroupOK
    
    $check = CheckUserPassword $qasAppPoolAccount $qasAppPoolPassword
    Write-Host $qasAppPoolAccount " = " $check
    $usersAndGroupOK = $check -and $usersAndGroupOK
    
    $check = CheckUserPassword $prdAppPoolAccount $prdAppPoolPassword
    Write-Host $prdAppPoolAccount " = " $check
    $usersAndGroupOK = $check -and $usersAndGroupOK
    
    #Site users
    $check = CheckGroupExists $intSiteUsersGroup
    Write-Host $intSiteUsersGroup " = " $check
    $check = $check -and $usersAndGroupOK
    
    $check = CheckGroupExists $qasSiteUsersGroup
    Write-Host $qasSiteUsersGroup " = " $check
    $usersAndGroupOK = $check -and $usersAndGroupOK
    
    $check = CheckGroupExists $prdSiteUsersGroup
    Write-Host $prdSiteUsersGroup " = " $check
    $check = $check -and $usersAndGroupOK
    
    #Logs readers
    $check = CheckGroupExists $intLogsReadersGroup
    Write-Host $intLogsReadersGroup " = " $check
    $check = $check -and $usersAndGroupOK
    
    $check = CheckGroupExists $qasLogsReadersGroup
    Write-Host $qasLogsReadersGroup " = " $check
    $usersAndGroupOK = $check -and $usersAndGroupOK
    
    $check = CheckGroupExists $prdLogsReadersGroup
    Write-Host $prdLogsReadersGroup " = " $check
    $check = $check -and $usersAndGroupOK
    
    $check = CheckGroupExists $siteDevelopersGroup
    Write-Host $siteDevelopersGroup " = " $check
    $usersAndGroupOK = $check -and $usersAndGroupOK
    
    if (-not $usersAndGroupOK)
    {
        Write-Error "Some accounts and groups are not correct." -ErrorAction Stop
    }
    
    ############## Constants ###################
    $sitesDirectory = "E:\Sites"

    $sb = {param($server,
                 $siteName,
                 $x64Bits,
                 $integratedMode,
                 $managedRuntimeVersion,
                 $hostHeader,
                 $appPoolAccount,
                 $appPoolPassword,
                 $writeAccessAppPoolAccount,
                 $siteUsersGroup,
                 $writeAccessSiteUsersGroup,
                 $logsReadersGroup,
                 $impersonate,
                 $siteDevelopersGroup)
        #Network share functions
        Function New-SecurityDescriptor (
        $ACEs = (throw "Missing one or more Trustees"),
        [string] $ComputerName = ".")
        {
        	#Create SeCDesc object
        	$SecDesc = ([WMIClass] "\\$ComputerName\root\cimv2:Win32_SecurityDescriptor").CreateInstance()
        	#Check if input is an array or not.
        	if ($ACEs -is [System.Array])
        	{
        		#Add Each ACE from the ACE array
        		foreach ($ACE in $ACEs )
        		{
        			$SecDesc.DACL += $ACE.psobject.baseobject
        		}
        	}
        	else
        	{
        		#Add the ACE
        		$SecDesc.DACL =  $ACEs
        	}
        	#Return the security Descriptor
        	return $SecDesc
        }

        Function New-ACE (
        	[string] $Name = (throw "Please provide user/group name for trustee"),
        	[string] $Domain = (throw "Please provide Domain name for trustee"),
        	[string] $Permission = "Read",
        	[string] $ComputerName = ".",
        	[switch] $Group = $false)
        {    
        	#Create the Trusteee Object
        	$Trustee = ([WMIClass] "\\$ComputerName\root\cimv2:Win32_Trustee").CreateInstance()
            
        	#Setup Trusteee object
        	$Trustee.Domain = $Domain
        	$Trustee.Name = $Name
        	
        	#Create ACE (Access Control List) object.
            $ACE = ([WMIClass] "\\$ComputerName\root\cimv2:Win32_ACE").CreateInstance()
            
        	#Select the AccessMask depending on the -Permission parameter
        	switch ($Permission)
        	{
        		"Read" 		 { $ACE.AccessMask = 1179817 }
        		"Change"  {	$ACE.AccessMask = 1245631 }
        		"Full"		   { $ACE.AccessMask = 2032127 }
        		default { throw "$Permission is not a supported permission value. Possible values are 'Read','Change','Full'" }
        	}

        	#Setup the rest of the ACE.
        	$ACE.AceFlags = 3
        	$ACE.AceType = 0
        	$ACE.Trustee = $Trustee
        	
            #Return the ACE
        	return $ACE
        }

        Function New-Share (
        	[string] $FolderPath = (throw "Please provide the share folder path (FolderPath)"),
        	[string] $ShareName = (throw "Please provide the Share Name"),
        	$ACEs,
        	[string] $Description = "",
        	[string] $ComputerName=".")
        {
        	#Start the Text for the message.
        	$text = "$ShareName ($FolderPath): "
        	#Package the SecurityDescriptor via the New-SecurityDescriptor Function.
        	$SecDesc = New-SecurityDescriptor $ACEs
        	#Create the share via WMI, get the return code and create the return message.
        	$Share = [WMICLASS] "\\$ComputerName\Root\Cimv2:Win32_Share"
        	$result = $Share.Create($FolderPath, $ShareName, 0, 16777216, $Description, "", $SecDesc)
        	switch ($result.ReturnValue)
        	{
        		0 {$text += "has been success fully created" }
        		2 {$text += "Error 2: Access Denied" }
        		8 {$text += "Error 8: Unknown Failure" }
        		9 {$text += "Error 9: Invalid Name"}
        		10 {$text += "Error 10: Invalid Level" }
        		21 {$text += "Error 21: Invalid Parameter" }
        		22 {$text += "Error 22 : Duplicate Share"}
        		23 {$text += "Error 23: Redirected Path" }
        		24 {$text += "Error 24: Unknown Device or Directory" }
        		25 {$text += "Error 25: Net Name Not Found" }
        	}

        	#Create Custom return object and Add results
        	$return = New-Object System.Object
        	$return | Add-Member -type NoteProperty -name ReturnCode -value $result.ReturnValue
        	$return | Add-Member -type NoteProperty -name Message -value $text
        	#Return result object
        	$return
        }
               
           
           #Import module to manage IIS
           Import-Module "WebAdministration" -ErrorAction Stop

           ########### Create the application pool ###########
           Write-Host "Application pool creation..."
           $applicationPoolName = "$siteName"

           Write-Host "Name of the application pool: $applicationPoolName"
           $appPool = New-WebAppPool -Name $applicationPoolName
            
           Begin-WebCommitDelay
            
           #Set application pool identity
           Write-Host "Set application pool identity: $appPoolAccount"
           Set-ItemProperty IIS:\AppPools\$applicationPoolName -name processModel -value @{userName=$appPoolAccount;password=$appPoolPassword;identitytype=3}
           
           #Set Architecture (x86 / x64)
           Write-Host "Set Architecture (x86 / x64): x64Bits = $x64Bits"
           
           if ($x64Bits)
           {
                Set-ItemProperty IIS:\AppPools\$applicationPoolName -name enable32BitAppOnWin64 -value $false
           }
           else
           {
                Set-ItemProperty IIS:\AppPools\$applicationPoolName -name enable32BitAppOnWin64 -value $true
           }
            
           #Set Pipeline Mode
           Write-Host "Set Pipeline Mode: Integrated Mode = $integratedMode"
           if ($integratedMode)
           {
               Set-ItemProperty IIS:\AppPools\$applicationPoolName -name managedPipelineMode -value 0 #Integrated
           }
           else
           {
               Set-ItemProperty IIS:\AppPools\$applicationPoolName -name managedPipelineMode -value 1 #Classic
           }
            
           #Set managedRuntimeVersion
           Write-Host "Set Managed Runtime Version: $managedRuntimeVersion"
           Set-ItemProperty IIS:\AppPools\$applicationPoolName -name managedRuntimeVersion -value $managedRuntimeVersion
           
           Write-Host "Commit changes"
           End-WebCommitDelay -Commit $true
            
           #Create site directory
           Write-Host "Create site directory"
           $siteDirectory = "E:\Sites\$siteName"
           Write-Host "Site directory: $siteDirectory"
           New-Item -ItemType Directory -Path $siteDirectory | Out-Null
          
           #Create Test page
           Write-Host "Create Test page"
           $testPageContent = "<%@ Page Language=""C#"" %><!DOCTYPE html PUBLIC ""-//W3C//DTD XHTML 1.0 Transitional//EN"" ""http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd""><html xmlns=""http://www.w3.org/1999/xhtml""><head runat=""server"">    <title>Test page</title></head><body><form id=""form1"" runat=""server""><div><H1>Test page</H1><H4>Date</H4> <%= DateTime.Now.ToString() %> <H4>.NET Framework version</H4> <%= Environment.Version.ToString()  %>	<H4>MachineName </H4> <%= Environment.MachineName.ToString()  %> </div></form></body></html>"
           Set-Content -Path $siteDirectory\default.aspx -value $testPageContent
                                   
           #Set rights
           Write-Host "Set rights"
           $siteDirectoryAcl = Get-Acl $siteDirectory
           
           $inherit = [system.security.accesscontrol.InheritanceFlags]"ContainerInherit, ObjectInherit"
           $propagation = [system.security.accesscontrol.PropagationFlags]"None"
           
           #Set application pool account rights
           Write-Host "Set application pool account rights: $appPoolAccount. Write: $writeAccessAppPoolAccount"
           if ($writeAccessAppPoolAccount)
           {
                $appPoolAccountFileRights = "Modify"
           }
           else
           {
                $appPoolAccountFileRights = "ReadAndExecute"
           }
           
           $appPoolAccountPermission = $appPoolAccount,$appPoolAccountFileRights,$inherit, $propagation,"Allow"
           $appPoolAccountAccessRule = new-object System.Security.AccessControl.FileSystemAccessRule $appPoolAccountPermission
           $siteDirectoryAcl.SetAccessRule($appPoolAccountAccessRule)
           
           #Set site users account rights
           Write-Host "Set site users account rights: $siteUsersGroup. Write: $writeAccessSiteUsersGroup"
           if ($writeAccessSiteUsersGroup)
           {
                $siteUsersGroupFileRights = "Modify"
           }
           else
           {
                $siteUsersGroupFileRights = "ReadAndExecute"
           }
           
           $siteUsersGroupPermission = $siteUsersGroup,$siteUsersGroupFileRights,$inherit, $propagation,"Allow"
           $siteUsersGroupAccessRule = new-object System.Security.AccessControl.FileSystemAccessRule $siteUsersGroupPermission
           $siteDirectoryAcl.SetAccessRule($siteUsersGroupAccessRule)
            
           if ($siteDevelopersGroup -ne $null)
           {
               #Set developers account rights
               Write-Host "Set developers account rights: $siteDevelopersGroup. Write: True"
               $siteDevelopersGroupPermission = $siteDevelopersGroup,"Modify",$inherit, $propagation,"Allow"
               $siteDevelopersGroupAccessRule = new-object System.Security.AccessControl.FileSystemAccessRule $siteDevelopersGroupPermission
               $siteDirectoryAcl.SetAccessRule($siteDevelopersGroupAccessRule)
           }
           
           Write-Host "Set ACL for site directory"
           $siteDirectoryAcl | Set-Acl $siteDirectory
           
           
           #Create share for developers
           if ($siteDevelopersGroup -ne $null)
           {
                Write-Host "Create share for developers"
                $siteDevelopersGroupSplit = $siteDevelopersGroup.split("\") 
                
                $siteDevelopersGroupAce = New-ACE -Domain $siteDevelopersGroupSplit[0] -Name $siteDevelopersGroupSplit[1] -Permission "Full" -ComputerName $server

                Write-Host "Share creation..."
                #Create the share on the local machine
                $result = New-Share -FolderPath $siteDirectory -ShareName "$siteName" -ACEs $siteDevelopersGroupAce 

                #Check if the share was succesfully created
                If ($result.ReturnCode -ne 0)
                {
                	Write-Warning $result.Message
                }   
                else
                {
                    Write-Host $result.Message
                }
           }
           
           #Create custom log directory
           Write-Host "Create custom logs directory"
           $customLogsDirectory = "G:\SiteLogs\$siteName"
           Write-Host "Custom logs directory: $customLogsDirectory"
           New-Item -ItemType Directory -Path $customLogsDirectory | Out-Null
           
           #Set rights for custom logs folder
           Write-Host "Set rights for custom logs folder"
           $customLogsDirectoryAcl = get-acl $customLogsDirectory
           
           #Read Access for log readers
           $logsReadersGroupPermission = $logsReadersGroup,"ReadAndExecute", $inherit, $propagation, "Allow"
           $logsReadersGroupAccessRule = new-object System.Security.AccessControl.FileSystemAccessRule $logsReadersGroupPermission
           $customLogsDirectoryAcl.SetAccessRule($logsReadersGroupAccessRule)
           
           if ($impersonate)
           {
                #Read/Write access for site users (if impersonate)
                $siteUsersGroupPermission = $siteUsersGroup, "Modify", $inherit, $propagation, "Allow"
                $siteUsersGroupAccessRule = new-object System.Security.AccessControl.FileSystemAccessRule $siteUsersGroupPermission
                $customLogsDirectoryAcl.SetAccessRule($siteUsersGroupAccessRule)
           }
           
           #Read/Write access for Application Pool account
           $appPoolAccountPermission = $appPoolAccount,"Modify", $inherit, $propagation, "Allow"
           $appPoolAccountAccessRule = new-object System.Security.AccessControl.FileSystemAccessRule $appPoolAccountPermission
           $customLogsDirectoryAcl.SetAccessRule($appPoolAccountAccessRule)
           
           Write-Host "Set ACL for custom logs directory"
           $customLogsDirectoryAcl | Set-Acl $customLogsDirectory
           
           #Create share
           Write-Host "Create share for custom logs directory"
           $logsReadersGroupSplit = $logsReadersGroup.split("\") 
           $logsReadersGroupAce = New-ACE -Domain $logsReadersGroupSplit[0] -Name $logsReadersGroupSplit[1] -Permission "Read" -ComputerName $server
           Write-Host "Share creation..."
           #Create the share on the local machine
           $result = New-Share -FolderPath $customLogsDirectory -ShareName "$siteName-Logs" -ACEs $logsReadersGroupAce 
           #Check if the share was succesfully created
           If ($result.ReturnCode -ne 0)
           {
                Write-Warning $result.Message
           }   
           else
           {
                Write-Host $result.Message
           }
           
           #Create site
           #Bug, if it's the first site created, the ID parameter is mandatory.
           Write-Host "Create site $siteName"
           if ((Get-Website) -eq $null)
           {
              $site = New-WebSite -Name "$siteName" -ID 1 -Port 80 -HostHeader $hostHeader -PhysicalPath $siteDirectory -ApplicationPool $applicationPoolName       
           }
           else
           {
              $site = New-WebSite -Name "$siteName" -Port 80 -HostHeader $hostHeader -PhysicalPath $siteDirectory -ApplicationPool $applicationPoolName        
           }
                      
           $siteId = $site.ID
           
           #Create IIS log directory
           Write-Host "Create IIS logs directory"
           $iisLogsDirectory = "G:\IISLogs\LogFiles\W3SVC$siteId"
           Write-Host "IIS logs directory: $iisLogsDirectory"
           New-Item -ItemType Directory -Path $iisLogsDirectory | Out-Null
           
           #Remove all rights 
           $iisLogsDirectoryAcl = Get-Acl $iisLogsDirectory
           $iisLogsDirectoryAcl.SetAccessRuleProtection($true, $false)
           
           #Full control admin 
           $administratorsPermission = "Administrators", "FullControl", $inherit, $propagation, "Allow"
           $administratorsAccessRule = new-object System.Security.AccessControl.FileSystemAccessRule $administratorsPermission
           $iisLogsDirectoryAcl.SetAccessRule($administratorsAccessRule)

           #Full control system 
           $systemPermission = "System", "FullControl", $inherit, $propagation, "Allow"
           $systemAccessRule = new-object System.Security.AccessControl.FileSystemAccessRule $systemPermission
           $iisLogsDirectoryAcl.SetAccessRule($systemAccessRule)
           
           #Add logs readers rights
           #Read Access for log readers
           $logsReadersGroupPermission = $logsReadersGroup,"ReadAndExecute", $inherit, $propagation, "Allow"
           $logsReadersGroupAccessRule = new-object System.Security.AccessControl.FileSystemAccessRule $logsReadersGroupPermission
           $iisLogsDirectoryAcl.SetAccessRule($logsReadersGroupAccessRule)
           
           $iisLogsDirectoryAcl | Set-Acl $iisLogsDirectory
           
           #Create share
           Write-Host "Create share for custom logs directory"
           $logsReadersGroupSplit = $logsReadersGroup.split("\") 
           $logsReadersGroupAce = New-ACE -Domain $logsReadersGroupSplit[0] -Name $logsReadersGroupSplit[1] -Permission "Read" -ComputerName $server
           Write-Host "Share creation..."
           #Create the share on the local machine
           $result = New-Share -FolderPath $iisLogsDirectory -ShareName "$siteName-IISLogs" -ACEs $logsReadersGroupAce 
           #Check if the share was succesfully created
           If ($result.ReturnCode -ne 0)
           {
                Write-Warning $result.Message
           }   
           else
           {
                Write-Host $result.Message
           }
           
           ############## FAILED REQUESTS LOG ################
           
           #Create IIS Failed requests log directory
           Write-Host "Create IIS failed requests logs directory"
           $iisFailedRequestLogsDirectory = "G:\IISLogs\FailedReqLogFiles\W3SVC$siteId"
           Write-Host "IIS failed requests logs directory: $iisFailedRequestLogsDirectory"
           New-Item -ItemType Directory -Path $iisFailedRequestLogsDirectory | Out-Null
           
           $iisFailedRequestLogsDirectoryAcl = Get-Acl $iisFailedRequestLogsDirectory
           
           #Read Access for log readers
           $logsReadersGroupPermission = $logsReadersGroup,"ReadAndExecute", $inherit, $propagation, "Allow"
           $logsReadersGroupAccessRule = new-object System.Security.AccessControl.FileSystemAccessRule $logsReadersGroupPermission
           $iisFailedRequestLogsDirectoryAcl.SetAccessRule($logsReadersGroupAccessRule)
           
           $iisFailedRequestLogsDirectoryAcl | Set-Acl $iisFailedRequestLogsDirectory
           
           #Create share
           Write-Host "Create share for custom logs directory"
           $logsReadersGroupSplit = $logsReadersGroup.split("\") 
           $logsReadersGroupAce = New-ACE -Domain $logsReadersGroupSplit[0] -Name $logsReadersGroupSplit[1] -Permission "Read" -ComputerName $server
           Write-Host "Share creation..."
           #Create the share on the local machine
           $result = New-Share -FolderPath $iisFailedRequestLogsDirectory -ShareName "$siteName-IISFailedReqLogs" -ACEs $logsReadersGroupAce 
           #Check if the share was succesfully created
           If ($result.ReturnCode -ne 0)
           {
                Write-Warning $result.Message
           }   
           else
           {
                Write-Host $result.Message
           }
           
        }

        #Local debug
        #Invoke-Command -ArgumentList "Server1",$siteName,$x64Bits,$integratedMode,$managedRuntimeVersion,$intHostHeader,$intAppPoolAccount,$intAppPoolPassword,$writeAccessAppPoolAccount,$intSiteUsersGroup,$writeAccessSiteUsersGroup,$intLogsReadersGroup,$impersonate,$siteDevelopersGroup -scriptblock $sb
        #Write-Error "DEBUG" -ErrorAction Stop


    #Check connection on all servers
    Write-Host
    Write-Host "#############################"
    Write-Host "Check connections"
    Write-Host "#############################"
    $allServers = $intServers + $qasServers + $prdServers
    $connectionErrors = $false
    foreach ($server in $allServers)
    {
        try
        {
            Write-Host "Check $server connection"
            $s = New-PsSession -computername $server
            Remove-PsSession -session $s
        }
        catch
        {
            Write-Warning "Server $server is unavailable"
            $connectionErrors = $true
        }
    }

    if ($connectionErrors)
    {
        $continue = Read-Host "Some servers are not available. Do you want to continue (Y/N)"
        if ($continue.ToUpper() -ne "Y")
        {
            Write-Error "Operation cancelled by user." -ErrorAction Stop
        }
    }
    
    Write-Host        
    Write-Host
    Write-Host "#########################################################"
    Write-Host "INT SERVERS"
    Write-Host "#########################################################"
    foreach ($intServer in $intServers)
    {
        Write-Host
        Write-Host "#############################"
        Write-Host "Server: $intServer"
        Write-Host "#############################"
        $s = New-PsSession -computername $intServer 
        try
        {
            Invoke-Command -session $s -scriptblock $sb -ArgumentList $intServer,$siteName,$x64Bits,$integratedMode,$managedRuntimeVersion,$intHostHeader,$intAppPoolAccount,$intAppPoolPassword,$writeAccessAppPoolAccount,$intSiteUsersGroup,$writeAccessSiteUsersGroup,$intLogsReadersGroup,$impersonate,$siteDevelopersGroup
        }
        finally
        {
            Remove-PsSession -session $s
        }
    }

    Write-Host
    Write-Host "#########################################################"
    Write-Host "QAS SERVERS"
    Write-Host "#########################################################"
    foreach ($qasServer in $qasServers)
    {
        Write-Host
        Write-Host "#############################"
        Write-Host "Server: $qasServer"
        Write-Host "#############################"
        $s = New-PsSession -computername $qasServer 
        try
        {
            Invoke-Command -session $s -scriptblock $sb -ArgumentList $qasServer,$siteName,$x64Bits,$integratedMode,$managedRuntimeVersion,$qasHostHeader,$qasAppPoolAccount,$qasAppPoolPassword,$writeAccessAppPoolAccount,$qasSiteUsersGroup,$writeAccessSiteUsersGroup,$qasLogsReadersGroup,$impersonate
        }
        finally
        {
            Remove-PsSession -session $s
        }
    }

    Write-Host
    Write-Host "#########################################################"
    Write-Host "PRD SERVERS"
    Write-Host "#########################################################"
    foreach ($prdServer in $prdServers)
    {
        Write-Host
        Write-Host "#############################"
        Write-Host "Server: $prdServer"
        Write-Host "#############################"
        $s = New-PsSession -computername $prdServer 
        try
        {
            Invoke-Command -session $s -scriptblock $sb -ArgumentList $prdServer,$siteName,$x64Bits,$integratedMode,$managedRuntimeVersion,$prdHostHeader,$prdAppPoolAccount,$prdAppPoolPassword,$writeAccessAppPoolAccount,$prdSiteUsersGroup,$writeAccessSiteUsersGroup,$prdLogsReadersGroup,$impersonate
        }
        finally
        {
            Remove-PsSession -session $s
        }
    }
}
catch
{
    Write-Error $_.ToString()
}
finally
{
    Stop-Transcript
}

Open in new window


XML File:
 
<?xml version="1.0" encoding="utf-8" ?>
<!--
  Site:
    ApplicationName = Site name
    x64Bits=         
      - true = 64bits
      - false = 32bits
    IntegratedMode=  
      - true= Integrated Mode
      - false= Classic Mode 
    ManagedRuntimeVersion =
      - v4.0 = .NET 4.0
      - v2.0 = .NET 2.0, 3.0, 3.5
    WriteAccessAppPoolAccount = false (As default)
      - true = Give write access for the application pool account on the site directory.
      - false = Don't give write access for the application pool account on the site directory.
    WriteAccessSiteUsersGroup = false (As default)
      - true = Give write access for the site users group account on the site directory.
      - false = Don't give write access for the site users group on the site directory.    
    Impersonate = 
      - true = The site will used impersonation, so site users group need a read/write access on the custom logs folder.
      - false = The site will not used impersonation, so site users group doesn't need a read/write access on the custom logs folder.
    DevelopersGroup = An AD group with the developers. The access is given only on the int environment.
  
  Environment:
    HostHeader = An host header to access the site
    AppPoolAccount = The service account used by the application pool
    AppPoolPassword = The password of the application pool account
    SiteUsersGroup = An AD group with all the users of the site (or "Authenticated Users")
    LogsReadersGroup = An AD group with the users allowed to read the logs of the application. (Custom, IIS + Failed requests logs) //idem idem
-->
<Site Name="VodafoneWeb"
      x64Bits="False"
      IntegratedMode="true"
      ManagedRuntimeVersion="v2.0"
      WriteAccessAppPoolAccount="false"
      WriteAccessSiteUsersGroup="false"
      Impersonate="false"
      ADGroup1>
  <Int>
    <HostHeader>Application.com</HostHeader>
    <AppPoolAccount>Domain\account-int</AppPoolAccount>
    <AppPoolPassword>xxxx</AppPoolPassword>
    <SiteUsersGroup>Domain\Group</SiteUsersGroup>
    <LogsReadersGroup>Domain\Group</LogsReadersGroup>
  </Int>
  <Qas>
    <HostHeader>Application.com</HostHeader>
    <AppPoolAccount>Domain\account-int</AppPoolAccount>
    <AppPoolPassword>xxxx</AppPoolPassword>
    <SiteUsersGroup>Domain\Group</SiteUsersGroup>
    <LogsReadersGroup>Domain\Group</LogsReadersGroup>
  </Qas>
  <Prd>
    <HostHeader>Application.com</HostHeader>
    <AppPoolAccount>Domain\account-int</AppPoolAccount>
    <AppPoolPassword>xxxx</AppPoolPassword>
    <SiteUsersGroup>Domain\Group</SiteUsersGroup>
    <LogsReadersGroup>Domain\Group</LogsReadersGroup>
  </Prd>
</Site>

Open in new window



Thanks in advance,
0
Comment
Question by:Gonzalo Becerra
  • 11
  • 5
16 Comments
 
LVL 23

Expert Comment

by:bhanukir7
Comment Utility
hi,

the error in the script is with resolving the int-prd-qa server names. This might be because either remote management is not enabled on those servers or the account which is running the script does not have the permissions.

Can you try running the same from a elevated command prompt or verify that Remote management is enabled on those servers and the user has the permissions to manage remotely.

regards
bhanu
0
 
LVL 1

Author Comment

by:Gonzalo Becerra
Comment Utility
The server names it's ok, i runned in the remote servers the following command

Enable-PSRemote

And then I executed the script with my account (is administrator of the spcified servers)
0
 
LVL 1

Author Comment

by:Gonzalo Becerra
Comment Utility
How can I run elevated command prompt? How can I verify if my user has permissions to manage remotly?
0
 
LVL 23

Expert Comment

by:bhanukir7
Comment Utility
hi,

you can run powershell or any application as elevated user by right clicking on the exe and select "run as administrator"

verify if winRM is running on the remote systems by typing at a elevated command prompt

winrm id -r:remotehostname

if not install winrm on those machines

regards
bhanu
0
 
LVL 1

Author Comment

by:Gonzalo Becerra
Comment Utility
Hi,

I executed this command pointing locally (pmichlauweb71) or remote server pmichlauweb71 and always I recieve the same error attached.

Error:
Error
Also I runned this command again "Enable-PSRemoting" on both servers and always recieve the message :
WinRM already is set up to receive requests on this machine.
WinRM already is set up for remote management on this machine.
0
 
LVL 1

Author Comment

by:Gonzalo Becerra
Comment Utility
Why we have this error? do you know how I can troubleshoot?
0
 
LVL 1

Author Comment

by:Gonzalo Becerra
Comment Utility
it's possible a Kerberos problem? how can I troubleshoot this issue?
0
 
LVL 23

Expert Comment

by:bhanukir7
Comment Utility
hi cerra,

my apologies for not getting back to you earlier.  you can try disabling kerbros authentication

Enabling or Disabling Authentication Options
The default authentication option at system installation is Kerberos. For more information, see Installation and Configuration for Windows Remote Management.

If your script or application requires a specific authentication method that is not enabled, you must change the configuration to enable this type of authentication. This change can be made using the Winrm command-line tool or through Group Policy for the Windows Remote Management Group Policy Object. You may also choose to disable certain methods of authentication.

To enable or disable authentication with the Winrm tool

1.To set the configuration for the WinRM client, use the Winrm Set command and specify the client. For example, the following command disables Digest authentication for the client.

winrm set winrm/config/client/auth @{Digest="false"}

2.To set the configuration for the WinRM server, use the Winrm Set command and specify the service. For example, the following command enables Kerberos authentication for the service.

http://msdn.microsoft.com/en-sg/library/aa384295(v=VS.85).aspx

Disable UAC temporarily on the windows 2008 remote machines and verify.



Read this technet article for better understanding.

0
How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

 
LVL 1

Author Comment

by:Gonzalo Becerra
Comment Utility
I have this configuration on both servers:
SERVER2 (Work)
SERVER1 (Fail)
PS C:\ACO-SRVS\Scripts\Site Creation> winrm get winrm/config/service/Auth
Auth
    Basic = false
    Kerberos = true
    Negotiate = true
    Certificate = false
    CredSSP = false
    CbtHardeningLevel = Relaxed

When I run this command I have this error:
PS C:\ACO-SRVS\Scripts\Site Creation> winrm set winrm/config/client/auth @(Negotiate="false")

The term 'Negotiate=false' is not recognized as the name of a cmdlet, function, script file, or operable program. Check
 the spelling of the name, or if a path was included, verify that the path is correct and try again.
At line:1 char:55
+ winrm set winrm/config/client/auth @(Negotiate="false" <<<< )
    + CategoryInfo          : ObjectNotFound: (Negotiate=false:String) [], CommandNotFoundException
    + FullyQualifiedErrorId : CommandNotFoundException
0
 
LVL 1

Author Comment

by:Gonzalo Becerra
Comment Utility
This is the actual configuration:

PS C:\ACO-SRVS\Scripts\Site Creation> winrm get winrm/config
Config
    MaxEnvelopeSizekb = 150
    MaxTimeoutms = 60000
    MaxBatchItems = 32000
    MaxProviderRequests = 4294967295
    Client
        NetworkDelayms = 5000
        URLPrefix = wsman
        AllowUnencrypted = false
        Auth
            Basic = true
            Digest = true
            Kerberos = true
            Negotiate = true
            Certificate = true
            CredSSP = false
        DefaultPorts
            HTTP = 5985
            HTTPS = 5986
        TrustedHosts = SERVER2
    Service
        RootSDDL = O:NSG:BAD:P(A;;GA;;;BA)S:P(AU;FA;GA;;;WD)(AU;SA;GWGX;;;WD)
        MaxConcurrentOperations = 4294967295
        MaxConcurrentOperationsPerUser = 15
        EnumerationTimeoutms = 60000
        MaxConnections = 25
        MaxPacketRetrievalTimeSeconds = 120
        AllowUnencrypted = false
        Auth
            Basic = false
            Kerberos = true
            Negotiate = true
            Certificate = false
            CredSSP = false
            CbtHardeningLevel = Relaxed
        DefaultPorts
            HTTP = 5985
            HTTPS = 5986
        IPv4Filter = *
        IPv6Filter = *
        EnableCompatibilityHttpListener = false
        EnableCompatibilityHttpsListener = false
        CertificateThumbprint
    Winrs
        AllowRemoteShellAccess = true
        IdleTimeout = 180000
        MaxConcurrentUsers = 5
        MaxShellRunTime = 2147483647
        MaxProcessesPerShell = 15
        MaxMemoryPerShellMB = 150
        MaxShellsPerUser = 5
0
 
LVL 23

Expert Comment

by:bhanukir7
Comment Utility
hi gbecerra,

you mentioned that in your earlier post it worked on one and failed on another.
###############################
I have this configuration on both servers:
SERVER2 (Work)
SERVER1 (Fail)
###############################

Is the OS running on both boxes the same. Was the path from where you ran the command same. I think there is some group policy or some security settings that are blocking this.

Can you request help from other experts as this problem of yours seems to be bit more complex and maybe you need to get input from other experts.

regards
bhanu
0
 
LVL 1

Author Comment

by:Gonzalo Becerra
Comment Utility
Thanks bhanu,

I checked the GPO and it's all in status "Not Configured" but I think the problem is related with Kerberos issue.

Who can help me to follow this issue?. Thanks in advance.
0
 
LVL 1

Accepted Solution

by:
Gonzalo Becerra earned 0 total points
Comment Utility
I opened a case in Microsoft to solve this issue:

- Problem: Duplicate SPN's
- Query to verify if we have SPN Duplicated:  ldifde -f dump_spn.txt -d "dc=DOMAIN,dc=com" -p subtree -r "(servicePrincipalName=HTTP/Servername*)" -l servicePrincipalName

- Solution: Verify the log dump_spn.txt and delete the duplicates SPN.
0
 
LVL 23

Expert Comment

by:bhanukir7
Comment Utility
hi Gbecerra,

Thanks for posting back the solution, as you are closing the question instead of deleting it, hopefully this will help other EE users.

BTW few links that can be more helpful for users having SPN issues :

http://support.microsoft.com/kb/321044

one good blog article i found covering in some more depth was this.

http://blog.joeware.net/2008/07/17/1407/


Regards
Bhanu
0
 
LVL 1

Author Comment

by:Gonzalo Becerra
Comment Utility
Thank you Bhanu for the articles :D
0
 
LVL 1

Author Closing Comment

by:Gonzalo Becerra
Comment Utility
The script is OK, I posted the solution.
0

Featured Post

6 Surprising Benefits of Threat Intelligence

All sorts of threat intelligence is available on the web. Intelligence you can learn from, and use to anticipate and prepare for future attacks.

Join & Write a Comment

The recent Microsoft changes on update philosophy for Windows pre-10 and their impact on existing WSUS implementations.
Possible fixes for Windows 7 and Windows Server 2008 updating problem. Solutions mentioned are from Microsoft themselves. I started a case with them from our Microsoft Silver Partner option to open a case and get direct support from Microsoft. If s…
This tutorial will walk an individual through the steps necessary to enable the VMware\Hyper-V licensed feature of Backup Exec 2012. In addition, how to add a VMware server and configure a backup job. The first step is to acquire the necessary licen…
In this fourth video of the Xpdf series, we discuss and demonstrate the PDFinfo utility, which retrieves the contents of a PDF's Info Dictionary, as well as some other information, including the page count. We show how to isolate the page count in a…

728 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

10 Experts available now in Live!

Get 1:1 Help Now