Aug 06

Configuring AnyConnect SSL VPN Client Connections

Overview

ASA: 8.3+ (Written/Tested on 9.0)

Authentication: Local (Local ASA User Database)

Type: Split-tunnel OR Non split-tunnel

The below configurations will work with 8.3+, but was written and tested with 9.0.  When setting up a Anyconnect VPN tunnel, you can push all traffic from the client over the VPN (Tunnel all) or you can use a split tunnel to only push traffic destined for selected subnets over the VPN tunnel.  In laymen terms, the clients internet traffic originates from their ISP in a split tunnel, and it originates from the ASA when using tunnel all.  The below configuration examples assume you have a basic setup equivalent to running factory-default and are setup to authenticate locally to the ASA.  I will give examples of each configuration below.

Network Diagram

Network Diagram Anyconnect VPN

The ASA has a command that gives an overview of how to configure an Anyconnect SSL VPN, which in global configuration mode is vpnsetup ssl-remote-access steps.  Here are the results of that command:

ciscoasa(config)# vpnsetup ssl-remote-access steps

Steps to configure a remote access SSL VPN remote access connection and AnyConnect with examples:

1. Configure and enable interface

        interface GigabitEthernet0/0
         ip address 10.10.4.200 255.255.255.0
         nameif outside
         no shutdown

        interface GigabitEthernet0/1
         ip address 192.168.0.20 255.255.255.0
         nameif inside
         no shutdown

2. Enable WebVPN on the interface

        webvpn
         enable outside

3. Configure default route

        route outside 0.0.0.0 0.0.0.0 10.10.4.200

4. Configure AAA authentication and tunnel group

        tunnel-group DefaultWEBVPNGroup type remote-access
        tunnel-group DefaultWEBVPNGroup general-attributes
         authentication-server-group LOCAL

5. If using LOCAL database, add users to the Database

        username test password t3stP@ssw0rd
        username test attributes
         service-type remote-access

Proceed to configure AnyConnect VPN client:

6. Point the ASA to an AnyConnect image

        webvpn
         svc image anyconnect-win-2.1.0148-k9.pkg

7. enable AnyConnect

        svc enable

8. Add an address pool to assign an ip address to the AnyConnect client

        ip local pool client-pool 192.168.1.1-192.168.1.254 mask 255.255.255.0

9. Configure group policy

        group-policy DfltGrpPolicy internal
        group-policy DfltGrpPolicy attributes
         vpn-tunnel-protocol svc webvpn

There are a few important things to note from Cisco’s directions:

  1. They are using the default names for configuring the group policy and tunnel groups, which will throw a warning that they already exist since they’re defaults
  2. The directions do not specify that you MUST attach the VPN Address pool to the tunnel group, which is necessary for it to work!
  3. They do not include how to create a split tunnel or a tunnel all to allow internet from the Anyconnect client.
  4. They are using outdated “svc” commands, which were replaced with “anyconnect”.

With that said, let’s move on to the configurations!

Anyconnect Configuration 1: Tunnel All

!Enable WebVPN, Set Anyconnect Image, and Enable Anyconnect
config t
webvpn
enable outside
tunnel-group-list enable
anyconnect image disk0:/anyconnect-win-3.1.05178-k9.pkg 1
anyconnect image disk0:/anyconnect-macosx-i386-3.1.05178-k9.pkg 2
anyconnect image disk0:/anyconnect-linux-3.1.05178-k9.pkg 3
anyconnect enable
end
!Create DHCP Pool for Anyconnect Clients
config t
ip local pool pool-anyconnect 192.168.100.1-192.168.100.254 mask 255.255.255.0
end
!Create Group Policy for Anyconnect
config t
group-policy GroupPolicy_Anyconnect internal
group-policy GroupPolicy_Anyconnect attributes
vpn-tunnel-protocol ssl-client
end
!Create Tunnel Group for Anyconnect
config t
tunnel-group TunnelGroup_Anyconnect type remote-access
tunnel-group TunnelGroup_Anyconnect general-attributes
authentication-server-group LOCAL
default-group-policy GroupPolicy_Anyconnect
address-pool pool-anyconnect
tunnel-group TunnelGroup_Anyconnect webvpn-attributes
group-alias 1-Admin enable
end
!Create NAT Exemption and Enable Outside Traffic to Enter/Exit the Same Interface
config t
object-group network obj-anyconnect
network-object 192.168.100.0 255.255.255.0
exit
nat (outside,outside) after-auto source dynamic obj-anyconnect interface
same-security-traffic permit intra-interface
end
!Tunnel All Traffic Over Anyconnect VPN and Force Use of DNS Servers
config t
group-policy GroupPolicy_Anyconnect attributes
split-tunnel-policy tunnelall
split-tunnel-all-dns enable
end
!(OPTIONAL)Create Local User for Anyconnect
config t
username user1 password P@SSWORD
username user1 attributes
service-type remote-access
end
!(OPTIONAL) Add DNS Settings for Anyconnect Client
config t
group-policy GroupPolicy_Anyconnect attributes
dns-server value 10.1.1.10 10.1.1.11
default-domain value domain.local
end
!(OPTIONAL) Allow Anyconnect IP Pool to Manage ASA
config t
ssh 192.168.100.0 255.255.255.0 inside
http 192.168.100.0 255.255.255.0 inside
management-access inside
end
!(OPTIONAL)Auto launch anyconnect
config t
group-policy GroupPolicy_Anyconnect attributes
webvpn
anyconnect ask none default anyconnect
end

 Anyconnect Configuration 2: Split Tunnel

!Enable WebVPN, Set Anyconnect Image, and Enable Anyconnect
config t
webvpn
enable outside
tunnel-group-list enable
anyconnect image disk0:/anyconnect-win-3.1.05178-k9.pkg 1
anyconnect image disk0:/anyconnect-macosx-i386-3.1.05178-k9.pkg 2
anyconnect image disk0:/anyconnect-linux-3.1.05178-k9.pkg 3
anyconnect enable
end
!Create DHCP Pool for Anyconnect Clients
config t
ip local pool pool-anyconnect 192.168.100.1-192.168.100.254 mask 255.255.255.0
end
!Create Group Policy for Anyconnect
config t
group-policy GroupPolicy_Anyconnect internal
group-policy GroupPolicy_Anyconnect attributes
vpn-tunnel-protocol ssl-client
end
!Create Tunnel Group for Anyconnect
config t
tunnel-group TunnelGroup_Anyconnect type remote-access
tunnel-group TunnelGroup_Anyconnect general-attributes
authentication-server-group LOCAL
default-group-policy GroupPolicy_Anyconnect
address-pool pool-anyconnect
tunnel-group TunnelGroup_Anyconnect webvpn-attributes
group-alias 1-Admin enable
end
!Create NAT Exemption
config t
object-group network obj-anyconnect
network-object 192.168.100.0 255.255.255.0
exit
nat (inside,outside) 2 source static any any destination static obj-anyconnect obj-anyconnect no-proxy-arp route-lookup
end
!Create Split Tunnel, Allow Access to VPN and Inside Subnets, and Apply to Group Policy
config t
access-list ACL_split-tunnel standard permit 192.168.100.0 255.255.255.0
access-list ACL_split-tunnel standard permit 10.1.1.0 255.255.255.0
group-policy GroupPolicy_Anyconnect attributes
split-tunnel-policy tunnelspecified
split-tunnel-network value ACL_split-tunnel
end
!(OPTIONAL)Create Local User for Anyconnect
config t
username user1 password P@SSWORD
username user1 attributes
service-type remote-access
end
!(OPTIONAL) Add DNS Settings for Anyconnect Client
config t
group-policy GroupPolicy_Anyconnect attributes
dns-server value 10.1.1.10 10.1.1.11
default-domain value domain.local
end
!(OPTIONAL) Allow Anyconnect IP Pool to Manage ASA
config t
ssh 192.168.100.0 255.255.255.0 inside
http 192.168.100.0 255.255.255.0 inside
management-access inside
end
!(OPTIONAL)Auto launch anyconnect
config t
group-policy GroupPolicy_Anyconnect attributes
webvpn
anyconnect ask none default anyconnect
end

 

Testing the Configuration

Open a web browser, connect to your ASA (https://vpn.domain.com OR https://172.31.100.1), and you’ll be prompted to login.  You can login with the user account you’ve created in the configuration above.  The Anyconnect client will automatically install, if it fails you may need to download and manually install it.  Once installed, you can connect to your ASA by the outside interface (vpn.domain.com OR 172.31.100.1) and authenticate with the user you’ve created.

Additional Notes

You may wish to use a 3rd party SSL certificates (ie: Verisign, Thawte, Godaddy, etc) so end users do not get prompted about certificate warnings.  Cisco ASA’s will regenerate it’s certificate upon reboot, and due to this you should create a self signed certificate whenever you cannot use a 3rd party.  You can create the self signed certificate as follows:

!Create Self Signed Certificate
config t
crypto ca trustpoint SELF
enroll
enrollment self
fqdn vpn.domain.com
subject cn=vpn.domain.com,dc=domain,dc=com
exit
crypto ca enroll SELF
!The following warnings will generate, answer accordingly as below:
!
!WARNING: The certificate enrollment is configured with an fqdn
!that differs from the system fqdn. If this certificate will be
!used for VPN authentication this may cause connection problems.
!
!Would you like to continue with this enrollment? [yes/no]: yes
!
!The fully-qualified domain name in the certificate will be: vpn.domain.com
!
!Include the device serial number in the subject name? [yes/no]: no
!
!Generate Self-Signed Certificate? [yes/no]: yes
!
!Attach the certificate to the outside interface
ssl trust-point SELF outside
end

 

Aug 05

DirMirror.vbs

Option Explicit
'=========================================================================
' DirMirror.vbs
' VERSION: 1.0
' AUTHOR: Brian Steinmeyer
' EMAIL: sigkill@sigkillit.com
' WEB: http://sigkillit.com
' DATE: 9/26/2013
' REQUIREMENTS:
' - robocopy.exe (Built in to Server2008+, Windows 7+)
' - blat.exe, blat.dll. blat.lib in the same directory as the script (http://www.blat.net)
' - Blat profile installed to email results
' - Recommended to use Stunnel to Encrypt Email Sessions, Especially If the Email Server
' is not on your subnet ex: Gmail
' COMMENTS: Requires robocopy for the backup and blat to email results. Define
' the Directory Source(what you need to backup), the Directory Destination
' (where you need to backup to), path to blat, blat profile, email subject,
' and email body
'=========================================================================

' ------ SCRIPT CONFIGURATION ------
Const WindowStyle = 0  '0=Hide Robocopy Console, 1=Show Robocopy Console
Dim DirSource: DirSource = "\\server\share\directory"
Dim DirDestination: DirDestination = Left(WScript.ScriptFullName,InstrRev(WScript.ScriptFullName,"\")) & "backup"
Dim intReturn 'Generic Return
Dim logErrors: logErrors = Replace(WScript.ScriptFullName,".vbs","_log.txt")
Dim emailBlatExe: emailBlatExe = "C:\blat\blat.exe" 'Custom Path to Blat.exe Default is Same Folder as Script
Dim emailProfile: emailProfile = "gmail" 'Blat Profile Name See (http://www.blat.net) For Info
Dim emailRecipient: emailRecipient = "email@domain.com" 'Email to Receive Backup Result
Dim eSubject: eSubject = "Server1 Backup"
Dim eBody: eBody = "Server1 Backup"
' ------ END CONFIGURATION ------

'MAIN CALLS
Call Logger(logErrors, "[" & Now() & "] " & vbCrLf & Wscript.ScriptName & vbCrLf & "Server: Spiceworks", True)
Call AllowSingleInstance(".",logErrors, emailBlatExe, emailProfile, emailRecipient, eSubject, eBody)
Call ConfirmDirectories(logErrors, DirSource, DirDestination, emailBlatExe, emailProfile, emailRecipient, eSubject, eBody)
Call RoboDirMirror(logErrors, DirSource, DirDestination, emailBlatExe, emailProfile, emailRecipient, eSubject, eBody)



' ***************************************************************************************************
' Function RoboDirMirror - Mirrors a Source Directory to a Mirror Directory Using Robocopy
' ***************************************************************************************************
Private Sub RoboDirMirror(logName, strSource, strDestination, emailBlatExe, emailProfile, emailRecipient, emailSubject, emailBody)

	'On Error Resume Next
	
	Call Logger(logName, vbCrLf & "[" & Now() & "] " & vbCrLf & "Run Robocopy to Mirror Directory", False)
	'Ensure Directories Don't End with Slash or Robocopy Will Error
	If Mid(strSource,Len(strSource),1) = "\" Then
		strSource = Mid(strSource,1,Len(strSource) - 1)
	End If
	If Mid(strDestination,Len(strDestination),1) = "\" Then
		strDestination = Mid(strDestination,1,Len(strDestination) - 1)
	End If
	
	Dim objShell: Set objShell = WScript.CreateObject("WScript.Shell")
	Dim strCommand: strCommand = "robocopy"
	Dim cmdOptions: cmdOptions = "/MIR /FFT /Z /XA:H /W:5 /log+:" & chr(34) & logName & chr(34)
	'Robocopy \\SourceServer\Share \\DestinationServer\Share /MIR /FFT /Z /XA:H /W:5
	Dim intReturn: intReturn = objShell.Run(strCommand & " " & chr(34) & strSource & chr(34) & " " & chr(34) & strDestination & chr(34) & " " & cmdOptions, WindowStyle, True)
	Select Case intReturn
	Case 0
		'No Files Copied
		Call Logger(logName, "RESULT: Success - No Files Copied", False)
		emailSubject = emailSubject & " Success"
		emailBody = emailBody & " Success - No Files Copied"
	Case 1
		'Files Copied
		Call Logger(logName, "RESULT: Success - Files Copied", False)
		emailSubject = emailSubject & " Success"
		emailBody = emailBody & " Success - Files Copied"
	Case 2
		'File on Source Does Not Exist on Destination
		Call Logger(logName, "RESULT: Success - New Files Found in Source that are Not in Destination", False)
		emailSubject = emailSubject & " Success"
		emailBody = emailBody & " Success - New Files Found in Source that are Not in Destination"
	Case 3
		'Combination of Case1 and Case2
		Call Logger(logName, "RESULT: Success - Files Copied (New Files Found in Source that are Not in Destination)", False)
		emailSubject = emailSubject & " Success"
		emailBody = emailBody & " Success - Files Copied (New Files Found in Source that are Not in Destination)"
	Case Else
		'Error
		Call Logger(logName, "RESULT: !~ERROR~! - Error Occurred on Robocopy", False)
		emailSubject = emailSubject & " FAILED"
		emailBody = emailBody & " FAILED - Error Occurred on Robocopy"
	End Select
	
	If Err.Number <> 0 Then
		Err.Clear
		Call Logger(logName, "!~ERROR~! - Unknown Error Occurred in RoboDirMirror Sub", False)
		emailSubject = emailSubject & " FAILED"
		emailBody = emailBody & " FAILED - Unknown Error Occurred in RoboDirMirror Sub"
	End If
	
	Call SendBlatEmail(emailBlatExe, emailProfile, emailRecipient, emailSubject, emailBody, logName)
	
End Sub



' ***************************************************************************************************
' Function ConfirmDirectories - Confirm Source and Destination Directories Exist
' ***************************************************************************************************
Private Sub ConfirmDirectories(logName, strSource, strDestination, emailBlatExe, emailProfile, emailRecipient, emailSubject, emailBody)

	'On Error Resume Next
	
	Call Logger(logName, vbCrLf & "[" & Now() & "] " & vbCrLf & "Confirm Source/Destination Directories Exist", False)
	' Create Objects
	Dim objFSO: Set objFSO = CreateObject("Scripting.FileSystemObject")
	Call Logger(logName, "SOURCE: " & strSource, False)
	Call Logger(logName, "DESTINATION: " & strDestination, False)
	If Not objFSO.FolderExists(strSource) Then
		'Source Not Exist
		Call Logger(logName, "!~ERROR~! - Source Directory Does Not Exist, Quitting Script!", False)
		emailSubject = emailSubject & " FAILED"
		emailBody = emailBody & " Failed - Source Directory Does Not Exist"
		Call SendBlatEmail(emailBlatExe, emailProfile, emailRecipient, emailSubject, emailBody, logName)
		Wscript.Quit
	Else
		Call Logger(logName, "Success - Source Directory Exists", False)
	End If
	
	If Not objFSO.FolderExists(strDestination) Then
		'Destination Not Exist
		Call Logger(logName, "Warning - Destination Directory Does Not Exist, Attempting to Create It", False)
		'Attempt to Create
		Call CreateFileOrDir(strDestination)
		If Not objFSO.FolderExists(strDestination) Then
			Call Logger(logName, "!~ERROR~! - Failed to Create Destination Directory, Quitting Script!", False)
			emailSubject = emailSubject & " FAILED"
			emailBody = emailBody & " Failed - Destination Directory Does Not Exist and Failed to Create It"
			Call SendBlatEmail(emailBlatExe, emailProfile, emailRecipient, emailSubject, emailBody, logName)
			Wscript.Quit
		Else
			Call Logger(logName, "Success - Created Destination Directory", False)
		End If
	Else
		Call Logger(logName, "Success - Destination Directory Exists", False)
	End If
	
	If Err.Number <> 0 Then
		Err.Clear
		Call Logger(logName, "!~ERROR~! - Unknown Error in ConfirmDirectories Sub, Quitting Script", False)
		emailSubject = emailSubject & " FAILED"
		emailBody = emailBody & " Failed - Unknown Error in ConfirmDirectories Sub"
		Call SendBlatEmail(emailBlatExe, emailProfile, emailRecipient, emailSubject, emailBody, logName)
		Wscript.Quit
	End If
	
End Sub



' ***************************************************************************************************
' Function AllowSingleInstance - Checks if only a single instance of the script is running - useful 
'                                for repetitive scheduled tasks
' ***************************************************************************************************
Private Sub AllowSingleInstance(strComputer, logName, emailBlatExe, emailProfile, emailRecipient, emailSubject, emailBody)
	
	On Error Resume Next
	
	Call Logger(logName, vbCrLf & "[" & Now() & "] " & vbCrLf & "Confirm Single Instance of " & Wscript.ScriptName, False)
	Dim intReturn: intReturn = 0  '0=Success, 1=Error, 2=Warning
	Dim objWMIService: Set objWMIService = GetObject("winmgmts:" & "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
	Dim colItems: Set colItems = objWMIService.ExecQuery("Select * from Win32_Process Where Name = 'cscript.exe'" & " OR Name = 'wscript.exe'")
	Dim intCount: intCount = 0
	Dim objItem, strTemp

	For Each objItem in colItems
		If Not IsNull(objItem.CommandLine) Then
			strTemp = Right(objItem.CommandLine, Len(objItem.CommandLine) - InStrRev(objItem.CommandLine, chr(34) & " " & chr(34)))
			strTemp = Trim(Replace(strTemp, chr(34), ""))
			If StrComp(Wscript.ScriptFullName, strTemp, 1) = 0 Then
				intCount = intCount + 1
			End If
		End If
	Next	
	
	Call Logger(logName, "Detected Instances: " & intCount, False)
	If intCount > 1 Then
		'Kill It
		Call Logger(logName, "!~ERROR~! - Only 1 instance is allowed, Quitting Script!", False)
		emailSubject = emailSubject & " FAILED"
		emailBody = emailBody & " Backup FAILED - Detected " & intCount & " running instances"
		Call SendBlatEmail(emailBlatExe, emailProfile, emailRecipient, emailSubject, emailBody, logName)
		Wscript.Quit
	End If
	
	If Err.Number <> 0 Then
		Err.Clear
		Call Logger(logName, "!~ERROR~! - Unknown Error in AllowSingleInstance Sub, Quitting Script!", False)
		emailSubject = emailSubject & " FAILED"
		emailBody = emailBody & " Backup FAILED - Unknown Error in AllowSingleInstance Sub"
		Call SendBlatEmail(emailBlatExe, emailProfile, emailRecipient, emailSubject, emailBody, logName)
		Wscript.Quit
	End If
	
	On Error Goto 0
	
End Sub



' ***************************************************************************************************
' Function CreateFileOrDir
' ***************************************************************************************************
Private Sub CreateFileOrDir(strPath)

    On Error Resume Next

    Dim objFSO: Set objFSO = CreateObject("Scripting.FileSystemObject")
    If objFSO.DriveExists(objFSO.GetDriveName(strPath)) Then
        If StrComp(objFSO.GetExtensionName(strPath), "", 1) = 0 Then
            If Not objFSO.FolderExists(strPath) Then
                If objFSO.FolderExists(objFSO.GetParentFolderName(strPath)) Then
                    objFSO.CreateFolder strPath 'Create Folder In Current Path
                Else
                    CreateFileOrDir(objFSO.GetParentFolderName(strPath)) 'Recurse Creating Parent Folder
                    CreateFileOrDir(strPath) 'Recurse Creating Current Folder
                End If
            End If
        Else
            If Not objFSO.FileExists(strPath) Then
                If objFSO.FolderExists(objFSO.GetParentFolderName(strPath)) Then
                    objFSO.CreateTextFile strPath, True  'Create File In Current Path
                Else
                    CreateFileOrDir(objFSO.GetParentFolderName(strPath))  'Recurse Creating Parent Folder
                    CreateFileOrDir(strPath)  'Recurse Creating Current Folder
                End If
            End If
        End If
    End If
   
    On Error Goto 0
   
End Sub



' ***************************************************************************************************
' Function SendBlatEmail - Sends Email Using Blat
' ***************************************************************************************************
Private Sub SendBlatEmail(blatPath, blatProfile, strRecipients, strSubject, strBody, strAttachment)

    'Need blat.exe, blat.dll, blat.lib
    On Error Resume Next
   
    Dim objFSO: Set objFSO = CreateObject("Scripting.FileSystemObject")
    Dim objShell: Set objShell = WScript.CreateObject("WScript.Shell")
    Dim scriptPath: scriptPath = Left(WScript.ScriptFullName,InstrRev(WScript.ScriptFullName,"\"))

    'Ensure Blat Exists
    If Not objFSO.FileExists(blatPath) Then
        If Not objFSO.FileExists(scriptPath & "blat.exe") Then
            Exit Sub
        Else
            blatPath = scriptPath & "blat.exe"
        End If
    End If
   
    'Set Blat Email Command
    Dim commandText: commandText = chr(34) & blatPath & chr(34)
    commandText = commandText & " -p " & chr(34) & blatProfile & chr(34)
    commandText = commandText & " -to " & strRecipients
    commandText = commandText & " -subject " & chr(34) & strSubject & " " & chr(34) 'Keep Space to Prevent Escaping the Quote
    commandText = commandText & " -body " & chr(34) & strBody & " " & chr(34) 'Keep Space to Prevent Escaping the Quote

    'Append Attachment(s)
    If objFSO.FileExists(strAttachment) Then
        commandText = commandText & " -attach " & chr(34) & strAttachment & chr(34)
    Else
        If objFSO.FileExists(scriptPath & strAttachment) Then
            commandText = commandText & " -attach " & chr(34) & scriptPath & strAttachment & chr(34)
        End If
    End If
   
    'Send Blat Email
    objShell.run commandText, True
   
    Set objFSO = Nothing
    Set objShell = Nothing
   
    If Err.Number <> 0 Then
        Err.Clear
    End If

    On Error Goto 0
   
End Sub



' ***************************************************************************************************
' Function Logger 
' ***************************************************************************************************
Private Sub Logger(fileName, logMessage, blnNewLog)

    On Error Resume Next
   
    Const ForReading = 1, ForWriting = 2, ForAppending = 8
    Dim objFSO: Set objFSO = CreateObject("Scripting.FileSystemObject")
    Dim scriptPath: scriptPath = Left(WScript.ScriptFullName,InstrRev(WScript.ScriptFullName,"\"))
    Dim logName
    If InStr(1,fileName,"\",1) > 0 Then
        logName = fileName
        If objFSO.DriveExists(objFSO.GetDriveName(logName)) Then
            If StrComp(objFSO.GetExtensionName(logName), "", 1) = 0 Then
                If Not objFSO.FolderExists(logName) Then
                    If objFSO.FolderExists(objFSO.GetParentFolderName(logName)) Then
                        objFSO.CreateFolder logName 'Create Folder In Current Path
                        Exit Sub
                    Else
                        Call Logger(objFSO.GetParentFolderName(logName), logMessage, blnNewLog) 'Recurse Creating Parent Folder
                        Call Logger(logName, logMessage, blnNewLog) 'Recurse Creating Current Folder
                        Exit Sub
                    End If
                End If
            Else
                If Not objFSO.FileExists(logName) Then
                    If Not objFSO.FolderExists(objFSO.GetParentFolderName(logName)) Then
                        Call Logger(objFSO.GetParentFolderName(logName), logMessage, blnNewLog)  'Recurse Creating Parent Folder
                        Call Logger(logName, logMessage, blnNewLog)  'Recurse Creating Current Folder
                    End If
                End If
            End If
        End If
    Else
        logName = scriptPath & fileName
    End If
    Dim logFile
    If blnNewLog = True Then
        Set logFile = objFSO.CreateTextFile(logName, True)
    Else
        If objFSO.FileExists(logName) Then
            Set logFile = objFSO.OpenTextFile(logName, ForAppending, True)
        Else
            Set logFile = objFSO.CreateTextFile(logName, True)
        End If
    End If
    logFile.WriteLine logMessage
    logFile.Close
    Set objFSO = Nothing
   
    On Error Goto 0

End Sub